Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2010 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 "build/build_config.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 <errno.h>
     13 #include <netinet/in.h>
     14 #include <sys/socket.h>
     15 #include <arpa/inet.h>
     16 #include "net/base/net_errors.h"
     17 #if defined(USE_SYSTEM_LIBEVENT)
     18 #include <event.h>
     19 #else
     20 #include "third_party/libevent/event.h"
     21 #endif
     22 #endif
     23 
     24 #include "base/eintr_wrapper.h"
     25 #include "base/threading/platform_thread.h"
     26 #include "net/base/net_util.h"
     27 #include "net/base/listen_socket.h"
     28 
     29 #if defined(OS_WIN)
     30 typedef int socklen_t;
     31 #endif  // defined(OS_WIN)
     32 
     33 namespace {
     34 
     35 const int kReadBufSize = 4096;
     36 
     37 }  // namespace
     38 
     39 #if defined(OS_WIN)
     40 const SOCKET ListenSocket::kInvalidSocket = INVALID_SOCKET;
     41 const int ListenSocket::kSocketError = SOCKET_ERROR;
     42 #elif defined(OS_POSIX)
     43 const SOCKET ListenSocket::kInvalidSocket = -1;
     44 const int ListenSocket::kSocketError = -1;
     45 #endif
     46 
     47 ListenSocket* ListenSocket::Listen(std::string ip, int port,
     48                                    ListenSocketDelegate* del) {
     49   SOCKET s = Listen(ip, port);
     50   if (s == kInvalidSocket) {
     51     // TODO(erikkay): error handling
     52   } else {
     53     ListenSocket* sock = new ListenSocket(s, del);
     54     sock->Listen();
     55     return sock;
     56   }
     57   return NULL;
     58 }
     59 
     60 void ListenSocket::Send(const char* bytes, int len, bool append_linefeed) {
     61   SendInternal(bytes, len);
     62   if (append_linefeed) {
     63     SendInternal("\r\n", 2);
     64   }
     65 }
     66 
     67 void ListenSocket::Send(const std::string& str, bool append_linefeed) {
     68   Send(str.data(), static_cast<int>(str.length()), append_linefeed);
     69 }
     70 
     71 void ListenSocket::PauseReads() {
     72   DCHECK(!reads_paused_);
     73   reads_paused_ = true;
     74 }
     75 
     76 void ListenSocket::ResumeReads() {
     77   DCHECK(reads_paused_);
     78   reads_paused_ = false;
     79   if (has_pending_reads_) {
     80     has_pending_reads_ = false;
     81     Read();
     82   }
     83 }
     84 
     85 ListenSocket::ListenSocket(SOCKET s, ListenSocketDelegate *del)
     86     : socket_(s),
     87       socket_delegate_(del),
     88       reads_paused_(false),
     89       has_pending_reads_(false) {
     90 #if defined(OS_WIN)
     91   socket_event_ = WSACreateEvent();
     92   // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT
     93   WatchSocket(NOT_WAITING);
     94 #endif
     95 }
     96 
     97 ListenSocket::~ListenSocket() {
     98 #if defined(OS_WIN)
     99   if (socket_event_) {
    100     WSACloseEvent(socket_event_);
    101     socket_event_ = WSA_INVALID_EVENT;
    102   }
    103 #endif
    104   CloseSocket(socket_);
    105 }
    106 
    107 SOCKET ListenSocket::Listen(std::string ip, int port) {
    108   SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    109   if (s != kInvalidSocket) {
    110 #if defined(OS_POSIX)
    111     // Allow rapid reuse.
    112     static const int kOn = 1;
    113     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
    114 #endif
    115     sockaddr_in addr;
    116     memset(&addr, 0, sizeof(addr));
    117     addr.sin_family = AF_INET;
    118     addr.sin_addr.s_addr = inet_addr(ip.c_str());
    119     addr.sin_port = htons(port);
    120     if (bind(s, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) {
    121 #if defined(OS_WIN)
    122       closesocket(s);
    123 #elif defined(OS_POSIX)
    124       close(s);
    125 #endif
    126       s = kInvalidSocket;
    127     }
    128   }
    129   return s;
    130 }
    131 
    132 SOCKET ListenSocket::Accept(SOCKET s) {
    133   sockaddr_in from;
    134   socklen_t from_len = sizeof(from);
    135   SOCKET conn =
    136       HANDLE_EINTR(accept(s, reinterpret_cast<sockaddr*>(&from), &from_len));
    137   if (conn != kInvalidSocket) {
    138     net::SetNonBlocking(conn);
    139   }
    140   return conn;
    141 }
    142 
    143 void ListenSocket::SendInternal(const char* bytes, int len) {
    144   char* send_buf = const_cast<char *>(bytes);
    145   int len_left = len;
    146   while (true) {
    147     int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0));
    148     if (sent == len_left) {  // A shortcut to avoid extraneous checks.
    149       break;
    150     }
    151     if (sent == kSocketError) {
    152 #if defined(OS_WIN)
    153       if (WSAGetLastError() != WSAEWOULDBLOCK) {
    154         LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError();
    155 #elif defined(OS_POSIX)
    156       if (errno != EWOULDBLOCK && errno != EAGAIN) {
    157         LOG(ERROR) << "send failed: errno==" << errno;
    158 #endif
    159         break;
    160       }
    161       // Otherwise we would block, and now we have to wait for a retry.
    162       // Fall through to PlatformThread::YieldCurrentThread()
    163     } else {
    164       // sent != len_left according to the shortcut above.
    165       // Shift the buffer start and send the remainder after a short while.
    166       send_buf += sent;
    167       len_left -= sent;
    168     }
    169     base::PlatformThread::YieldCurrentThread();
    170   }
    171 }
    172 
    173 void ListenSocket::Listen() {
    174   int backlog = 10;  // TODO(erikkay): maybe don't allow any backlog?
    175   listen(socket_, backlog);
    176   // TODO(erikkay): error handling
    177 #if defined(OS_POSIX)
    178   WatchSocket(WAITING_ACCEPT);
    179 #endif
    180 }
    181 
    182 void ListenSocket::Accept() {
    183   SOCKET conn = Accept(socket_);
    184   if (conn != kInvalidSocket) {
    185     scoped_refptr<ListenSocket> sock(
    186         new ListenSocket(conn, socket_delegate_));
    187     // it's up to the delegate to AddRef if it wants to keep it around
    188 #if defined(OS_POSIX)
    189     sock->WatchSocket(WAITING_READ);
    190 #endif
    191     socket_delegate_->DidAccept(this, sock);
    192   } else {
    193     // TODO(ibrar): some error handling required here
    194   }
    195 }
    196 
    197 void ListenSocket::Read() {
    198   char buf[kReadBufSize + 1];  // +1 for null termination
    199   int len;
    200   do {
    201     len = HANDLE_EINTR(recv(socket_, buf, kReadBufSize, 0));
    202     if (len == kSocketError) {
    203 #if defined(OS_WIN)
    204       int err = WSAGetLastError();
    205       if (err == WSAEWOULDBLOCK) {
    206 #elif defined(OS_POSIX)
    207       if (errno == EWOULDBLOCK || errno == EAGAIN) {
    208 #endif
    209         break;
    210       } else {
    211         // TODO(ibrar): some error handling required here
    212         break;
    213       }
    214     } else if (len == 0) {
    215       // In Windows, Close() is called by OnObjectSignaled.  In POSIX, we need
    216       // to call it here.
    217 #if defined(OS_POSIX)
    218       Close();
    219 #endif
    220     } else {
    221       // TODO(ibrar): maybe change DidRead to take a length instead
    222       DCHECK(len > 0 && len <= kReadBufSize);
    223       buf[len] = 0;  // already create a buffer with +1 length
    224       socket_delegate_->DidRead(this, buf, len);
    225     }
    226   } while (len == kReadBufSize);
    227 }
    228 
    229 void ListenSocket::Close() {
    230 #if defined(OS_POSIX)
    231   if (wait_state_ == WAITING_CLOSE)
    232     return;
    233   wait_state_ = WAITING_CLOSE;
    234 #endif
    235   socket_delegate_->DidClose(this);
    236 }
    237 
    238 void ListenSocket::CloseSocket(SOCKET s) {
    239   if (s && s != kInvalidSocket) {
    240     UnwatchSocket();
    241 #if defined(OS_WIN)
    242     closesocket(s);
    243 #elif defined(OS_POSIX)
    244     close(s);
    245 #endif
    246   }
    247 }
    248 
    249 void ListenSocket::WatchSocket(WaitState state) {
    250 #if defined(OS_WIN)
    251   WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ);
    252   watcher_.StartWatching(socket_event_, this);
    253 #elif defined(OS_POSIX)
    254   // Implicitly calls StartWatchingFileDescriptor().
    255   MessageLoopForIO::current()->WatchFileDescriptor(
    256       socket_, true, MessageLoopForIO::WATCH_READ, &watcher_, this);
    257   wait_state_ = state;
    258 #endif
    259 }
    260 
    261 void ListenSocket::UnwatchSocket() {
    262 #if defined(OS_WIN)
    263   watcher_.StopWatching();
    264 #elif defined(OS_POSIX)
    265   watcher_.StopWatchingFileDescriptor();
    266 #endif
    267 }
    268 
    269 // TODO(ibrar): We can add these functions into OS dependent files
    270 #if defined(OS_WIN)
    271 // MessageLoop watcher callback
    272 void ListenSocket::OnObjectSignaled(HANDLE object) {
    273   WSANETWORKEVENTS ev;
    274   if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) {
    275     // TODO
    276     return;
    277   }
    278 
    279   // The object was reset by WSAEnumNetworkEvents.  Watch for the next signal.
    280   watcher_.StartWatching(object, this);
    281 
    282   if (ev.lNetworkEvents == 0) {
    283     // Occasionally the event is set even though there is no new data.
    284     // The net seems to think that this is ignorable.
    285     return;
    286   }
    287   if (ev.lNetworkEvents & FD_ACCEPT) {
    288     Accept();
    289   }
    290   if (ev.lNetworkEvents & FD_READ) {
    291     if (reads_paused_) {
    292       has_pending_reads_ = true;
    293     } else {
    294       Read();
    295     }
    296   }
    297   if (ev.lNetworkEvents & FD_CLOSE) {
    298     Close();
    299   }
    300 }
    301 #elif defined(OS_POSIX)
    302 void ListenSocket::OnFileCanReadWithoutBlocking(int fd) {
    303   if (wait_state_ == WAITING_ACCEPT) {
    304     Accept();
    305   }
    306   if (wait_state_ == WAITING_READ) {
    307     if (reads_paused_) {
    308       has_pending_reads_ = true;
    309     } else {
    310       Read();
    311     }
    312   }
    313   if (wait_state_ == WAITING_CLOSE) {
    314     // Close() is called by Read() in the Linux case.
    315     // TODO(erikkay): this seems to get hit multiple times after the close
    316   }
    317 }
    318 
    319 void ListenSocket::OnFileCanWriteWithoutBlocking(int fd) {
    320   // MessagePumpLibevent callback, we don't listen for write events
    321   // so we shouldn't ever reach here.
    322   NOTREACHED();
    323 }
    324 
    325 #endif
    326