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"
10 #include <sys/socket.h>
12 #include "build/build_config.h"
15 #include <netinet/in.h>
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"
29 const int kInvalidSocket
= -1;
33 TCPServerSocketLibevent::TCPServerSocketLibevent(
35 const net::NetLog::Source
& source
)
36 : socket_(kInvalidSocket
),
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
)
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
);
64 PLOG(ERROR
) << "socket() returned an error";
65 return MapSystemError(errno
);
68 if (SetNonBlocking(socket_
)) {
69 int result
= MapSystemError(errno
);
74 int result
= SetSocketOptions();
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
);
84 PLOG(ERROR
) << "bind() returned an error";
85 result
= MapSystemError(errno
);
90 result
= listen(socket_
, backlog
);
92 PLOG(ERROR
) << "listen() returned an error";
93 result
= MapSystemError(errno
);
101 int TCPServerSocketLibevent::GetLocalAddress(IPEndPoint
* address
) const {
102 DCHECK(CalledOnValidThread());
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
))
114 int TCPServerSocketLibevent::Accept(
115 scoped_ptr
<StreamSocket
>* socket
, const CompletionCallback
& callback
) {
116 DCHECK(CalledOnValidThread());
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
;
140 int TCPServerSocketLibevent::SetSocketOptions() {
142 if (reuse_address_
) {
143 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_REUSEADDR
, &true_value
,
146 return MapSystemError(errno
);
151 int TCPServerSocketLibevent::AcceptInternal(
152 scoped_ptr
<StreamSocket
>* socket
) {
153 SockaddrStorage storage
;
154 int new_socket
= HANDLE_EINTR(accept(socket_
,
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
);
165 if (!address
.FromSockAddr(storage
.addr
, storage
.addr_len
)) {
167 if (HANDLE_EINTR(close(new_socket
)) < 0)
168 PLOG(ERROR
) << "close";
169 net_log_
.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT
, 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
);
182 socket
->reset(tcp_socket
.release());
183 net_log_
.EndEvent(NetLog::TYPE_TCP_ACCEPT
,
184 CreateNetLogIPEndPointCallback(&address
));
188 void TCPServerSocketLibevent::Close() {
189 if (socket_
!= kInvalidSocket
) {
190 bool ok
= accept_socket_watcher_
.StopWatchingFileDescriptor();
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();
206 CompletionCallback callback
= accept_callback_
;
207 accept_callback_
.Reset();
208 callback
.Run(result
);
212 void TCPServerSocketLibevent::OnFileCanWriteWithoutBlocking(int fd
) {