| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "net/socket/tcp_server_socket_libevent.h" | 5 #include "net/socket/tcp_socket_libevent.h" | 
| 6 | 6 | 
| 7 #include <errno.h> | 7 #include <errno.h> | 
| 8 #include <fcntl.h> | 8 #include <fcntl.h> | 
| 9 #include <netdb.h> | 9 #include <netdb.h> | 
| 10 #include <sys/socket.h> | 10 #include <sys/socket.h> | 
| 11 | 11 | 
| 12 #include "build/build_config.h" | 12 #include "build/build_config.h" | 
| 13 | 13 | 
| 14 #if defined(OS_POSIX) | 14 #if defined(OS_POSIX) | 
| 15 #include <netinet/in.h> | 15 #include <netinet/in.h> | 
| 16 #endif | 16 #endif | 
| 17 | 17 | 
|  | 18 #include "base/logging.h" | 
| 18 #include "base/posix/eintr_wrapper.h" | 19 #include "base/posix/eintr_wrapper.h" | 
| 19 #include "net/base/ip_endpoint.h" | 20 #include "net/base/ip_endpoint.h" | 
| 20 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" | 
| 21 #include "net/base/net_util.h" | 22 #include "net/base/net_util.h" | 
| 22 #include "net/socket/socket_net_log_params.h" | 23 #include "net/socket/socket_net_log_params.h" | 
| 23 #include "net/socket/tcp_client_socket.h" |  | 
| 24 | 24 | 
| 25 namespace net { | 25 namespace net { | 
| 26 | 26 | 
| 27 namespace { | 27 namespace { | 
| 28 | 28 | 
| 29 const int kInvalidSocket = -1; | 29 const int kInvalidSocket = -1; | 
| 30 | 30 | 
| 31 }  // namespace | 31 }  // namespace | 
| 32 | 32 | 
| 33 TCPServerSocketLibevent::TCPServerSocketLibevent( | 33 TCPSocketLibevent::TCPSocketLibevent(NetLog* net_log, | 
| 34     net::NetLog* net_log, | 34                                      const NetLog::Source& source) | 
| 35     const net::NetLog::Source& source) |  | 
| 36     : socket_(kInvalidSocket), | 35     : socket_(kInvalidSocket), | 
| 37       accept_socket_(NULL), | 36       accept_socket_(NULL), | 
|  | 37       accept_address_(NULL), | 
| 38       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { | 38       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { | 
| 39   net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 39   net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 
| 40                       source.ToEventParametersCallback()); | 40                       source.ToEventParametersCallback()); | 
| 41 } | 41 } | 
| 42 | 42 | 
| 43 TCPServerSocketLibevent::~TCPServerSocketLibevent() { | 43 TCPSocketLibevent::~TCPSocketLibevent() { | 
| 44   if (socket_ != kInvalidSocket) | 44   if (socket_ != kInvalidSocket) | 
| 45     Close(); | 45     Close(); | 
| 46   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 46   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 
| 47 } | 47 } | 
| 48 | 48 | 
| 49 int TCPServerSocketLibevent::Listen(const IPEndPoint& address, int backlog) { | 49 int TCPSocketLibevent::Create(AddressFamily family) { | 
| 50   DCHECK(CalledOnValidThread()); | 50   DCHECK(CalledOnValidThread()); | 
| 51   DCHECK_GT(backlog, 0); |  | 
| 52   DCHECK_EQ(socket_, kInvalidSocket); | 51   DCHECK_EQ(socket_, kInvalidSocket); | 
| 53 | 52 | 
| 54   socket_ = socket(address.GetSockAddrFamily(), SOCK_STREAM, IPPROTO_TCP); | 53   socket_ = socket(ConvertAddressFamily(family), SOCK_STREAM, IPPROTO_TCP); | 
| 55   if (socket_ < 0) { | 54   if (socket_ < 0) { | 
| 56     PLOG(ERROR) << "socket() returned an error"; | 55     PLOG(ERROR) << "socket() returned an error"; | 
| 57     return MapSystemError(errno); | 56     return MapSystemError(errno); | 
| 58   } | 57   } | 
| 59 | 58 | 
| 60   if (SetNonBlocking(socket_)) { | 59   if (SetNonBlocking(socket_)) { | 
| 61     int result = MapSystemError(errno); | 60     int result = MapSystemError(errno); | 
| 62     Close(); | 61     Close(); | 
| 63     return result; | 62     return result; | 
| 64   } | 63   } | 
| 65 | 64 | 
| 66   int result = SetSocketOptions(); | 65   return OK; | 
| 67   if (result != OK) { | 66 } | 
| 68     Close(); |  | 
| 69     return result; |  | 
| 70   } |  | 
| 71 | 67 | 
| 72   SockaddrStorage storage; | 68 int TCPSocketLibevent::Adopt(int socket) { | 
| 73   if (!address.ToSockAddr(storage.addr, &storage.addr_len)) { | 69   DCHECK(CalledOnValidThread()); | 
| 74     Close(); | 70   DCHECK_EQ(socket_, kInvalidSocket); | 
| 75     return ERR_ADDRESS_INVALID; |  | 
| 76   } |  | 
| 77 | 71 | 
| 78   result = bind(socket_, storage.addr, storage.addr_len); | 72   socket_ = socket; | 
| 79   if (result < 0) { |  | 
| 80     PLOG(ERROR) << "bind() returned an error"; |  | 
| 81     result = MapSystemError(errno); |  | 
| 82     Close(); |  | 
| 83     return result; |  | 
| 84   } |  | 
| 85 | 73 | 
| 86   result = listen(socket_, backlog); | 74   if (SetNonBlocking(socket_)) { | 
| 87   if (result < 0) { | 75     int result = MapSystemError(errno); | 
| 88     PLOG(ERROR) << "listen() returned an error"; |  | 
| 89     result = MapSystemError(errno); |  | 
| 90     Close(); | 76     Close(); | 
| 91     return result; | 77     return result; | 
| 92   } | 78   } | 
| 93 | 79 | 
| 94   return OK; | 80   return OK; | 
| 95 } | 81 } | 
| 96 | 82 | 
| 97 int TCPServerSocketLibevent::GetLocalAddress(IPEndPoint* address) const { | 83 int TCPSocketLibevent::Release() { | 
|  | 84   DCHECK(CalledOnValidThread()); | 
|  | 85   DCHECK(accept_callback_.is_null()); | 
|  | 86 | 
|  | 87   int result = socket_; | 
|  | 88   socket_ = kInvalidSocket; | 
|  | 89   return result; | 
|  | 90 } | 
|  | 91 | 
|  | 92 int TCPSocketLibevent::Bind(const IPEndPoint& address) { | 
|  | 93   DCHECK(CalledOnValidThread()); | 
|  | 94   DCHECK_NE(socket_, kInvalidSocket); | 
|  | 95 | 
|  | 96   SockaddrStorage storage; | 
|  | 97   if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 
|  | 98     return ERR_ADDRESS_INVALID; | 
|  | 99 | 
|  | 100   int result = bind(socket_, storage.addr, storage.addr_len); | 
|  | 101   if (result < 0) { | 
|  | 102     PLOG(ERROR) << "bind() returned an error"; | 
|  | 103     return MapSystemError(errno); | 
|  | 104   } | 
|  | 105 | 
|  | 106   return OK; | 
|  | 107 } | 
|  | 108 | 
|  | 109 int TCPSocketLibevent::GetLocalAddress(IPEndPoint* address) const { | 
| 98   DCHECK(CalledOnValidThread()); | 110   DCHECK(CalledOnValidThread()); | 
| 99   DCHECK(address); | 111   DCHECK(address); | 
| 100 | 112 | 
| 101   SockaddrStorage storage; | 113   SockaddrStorage storage; | 
| 102   if (getsockname(socket_, storage.addr, &storage.addr_len) < 0) | 114   if (getsockname(socket_, storage.addr, &storage.addr_len) < 0) | 
| 103     return MapSystemError(errno); | 115     return MapSystemError(errno); | 
| 104   if (!address->FromSockAddr(storage.addr, storage.addr_len)) | 116   if (!address->FromSockAddr(storage.addr, storage.addr_len)) | 
| 105     return ERR_FAILED; | 117     return ERR_FAILED; | 
| 106 | 118 | 
| 107   return OK; | 119   return OK; | 
| 108 } | 120 } | 
| 109 | 121 | 
| 110 int TCPServerSocketLibevent::Accept( | 122 int TCPSocketLibevent::Listen(int backlog) { | 
| 111     scoped_ptr<StreamSocket>* socket, const CompletionCallback& callback) { | 123   DCHECK(CalledOnValidThread()); | 
|  | 124   DCHECK_GT(backlog, 0); | 
|  | 125   DCHECK_NE(socket_, kInvalidSocket); | 
|  | 126 | 
|  | 127   int result = listen(socket_, backlog); | 
|  | 128   if (result < 0) { | 
|  | 129     PLOG(ERROR) << "listen() returned an error"; | 
|  | 130     return MapSystemError(errno); | 
|  | 131   } | 
|  | 132 | 
|  | 133   return OK; | 
|  | 134 } | 
|  | 135 | 
|  | 136 int TCPSocketLibevent::Accept(scoped_ptr<TCPSocketLibevent>* socket, | 
|  | 137                               IPEndPoint* address, | 
|  | 138                               const CompletionCallback& callback) { | 
| 112   DCHECK(CalledOnValidThread()); | 139   DCHECK(CalledOnValidThread()); | 
| 113   DCHECK(socket); | 140   DCHECK(socket); | 
|  | 141   DCHECK(address); | 
| 114   DCHECK(!callback.is_null()); | 142   DCHECK(!callback.is_null()); | 
| 115   DCHECK(accept_callback_.is_null()); | 143   DCHECK(accept_callback_.is_null()); | 
| 116 | 144 | 
| 117   net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); | 145   net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); | 
| 118 | 146 | 
| 119   int result = AcceptInternal(socket); | 147   int result = AcceptInternal(socket, address); | 
| 120 | 148 | 
| 121   if (result == ERR_IO_PENDING) { | 149   if (result == ERR_IO_PENDING) { | 
| 122     if (!base::MessageLoopForIO::current()->WatchFileDescriptor( | 150     if (!base::MessageLoopForIO::current()->WatchFileDescriptor( | 
| 123             socket_, true, base::MessageLoopForIO::WATCH_READ, | 151             socket_, true, base::MessageLoopForIO::WATCH_READ, | 
| 124             &accept_socket_watcher_, this)) { | 152             &accept_socket_watcher_, this)) { | 
| 125       PLOG(ERROR) << "WatchFileDescriptor failed on read"; | 153       PLOG(ERROR) << "WatchFileDescriptor failed on read"; | 
| 126       return MapSystemError(errno); | 154       return MapSystemError(errno); | 
| 127     } | 155     } | 
| 128 | 156 | 
| 129     accept_socket_ = socket; | 157     accept_socket_ = socket; | 
|  | 158     accept_address_ = address; | 
| 130     accept_callback_ = callback; | 159     accept_callback_ = callback; | 
| 131   } | 160   } | 
| 132 | 161 | 
| 133   return result; | 162   return result; | 
| 134 } | 163 } | 
| 135 | 164 | 
| 136 int TCPServerSocketLibevent::SetSocketOptions() { | 165 int TCPSocketLibevent::SetDefaultOptionsForServer() { | 
|  | 166   return SetAddressReuse(true); | 
|  | 167 } | 
|  | 168 | 
|  | 169 int TCPSocketLibevent::SetAddressReuse(bool allow) { | 
| 137   // SO_REUSEADDR is useful for server sockets to bind to a recently unbound | 170   // SO_REUSEADDR is useful for server sockets to bind to a recently unbound | 
| 138   // port. When a socket is closed, the end point changes its state to TIME_WAIT | 171   // port. When a socket is closed, the end point changes its state to TIME_WAIT | 
| 139   // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer | 172   // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer | 
| 140   // acknowledges its closure. For server sockets, it is usually safe to | 173   // acknowledges its closure. For server sockets, it is usually safe to | 
| 141   // bind to a TIME_WAIT end point immediately, which is a widely adopted | 174   // bind to a TIME_WAIT end point immediately, which is a widely adopted | 
| 142   // behavior. | 175   // behavior. | 
| 143   // | 176   // | 
| 144   // Note that on *nix, SO_REUSEADDR does not enable the TCP socket to bind to | 177   // Note that on *nix, SO_REUSEADDR does not enable the TCP socket to bind to | 
| 145   // an end point that is already bound by another socket. To do that one must | 178   // an end point that is already bound by another socket. To do that one must | 
| 146   // set SO_REUSEPORT instead. This option is not provided on Linux prior | 179   // set SO_REUSEPORT instead. This option is not provided on Linux prior | 
| 147   // to 3.9. | 180   // to 3.9. | 
| 148   // | 181   // | 
| 149   // SO_REUSEPORT is provided in MacOS X and iOS. | 182   // SO_REUSEPORT is provided in MacOS X and iOS. | 
| 150   int true_value = 1; | 183   int boolean_value = allow ? 1 : 0; | 
| 151   int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, | 184   int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &boolean_value, | 
| 152                       sizeof(true_value)); | 185                       sizeof(boolean_value)); | 
| 153   if (rv < 0) | 186   if (rv < 0) | 
| 154     return MapSystemError(errno); | 187     return MapSystemError(errno); | 
| 155   return OK; | 188   return OK; | 
| 156 } | 189 } | 
| 157 | 190 | 
| 158 int TCPServerSocketLibevent::AcceptInternal( | 191 void TCPSocketLibevent::Close() { | 
| 159     scoped_ptr<StreamSocket>* socket) { | 192   if (socket_ != kInvalidSocket) { | 
|  | 193     bool ok = accept_socket_watcher_.StopWatchingFileDescriptor(); | 
|  | 194     DCHECK(ok); | 
|  | 195     if (HANDLE_EINTR(close(socket_)) < 0) | 
|  | 196       PLOG(ERROR) << "close"; | 
|  | 197     socket_ = kInvalidSocket; | 
|  | 198   } | 
|  | 199 } | 
|  | 200 | 
|  | 201 int TCPSocketLibevent::AcceptInternal(scoped_ptr<TCPSocketLibevent>* socket, | 
|  | 202                                       IPEndPoint* address) { | 
| 160   SockaddrStorage storage; | 203   SockaddrStorage storage; | 
| 161   int new_socket = HANDLE_EINTR(accept(socket_, | 204   int new_socket = HANDLE_EINTR(accept(socket_, | 
| 162                                        storage.addr, | 205                                        storage.addr, | 
| 163                                        &storage.addr_len)); | 206                                        &storage.addr_len)); | 
| 164   if (new_socket < 0) { | 207   if (new_socket < 0) { | 
| 165     int net_error = MapSystemError(errno); | 208     int net_error = MapSystemError(errno); | 
| 166     if (net_error != ERR_IO_PENDING) | 209     if (net_error != ERR_IO_PENDING) | 
| 167       net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); | 210       net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); | 
| 168     return net_error; | 211     return net_error; | 
| 169   } | 212   } | 
| 170 | 213 | 
| 171   IPEndPoint address; | 214   IPEndPoint ip_end_point; | 
| 172   if (!address.FromSockAddr(storage.addr, storage.addr_len)) { | 215   if (!ip_end_point.FromSockAddr(storage.addr, storage.addr_len)) { | 
| 173     NOTREACHED(); | 216     NOTREACHED(); | 
| 174     if (HANDLE_EINTR(close(new_socket)) < 0) | 217     if (HANDLE_EINTR(close(new_socket)) < 0) | 
| 175       PLOG(ERROR) << "close"; | 218       PLOG(ERROR) << "close"; | 
| 176     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED); | 219     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED); | 
| 177     return ERR_FAILED; | 220     return ERR_FAILED; | 
| 178   } | 221   } | 
| 179   scoped_ptr<TCPClientSocket> tcp_socket(new TCPClientSocket( | 222   scoped_ptr<TCPSocketLibevent> tcp_socket(new TCPSocketLibevent( | 
| 180       AddressList(address), |  | 
| 181       net_log_.net_log(), net_log_.source())); | 223       net_log_.net_log(), net_log_.source())); | 
| 182   int adopt_result = tcp_socket->AdoptSocket(new_socket); | 224   int adopt_result = tcp_socket->Adopt(new_socket); | 
| 183   if (adopt_result != OK) { | 225   if (adopt_result != OK) { | 
| 184     if (HANDLE_EINTR(close(new_socket)) < 0) |  | 
| 185       PLOG(ERROR) << "close"; |  | 
| 186     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result); | 226     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result); | 
| 187     return adopt_result; | 227     return adopt_result; | 
| 188   } | 228   } | 
| 189   socket->reset(tcp_socket.release()); | 229   *socket = tcp_socket.Pass(); | 
|  | 230   *address = ip_end_point; | 
| 190   net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, | 231   net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, | 
| 191                     CreateNetLogIPEndPointCallback(&address)); | 232                     CreateNetLogIPEndPointCallback(&ip_end_point)); | 
| 192   return OK; | 233   return OK; | 
| 193 } | 234 } | 
| 194 | 235 | 
| 195 void TCPServerSocketLibevent::Close() { | 236 void TCPSocketLibevent::OnFileCanReadWithoutBlocking(int fd) { | 
| 196   if (socket_ != kInvalidSocket) { |  | 
| 197     bool ok = accept_socket_watcher_.StopWatchingFileDescriptor(); |  | 
| 198     DCHECK(ok); |  | 
| 199     if (HANDLE_EINTR(close(socket_)) < 0) |  | 
| 200       PLOG(ERROR) << "close"; |  | 
| 201     socket_ = kInvalidSocket; |  | 
| 202   } |  | 
| 203 } |  | 
| 204 |  | 
| 205 void TCPServerSocketLibevent::OnFileCanReadWithoutBlocking(int fd) { |  | 
| 206   DCHECK(CalledOnValidThread()); | 237   DCHECK(CalledOnValidThread()); | 
| 207 | 238 | 
| 208   int result = AcceptInternal(accept_socket_); | 239   int result = AcceptInternal(accept_socket_, accept_address_); | 
| 209   if (result != ERR_IO_PENDING) { | 240   if (result != ERR_IO_PENDING) { | 
| 210     accept_socket_ = NULL; | 241     accept_socket_ = NULL; | 
|  | 242     accept_address_ = NULL; | 
| 211     bool ok = accept_socket_watcher_.StopWatchingFileDescriptor(); | 243     bool ok = accept_socket_watcher_.StopWatchingFileDescriptor(); | 
| 212     DCHECK(ok); | 244     DCHECK(ok); | 
| 213     CompletionCallback callback = accept_callback_; | 245     CompletionCallback callback = accept_callback_; | 
| 214     accept_callback_.Reset(); | 246     accept_callback_.Reset(); | 
| 215     callback.Run(result); | 247     callback.Run(result); | 
| 216   } | 248   } | 
| 217 } | 249 } | 
| 218 | 250 | 
| 219 void TCPServerSocketLibevent::OnFileCanWriteWithoutBlocking(int fd) { | 251 void TCPSocketLibevent::OnFileCanWriteWithoutBlocking(int fd) { | 
| 220   NOTREACHED(); | 252   NOTREACHED(); | 
| 221 } | 253 } | 
| 222 | 254 | 
| 223 }  // namespace net | 255 }  // namespace net | 
| OLD | NEW | 
|---|