Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: net/udp/udp_socket_win.cc

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/udp/udp_socket_win.h ('k') | net/url_request/data_protocol_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/basictypes.h"
10 #include "base/callback.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/metrics/histogram.h"
15 #include "base/metrics/sparse_histogram.h"
16 #include "base/profiler/scoped_tracker.h"
17 #include "base/rand_util.h"
18 #include "net/base/io_buffer.h"
19 #include "net/base/ip_endpoint.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/net_log.h"
22 #include "net/base/net_util.h"
23 #include "net/base/network_activity_monitor.h"
24 #include "net/base/winsock_init.h"
25 #include "net/base/winsock_util.h"
26 #include "net/socket/socket_descriptor.h"
27 #include "net/udp/udp_net_log_parameters.h"
28
29 namespace {
30
31 const int kBindRetries = 10;
32 const int kPortStart = 1024;
33 const int kPortEnd = 65535;
34
35 } // namespace
36
37 namespace net {
38
39 // This class encapsulates all the state that has to be preserved as long as
40 // there is a network IO operation in progress. If the owner UDPSocketWin
41 // is destroyed while an operation is in progress, the Core is detached and it
42 // lives until the operation completes and the OS doesn't reference any resource
43 // declared on this class anymore.
44 class UDPSocketWin::Core : public base::RefCounted<Core> {
45 public:
46 explicit Core(UDPSocketWin* socket);
47
48 // Start watching for the end of a read or write operation.
49 void WatchForRead();
50 void WatchForWrite();
51
52 // The UDPSocketWin is going away.
53 void Detach() { socket_ = NULL; }
54
55 // The separate OVERLAPPED variables for asynchronous operation.
56 OVERLAPPED read_overlapped_;
57 OVERLAPPED write_overlapped_;
58
59 // The buffers used in Read() and Write().
60 scoped_refptr<IOBuffer> read_iobuffer_;
61 scoped_refptr<IOBuffer> write_iobuffer_;
62
63 // The address storage passed to WSARecvFrom().
64 SockaddrStorage recv_addr_storage_;
65
66 private:
67 friend class base::RefCounted<Core>;
68
69 class ReadDelegate : public base::win::ObjectWatcher::Delegate {
70 public:
71 explicit ReadDelegate(Core* core) : core_(core) {}
72 virtual ~ReadDelegate() {}
73
74 // base::ObjectWatcher::Delegate methods:
75 virtual void OnObjectSignaled(HANDLE object);
76
77 private:
78 Core* const core_;
79 };
80
81 class WriteDelegate : public base::win::ObjectWatcher::Delegate {
82 public:
83 explicit WriteDelegate(Core* core) : core_(core) {}
84 virtual ~WriteDelegate() {}
85
86 // base::ObjectWatcher::Delegate methods:
87 virtual void OnObjectSignaled(HANDLE object);
88
89 private:
90 Core* const core_;
91 };
92
93 ~Core();
94
95 // The socket that created this object.
96 UDPSocketWin* socket_;
97
98 // |reader_| handles the signals from |read_watcher_|.
99 ReadDelegate reader_;
100 // |writer_| handles the signals from |write_watcher_|.
101 WriteDelegate writer_;
102
103 // |read_watcher_| watches for events from Read().
104 base::win::ObjectWatcher read_watcher_;
105 // |write_watcher_| watches for events from Write();
106 base::win::ObjectWatcher write_watcher_;
107
108 DISALLOW_COPY_AND_ASSIGN(Core);
109 };
110
111 UDPSocketWin::Core::Core(UDPSocketWin* socket)
112 : socket_(socket),
113 reader_(this),
114 writer_(this) {
115 memset(&read_overlapped_, 0, sizeof(read_overlapped_));
116 memset(&write_overlapped_, 0, sizeof(write_overlapped_));
117
118 read_overlapped_.hEvent = WSACreateEvent();
119 write_overlapped_.hEvent = WSACreateEvent();
120 }
121
122 UDPSocketWin::Core::~Core() {
123 // Make sure the message loop is not watching this object anymore.
124 read_watcher_.StopWatching();
125 write_watcher_.StopWatching();
126
127 WSACloseEvent(read_overlapped_.hEvent);
128 memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_));
129 WSACloseEvent(write_overlapped_.hEvent);
130 memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_));
131 }
132
133 void UDPSocketWin::Core::WatchForRead() {
134 // We grab an extra reference because there is an IO operation in progress.
135 // Balanced in ReadDelegate::OnObjectSignaled().
136 AddRef();
137 read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_);
138 }
139
140 void UDPSocketWin::Core::WatchForWrite() {
141 // We grab an extra reference because there is an IO operation in progress.
142 // Balanced in WriteDelegate::OnObjectSignaled().
143 AddRef();
144 write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);
145 }
146
147 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) {
148 // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
149 tracked_objects::ScopedTracker tracking_profile(
150 FROM_HERE_WITH_EXPLICIT_FUNCTION(
151 "418183 UDPSocketWin::Core::ReadDelegate::OnObjectSignaled"));
152
153 DCHECK_EQ(object, core_->read_overlapped_.hEvent);
154 if (core_->socket_)
155 core_->socket_->DidCompleteRead();
156
157 core_->Release();
158 }
159
160 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object) {
161 // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
162 tracked_objects::ScopedTracker tracking_profile(
163 FROM_HERE_WITH_EXPLICIT_FUNCTION(
164 "418183 UDPSocketWin::Core::WriteDelegate::OnObjectSignaled"));
165
166 DCHECK_EQ(object, core_->write_overlapped_.hEvent);
167 if (core_->socket_)
168 core_->socket_->DidCompleteWrite();
169
170 core_->Release();
171 }
172 //-----------------------------------------------------------------------------
173
174 QwaveAPI::QwaveAPI() : qwave_supported_(false) {
175 HMODULE qwave = LoadLibrary(L"qwave.dll");
176 if (!qwave)
177 return;
178 create_handle_func_ =
179 (CreateHandleFn)GetProcAddress(qwave, "QOSCreateHandle");
180 close_handle_func_ =
181 (CloseHandleFn)GetProcAddress(qwave, "QOSCloseHandle");
182 add_socket_to_flow_func_ =
183 (AddSocketToFlowFn)GetProcAddress(qwave, "QOSAddSocketToFlow");
184 remove_socket_from_flow_func_ =
185 (RemoveSocketFromFlowFn)GetProcAddress(qwave, "QOSRemoveSocketFromFlow");
186 set_flow_func_ = (SetFlowFn)GetProcAddress(qwave, "QOSSetFlow");
187
188 if (create_handle_func_ && close_handle_func_ &&
189 add_socket_to_flow_func_ && remove_socket_from_flow_func_ &&
190 set_flow_func_) {
191 qwave_supported_ = true;
192 }
193 }
194
195 QwaveAPI& QwaveAPI::Get() {
196 static base::LazyInstance<QwaveAPI>::Leaky lazy_qwave =
197 LAZY_INSTANCE_INITIALIZER;
198 return lazy_qwave.Get();
199 }
200
201 bool QwaveAPI::qwave_supported() const {
202 return qwave_supported_;
203 }
204 BOOL QwaveAPI::CreateHandle(PQOS_VERSION version, PHANDLE handle) {
205 return create_handle_func_(version, handle);
206 }
207 BOOL QwaveAPI::CloseHandle(HANDLE handle) {
208 return close_handle_func_(handle);
209 }
210
211 BOOL QwaveAPI::AddSocketToFlow(HANDLE handle,
212 SOCKET socket,
213 PSOCKADDR addr,
214 QOS_TRAFFIC_TYPE traffic_type,
215 DWORD flags,
216 PQOS_FLOWID flow_id) {
217 return add_socket_to_flow_func_(handle,
218 socket,
219 addr,
220 traffic_type,
221 flags,
222 flow_id);
223 }
224
225 BOOL QwaveAPI::RemoveSocketFromFlow(HANDLE handle,
226 SOCKET socket,
227 QOS_FLOWID flow_id,
228 DWORD reserved) {
229 return remove_socket_from_flow_func_(handle, socket, flow_id, reserved);
230 }
231
232 BOOL QwaveAPI::SetFlow(HANDLE handle,
233 QOS_FLOWID flow_id,
234 QOS_SET_FLOW op,
235 ULONG size,
236 PVOID data,
237 DWORD reserved,
238 LPOVERLAPPED overlapped) {
239 return set_flow_func_(handle,
240 flow_id,
241 op,
242 size,
243 data,
244 reserved,
245 overlapped);
246 }
247
248
249 //-----------------------------------------------------------------------------
250
251 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type,
252 const RandIntCallback& rand_int_cb,
253 net::NetLog* net_log,
254 const net::NetLog::Source& source)
255 : socket_(INVALID_SOCKET),
256 addr_family_(0),
257 is_connected_(false),
258 socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
259 multicast_interface_(0),
260 multicast_time_to_live_(1),
261 bind_type_(bind_type),
262 rand_int_cb_(rand_int_cb),
263 use_non_blocking_io_(false),
264 read_iobuffer_len_(0),
265 write_iobuffer_len_(0),
266 recv_from_address_(NULL),
267 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)),
268 qos_handle_(NULL),
269 qos_flow_id_(0) {
270 EnsureWinsockInit();
271 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
272 source.ToEventParametersCallback());
273 if (bind_type == DatagramSocket::RANDOM_BIND)
274 DCHECK(!rand_int_cb.is_null());
275 }
276
277 UDPSocketWin::~UDPSocketWin() {
278 Close();
279 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
280 }
281
282 int UDPSocketWin::Open(AddressFamily address_family) {
283 DCHECK(CalledOnValidThread());
284 DCHECK_EQ(socket_, INVALID_SOCKET);
285
286 addr_family_ = ConvertAddressFamily(address_family);
287 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP);
288 if (socket_ == INVALID_SOCKET)
289 return MapSystemError(WSAGetLastError());
290 if (!use_non_blocking_io_) {
291 core_ = new Core(this);
292 } else {
293 read_write_event_.Set(WSACreateEvent());
294 WSAEventSelect(socket_, read_write_event_.Get(), FD_READ | FD_WRITE);
295 }
296 return OK;
297 }
298
299 void UDPSocketWin::Close() {
300 DCHECK(CalledOnValidThread());
301
302 if (socket_ == INVALID_SOCKET)
303 return;
304
305 if (qos_handle_) {
306 QwaveAPI::Get().CloseHandle(qos_handle_);
307 }
308
309 // Zero out any pending read/write callback state.
310 read_callback_.Reset();
311 recv_from_address_ = NULL;
312 write_callback_.Reset();
313
314 base::TimeTicks start_time = base::TimeTicks::Now();
315 closesocket(socket_);
316 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
317 base::TimeTicks::Now() - start_time);
318 socket_ = INVALID_SOCKET;
319 addr_family_ = 0;
320 is_connected_ = false;
321
322 read_write_watcher_.StopWatching();
323 read_write_event_.Close();
324
325 if (core_) {
326 core_->Detach();
327 core_ = NULL;
328 }
329 }
330
331 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
332 DCHECK(CalledOnValidThread());
333 DCHECK(address);
334 if (!is_connected())
335 return ERR_SOCKET_NOT_CONNECTED;
336
337 // TODO(szym): Simplify. http://crbug.com/126152
338 if (!remote_address_.get()) {
339 SockaddrStorage storage;
340 if (getpeername(socket_, storage.addr, &storage.addr_len))
341 return MapSystemError(WSAGetLastError());
342 scoped_ptr<IPEndPoint> remote_address(new IPEndPoint());
343 if (!remote_address->FromSockAddr(storage.addr, storage.addr_len))
344 return ERR_ADDRESS_INVALID;
345 remote_address_.reset(remote_address.release());
346 }
347
348 *address = *remote_address_;
349 return OK;
350 }
351
352 int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const {
353 DCHECK(CalledOnValidThread());
354 DCHECK(address);
355 if (!is_connected())
356 return ERR_SOCKET_NOT_CONNECTED;
357
358 // TODO(szym): Simplify. http://crbug.com/126152
359 if (!local_address_.get()) {
360 SockaddrStorage storage;
361 if (getsockname(socket_, storage.addr, &storage.addr_len))
362 return MapSystemError(WSAGetLastError());
363 scoped_ptr<IPEndPoint> local_address(new IPEndPoint());
364 if (!local_address->FromSockAddr(storage.addr, storage.addr_len))
365 return ERR_ADDRESS_INVALID;
366 local_address_.reset(local_address.release());
367 net_log_.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS,
368 CreateNetLogUDPConnectCallback(local_address_.get()));
369 }
370
371 *address = *local_address_;
372 return OK;
373 }
374
375 int UDPSocketWin::Read(IOBuffer* buf,
376 int buf_len,
377 const CompletionCallback& callback) {
378 return RecvFrom(buf, buf_len, NULL, callback);
379 }
380
381 int UDPSocketWin::RecvFrom(IOBuffer* buf,
382 int buf_len,
383 IPEndPoint* address,
384 const CompletionCallback& callback) {
385 DCHECK(CalledOnValidThread());
386 DCHECK_NE(INVALID_SOCKET, socket_);
387 CHECK(read_callback_.is_null());
388 DCHECK(!recv_from_address_);
389 DCHECK(!callback.is_null()); // Synchronous operation not supported.
390 DCHECK_GT(buf_len, 0);
391
392 int nread = core_ ? InternalRecvFromOverlapped(buf, buf_len, address)
393 : InternalRecvFromNonBlocking(buf, buf_len, address);
394 if (nread != ERR_IO_PENDING)
395 return nread;
396
397 read_callback_ = callback;
398 recv_from_address_ = address;
399 return ERR_IO_PENDING;
400 }
401
402 int UDPSocketWin::Write(IOBuffer* buf,
403 int buf_len,
404 const CompletionCallback& callback) {
405 return SendToOrWrite(buf, buf_len, NULL, callback);
406 }
407
408 int UDPSocketWin::SendTo(IOBuffer* buf,
409 int buf_len,
410 const IPEndPoint& address,
411 const CompletionCallback& callback) {
412 return SendToOrWrite(buf, buf_len, &address, callback);
413 }
414
415 int UDPSocketWin::SendToOrWrite(IOBuffer* buf,
416 int buf_len,
417 const IPEndPoint* address,
418 const CompletionCallback& callback) {
419 DCHECK(CalledOnValidThread());
420 DCHECK_NE(INVALID_SOCKET, socket_);
421 CHECK(write_callback_.is_null());
422 DCHECK(!callback.is_null()); // Synchronous operation not supported.
423 DCHECK_GT(buf_len, 0);
424 DCHECK(!send_to_address_.get());
425
426 int nwrite = core_ ? InternalSendToOverlapped(buf, buf_len, address)
427 : InternalSendToNonBlocking(buf, buf_len, address);
428 if (nwrite != ERR_IO_PENDING)
429 return nwrite;
430
431 if (address)
432 send_to_address_.reset(new IPEndPoint(*address));
433 write_callback_ = callback;
434 return ERR_IO_PENDING;
435 }
436
437 int UDPSocketWin::Connect(const IPEndPoint& address) {
438 DCHECK_NE(socket_, INVALID_SOCKET);
439 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT,
440 CreateNetLogUDPConnectCallback(&address));
441 int rv = InternalConnect(address);
442 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv);
443 is_connected_ = (rv == OK);
444 return rv;
445 }
446
447 int UDPSocketWin::InternalConnect(const IPEndPoint& address) {
448 DCHECK(!is_connected());
449 DCHECK(!remote_address_.get());
450
451 int rv = 0;
452 if (bind_type_ == DatagramSocket::RANDOM_BIND) {
453 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
454 // representing INADDR_ANY or in6addr_any.
455 size_t addr_size = (address.GetSockAddrFamily() == AF_INET) ?
456 kIPv4AddressSize : kIPv6AddressSize;
457 IPAddressNumber addr_any(addr_size);
458 rv = RandomBind(addr_any);
459 }
460 // else connect() does the DatagramSocket::DEFAULT_BIND
461
462 if (rv < 0) {
463 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv);
464 return rv;
465 }
466
467 SockaddrStorage storage;
468 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
469 return ERR_ADDRESS_INVALID;
470
471 rv = connect(socket_, storage.addr, storage.addr_len);
472 if (rv < 0)
473 return MapSystemError(WSAGetLastError());
474
475 remote_address_.reset(new IPEndPoint(address));
476 return rv;
477 }
478
479 int UDPSocketWin::Bind(const IPEndPoint& address) {
480 DCHECK_NE(socket_, INVALID_SOCKET);
481 DCHECK(!is_connected());
482
483 int rv = SetMulticastOptions();
484 if (rv < 0)
485 return rv;
486
487 rv = DoBind(address);
488 if (rv < 0)
489 return rv;
490
491 local_address_.reset();
492 is_connected_ = true;
493 return rv;
494 }
495
496 int UDPSocketWin::SetReceiveBufferSize(int32 size) {
497 DCHECK_NE(socket_, INVALID_SOCKET);
498 DCHECK(CalledOnValidThread());
499 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
500 reinterpret_cast<const char*>(&size), sizeof(size));
501 if (rv != 0)
502 return MapSystemError(WSAGetLastError());
503
504 // According to documentation, setsockopt may succeed, but we need to check
505 // the results via getsockopt to be sure it works on Windows.
506 int32 actual_size = 0;
507 int option_size = sizeof(actual_size);
508 rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
509 reinterpret_cast<char*>(&actual_size), &option_size);
510 if (rv != 0)
511 return MapSystemError(WSAGetLastError());
512 if (actual_size >= size)
513 return OK;
514 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
515 actual_size, 1000, 1000000, 50);
516 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE;
517 }
518
519 int UDPSocketWin::SetSendBufferSize(int32 size) {
520 DCHECK_NE(socket_, INVALID_SOCKET);
521 DCHECK(CalledOnValidThread());
522 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
523 reinterpret_cast<const char*>(&size), sizeof(size));
524 if (rv != 0)
525 return MapSystemError(WSAGetLastError());
526 // According to documentation, setsockopt may succeed, but we need to check
527 // the results via getsockopt to be sure it works on Windows.
528 int32 actual_size = 0;
529 int option_size = sizeof(actual_size);
530 rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
531 reinterpret_cast<char*>(&actual_size), &option_size);
532 if (rv != 0)
533 return MapSystemError(WSAGetLastError());
534 if (actual_size >= size)
535 return OK;
536 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
537 actual_size, 1000, 1000000, 50);
538 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE;
539 }
540
541 int UDPSocketWin::AllowAddressReuse() {
542 DCHECK_NE(socket_, INVALID_SOCKET);
543 DCHECK(CalledOnValidThread());
544 DCHECK(!is_connected());
545
546 BOOL true_value = TRUE;
547 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
548 reinterpret_cast<const char*>(&true_value),
549 sizeof(true_value));
550 return rv == 0 ? OK : MapSystemError(WSAGetLastError());
551 }
552
553 int UDPSocketWin::SetBroadcast(bool broadcast) {
554 DCHECK_NE(socket_, INVALID_SOCKET);
555 DCHECK(CalledOnValidThread());
556
557 BOOL value = broadcast ? TRUE : FALSE;
558 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
559 reinterpret_cast<const char*>(&value), sizeof(value));
560 return rv == 0 ? OK : MapSystemError(WSAGetLastError());
561 }
562
563 void UDPSocketWin::DoReadCallback(int rv) {
564 DCHECK_NE(rv, ERR_IO_PENDING);
565 DCHECK(!read_callback_.is_null());
566
567 // since Run may result in Read being called, clear read_callback_ up front.
568 CompletionCallback c = read_callback_;
569 read_callback_.Reset();
570 c.Run(rv);
571 }
572
573 void UDPSocketWin::DoWriteCallback(int rv) {
574 DCHECK_NE(rv, ERR_IO_PENDING);
575 DCHECK(!write_callback_.is_null());
576
577 // since Run may result in Write being called, clear write_callback_ up front.
578 CompletionCallback c = write_callback_;
579 write_callback_.Reset();
580 c.Run(rv);
581 }
582
583 void UDPSocketWin::DidCompleteRead() {
584 DWORD num_bytes, flags;
585 BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_,
586 &num_bytes, FALSE, &flags);
587 WSAResetEvent(core_->read_overlapped_.hEvent);
588 int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
589 // Convert address.
590 IPEndPoint address;
591 IPEndPoint* address_to_log = NULL;
592 if (result >= 0) {
593 if (address.FromSockAddr(core_->recv_addr_storage_.addr,
594 core_->recv_addr_storage_.addr_len)) {
595 if (recv_from_address_)
596 *recv_from_address_ = address;
597 address_to_log = &address;
598 } else {
599 result = ERR_ADDRESS_INVALID;
600 }
601 }
602 LogRead(result, core_->read_iobuffer_->data(), address_to_log);
603 core_->read_iobuffer_ = NULL;
604 recv_from_address_ = NULL;
605 DoReadCallback(result);
606 }
607
608 void UDPSocketWin::DidCompleteWrite() {
609 DWORD num_bytes, flags;
610 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
611 &num_bytes, FALSE, &flags);
612 WSAResetEvent(core_->write_overlapped_.hEvent);
613 int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
614 LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get());
615
616 send_to_address_.reset();
617 core_->write_iobuffer_ = NULL;
618 DoWriteCallback(result);
619 }
620
621 void UDPSocketWin::OnObjectSignaled(HANDLE object) {
622 DCHECK(object == read_write_event_.Get());
623 WSANETWORKEVENTS network_events;
624 int os_error = 0;
625 int rv =
626 WSAEnumNetworkEvents(socket_, read_write_event_.Get(), &network_events);
627 if (rv == SOCKET_ERROR) {
628 os_error = WSAGetLastError();
629 rv = MapSystemError(os_error);
630 if (read_iobuffer_) {
631 read_iobuffer_ = NULL;
632 read_iobuffer_len_ = 0;
633 recv_from_address_ = NULL;
634 DoReadCallback(rv);
635 }
636 if (write_iobuffer_) {
637 write_iobuffer_ = NULL;
638 write_iobuffer_len_ = 0;
639 send_to_address_.reset();
640 DoWriteCallback(rv);
641 }
642 return;
643 }
644 if ((network_events.lNetworkEvents & FD_READ) && read_iobuffer_) {
645 OnReadSignaled();
646 }
647 if ((network_events.lNetworkEvents & FD_WRITE) && write_iobuffer_) {
648 OnWriteSignaled();
649 }
650
651 // There's still pending read / write. Watch for further events.
652 if (read_iobuffer_ || write_iobuffer_) {
653 WatchForReadWrite();
654 }
655 }
656
657 void UDPSocketWin::OnReadSignaled() {
658 int rv = InternalRecvFromNonBlocking(read_iobuffer_.get(), read_iobuffer_len_,
659 recv_from_address_);
660 if (rv == ERR_IO_PENDING)
661 return;
662 read_iobuffer_ = NULL;
663 read_iobuffer_len_ = 0;
664 recv_from_address_ = NULL;
665 DoReadCallback(rv);
666 }
667
668 void UDPSocketWin::OnWriteSignaled() {
669 int rv = InternalSendToNonBlocking(write_iobuffer_.get(), write_iobuffer_len_,
670 send_to_address_.get());
671 if (rv == ERR_IO_PENDING)
672 return;
673 write_iobuffer_ = NULL;
674 write_iobuffer_len_ = 0;
675 send_to_address_.reset();
676 DoWriteCallback(rv);
677 }
678
679 void UDPSocketWin::WatchForReadWrite() {
680 if (read_write_watcher_.IsWatching())
681 return;
682 bool watched =
683 read_write_watcher_.StartWatching(read_write_event_.Get(), this);
684 DCHECK(watched);
685 }
686
687 void UDPSocketWin::LogRead(int result,
688 const char* bytes,
689 const IPEndPoint* address) const {
690 if (result < 0) {
691 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
692 return;
693 }
694
695 if (net_log_.IsLogging()) {
696 net_log_.AddEvent(
697 NetLog::TYPE_UDP_BYTES_RECEIVED,
698 CreateNetLogUDPDataTranferCallback(result, bytes, address));
699 }
700
701 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result);
702 }
703
704 void UDPSocketWin::LogWrite(int result,
705 const char* bytes,
706 const IPEndPoint* address) const {
707 if (result < 0) {
708 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result);
709 return;
710 }
711
712 if (net_log_.IsLogging()) {
713 net_log_.AddEvent(
714 NetLog::TYPE_UDP_BYTES_SENT,
715 CreateNetLogUDPDataTranferCallback(result, bytes, address));
716 }
717
718 NetworkActivityMonitor::GetInstance()->IncrementBytesSent(result);
719 }
720
721 int UDPSocketWin::InternalRecvFromOverlapped(IOBuffer* buf,
722 int buf_len,
723 IPEndPoint* address) {
724 DCHECK(!core_->read_iobuffer_.get());
725 SockaddrStorage& storage = core_->recv_addr_storage_;
726 storage.addr_len = sizeof(storage.addr_storage);
727
728 WSABUF read_buffer;
729 read_buffer.buf = buf->data();
730 read_buffer.len = buf_len;
731
732 DWORD flags = 0;
733 DWORD num;
734 CHECK_NE(INVALID_SOCKET, socket_);
735 AssertEventNotSignaled(core_->read_overlapped_.hEvent);
736 int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr,
737 &storage.addr_len, &core_->read_overlapped_, NULL);
738 if (rv == 0) {
739 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
740 int result = num;
741 // Convert address.
742 IPEndPoint address_storage;
743 IPEndPoint* address_to_log = NULL;
744 if (result >= 0) {
745 if (address_storage.FromSockAddr(core_->recv_addr_storage_.addr,
746 core_->recv_addr_storage_.addr_len)) {
747 if (address)
748 *address = address_storage;
749 address_to_log = &address_storage;
750 } else {
751 result = ERR_ADDRESS_INVALID;
752 }
753 }
754 LogRead(result, buf->data(), address_to_log);
755 return result;
756 }
757 } else {
758 int os_error = WSAGetLastError();
759 if (os_error != WSA_IO_PENDING) {
760 int result = MapSystemError(os_error);
761 LogRead(result, NULL, NULL);
762 return result;
763 }
764 }
765 core_->WatchForRead();
766 core_->read_iobuffer_ = buf;
767 return ERR_IO_PENDING;
768 }
769
770 int UDPSocketWin::InternalSendToOverlapped(IOBuffer* buf,
771 int buf_len,
772 const IPEndPoint* address) {
773 DCHECK(!core_->write_iobuffer_.get());
774 SockaddrStorage storage;
775 struct sockaddr* addr = storage.addr;
776 // Convert address.
777 if (!address) {
778 addr = NULL;
779 storage.addr_len = 0;
780 } else {
781 if (!address->ToSockAddr(addr, &storage.addr_len)) {
782 int result = ERR_ADDRESS_INVALID;
783 LogWrite(result, NULL, NULL);
784 return result;
785 }
786 }
787
788 WSABUF write_buffer;
789 write_buffer.buf = buf->data();
790 write_buffer.len = buf_len;
791
792 DWORD flags = 0;
793 DWORD num;
794 AssertEventNotSignaled(core_->write_overlapped_.hEvent);
795 int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags,
796 addr, storage.addr_len, &core_->write_overlapped_, NULL);
797 if (rv == 0) {
798 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
799 int result = num;
800 LogWrite(result, buf->data(), address);
801 return result;
802 }
803 } else {
804 int os_error = WSAGetLastError();
805 if (os_error != WSA_IO_PENDING) {
806 int result = MapSystemError(os_error);
807 LogWrite(result, NULL, NULL);
808 return result;
809 }
810 }
811
812 core_->WatchForWrite();
813 core_->write_iobuffer_ = buf;
814 return ERR_IO_PENDING;
815 }
816
817 int UDPSocketWin::InternalRecvFromNonBlocking(IOBuffer* buf,
818 int buf_len,
819 IPEndPoint* address) {
820 DCHECK(!read_iobuffer_ || read_iobuffer_.get() == buf);
821 SockaddrStorage storage;
822 storage.addr_len = sizeof(storage.addr_storage);
823
824 CHECK_NE(INVALID_SOCKET, socket_);
825 int rv = recvfrom(socket_, buf->data(), buf_len, 0, storage.addr,
826 &storage.addr_len);
827 if (rv == SOCKET_ERROR) {
828 int os_error = WSAGetLastError();
829 if (os_error == WSAEWOULDBLOCK) {
830 read_iobuffer_ = buf;
831 read_iobuffer_len_ = buf_len;
832 WatchForReadWrite();
833 return ERR_IO_PENDING;
834 }
835 rv = MapSystemError(os_error);
836 LogRead(rv, NULL, NULL);
837 return rv;
838 }
839 IPEndPoint address_storage;
840 IPEndPoint* address_to_log = NULL;
841 if (rv >= 0) {
842 if (address_storage.FromSockAddr(storage.addr, storage.addr_len)) {
843 if (address)
844 *address = address_storage;
845 address_to_log = &address_storage;
846 } else {
847 rv = ERR_ADDRESS_INVALID;
848 }
849 }
850 LogRead(rv, buf->data(), address_to_log);
851 return rv;
852 }
853
854 int UDPSocketWin::InternalSendToNonBlocking(IOBuffer* buf,
855 int buf_len,
856 const IPEndPoint* address) {
857 DCHECK(!write_iobuffer_ || write_iobuffer_.get() == buf);
858 SockaddrStorage storage;
859 struct sockaddr* addr = storage.addr;
860 // Convert address.
861 if (address) {
862 if (!address->ToSockAddr(addr, &storage.addr_len)) {
863 int result = ERR_ADDRESS_INVALID;
864 LogWrite(result, NULL, NULL);
865 return result;
866 }
867 } else {
868 addr = NULL;
869 storage.addr_len = 0;
870 }
871
872 int rv = sendto(socket_, buf->data(), buf_len, 0, addr, storage.addr_len);
873 if (rv == SOCKET_ERROR) {
874 int os_error = WSAGetLastError();
875 if (os_error == WSAEWOULDBLOCK) {
876 write_iobuffer_ = buf;
877 write_iobuffer_len_ = buf_len;
878 WatchForReadWrite();
879 return ERR_IO_PENDING;
880 }
881 rv = MapSystemError(os_error);
882 LogWrite(rv, NULL, NULL);
883 return rv;
884 }
885 LogWrite(rv, buf->data(), address);
886 return rv;
887 }
888
889 int UDPSocketWin::SetMulticastOptions() {
890 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
891 DWORD loop = 0;
892 int protocol_level =
893 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
894 int option =
895 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP;
896 int rv = setsockopt(socket_, protocol_level, option,
897 reinterpret_cast<const char*>(&loop), sizeof(loop));
898 if (rv < 0)
899 return MapSystemError(WSAGetLastError());
900 }
901 if (multicast_time_to_live_ != 1) {
902 DWORD hops = multicast_time_to_live_;
903 int protocol_level =
904 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
905 int option =
906 addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS;
907 int rv = setsockopt(socket_, protocol_level, option,
908 reinterpret_cast<const char*>(&hops), sizeof(hops));
909 if (rv < 0)
910 return MapSystemError(WSAGetLastError());
911 }
912 if (multicast_interface_ != 0) {
913 switch (addr_family_) {
914 case AF_INET: {
915 in_addr address;
916 address.s_addr = htonl(multicast_interface_);
917 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
918 reinterpret_cast<const char*>(&address),
919 sizeof(address));
920 if (rv)
921 return MapSystemError(WSAGetLastError());
922 break;
923 }
924 case AF_INET6: {
925 uint32 interface_index = multicast_interface_;
926 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
927 reinterpret_cast<const char*>(&interface_index),
928 sizeof(interface_index));
929 if (rv)
930 return MapSystemError(WSAGetLastError());
931 break;
932 }
933 default:
934 NOTREACHED() << "Invalid address family";
935 return ERR_ADDRESS_INVALID;
936 }
937 }
938 return OK;
939 }
940
941 int UDPSocketWin::DoBind(const IPEndPoint& address) {
942 SockaddrStorage storage;
943 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
944 return ERR_ADDRESS_INVALID;
945 int rv = bind(socket_, storage.addr, storage.addr_len);
946 if (rv == 0)
947 return OK;
948 int last_error = WSAGetLastError();
949 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error);
950 // Map some codes that are special to bind() separately.
951 // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
952 // returned instead of WSAEADDRINUSE, depending on whether the socket
953 // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
954 // conflicting socket is owned by a different user account. See the MSDN
955 // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
956 if (last_error == WSAEACCES || last_error == WSAEADDRNOTAVAIL)
957 return ERR_ADDRESS_IN_USE;
958 return MapSystemError(last_error);
959 }
960
961 int UDPSocketWin::RandomBind(const IPAddressNumber& address) {
962 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
963
964 for (int i = 0; i < kBindRetries; ++i) {
965 int rv = DoBind(IPEndPoint(
966 address, static_cast<uint16>(rand_int_cb_.Run(kPortStart, kPortEnd))));
967 if (rv == OK || rv != ERR_ADDRESS_IN_USE)
968 return rv;
969 }
970 return DoBind(IPEndPoint(address, 0));
971 }
972
973 int UDPSocketWin::JoinGroup(
974 const IPAddressNumber& group_address) const {
975 DCHECK(CalledOnValidThread());
976 if (!is_connected())
977 return ERR_SOCKET_NOT_CONNECTED;
978
979 switch (group_address.size()) {
980 case kIPv4AddressSize: {
981 if (addr_family_ != AF_INET)
982 return ERR_ADDRESS_INVALID;
983 ip_mreq mreq;
984 mreq.imr_interface.s_addr = htonl(multicast_interface_);
985 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
986 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
987 reinterpret_cast<const char*>(&mreq),
988 sizeof(mreq));
989 if (rv)
990 return MapSystemError(WSAGetLastError());
991 return OK;
992 }
993 case kIPv6AddressSize: {
994 if (addr_family_ != AF_INET6)
995 return ERR_ADDRESS_INVALID;
996 ipv6_mreq mreq;
997 mreq.ipv6mr_interface = multicast_interface_;
998 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
999 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
1000 reinterpret_cast<const char*>(&mreq),
1001 sizeof(mreq));
1002 if (rv)
1003 return MapSystemError(WSAGetLastError());
1004 return OK;
1005 }
1006 default:
1007 NOTREACHED() << "Invalid address family";
1008 return ERR_ADDRESS_INVALID;
1009 }
1010 }
1011
1012 int UDPSocketWin::LeaveGroup(
1013 const IPAddressNumber& group_address) const {
1014 DCHECK(CalledOnValidThread());
1015 if (!is_connected())
1016 return ERR_SOCKET_NOT_CONNECTED;
1017
1018 switch (group_address.size()) {
1019 case kIPv4AddressSize: {
1020 if (addr_family_ != AF_INET)
1021 return ERR_ADDRESS_INVALID;
1022 ip_mreq mreq;
1023 mreq.imr_interface.s_addr = htonl(multicast_interface_);
1024 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
1025 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
1026 reinterpret_cast<const char*>(&mreq), sizeof(mreq));
1027 if (rv)
1028 return MapSystemError(WSAGetLastError());
1029 return OK;
1030 }
1031 case kIPv6AddressSize: {
1032 if (addr_family_ != AF_INET6)
1033 return ERR_ADDRESS_INVALID;
1034 ipv6_mreq mreq;
1035 mreq.ipv6mr_interface = multicast_interface_;
1036 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
1037 int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
1038 reinterpret_cast<const char*>(&mreq), sizeof(mreq));
1039 if (rv)
1040 return MapSystemError(WSAGetLastError());
1041 return OK;
1042 }
1043 default:
1044 NOTREACHED() << "Invalid address family";
1045 return ERR_ADDRESS_INVALID;
1046 }
1047 }
1048
1049 int UDPSocketWin::SetMulticastInterface(uint32 interface_index) {
1050 DCHECK(CalledOnValidThread());
1051 if (is_connected())
1052 return ERR_SOCKET_IS_CONNECTED;
1053 multicast_interface_ = interface_index;
1054 return OK;
1055 }
1056
1057 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) {
1058 DCHECK(CalledOnValidThread());
1059 if (is_connected())
1060 return ERR_SOCKET_IS_CONNECTED;
1061
1062 if (time_to_live < 0 || time_to_live > 255)
1063 return ERR_INVALID_ARGUMENT;
1064 multicast_time_to_live_ = time_to_live;
1065 return OK;
1066 }
1067
1068 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
1069 DCHECK(CalledOnValidThread());
1070 if (is_connected())
1071 return ERR_SOCKET_IS_CONNECTED;
1072
1073 if (loopback)
1074 socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
1075 else
1076 socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
1077 return OK;
1078 }
1079
1080 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) {
1081 if (dscp == DSCP_NO_CHANGE) {
1082 return OK;
1083 }
1084
1085 if (!is_connected())
1086 return ERR_SOCKET_NOT_CONNECTED;
1087
1088 QwaveAPI& qos(QwaveAPI::Get());
1089
1090 if (!qos.qwave_supported())
1091 return ERROR_NOT_SUPPORTED;
1092
1093 if (qos_handle_ == NULL) {
1094 QOS_VERSION version;
1095 version.MajorVersion = 1;
1096 version.MinorVersion = 0;
1097 qos.CreateHandle(&version, &qos_handle_);
1098 if (qos_handle_ == NULL)
1099 return ERROR_NOT_SUPPORTED;
1100 }
1101
1102 QOS_TRAFFIC_TYPE traffic_type = QOSTrafficTypeBestEffort;
1103 switch (dscp) {
1104 case DSCP_CS0:
1105 traffic_type = QOSTrafficTypeBestEffort;
1106 break;
1107 case DSCP_CS1:
1108 traffic_type = QOSTrafficTypeBackground;
1109 break;
1110 case DSCP_AF11:
1111 case DSCP_AF12:
1112 case DSCP_AF13:
1113 case DSCP_CS2:
1114 case DSCP_AF21:
1115 case DSCP_AF22:
1116 case DSCP_AF23:
1117 case DSCP_CS3:
1118 case DSCP_AF31:
1119 case DSCP_AF32:
1120 case DSCP_AF33:
1121 case DSCP_CS4:
1122 traffic_type = QOSTrafficTypeExcellentEffort;
1123 break;
1124 case DSCP_AF41:
1125 case DSCP_AF42:
1126 case DSCP_AF43:
1127 case DSCP_CS5:
1128 traffic_type = QOSTrafficTypeAudioVideo;
1129 break;
1130 case DSCP_EF:
1131 case DSCP_CS6:
1132 traffic_type = QOSTrafficTypeVoice;
1133 break;
1134 case DSCP_CS7:
1135 traffic_type = QOSTrafficTypeControl;
1136 break;
1137 case DSCP_NO_CHANGE:
1138 NOTREACHED();
1139 break;
1140 }
1141 if (qos_flow_id_ != 0) {
1142 qos.RemoveSocketFromFlow(qos_handle_, NULL, qos_flow_id_, 0);
1143 qos_flow_id_ = 0;
1144 }
1145 if (!qos.AddSocketToFlow(qos_handle_,
1146 socket_,
1147 NULL,
1148 traffic_type,
1149 QOS_NON_ADAPTIVE_FLOW,
1150 &qos_flow_id_)) {
1151 DWORD err = GetLastError();
1152 if (err == ERROR_DEVICE_REINITIALIZATION_NEEDED) {
1153 qos.CloseHandle(qos_handle_);
1154 qos_flow_id_ = 0;
1155 qos_handle_ = 0;
1156 }
1157 return MapSystemError(err);
1158 }
1159 // This requires admin rights, and may fail, if so we ignore it
1160 // as AddSocketToFlow should still do *approximately* the right thing.
1161 DWORD buf = dscp;
1162 qos.SetFlow(qos_handle_,
1163 qos_flow_id_,
1164 QOSSetOutgoingDSCPValue,
1165 sizeof(buf),
1166 &buf,
1167 0,
1168 NULL);
1169
1170 return OK;
1171 }
1172
1173 void UDPSocketWin::DetachFromThread() {
1174 base::NonThreadSafe::DetachFromThread();
1175 }
1176
1177 void UDPSocketWin::UseNonBlockingIO() {
1178 DCHECK(!core_);
1179 use_non_blocking_io_ = true;
1180 }
1181
1182 } // namespace net
OLDNEW
« no previous file with comments | « net/udp/udp_socket_win.h ('k') | net/url_request/data_protocol_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698