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