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/udp/udp_socket_win.h"
6
7 #include <mstcpip.h>
8
9 #include "base/eintr_wrapper.h"
10 #include "base/logging.h"
11 #include "base/memory/memory_debug.h"
12 #include "base/message_loop.h"
13 #include "base/metrics/stats_counters.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/ip_endpoint.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/net_log.h"
18 #include "net/base/net_util.h"
19 #include "net/base/winsock_init.h"
20 #include "net/base/winsock_util.h"
21
22 namespace net {
23
OnObjectSignaled(HANDLE object)24 void UDPSocketWin::ReadDelegate::OnObjectSignaled(HANDLE object) {
25 DCHECK_EQ(object, socket_->read_overlapped_.hEvent);
26 socket_->DidCompleteRead();
27 }
28
OnObjectSignaled(HANDLE object)29 void UDPSocketWin::WriteDelegate::OnObjectSignaled(HANDLE object) {
30 DCHECK_EQ(object, socket_->write_overlapped_.hEvent);
31 socket_->DidCompleteWrite();
32 }
33
UDPSocketWin(net::NetLog * net_log,const net::NetLog::Source & source)34 UDPSocketWin::UDPSocketWin(net::NetLog* net_log,
35 const net::NetLog::Source& source)
36 : socket_(INVALID_SOCKET),
37 ALLOW_THIS_IN_INITIALIZER_LIST(read_delegate_(this)),
38 ALLOW_THIS_IN_INITIALIZER_LIST(write_delegate_(this)),
39 recv_from_address_(NULL),
40 read_callback_(NULL),
41 write_callback_(NULL),
42 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
43 EnsureWinsockInit();
44 scoped_refptr<NetLog::EventParameters> params;
45 if (source.is_valid())
46 params = new NetLogSourceParameter("source_dependency", source);
47 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
48 memset(&read_overlapped_, 0, sizeof(read_overlapped_));
49 read_overlapped_.hEvent = WSACreateEvent();
50 memset(&write_overlapped_, 0, sizeof(write_overlapped_));
51 write_overlapped_.hEvent = WSACreateEvent();
52 }
53
~UDPSocketWin()54 UDPSocketWin::~UDPSocketWin() {
55 Close();
56 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL);
57 }
58
Close()59 void UDPSocketWin::Close() {
60 DCHECK(CalledOnValidThread());
61
62 if (!is_connected())
63 return;
64
65 // Zero out any pending read/write callback state.
66 read_callback_ = NULL;
67 recv_from_address_ = NULL;
68 write_callback_ = NULL;
69
70 read_watcher_.StopWatching();
71 write_watcher_.StopWatching();
72
73 closesocket(socket_);
74 socket_ = INVALID_SOCKET;
75 }
76
GetPeerAddress(IPEndPoint * address) const77 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
78 DCHECK(CalledOnValidThread());
79 DCHECK(address);
80 if (!is_connected())
81 return ERR_SOCKET_NOT_CONNECTED;
82
83 if (!remote_address_.get()) {
84 struct sockaddr_storage addr_storage;
85 int addr_len = sizeof(addr_storage);
86 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
87 if (getpeername(socket_, addr, &addr_len))
88 return MapSystemError(WSAGetLastError());
89 scoped_ptr<IPEndPoint> address(new IPEndPoint());
90 if (!address->FromSockAddr(addr, addr_len))
91 return ERR_FAILED;
92 remote_address_.reset(address.release());
93 }
94
95 *address = *remote_address_;
96 return OK;
97 }
98
GetLocalAddress(IPEndPoint * address) const99 int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const {
100 DCHECK(CalledOnValidThread());
101 DCHECK(address);
102 if (!is_connected())
103 return ERR_SOCKET_NOT_CONNECTED;
104
105 if (!local_address_.get()) {
106 struct sockaddr_storage addr_storage;
107 socklen_t addr_len = sizeof(addr_storage);
108 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
109 if (getsockname(socket_, addr, &addr_len))
110 return MapSystemError(WSAGetLastError());
111 scoped_ptr<IPEndPoint> address(new IPEndPoint());
112 if (!address->FromSockAddr(addr, addr_len))
113 return ERR_FAILED;
114 local_address_.reset(address.release());
115 }
116
117 *address = *local_address_;
118 return OK;
119 }
120
Read(IOBuffer * buf,int buf_len,CompletionCallback * callback)121 int UDPSocketWin::Read(IOBuffer* buf,
122 int buf_len,
123 CompletionCallback* callback) {
124 return RecvFrom(buf, buf_len, NULL, callback);
125 }
126
RecvFrom(IOBuffer * buf,int buf_len,IPEndPoint * address,CompletionCallback * callback)127 int UDPSocketWin::RecvFrom(IOBuffer* buf,
128 int buf_len,
129 IPEndPoint* address,
130 CompletionCallback* callback) {
131 DCHECK(CalledOnValidThread());
132 DCHECK_NE(INVALID_SOCKET, socket_);
133 DCHECK(!read_callback_);
134 DCHECK(!recv_from_address_);
135 DCHECK(callback); // Synchronous operation not supported.
136 DCHECK_GT(buf_len, 0);
137
138 int nread = InternalRecvFrom(buf, buf_len, address);
139 if (nread != ERR_IO_PENDING)
140 return nread;
141
142 read_iobuffer_ = buf;
143 read_callback_ = callback;
144 recv_from_address_ = address;
145 return ERR_IO_PENDING;
146 }
147
Write(IOBuffer * buf,int buf_len,CompletionCallback * callback)148 int UDPSocketWin::Write(IOBuffer* buf,
149 int buf_len,
150 CompletionCallback* callback) {
151 return SendToOrWrite(buf, buf_len, NULL, callback);
152 }
153
SendTo(IOBuffer * buf,int buf_len,const IPEndPoint & address,CompletionCallback * callback)154 int UDPSocketWin::SendTo(IOBuffer* buf,
155 int buf_len,
156 const IPEndPoint& address,
157 CompletionCallback* callback) {
158 return SendToOrWrite(buf, buf_len, &address, callback);
159 }
160
SendToOrWrite(IOBuffer * buf,int buf_len,const IPEndPoint * address,CompletionCallback * callback)161 int UDPSocketWin::SendToOrWrite(IOBuffer* buf,
162 int buf_len,
163 const IPEndPoint* address,
164 CompletionCallback* callback) {
165 DCHECK(CalledOnValidThread());
166 DCHECK_NE(INVALID_SOCKET, socket_);
167 DCHECK(!write_callback_);
168 DCHECK(callback); // Synchronous operation not supported.
169 DCHECK_GT(buf_len, 0);
170
171 int nwrite = InternalSendTo(buf, buf_len, address);
172 if (nwrite != ERR_IO_PENDING)
173 return nwrite;
174
175 write_iobuffer_ = buf;
176 write_callback_ = callback;
177 return ERR_IO_PENDING;
178 }
179
Connect(const IPEndPoint & address)180 int UDPSocketWin::Connect(const IPEndPoint& address) {
181 DCHECK(!is_connected());
182 DCHECK(!remote_address_.get());
183 int rv = CreateSocket(address);
184 if (rv < 0)
185 return rv;
186
187 struct sockaddr_storage addr_storage;
188 size_t addr_len = sizeof(addr_storage);
189 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
190 if (!address.ToSockAddr(addr, &addr_len))
191 return ERR_FAILED;
192
193 rv = connect(socket_, addr, addr_len);
194 if (rv < 0)
195 return MapSystemError(WSAGetLastError());
196
197 remote_address_.reset(new IPEndPoint(address));
198 return rv;
199 }
200
Bind(const IPEndPoint & address)201 int UDPSocketWin::Bind(const IPEndPoint& address) {
202 DCHECK(!is_connected());
203 DCHECK(!local_address_.get());
204 int rv = CreateSocket(address);
205 if (rv < 0)
206 return rv;
207
208 struct sockaddr_storage addr_storage;
209 size_t addr_len = sizeof(addr_storage);
210 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
211 if (!address.ToSockAddr(addr, &addr_len))
212 return ERR_FAILED;
213
214 rv = bind(socket_, addr, addr_len);
215 if (rv < 0)
216 return MapSystemError(WSAGetLastError());
217
218 local_address_.reset();
219 return rv;
220 }
221
CreateSocket(const IPEndPoint & address)222 int UDPSocketWin::CreateSocket(const IPEndPoint& address) {
223 socket_ = WSASocket(address.GetFamily(), SOCK_DGRAM, IPPROTO_UDP, NULL, 0,
224 WSA_FLAG_OVERLAPPED);
225 if (socket_ == INVALID_SOCKET)
226 return MapSystemError(WSAGetLastError());
227 return OK;
228 }
229
DoReadCallback(int rv)230 void UDPSocketWin::DoReadCallback(int rv) {
231 DCHECK_NE(rv, ERR_IO_PENDING);
232 DCHECK(read_callback_);
233
234 // since Run may result in Read being called, clear read_callback_ up front.
235 CompletionCallback* c = read_callback_;
236 read_callback_ = NULL;
237 c->Run(rv);
238 }
239
DoWriteCallback(int rv)240 void UDPSocketWin::DoWriteCallback(int rv) {
241 DCHECK_NE(rv, ERR_IO_PENDING);
242 DCHECK(write_callback_);
243
244 // since Run may result in Write being called, clear write_callback_ up front.
245 CompletionCallback* c = write_callback_;
246 write_callback_ = NULL;
247 c->Run(rv);
248 }
249
DidCompleteRead()250 void UDPSocketWin::DidCompleteRead() {
251 DWORD num_bytes, flags;
252 BOOL ok = WSAGetOverlappedResult(socket_, &read_overlapped_,
253 &num_bytes, FALSE, &flags);
254 WSAResetEvent(read_overlapped_.hEvent);
255 int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
256 if (ok) {
257 if (!ProcessSuccessfulRead(num_bytes, recv_from_address_))
258 result = ERR_FAILED;
259 }
260 read_iobuffer_ = NULL;
261 recv_from_address_ = NULL;
262 DoReadCallback(result);
263 }
264
ProcessSuccessfulRead(int num_bytes,IPEndPoint * address)265 bool UDPSocketWin::ProcessSuccessfulRead(int num_bytes, IPEndPoint* address) {
266 base::StatsCounter read_bytes("udp.read_bytes");
267 read_bytes.Add(num_bytes);
268
269 // Convert address.
270 if (address) {
271 struct sockaddr* addr =
272 reinterpret_cast<struct sockaddr*>(&recv_addr_storage_);
273 if (!address->FromSockAddr(addr, recv_addr_len_))
274 return false;
275 }
276
277 return true;
278 }
279
DidCompleteWrite()280 void UDPSocketWin::DidCompleteWrite() {
281 DWORD num_bytes, flags;
282 BOOL ok = WSAGetOverlappedResult(socket_, &write_overlapped_,
283 &num_bytes, FALSE, &flags);
284 WSAResetEvent(write_overlapped_.hEvent);
285 int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
286 if (ok)
287 ProcessSuccessfulWrite(num_bytes);
288 write_iobuffer_ = NULL;
289 DoWriteCallback(result);
290 }
291
ProcessSuccessfulWrite(int num_bytes)292 void UDPSocketWin::ProcessSuccessfulWrite(int num_bytes) {
293 base::StatsCounter write_bytes("udp.write_bytes");
294 write_bytes.Add(num_bytes);
295 }
296
InternalRecvFrom(IOBuffer * buf,int buf_len,IPEndPoint * address)297 int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len,
298 IPEndPoint* address) {
299 recv_addr_len_ = sizeof(recv_addr_storage_);
300 struct sockaddr* addr =
301 reinterpret_cast<struct sockaddr*>(&recv_addr_storage_);
302
303 WSABUF read_buffer;
304 read_buffer.buf = buf->data();
305 read_buffer.len = buf_len;
306
307 DWORD flags = 0;
308 DWORD num;
309 AssertEventNotSignaled(read_overlapped_.hEvent);
310 int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, addr,
311 &recv_addr_len_, &read_overlapped_, NULL);
312 if (rv == 0) {
313 if (ResetEventIfSignaled(read_overlapped_.hEvent)) {
314 // Because of how WSARecv fills memory when used asynchronously, Purify
315 // isn't able to detect that it's been initialized, so it scans for 0xcd
316 // in the buffer and reports UMRs (uninitialized memory reads) for those
317 // individual bytes. We override that in PURIFY builds to avoid the
318 // false error reports.
319 // See bug 5297.
320 base::MemoryDebug::MarkAsInitialized(read_buffer.buf, num);
321 if (!ProcessSuccessfulRead(num, address))
322 return ERR_FAILED;
323 return static_cast<int>(num);
324 }
325 } else {
326 int os_error = WSAGetLastError();
327 if (os_error != WSA_IO_PENDING)
328 return MapSystemError(os_error);
329 }
330 read_watcher_.StartWatching(read_overlapped_.hEvent, &read_delegate_);
331 return ERR_IO_PENDING;
332 }
333
InternalSendTo(IOBuffer * buf,int buf_len,const IPEndPoint * address)334 int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len,
335 const IPEndPoint* address) {
336 struct sockaddr_storage addr_storage;
337 size_t addr_len = sizeof(addr_storage);
338 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
339
340 // Convert address.
341 if (!address) {
342 addr = NULL;
343 addr_len = 0;
344 } else {
345 if (!address->ToSockAddr(addr, &addr_len))
346 return ERR_FAILED;
347 }
348
349 WSABUF write_buffer;
350 write_buffer.buf = buf->data();
351 write_buffer.len = buf_len;
352
353 DWORD flags = 0;
354 DWORD num;
355 AssertEventNotSignaled(write_overlapped_.hEvent);
356 int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags,
357 addr, addr_len, &write_overlapped_, NULL);
358 if (rv == 0) {
359 if (ResetEventIfSignaled(write_overlapped_.hEvent)) {
360 ProcessSuccessfulWrite(num);
361 return static_cast<int>(num);
362 }
363 } else {
364 int os_error = WSAGetLastError();
365 if (os_error != WSA_IO_PENDING)
366 return MapSystemError(os_error);
367 }
368
369 write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_);
370 return ERR_IO_PENDING;
371 }
372
373 } // namespace net
374