OLD | NEW |
---|---|
(Empty) | |
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 "base/eintr_wrapper.h" | |
willchan no longer on Chromium
2011/04/13 16:08:51
This should not be needed.
Sergey Ulanov
2011/04/13 21:20:19
Done.
| |
10 #include "net/base/ip_endpoint.h" | |
11 #include "net/base/net_errors.h" | |
12 #include "net/base/net_util.h" | |
13 #include "net/base/winsock_init.h" | |
14 #include "net/base/winsock_util.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_address_(NULL), | |
24 accept_callback_(NULL), | |
25 net_log_(net_log), | |
26 net_log_source_(source) { | |
27 EnsureWinsockInit(); | |
28 } | |
29 | |
30 TCPServerSocketWin::~TCPServerSocketWin() { | |
31 Close(); | |
32 } | |
33 | |
34 int TCPServerSocketWin::Listen(const IPEndPoint& address, int backlog) { | |
35 DCHECK(CalledOnValidThread()); | |
36 DCHECK_GT(backlog, 0); | |
37 DCHECK_EQ(socket_, INVALID_SOCKET); | |
38 DCHECK_EQ(socket_event_, WSA_INVALID_EVENT); | |
39 | |
40 socket_event_ = WSACreateEvent(); | |
41 if (socket_event_ == WSA_INVALID_EVENT) { | |
42 PLOG(ERROR) << "WSACreateEvent()"; | |
43 return ERR_FAILED; | |
44 } | |
45 | |
46 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
47 if (socket_ < 0) { | |
48 PLOG(ERROR) << "socket() returned an error"; | |
49 return MapSystemError(WSAGetLastError()); | |
50 } | |
51 | |
52 if (SetNonBlocking(socket_)) { | |
53 int result = MapSystemError(WSAGetLastError()); | |
54 Close(); | |
55 return result; | |
56 } | |
57 | |
58 struct sockaddr_storage addr_storage; | |
59 size_t addr_len = sizeof(addr_storage); | |
60 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
61 if (!address.ToSockAddr(addr, &addr_len)) | |
62 return ERR_INVALID_ARGUMENT; | |
63 | |
64 int result = bind(socket_, addr, addr_len); | |
65 if (result < 0) { | |
66 PLOG(ERROR) << "bind() returned an error"; | |
67 result = MapSystemError(WSAGetLastError()); | |
68 Close(); | |
69 return result; | |
70 } | |
71 | |
72 result = listen(socket_, backlog); | |
73 if (result < 0) { | |
74 PLOG(ERROR) << "listen() returned an error"; | |
75 result = MapSystemError(WSAGetLastError()); | |
76 Close(); | |
77 return result; | |
78 } | |
79 | |
80 return OK; | |
81 } | |
82 | |
83 int TCPServerSocketWin::GetLocalAddress(IPEndPoint* address) const { | |
84 DCHECK(CalledOnValidThread()); | |
85 DCHECK(address); | |
86 | |
87 struct sockaddr_storage addr_storage; | |
88 socklen_t addr_len = sizeof(addr_storage); | |
89 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
90 if (getsockname(socket_, addr, &addr_len)) | |
91 return MapSystemError(WSAGetLastError()); | |
92 if (!address->FromSockAddr(addr, addr_len)) | |
93 return ERR_FAILED; | |
94 | |
95 return OK; | |
96 } | |
97 | |
98 int TCPServerSocketWin::Accept( | |
99 TCPClientSocket** socket, net::IPEndPoint* address, | |
100 CompletionCallback* callback) { | |
101 DCHECK(CalledOnValidThread()); | |
102 DCHECK(socket); | |
103 DCHECK(address); | |
104 DCHECK(callback); | |
105 DCHECK(!accept_callback_); | |
106 | |
107 int result = AcceptInternal(socket, address); | |
108 | |
109 if (result == ERR_IO_PENDING) { | |
110 // Start watching | |
111 WSAEventSelect(socket_, socket_event_, FD_ACCEPT); | |
112 accept_watcher_.StartWatching(socket_event_, this); | |
113 | |
114 accept_socket_ = socket; | |
115 accept_address_ = address; | |
116 accept_callback_ = callback; | |
117 } | |
118 | |
119 return result; | |
120 } | |
121 | |
122 int TCPServerSocketWin::AcceptInternal( | |
123 TCPClientSocket** socket, net::IPEndPoint* address) { | |
124 struct sockaddr_storage addr_storage; | |
125 socklen_t addr_len = sizeof(addr_storage); | |
126 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
127 | |
128 int result = accept(socket_, addr, &addr_len); | |
129 if (result < 0) | |
130 return MapSystemError(WSAGetLastError()); | |
131 | |
132 if (!address->FromSockAddr(addr, addr_len)) { | |
133 NOTREACHED(); | |
134 HANDLE_EINTR(closesocket(result)); | |
135 return ERR_FAILED; | |
136 } | |
137 *socket = new TCPClientSocket(AddressList(), net_log_, net_log_source_); | |
willchan no longer on Chromium
2011/04/13 16:08:51
You should fix AddressList() here too.
Sergey Ulanov
2011/04/13 21:20:19
Done.
| |
138 (*socket)->AdoptSocket(result); | |
139 return OK; | |
140 } | |
141 | |
142 void TCPServerSocketWin::Close() { | |
143 if (socket_ != INVALID_SOCKET) { | |
144 HANDLE_EINTR(closesocket(socket_)); | |
willchan no longer on Chromium
2011/04/13 16:08:51
HANDLE_EINTR isn't necessary, it's just for POSIX.
Sergey Ulanov
2011/04/13 21:20:19
Done.
| |
145 socket_ = INVALID_SOCKET; | |
146 } | |
147 | |
148 if (socket_event_) { | |
149 WSACloseEvent(socket_event_); | |
150 socket_event_ = WSA_INVALID_EVENT; | |
151 } | |
152 } | |
153 | |
154 void TCPServerSocketWin::OnObjectSignaled(HANDLE object) { | |
155 WSANETWORKEVENTS ev; | |
156 if (WSAEnumNetworkEvents(socket_, socket_event_, &ev) == SOCKET_ERROR) { | |
157 PLOG(ERROR) << "WSAEnumNetworkEvents()"; | |
158 return; | |
159 } | |
160 | |
161 if (ev.lNetworkEvents & FD_ACCEPT) { | |
162 int result = AcceptInternal(accept_socket_, accept_address_); | |
163 if (result == 0) { | |
164 CompletionCallback* c = accept_callback_; | |
165 accept_callback_ = NULL; | |
166 accept_socket_ = NULL; | |
167 accept_address_ = NULL; | |
168 c->Run(0); | |
169 } else { | |
170 PLOG(ERROR) << "accept() returned error after accept event was signalled"; | |
171 } | |
172 } | |
173 } | |
174 | |
175 } // namespace net | |
OLD | NEW |