Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2011 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.
      4 
      5 #include "net/socket/tcp_server_socket_win.h"
      6 
      7 #include <mstcpip.h>
      8 
      9 #include "net/base/ip_endpoint.h"
     10 #include "net/base/net_errors.h"
     11 #include "net/base/net_util.h"
     12 #include "net/base/winsock_init.h"
     13 #include "net/base/winsock_util.h"
     14 #include "net/socket/tcp_client_socket.h"
     15 
     16 namespace net {
     17 
     18 TCPServerSocketWin::TCPServerSocketWin(net::NetLog* net_log,
     19                                        const net::NetLog::Source& source)
     20     : socket_(INVALID_SOCKET),
     21       socket_event_(WSA_INVALID_EVENT),
     22       accept_socket_(NULL),
     23       accept_callback_(NULL),
     24       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
     25   scoped_refptr<NetLog::EventParameters> params;
     26   if (source.is_valid())
     27     params = new NetLogSourceParameter("source_dependency", source);
     28   net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
     29   EnsureWinsockInit();
     30 }
     31 
     32 TCPServerSocketWin::~TCPServerSocketWin() {
     33   Close();
     34   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL);
     35 }
     36 
     37 int TCPServerSocketWin::Listen(const IPEndPoint& address, int backlog) {
     38   DCHECK(CalledOnValidThread());
     39   DCHECK_GT(backlog, 0);
     40   DCHECK_EQ(socket_, INVALID_SOCKET);
     41   DCHECK_EQ(socket_event_, WSA_INVALID_EVENT);
     42 
     43   socket_event_ = WSACreateEvent();
     44   if (socket_event_ == WSA_INVALID_EVENT) {
     45     PLOG(ERROR) << "WSACreateEvent()";
     46     return ERR_FAILED;
     47   }
     48 
     49   socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     50   if (socket_ < 0) {
     51     PLOG(ERROR) << "socket() returned an error";
     52     return MapSystemError(WSAGetLastError());
     53   }
     54 
     55   if (SetNonBlocking(socket_)) {
     56     int result = MapSystemError(WSAGetLastError());
     57     Close();
     58     return result;
     59   }
     60 
     61   struct sockaddr_storage addr_storage;
     62   size_t addr_len = sizeof(addr_storage);
     63   struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
     64   if (!address.ToSockAddr(addr, &addr_len))
     65     return ERR_INVALID_ARGUMENT;
     66 
     67   int result = bind(socket_, addr, addr_len);
     68   if (result < 0) {
     69     PLOG(ERROR) << "bind() returned an error";
     70     result = MapSystemError(WSAGetLastError());
     71     Close();
     72     return result;
     73   }
     74 
     75   result = listen(socket_, backlog);
     76   if (result < 0) {
     77     PLOG(ERROR) << "listen() returned an error";
     78     result = MapSystemError(WSAGetLastError());
     79     Close();
     80     return result;
     81   }
     82 
     83   return OK;
     84 }
     85 
     86 int TCPServerSocketWin::GetLocalAddress(IPEndPoint* address) const {
     87   DCHECK(CalledOnValidThread());
     88   DCHECK(address);
     89 
     90   struct sockaddr_storage addr_storage;
     91   socklen_t addr_len = sizeof(addr_storage);
     92   struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
     93   if (getsockname(socket_, addr, &addr_len))
     94     return MapSystemError(WSAGetLastError());
     95   if (!address->FromSockAddr(addr, addr_len))
     96     return ERR_FAILED;
     97 
     98   return OK;
     99 }
    100 
    101 int TCPServerSocketWin::Accept(
    102     scoped_ptr<ClientSocket>* socket, CompletionCallback* callback) {
    103   DCHECK(CalledOnValidThread());
    104   DCHECK(socket);
    105   DCHECK(callback);
    106   DCHECK(!accept_callback_);
    107 
    108   net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT, NULL);
    109 
    110   int result = AcceptInternal(socket);
    111 
    112   if (result == ERR_IO_PENDING) {
    113     // Start watching
    114     WSAEventSelect(socket_, socket_event_, FD_ACCEPT);
    115     accept_watcher_.StartWatching(socket_event_, this);
    116 
    117     accept_socket_ = socket;
    118     accept_callback_ = callback;
    119   }
    120 
    121   return result;
    122 }
    123 
    124 int TCPServerSocketWin::AcceptInternal(scoped_ptr<ClientSocket>* socket) {
    125   struct sockaddr_storage addr_storage;
    126   socklen_t addr_len = sizeof(addr_storage);
    127   struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
    128 
    129   int result = accept(socket_, addr, &addr_len);
    130   if (result < 0) {
    131     int net_error = MapSystemError(WSAGetLastError());
    132     if (net_error != ERR_IO_PENDING)
    133       net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error);
    134     return net_error;
    135   }
    136 
    137   IPEndPoint address;
    138   if (!address.FromSockAddr(addr, addr_len)) {
    139     NOTREACHED();
    140     if (closesocket(result) < 0)
    141       PLOG(ERROR) << "closesocket";
    142     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED);
    143     return ERR_FAILED;
    144   }
    145   TCPClientSocket* tcp_socket = new TCPClientSocket(
    146       AddressList(address.address(), address.port(), false),
    147       net_log_.net_log(), net_log_.source());
    148   tcp_socket->AdoptSocket(result);
    149   socket->reset(tcp_socket);
    150   net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT,
    151                     make_scoped_refptr(new NetLogStringParameter(
    152                         "address", address.ToString())));
    153   return OK;
    154 }
    155 
    156 void TCPServerSocketWin::Close() {
    157   if (socket_ != INVALID_SOCKET) {
    158     if (closesocket(socket_) < 0)
    159       PLOG(ERROR) << "closesocket";
    160     socket_ = INVALID_SOCKET;
    161   }
    162 
    163   if (socket_event_) {
    164     WSACloseEvent(socket_event_);
    165     socket_event_ = WSA_INVALID_EVENT;
    166   }
    167 }
    168 
    169 void TCPServerSocketWin::OnObjectSignaled(HANDLE object) {
    170   WSANETWORKEVENTS ev;
    171   if (WSAEnumNetworkEvents(socket_, socket_event_, &ev) == SOCKET_ERROR) {
    172     PLOG(ERROR) << "WSAEnumNetworkEvents()";
    173     return;
    174   }
    175 
    176   if (ev.lNetworkEvents & FD_ACCEPT) {
    177     int result = AcceptInternal(accept_socket_);
    178     if (result != ERR_IO_PENDING) {
    179       CompletionCallback* c = accept_callback_;
    180       accept_callback_ = NULL;
    181       accept_socket_ = NULL;
    182       c->Run(result);
    183     }
    184   }
    185 }
    186 
    187 }  // namespace net
    188