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