13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "build/build_config.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// winsock2.h must be included first in order to ensure it is included before
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// windows.h.
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <winsock2.h>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h>
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <netinet/in.h>
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/socket.h>
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <arpa/inet.h>
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(USE_SYSTEM_LIBEVENT)
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <event.h>
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "third_party/libevent/event.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/eintr_wrapper.h"
253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h"
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_util.h"
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/listen_socket.h"
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef int socklen_t;
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // defined(OS_WIN)
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kReadBufSize = 4096;
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst SOCKET ListenSocket::kInvalidSocket = INVALID_SOCKET;
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int ListenSocket::kSocketError = SOCKET_ERROR;
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst SOCKET ListenSocket::kInvalidSocket = -1;
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int ListenSocket::kSocketError = -1;
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenListenSocket* ListenSocket::Listen(std::string ip, int port,
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   ListenSocketDelegate* del) {
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  SOCKET s = Listen(ip, port);
5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (s == kInvalidSocket) {
5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // TODO(erikkay): error handling
5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ListenSocket* sock = new ListenSocket(s, del);
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    sock->Listen();
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return sock;
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return NULL;
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ListenSocket::Send(const char* bytes, int len, bool append_linefeed) {
6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  SendInternal(bytes, len);
6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (append_linefeed) {
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SendInternal("\r\n", 2);
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ListenSocket::Send(const std::string& str, bool append_linefeed) {
6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Send(str.data(), static_cast<int>(str.length()), append_linefeed);
6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ListenSocket::PauseReads() {
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!reads_paused_);
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  reads_paused_ = true;
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ListenSocket::ResumeReads() {
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(reads_paused_);
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  reads_paused_ = false;
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (has_pending_reads_) {
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    has_pending_reads_ = false;
8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    Read();
8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottListenSocket::ListenSocket(SOCKET s, ListenSocketDelegate *del)
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : socket_(s),
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      socket_delegate_(del),
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reads_paused_(false),
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      has_pending_reads_(false) {
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_event_ = WSACreateEvent();
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WatchSocket(NOT_WAITING);
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottListenSocket::~ListenSocket() {
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (socket_event_) {
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    WSACloseEvent(socket_event_);
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    socket_event_ = WSA_INVALID_EVENT;
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CloseSocket(socket_);
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSOCKET ListenSocket::Listen(std::string ip, int port) {
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (s != kInvalidSocket) {
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_POSIX)
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Allow rapid reuse.
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    static const int kOn = 1;
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    sockaddr_in addr;
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memset(&addr, 0, sizeof(addr));
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    addr.sin_family = AF_INET;
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    addr.sin_addr.s_addr = inet_addr(ip.c_str());
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    addr.sin_port = htons(port);
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (bind(s, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) {
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      closesocket(s);
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      close(s);
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      s = kInvalidSocket;
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return s;
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSOCKET ListenSocket::Accept(SOCKET s) {
13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sockaddr_in from;
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  socklen_t from_len = sizeof(from);
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  SOCKET conn =
13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      HANDLE_EINTR(accept(s, reinterpret_cast<sockaddr*>(&from), &from_len));
13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (conn != kInvalidSocket) {
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net::SetNonBlocking(conn);
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return conn;
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ListenSocket::SendInternal(const char* bytes, int len) {
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  char* send_buf = const_cast<char *>(bytes);
14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int len_left = len;
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  while (true) {
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0));
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (sent == len_left) {  // A shortcut to avoid extraneous checks.
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (sent == kSocketError) {
15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN)
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (WSAGetLastError() != WSAEWOULDBLOCK) {
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError();
15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#elif defined(OS_POSIX)
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (errno != EWOULDBLOCK && errno != EAGAIN) {
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        LOG(ERROR) << "send failed: errno==" << errno;
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        break;
16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // Otherwise we would block, and now we have to wait for a retry.
16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // Fall through to PlatformThread::YieldCurrentThread()
16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    } else {
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // sent != len_left according to the shortcut above.
16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // Shift the buffer start and send the remainder after a short while.
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      send_buf += sent;
16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      len_left -= sent;
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::PlatformThread::YieldCurrentThread();
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ListenSocket::Listen() {
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int backlog = 10;  // TODO(erikkay): maybe don't allow any backlog?
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  listen(socket_, backlog);
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(erikkay): error handling
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX)
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WatchSocket(WAITING_ACCEPT);
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ListenSocket::Accept() {
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SOCKET conn = Accept(socket_);
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (conn != kInvalidSocket) {
185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<ListenSocket> sock(
186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        new ListenSocket(conn, socket_delegate_));
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // it's up to the delegate to AddRef if it wants to keep it around
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX)
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    sock->WatchSocket(WAITING_READ);
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    socket_delegate_->DidAccept(this, sock);
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO(ibrar): some error handling required here
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ListenSocket::Read() {
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char buf[kReadBufSize + 1];  // +1 for null termination
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int len;
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  do {
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    len = HANDLE_EINTR(recv(socket_, buf, kReadBufSize, 0));
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (len == kSocketError) {
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int err = WSAGetLastError();
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (err == WSAEWOULDBLOCK) {
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (errno == EWOULDBLOCK || errno == EAGAIN) {
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // TODO(ibrar): some error handling required here
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else if (len == 0) {
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // In Windows, Close() is called by OnObjectSignaled.  In POSIX, we need
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // to call it here.
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX)
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Close();
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // TODO(ibrar): maybe change DidRead to take a length instead
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK(len > 0 && len <= kReadBufSize);
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      buf[len] = 0;  // already create a buffer with +1 length
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      socket_delegate_->DidRead(this, buf, len);
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (len == kReadBufSize);
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ListenSocket::Close() {
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX)
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (wait_state_ == WAITING_CLOSE)
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  wait_state_ = WAITING_CLOSE;
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_delegate_->DidClose(this);
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ListenSocket::CloseSocket(SOCKET s) {
23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (s && s != kInvalidSocket) {
24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    UnwatchSocket();
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    closesocket(s);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    close(s);
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ListenSocket::WatchSocket(WaitState state) {
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ);
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watcher_.StartWatching(socket_event_, this);
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Implicitly calls StartWatchingFileDescriptor().
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoopForIO::current()->WatchFileDescriptor(
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      socket_, true, MessageLoopForIO::WATCH_READ, &watcher_, this);
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  wait_state_ = state;
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ListenSocket::UnwatchSocket() {
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  watcher_.StopWatching();
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  watcher_.StopWatchingFileDescriptor();
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(ibrar): We can add these functions into OS dependent files
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// MessageLoop watcher callback
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ListenSocket::OnObjectSignaled(HANDLE object) {
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WSANETWORKEVENTS ev;
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) {
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The object was reset by WSAEnumNetworkEvents.  Watch for the next signal.
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watcher_.StartWatching(object, this);
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ev.lNetworkEvents == 0) {
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Occasionally the event is set even though there is no new data.
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The net seems to think that this is ignorable.
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ev.lNetworkEvents & FD_ACCEPT) {
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Accept();
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ev.lNetworkEvents & FD_READ) {
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (reads_paused_) {
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      has_pending_reads_ = true;
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Read();
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ev.lNetworkEvents & FD_CLOSE) {
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Close();
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ListenSocket::OnFileCanReadWithoutBlocking(int fd) {
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (wait_state_ == WAITING_ACCEPT) {
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Accept();
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (wait_state_ == WAITING_READ) {
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (reads_paused_) {
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      has_pending_reads_ = true;
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Read();
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (wait_state_ == WAITING_CLOSE) {
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Close() is called by Read() in the Linux case.
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO(erikkay): this seems to get hit multiple times after the close
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ListenSocket::OnFileCanWriteWithoutBlocking(int fd) {
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // MessagePumpLibevent callback, we don't listen for write events
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // so we shouldn't ever reach here.
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  NOTREACHED();
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
326