1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/socket/tcp_server_socket_libevent.h" 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <errno.h> 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <fcntl.h> 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <netdb.h> 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <sys/socket.h> 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "build/build_config.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_POSIX) 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <netinet/in.h> 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(USE_SYSTEM_LIBEVENT) 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <event.h> 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#else 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "third_party/libevent/event.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/eintr_wrapper.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/ip_endpoint.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/net_errors.h" 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/net_util.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/socket/tcp_client_socket.h" 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace net { 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace { 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kInvalidSocket = -1; 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTCPServerSocketLibevent::TCPServerSocketLibevent( 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog* net_log, 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const net::NetLog::Source& source) 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : socket_(kInvalidSocket), 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen accept_socket_(NULL), 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen accept_callback_(NULL), 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<NetLog::EventParameters> params; 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (source.is_valid()) 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params = new NetLogSourceParameter("source_dependency", source); 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTCPServerSocketLibevent::~TCPServerSocketLibevent() { 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (socket_ != kInvalidSocket) 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Close(); 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint TCPServerSocketLibevent::Listen(const IPEndPoint& address, int backlog) { 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(CalledOnValidThread()); 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_GT(backlog, 0); 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(socket_, kInvalidSocket); 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (socket_ < 0) { 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PLOG(ERROR) << "socket() returned an error"; 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return MapSystemError(errno); 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (SetNonBlocking(socket_)) { 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result = MapSystemError(errno); 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Close(); 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct sockaddr_storage addr_storage; 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen size_t addr_len = sizeof(addr_storage); 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!address.ToSockAddr(addr, &addr_len)) 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ERR_INVALID_ARGUMENT; 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result = bind(socket_, addr, addr_len); 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (result < 0) { 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PLOG(ERROR) << "bind() returned an error"; 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result = MapSystemError(errno); 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Close(); 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result = listen(socket_, backlog); 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (result < 0) { 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PLOG(ERROR) << "listen() returned an error"; 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result = MapSystemError(errno); 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Close(); 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return OK; 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint TCPServerSocketLibevent::GetLocalAddress(IPEndPoint* address) const { 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(CalledOnValidThread()); 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(address); 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct sockaddr_storage addr_storage; 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socklen_t addr_len = sizeof(addr_storage); 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (getsockname(socket_, addr, &addr_len) < 0) 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return MapSystemError(errno); 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!address->FromSockAddr(addr, addr_len)) 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ERR_FAILED; 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return OK; 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint TCPServerSocketLibevent::Accept( 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<ClientSocket>* socket, CompletionCallback* callback) { 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(CalledOnValidThread()); 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(socket); 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(callback); 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!accept_callback_); 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT, NULL); 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result = AcceptInternal(socket); 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (result == ERR_IO_PENDING) { 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!MessageLoopForIO::current()->WatchFileDescriptor( 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket_, true, MessageLoopForIO::WATCH_READ, 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &accept_socket_watcher_, this)) { 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PLOG(ERROR) << "WatchFileDescriptor failed on read"; 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return MapSystemError(errno); 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen accept_socket_ = socket; 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen accept_callback_ = callback; 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint TCPServerSocketLibevent::AcceptInternal( 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<ClientSocket>* socket) { 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct sockaddr_storage addr_storage; 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socklen_t addr_len = sizeof(addr_storage); 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result = HANDLE_EINTR(accept(socket_, addr, &addr_len)); 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (result < 0) { 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int net_error = MapSystemError(errno); 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_error != ERR_IO_PENDING) 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net_error; 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPEndPoint address; 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!address.FromSockAddr(addr, addr_len)) { 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (HANDLE_EINTR(close(result)) < 0) 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PLOG(ERROR) << "close"; 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED); 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ERR_FAILED; 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TCPClientSocket* tcp_socket = new TCPClientSocket( 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AddressList(address.address(), address.port(), false), 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.net_log(), net_log_.source()); 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tcp_socket->AdoptSocket(result); 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket->reset(tcp_socket); 166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new NetLogStringParameter( 168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "address", address.ToString()))); 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return OK; 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TCPServerSocketLibevent::Close() { 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (socket_ != kInvalidSocket) { 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (HANDLE_EINTR(close(socket_)) < 0) 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PLOG(ERROR) << "close"; 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket_ = kInvalidSocket; 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TCPServerSocketLibevent::OnFileCanReadWithoutBlocking(int fd) { 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(CalledOnValidThread()); 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result = AcceptInternal(accept_socket_); 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (result != ERR_IO_PENDING) { 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CompletionCallback* c = accept_callback_; 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen accept_callback_ = NULL; 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen accept_socket_ = NULL; 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen c->Run(result); 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TCPServerSocketLibevent::OnFileCanWriteWithoutBlocking(int fd) { 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace net 197