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