[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / net / socket / tcp_server_socket_libevent.cc
blob589fd119ed8878fc130932ac440846c7bc9da07f
1 // Copyright (c) 2012 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.
5 #include "net/socket/tcp_server_socket_libevent.h"
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <netdb.h>
10 #include <sys/socket.h>
12 #include "build/build_config.h"
14 #if defined(OS_POSIX)
15 #include <netinet/in.h>
16 #endif
18 #include "base/posix/eintr_wrapper.h"
19 #include "net/base/ip_endpoint.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/net_util.h"
22 #include "net/socket/socket_net_log_params.h"
23 #include "net/socket/tcp_client_socket.h"
25 namespace net {
27 namespace {
29 const int kInvalidSocket = -1;
31 } // namespace
33 TCPServerSocketLibevent::TCPServerSocketLibevent(
34 net::NetLog* net_log,
35 const net::NetLog::Source& source)
36 : socket_(kInvalidSocket),
37 accept_socket_(NULL),
38 reuse_address_(false),
39 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
40 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
41 source.ToEventParametersCallback());
44 TCPServerSocketLibevent::~TCPServerSocketLibevent() {
45 if (socket_ != kInvalidSocket)
46 Close();
47 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
50 void TCPServerSocketLibevent::AllowAddressReuse() {
51 DCHECK(CalledOnValidThread());
52 DCHECK_EQ(socket_, kInvalidSocket);
54 reuse_address_ = true;
57 int TCPServerSocketLibevent::Listen(const IPEndPoint& address, int backlog) {
58 DCHECK(CalledOnValidThread());
59 DCHECK_GT(backlog, 0);
60 DCHECK_EQ(socket_, kInvalidSocket);
62 socket_ = socket(address.GetSockAddrFamily(), SOCK_STREAM, IPPROTO_TCP);
63 if (socket_ < 0) {
64 PLOG(ERROR) << "socket() returned an error";
65 return MapSystemError(errno);
68 if (SetNonBlocking(socket_)) {
69 int result = MapSystemError(errno);
70 Close();
71 return result;
74 int result = SetSocketOptions();
75 if (result != OK)
76 return result;
78 SockaddrStorage storage;
79 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
80 return ERR_INVALID_ARGUMENT;
82 result = bind(socket_, storage.addr, storage.addr_len);
83 if (result < 0) {
84 PLOG(ERROR) << "bind() returned an error";
85 result = MapSystemError(errno);
86 Close();
87 return result;
90 result = listen(socket_, backlog);
91 if (result < 0) {
92 PLOG(ERROR) << "listen() returned an error";
93 result = MapSystemError(errno);
94 Close();
95 return result;
98 return OK;
101 int TCPServerSocketLibevent::GetLocalAddress(IPEndPoint* address) const {
102 DCHECK(CalledOnValidThread());
103 DCHECK(address);
105 SockaddrStorage storage;
106 if (getsockname(socket_, storage.addr, &storage.addr_len) < 0)
107 return MapSystemError(errno);
108 if (!address->FromSockAddr(storage.addr, storage.addr_len))
109 return ERR_FAILED;
111 return OK;
114 int TCPServerSocketLibevent::Accept(
115 scoped_ptr<StreamSocket>* socket, const CompletionCallback& callback) {
116 DCHECK(CalledOnValidThread());
117 DCHECK(socket);
118 DCHECK(!callback.is_null());
119 DCHECK(accept_callback_.is_null());
121 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT);
123 int result = AcceptInternal(socket);
125 if (result == ERR_IO_PENDING) {
126 if (!MessageLoopForIO::current()->WatchFileDescriptor(
127 socket_, true, MessageLoopForIO::WATCH_READ,
128 &accept_socket_watcher_, this)) {
129 PLOG(ERROR) << "WatchFileDescriptor failed on read";
130 return MapSystemError(errno);
133 accept_socket_ = socket;
134 accept_callback_ = callback;
137 return result;
140 int TCPServerSocketLibevent::SetSocketOptions() {
141 int true_value = 1;
142 if (reuse_address_) {
143 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &true_value,
144 sizeof(true_value));
145 if (rv < 0)
146 return MapSystemError(errno);
148 return OK;
151 int TCPServerSocketLibevent::AcceptInternal(
152 scoped_ptr<StreamSocket>* socket) {
153 SockaddrStorage storage;
154 int new_socket = HANDLE_EINTR(accept(socket_,
155 storage.addr,
156 &storage.addr_len));
157 if (new_socket < 0) {
158 int net_error = MapSystemError(errno);
159 if (net_error != ERR_IO_PENDING)
160 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error);
161 return net_error;
164 IPEndPoint address;
165 if (!address.FromSockAddr(storage.addr, storage.addr_len)) {
166 NOTREACHED();
167 if (HANDLE_EINTR(close(new_socket)) < 0)
168 PLOG(ERROR) << "close";
169 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED);
170 return ERR_FAILED;
172 scoped_ptr<TCPClientSocket> tcp_socket(new TCPClientSocket(
173 AddressList(address),
174 net_log_.net_log(), net_log_.source()));
175 int adopt_result = tcp_socket->AdoptSocket(new_socket);
176 if (adopt_result != OK) {
177 if (HANDLE_EINTR(close(new_socket)) < 0)
178 PLOG(ERROR) << "close";
179 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result);
180 return adopt_result;
182 socket->reset(tcp_socket.release());
183 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT,
184 CreateNetLogIPEndPointCallback(&address));
185 return OK;
188 void TCPServerSocketLibevent::Close() {
189 if (socket_ != kInvalidSocket) {
190 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
191 DCHECK(ok);
192 if (HANDLE_EINTR(close(socket_)) < 0)
193 PLOG(ERROR) << "close";
194 socket_ = kInvalidSocket;
198 void TCPServerSocketLibevent::OnFileCanReadWithoutBlocking(int fd) {
199 DCHECK(CalledOnValidThread());
201 int result = AcceptInternal(accept_socket_);
202 if (result != ERR_IO_PENDING) {
203 accept_socket_ = NULL;
204 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
205 DCHECK(ok);
206 CompletionCallback callback = accept_callback_;
207 accept_callback_.Reset();
208 callback.Run(result);
212 void TCPServerSocketLibevent::OnFileCanWriteWithoutBlocking(int fd) {
213 NOTREACHED();
216 } // namespace net