• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TCPServerSocketWin(net::NetLog * net_log,const net::NetLog::Source & source)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 
~TCPServerSocketWin()32 TCPServerSocketWin::~TCPServerSocketWin() {
33   Close();
34   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL);
35 }
36 
Listen(const IPEndPoint & address,int backlog)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 
GetLocalAddress(IPEndPoint * address) const86 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 
Accept(scoped_ptr<ClientSocket> * socket,CompletionCallback * callback)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 
AcceptInternal(scoped_ptr<ClientSocket> * socket)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 
Close()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 
OnObjectSignaled(HANDLE object)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