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_win.h" | 5 #include "net/socket/tcp_socket_win.h" |
6 | 6 |
7 #include <mstcpip.h> | 7 #include <mstcpip.h> |
8 | 8 |
| 9 #include "base/logging.h" |
9 #include "net/base/ip_endpoint.h" | 10 #include "net/base/ip_endpoint.h" |
10 #include "net/base/net_errors.h" | 11 #include "net/base/net_errors.h" |
11 #include "net/base/net_util.h" | 12 #include "net/base/net_util.h" |
12 #include "net/base/winsock_init.h" | 13 #include "net/base/winsock_init.h" |
13 #include "net/base/winsock_util.h" | 14 #include "net/base/winsock_util.h" |
14 #include "net/socket/socket_descriptor.h" | 15 #include "net/socket/socket_descriptor.h" |
15 #include "net/socket/socket_net_log_params.h" | 16 #include "net/socket/socket_net_log_params.h" |
16 #include "net/socket/tcp_client_socket.h" | |
17 | 17 |
18 namespace net { | 18 namespace net { |
19 | 19 |
20 TCPServerSocketWin::TCPServerSocketWin(net::NetLog* net_log, | 20 TCPSocketWin::TCPSocketWin(net::NetLog* net_log, |
21 const net::NetLog::Source& source) | 21 const net::NetLog::Source& source) |
22 : socket_(INVALID_SOCKET), | 22 : socket_(INVALID_SOCKET), |
23 socket_event_(WSA_INVALID_EVENT), | 23 socket_event_(WSA_INVALID_EVENT), |
24 accept_socket_(NULL), | 24 accept_socket_(NULL), |
| 25 accept_address_(NULL), |
25 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { | 26 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { |
26 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 27 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
27 source.ToEventParametersCallback()); | 28 source.ToEventParametersCallback()); |
28 EnsureWinsockInit(); | 29 EnsureWinsockInit(); |
29 } | 30 } |
30 | 31 |
31 TCPServerSocketWin::~TCPServerSocketWin() { | 32 TCPSocketWin::~TCPSocketWin() { |
32 Close(); | 33 Close(); |
33 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 34 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); |
34 } | 35 } |
35 | 36 |
36 int TCPServerSocketWin::Listen(const IPEndPoint& address, int backlog) { | 37 int TCPSocketWin::Create(AddressFamily family) { |
37 DCHECK(CalledOnValidThread()); | 38 DCHECK(CalledOnValidThread()); |
38 DCHECK_GT(backlog, 0); | |
39 DCHECK_EQ(socket_, INVALID_SOCKET); | 39 DCHECK_EQ(socket_, INVALID_SOCKET); |
40 DCHECK_EQ(socket_event_, WSA_INVALID_EVENT); | |
41 | 40 |
42 socket_event_ = WSACreateEvent(); | 41 socket_ = CreatePlatformSocket(ConvertAddressFamily(family), SOCK_STREAM, |
43 if (socket_event_ == WSA_INVALID_EVENT) { | |
44 PLOG(ERROR) << "WSACreateEvent()"; | |
45 return ERR_FAILED; | |
46 } | |
47 | |
48 socket_ = CreatePlatformSocket(address.GetSockAddrFamily(), SOCK_STREAM, | |
49 IPPROTO_TCP); | 42 IPPROTO_TCP); |
50 if (socket_ == INVALID_SOCKET) { | 43 if (socket_ == INVALID_SOCKET) { |
51 PLOG(ERROR) << "socket() returned an error"; | 44 PLOG(ERROR) << "CreatePlatformSocket() returned an error"; |
52 return MapSystemError(WSAGetLastError()); | 45 return MapSystemError(WSAGetLastError()); |
53 } | 46 } |
54 | 47 |
55 if (SetNonBlocking(socket_)) { | 48 if (SetNonBlocking(socket_)) { |
56 int result = MapSystemError(WSAGetLastError()); | 49 int result = MapSystemError(WSAGetLastError()); |
57 Close(); | 50 Close(); |
58 return result; | 51 return result; |
59 } | 52 } |
60 | 53 |
61 int result = SetSocketOptions(); | 54 return OK; |
62 if (result != OK) { | 55 } |
63 Close(); | |
64 return result; | |
65 } | |
66 | 56 |
67 SockaddrStorage storage; | 57 int TCPSocketWin::Adopt(SOCKET socket) { |
68 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) { | 58 DCHECK(CalledOnValidThread()); |
69 Close(); | 59 DCHECK_EQ(socket_, INVALID_SOCKET); |
70 return ERR_ADDRESS_INVALID; | |
71 } | |
72 | 60 |
73 result = bind(socket_, storage.addr, storage.addr_len); | 61 socket_ = socket; |
74 if (result < 0) { | |
75 PLOG(ERROR) << "bind() returned an error"; | |
76 result = MapSystemError(WSAGetLastError()); | |
77 Close(); | |
78 return result; | |
79 } | |
80 | 62 |
81 result = listen(socket_, backlog); | 63 if (SetNonBlocking(socket_)) { |
82 if (result < 0) { | 64 int result = MapSystemError(WSAGetLastError()); |
83 PLOG(ERROR) << "listen() returned an error"; | |
84 result = MapSystemError(WSAGetLastError()); | |
85 Close(); | 65 Close(); |
86 return result; | 66 return result; |
87 } | 67 } |
88 | 68 |
89 return OK; | 69 return OK; |
90 } | 70 } |
91 | 71 |
92 int TCPServerSocketWin::GetLocalAddress(IPEndPoint* address) const { | 72 SOCKET TCPSocketWin::Release() { |
| 73 DCHECK(CalledOnValidThread()); |
| 74 DCHECK_EQ(socket_event_, WSA_INVALID_EVENT); |
| 75 DCHECK(accept_callback_.is_null()); |
| 76 |
| 77 SOCKET result = socket_; |
| 78 socket_ = INVALID_SOCKET; |
| 79 return result; |
| 80 } |
| 81 |
| 82 int TCPSocketWin::Bind(const IPEndPoint& address) { |
| 83 DCHECK(CalledOnValidThread()); |
| 84 DCHECK_NE(socket_, INVALID_SOCKET); |
| 85 |
| 86 SockaddrStorage storage; |
| 87 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 88 return ERR_ADDRESS_INVALID; |
| 89 |
| 90 int result = bind(socket_, storage.addr, storage.addr_len); |
| 91 if (result < 0) { |
| 92 PLOG(ERROR) << "bind() returned an error"; |
| 93 return MapSystemError(WSAGetLastError()); |
| 94 } |
| 95 |
| 96 return OK; |
| 97 } |
| 98 |
| 99 int TCPSocketWin::GetLocalAddress(IPEndPoint* address) const { |
93 DCHECK(CalledOnValidThread()); | 100 DCHECK(CalledOnValidThread()); |
94 DCHECK(address); | 101 DCHECK(address); |
95 | 102 |
96 SockaddrStorage storage; | 103 SockaddrStorage storage; |
97 if (getsockname(socket_, storage.addr, &storage.addr_len)) | 104 if (getsockname(socket_, storage.addr, &storage.addr_len)) |
98 return MapSystemError(WSAGetLastError()); | 105 return MapSystemError(WSAGetLastError()); |
99 if (!address->FromSockAddr(storage.addr, storage.addr_len)) | 106 if (!address->FromSockAddr(storage.addr, storage.addr_len)) |
100 return ERR_FAILED; | 107 return ERR_FAILED; |
101 | 108 |
102 return OK; | 109 return OK; |
103 } | 110 } |
104 | 111 |
105 int TCPServerSocketWin::Accept( | 112 int TCPSocketWin::Listen(int backlog) { |
106 scoped_ptr<StreamSocket>* socket, const CompletionCallback& callback) { | 113 DCHECK(CalledOnValidThread()); |
| 114 DCHECK_GT(backlog, 0); |
| 115 DCHECK_NE(socket_, INVALID_SOCKET); |
| 116 DCHECK_EQ(socket_event_, WSA_INVALID_EVENT); |
| 117 |
| 118 socket_event_ = WSACreateEvent(); |
| 119 if (socket_event_ == WSA_INVALID_EVENT) { |
| 120 PLOG(ERROR) << "WSACreateEvent()"; |
| 121 return ERR_FAILED; |
| 122 } |
| 123 |
| 124 int result = listen(socket_, backlog); |
| 125 if (result < 0) { |
| 126 PLOG(ERROR) << "listen() returned an error"; |
| 127 result = MapSystemError(WSAGetLastError()); |
| 128 return result; |
| 129 } |
| 130 |
| 131 return OK; |
| 132 } |
| 133 |
| 134 int TCPSocketWin::Accept(scoped_ptr<TCPSocketWin>* socket, |
| 135 IPEndPoint* address, |
| 136 const CompletionCallback& callback) { |
107 DCHECK(CalledOnValidThread()); | 137 DCHECK(CalledOnValidThread()); |
108 DCHECK(socket); | 138 DCHECK(socket); |
| 139 DCHECK(address); |
109 DCHECK(!callback.is_null()); | 140 DCHECK(!callback.is_null()); |
110 DCHECK(accept_callback_.is_null()); | 141 DCHECK(accept_callback_.is_null()); |
111 | 142 |
112 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); | 143 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); |
113 | 144 |
114 int result = AcceptInternal(socket); | 145 int result = AcceptInternal(socket, address); |
115 | 146 |
116 if (result == ERR_IO_PENDING) { | 147 if (result == ERR_IO_PENDING) { |
117 // Start watching | 148 // Start watching. |
118 WSAEventSelect(socket_, socket_event_, FD_ACCEPT); | 149 WSAEventSelect(socket_, socket_event_, FD_ACCEPT); |
119 accept_watcher_.StartWatching(socket_event_, this); | 150 accept_watcher_.StartWatching(socket_event_, this); |
120 | 151 |
121 accept_socket_ = socket; | 152 accept_socket_ = socket; |
| 153 accept_address_ = address; |
122 accept_callback_ = callback; | 154 accept_callback_ = callback; |
123 } | 155 } |
124 | 156 |
125 return result; | 157 return result; |
126 } | 158 } |
127 | 159 |
128 int TCPServerSocketWin::SetSocketOptions() { | 160 int TCPSocketWin::SetDefaultOptionsForServer() { |
| 161 return SetExclusiveAddrUse(); |
| 162 } |
| 163 |
| 164 int TCPSocketWin::SetExclusiveAddrUse() { |
129 // On Windows, a bound end point can be hijacked by another process by | 165 // On Windows, a bound end point can be hijacked by another process by |
130 // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE | 166 // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE |
131 // was introduced in Windows NT 4.0 SP4. If the socket that is bound to the | 167 // was introduced in Windows NT 4.0 SP4. If the socket that is bound to the |
132 // end point has SO_EXCLUSIVEADDRUSE enabled, it is not possible for another | 168 // end point has SO_EXCLUSIVEADDRUSE enabled, it is not possible for another |
133 // socket to forcibly bind to the end point until the end point is unbound. | 169 // socket to forcibly bind to the end point until the end point is unbound. |
134 // It is recommend that all server applications must use SO_EXCLUSIVEADDRUSE. | 170 // It is recommend that all server applications must use SO_EXCLUSIVEADDRUSE. |
135 // MSDN: http://goo.gl/M6fjQ. | 171 // MSDN: http://goo.gl/M6fjQ. |
136 // | 172 // |
137 // Unlike on *nix, on Windows a TCP server socket can always bind to an end | 173 // Unlike on *nix, on Windows a TCP server socket can always bind to an end |
138 // point in TIME_WAIT state without setting SO_REUSEADDR, therefore it is not | 174 // point in TIME_WAIT state without setting SO_REUSEADDR, therefore it is not |
139 // needed here. | 175 // needed here. |
140 // | 176 // |
141 // SO_EXCLUSIVEADDRUSE will prevent a TCP client socket from binding to an end | 177 // SO_EXCLUSIVEADDRUSE will prevent a TCP client socket from binding to an end |
142 // point in TIME_WAIT status. It does not have this effect for a TCP server | 178 // point in TIME_WAIT status. It does not have this effect for a TCP server |
143 // socket. | 179 // socket. |
144 | 180 |
145 BOOL true_value = 1; | 181 BOOL true_value = 1; |
146 int rv = setsockopt(socket_, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, | 182 int rv = setsockopt(socket_, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, |
147 reinterpret_cast<const char*>(&true_value), | 183 reinterpret_cast<const char*>(&true_value), |
148 sizeof(true_value)); | 184 sizeof(true_value)); |
149 if (rv < 0) | 185 if (rv < 0) |
150 return MapSystemError(errno); | 186 return MapSystemError(errno); |
151 return OK; | 187 return OK; |
152 } | 188 } |
153 | 189 |
154 int TCPServerSocketWin::AcceptInternal(scoped_ptr<StreamSocket>* socket) { | 190 void TCPSocketWin::Close() { |
| 191 if (socket_ != INVALID_SOCKET) { |
| 192 if (closesocket(socket_) < 0) |
| 193 PLOG(ERROR) << "closesocket"; |
| 194 socket_ = INVALID_SOCKET; |
| 195 } |
| 196 |
| 197 if (socket_event_) { |
| 198 WSACloseEvent(socket_event_); |
| 199 socket_event_ = WSA_INVALID_EVENT; |
| 200 } |
| 201 } |
| 202 |
| 203 int TCPSocketWin::AcceptInternal(scoped_ptr<TCPSocketWin>* socket, |
| 204 IPEndPoint* address) { |
155 SockaddrStorage storage; | 205 SockaddrStorage storage; |
156 int new_socket = accept(socket_, storage.addr, &storage.addr_len); | 206 int new_socket = accept(socket_, storage.addr, &storage.addr_len); |
157 if (new_socket < 0) { | 207 if (new_socket < 0) { |
158 int net_error = MapSystemError(WSAGetLastError()); | 208 int net_error = MapSystemError(WSAGetLastError()); |
159 if (net_error != ERR_IO_PENDING) | 209 if (net_error != ERR_IO_PENDING) |
160 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); | 210 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); |
161 return net_error; | 211 return net_error; |
162 } | 212 } |
163 | 213 |
164 IPEndPoint address; | 214 IPEndPoint ip_end_point; |
165 if (!address.FromSockAddr(storage.addr, storage.addr_len)) { | 215 if (!ip_end_point.FromSockAddr(storage.addr, storage.addr_len)) { |
166 NOTREACHED(); | 216 NOTREACHED(); |
167 if (closesocket(new_socket) < 0) | 217 if (closesocket(new_socket) < 0) |
168 PLOG(ERROR) << "closesocket"; | 218 PLOG(ERROR) << "closesocket"; |
169 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED); | 219 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED); |
170 return ERR_FAILED; | 220 return ERR_FAILED; |
171 } | 221 } |
172 scoped_ptr<TCPClientSocket> tcp_socket(new TCPClientSocket( | 222 scoped_ptr<TCPSocketWin> tcp_socket(new TCPSocketWin( |
173 AddressList(address), | |
174 net_log_.net_log(), net_log_.source())); | 223 net_log_.net_log(), net_log_.source())); |
175 int adopt_result = tcp_socket->AdoptSocket(new_socket); | 224 int adopt_result = tcp_socket->Adopt(new_socket); |
176 if (adopt_result != OK) { | 225 if (adopt_result != OK) { |
177 if (closesocket(new_socket) < 0) | |
178 PLOG(ERROR) << "closesocket"; | |
179 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result); | 226 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result); |
180 return adopt_result; | 227 return adopt_result; |
181 } | 228 } |
182 socket->reset(tcp_socket.release()); | 229 *socket = tcp_socket.Pass(); |
| 230 *address = ip_end_point; |
183 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, | 231 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, |
184 CreateNetLogIPEndPointCallback(&address)); | 232 CreateNetLogIPEndPointCallback(&ip_end_point)); |
185 return OK; | 233 return OK; |
186 } | 234 } |
187 | 235 |
188 void TCPServerSocketWin::Close() { | 236 void TCPSocketWin::OnObjectSignaled(HANDLE object) { |
189 if (socket_ != INVALID_SOCKET) { | |
190 if (closesocket(socket_) < 0) | |
191 PLOG(ERROR) << "closesocket"; | |
192 socket_ = INVALID_SOCKET; | |
193 } | |
194 | |
195 if (socket_event_) { | |
196 WSACloseEvent(socket_event_); | |
197 socket_event_ = WSA_INVALID_EVENT; | |
198 } | |
199 } | |
200 | |
201 void TCPServerSocketWin::OnObjectSignaled(HANDLE object) { | |
202 WSANETWORKEVENTS ev; | 237 WSANETWORKEVENTS ev; |
203 if (WSAEnumNetworkEvents(socket_, socket_event_, &ev) == SOCKET_ERROR) { | 238 if (WSAEnumNetworkEvents(socket_, socket_event_, &ev) == SOCKET_ERROR) { |
204 PLOG(ERROR) << "WSAEnumNetworkEvents()"; | 239 PLOG(ERROR) << "WSAEnumNetworkEvents()"; |
205 return; | 240 return; |
206 } | 241 } |
207 | 242 |
208 if (ev.lNetworkEvents & FD_ACCEPT) { | 243 if (ev.lNetworkEvents & FD_ACCEPT) { |
209 int result = AcceptInternal(accept_socket_); | 244 int result = AcceptInternal(accept_socket_, accept_address_); |
210 if (result != ERR_IO_PENDING) { | 245 if (result != ERR_IO_PENDING) { |
211 accept_socket_ = NULL; | 246 accept_socket_ = NULL; |
| 247 accept_address_ = NULL; |
212 CompletionCallback callback = accept_callback_; | 248 CompletionCallback callback = accept_callback_; |
213 accept_callback_.Reset(); | 249 accept_callback_.Reset(); |
214 callback.Run(result); | 250 callback.Run(result); |
215 } | 251 } |
216 } | 252 } |
217 } | 253 } |
218 | 254 |
219 } // namespace net | 255 } // namespace net |
OLD | NEW |