Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/socket/stream_listen_socket.h"
      6 
      7 #if defined(OS_WIN)
      8 // winsock2.h must be included first in order to ensure it is included before
      9 // windows.h.
     10 #include <winsock2.h>
     11 #elif defined(OS_POSIX)
     12 #include <arpa/inet.h>
     13 #include <errno.h>
     14 #include <netinet/in.h>
     15 #include <sys/socket.h>
     16 #include <sys/types.h>
     17 #include "net/base/net_errors.h"
     18 #endif
     19 
     20 #include "base/logging.h"
     21 #include "base/memory/ref_counted.h"
     22 #include "base/memory/scoped_ptr.h"
     23 #include "base/posix/eintr_wrapper.h"
     24 #include "base/sys_byteorder.h"
     25 #include "base/threading/platform_thread.h"
     26 #include "build/build_config.h"
     27 #include "net/base/ip_endpoint.h"
     28 #include "net/base/net_errors.h"
     29 #include "net/base/net_util.h"
     30 #include "net/socket/socket_descriptor.h"
     31 
     32 using std::string;
     33 
     34 #if defined(OS_WIN)
     35 typedef int socklen_t;
     36 #endif  // defined(OS_WIN)
     37 
     38 namespace net {
     39 
     40 namespace {
     41 
     42 const int kReadBufSize = 4096;
     43 
     44 }  // namespace
     45 
     46 #if defined(OS_WIN)
     47 const int StreamListenSocket::kSocketError = SOCKET_ERROR;
     48 #elif defined(OS_POSIX)
     49 const int StreamListenSocket::kSocketError = -1;
     50 #endif
     51 
     52 StreamListenSocket::StreamListenSocket(SocketDescriptor s,
     53                                        StreamListenSocket::Delegate* del)
     54     : socket_delegate_(del),
     55       socket_(s),
     56       reads_paused_(false),
     57       has_pending_reads_(false) {
     58 #if defined(OS_WIN)
     59   socket_event_ = WSACreateEvent();
     60   // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT.
     61   WatchSocket(NOT_WAITING);
     62 #elif defined(OS_POSIX)
     63   wait_state_ = NOT_WAITING;
     64 #endif
     65 }
     66 
     67 StreamListenSocket::~StreamListenSocket() {
     68   CloseSocket();
     69 #if defined(OS_WIN)
     70   if (socket_event_) {
     71     WSACloseEvent(socket_event_);
     72     socket_event_ = WSA_INVALID_EVENT;
     73   }
     74 #endif
     75 }
     76 
     77 void StreamListenSocket::Send(const char* bytes, int len,
     78                               bool append_linefeed) {
     79   SendInternal(bytes, len);
     80   if (append_linefeed)
     81     SendInternal("\r\n", 2);
     82 }
     83 
     84 void StreamListenSocket::Send(const string& str, bool append_linefeed) {
     85   Send(str.data(), static_cast<int>(str.length()), append_linefeed);
     86 }
     87 
     88 int StreamListenSocket::GetLocalAddress(IPEndPoint* address) {
     89   SockaddrStorage storage;
     90   if (getsockname(socket_, storage.addr, &storage.addr_len)) {
     91 #if defined(OS_WIN)
     92     int err = WSAGetLastError();
     93 #else
     94     int err = errno;
     95 #endif
     96     return MapSystemError(err);
     97   }
     98   if (!address->FromSockAddr(storage.addr, storage.addr_len))
     99     return ERR_FAILED;
    100   return OK;
    101 }
    102 
    103 SocketDescriptor StreamListenSocket::AcceptSocket() {
    104   SocketDescriptor conn = HANDLE_EINTR(accept(socket_, NULL, NULL));
    105   if (conn == kInvalidSocket)
    106     LOG(ERROR) << "Error accepting connection.";
    107   else
    108     SetNonBlocking(conn);
    109   return conn;
    110 }
    111 
    112 void StreamListenSocket::SendInternal(const char* bytes, int len) {
    113   char* send_buf = const_cast<char *>(bytes);
    114   int len_left = len;
    115   while (true) {
    116     int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0));
    117     if (sent == len_left) {  // A shortcut to avoid extraneous checks.
    118       break;
    119     }
    120     if (sent == kSocketError) {
    121 #if defined(OS_WIN)
    122       if (WSAGetLastError() != WSAEWOULDBLOCK) {
    123         LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError();
    124 #elif defined(OS_POSIX)
    125       if (errno != EWOULDBLOCK && errno != EAGAIN) {
    126         LOG(ERROR) << "send failed: errno==" << errno;
    127 #endif
    128         break;
    129       }
    130       // Otherwise we would block, and now we have to wait for a retry.
    131       // Fall through to PlatformThread::YieldCurrentThread()
    132     } else {
    133       // sent != len_left according to the shortcut above.
    134       // Shift the buffer start and send the remainder after a short while.
    135       send_buf += sent;
    136       len_left -= sent;
    137     }
    138     base::PlatformThread::YieldCurrentThread();
    139   }
    140 }
    141 
    142 void StreamListenSocket::Listen() {
    143   int backlog = 10;  // TODO(erikkay): maybe don't allow any backlog?
    144   if (listen(socket_, backlog) == -1) {
    145     // TODO(erikkay): error handling.
    146     LOG(ERROR) << "Could not listen on socket.";
    147     return;
    148   }
    149 #if defined(OS_POSIX)
    150   WatchSocket(WAITING_ACCEPT);
    151 #endif
    152 }
    153 
    154 void StreamListenSocket::Read() {
    155   char buf[kReadBufSize + 1];  // +1 for null termination.
    156   int len;
    157   do {
    158     len = HANDLE_EINTR(recv(socket_, buf, kReadBufSize, 0));
    159     if (len == kSocketError) {
    160 #if defined(OS_WIN)
    161       int err = WSAGetLastError();
    162       if (err == WSAEWOULDBLOCK) {
    163 #elif defined(OS_POSIX)
    164       if (errno == EWOULDBLOCK || errno == EAGAIN) {
    165 #endif
    166         break;
    167       } else {
    168         // TODO(ibrar): some error handling required here.
    169         break;
    170       }
    171     } else if (len == 0) {
    172       // In Windows, Close() is called by OnObjectSignaled. In POSIX, we need
    173       // to call it here.
    174 #if defined(OS_POSIX)
    175       Close();
    176 #endif
    177     } else {
    178       // TODO(ibrar): maybe change DidRead to take a length instead.
    179       DCHECK_GT(len, 0);
    180       DCHECK_LE(len, kReadBufSize);
    181       buf[len] = 0;  // Already create a buffer with +1 length.
    182       socket_delegate_->DidRead(this, buf, len);
    183     }
    184   } while (len == kReadBufSize);
    185 }
    186 
    187 void StreamListenSocket::Close() {
    188 #if defined(OS_POSIX)
    189   if (wait_state_ == NOT_WAITING)
    190     return;
    191   wait_state_ = NOT_WAITING;
    192 #endif
    193   UnwatchSocket();
    194   socket_delegate_->DidClose(this);
    195 }
    196 
    197 void StreamListenSocket::CloseSocket() {
    198   if (socket_ != kInvalidSocket) {
    199     UnwatchSocket();
    200 #if defined(OS_WIN)
    201     closesocket(socket_);
    202 #elif defined(OS_POSIX)
    203     close(socket_);
    204 #endif
    205   }
    206 }
    207 
    208 void StreamListenSocket::WatchSocket(WaitState state) {
    209 #if defined(OS_WIN)
    210   WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ);
    211   watcher_.StartWatching(socket_event_, this);
    212 #elif defined(OS_POSIX)
    213   // Implicitly calls StartWatchingFileDescriptor().
    214   base::MessageLoopForIO::current()->WatchFileDescriptor(
    215       socket_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this);
    216   wait_state_ = state;
    217 #endif
    218 }
    219 
    220 void StreamListenSocket::UnwatchSocket() {
    221 #if defined(OS_WIN)
    222   watcher_.StopWatching();
    223 #elif defined(OS_POSIX)
    224   watcher_.StopWatchingFileDescriptor();
    225 #endif
    226 }
    227 
    228 // TODO(ibrar): We can add these functions into OS dependent files.
    229 #if defined(OS_WIN)
    230 // MessageLoop watcher callback.
    231 void StreamListenSocket::OnObjectSignaled(HANDLE object) {
    232   WSANETWORKEVENTS ev;
    233   if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) {
    234     // TODO
    235     return;
    236   }
    237 
    238   if (ev.lNetworkEvents & FD_CLOSE) {
    239     Close();
    240     // Close might have deleted this object. We should return immediately.
    241     return;
    242   }
    243 
    244   // The object was reset by WSAEnumNetworkEvents.  Watch for the next signal.
    245   watcher_.StartWatching(object, this);
    246 
    247   if (ev.lNetworkEvents == 0) {
    248     // Occasionally the event is set even though there is no new data.
    249     // The net seems to think that this is ignorable.
    250     return;
    251   }
    252   if (ev.lNetworkEvents & FD_ACCEPT) {
    253     Accept();
    254   }
    255   if (ev.lNetworkEvents & FD_READ) {
    256     if (reads_paused_) {
    257       has_pending_reads_ = true;
    258     } else {
    259       Read();
    260       // Read() might call Close() internally and 'this' can be invalid here
    261       return;
    262     }
    263   }
    264 }
    265 #elif defined(OS_POSIX)
    266 void StreamListenSocket::OnFileCanReadWithoutBlocking(int fd) {
    267   switch (wait_state_) {
    268     case WAITING_ACCEPT:
    269       Accept();
    270       break;
    271     case WAITING_READ:
    272       if (reads_paused_) {
    273         has_pending_reads_ = true;
    274       } else {
    275         Read();
    276       }
    277       break;
    278     default:
    279       // Close() is called by Read() in the Linux case.
    280       NOTREACHED();
    281       break;
    282   }
    283 }
    284 
    285 void StreamListenSocket::OnFileCanWriteWithoutBlocking(int fd) {
    286   // MessagePumpLibevent callback, we don't listen for write events
    287   // so we shouldn't ever reach here.
    288   NOTREACHED();
    289 }
    290 
    291 #endif
    292 
    293 void StreamListenSocket::PauseReads() {
    294   DCHECK(!reads_paused_);
    295   reads_paused_ = true;
    296 }
    297 
    298 void StreamListenSocket::ResumeReads() {
    299   DCHECK(reads_paused_);
    300   reads_paused_ = false;
    301   if (has_pending_reads_) {
    302     has_pending_reads_ = false;
    303     Read();
    304   }
    305 }
    306 
    307 }  // namespace net
    308