OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/udp/udp_socket_win.h" | 5 #include "net/udp/udp_socket_win.h" |
6 | 6 |
7 #include <mstcpip.h> | 7 #include <mstcpip.h> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
248 | 248 |
249 | 249 |
250 //----------------------------------------------------------------------------- | 250 //----------------------------------------------------------------------------- |
251 | 251 |
252 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, | 252 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, |
253 const RandIntCallback& rand_int_cb, | 253 const RandIntCallback& rand_int_cb, |
254 net::NetLog* net_log, | 254 net::NetLog* net_log, |
255 const net::NetLog::Source& source) | 255 const net::NetLog::Source& source) |
256 : socket_(INVALID_SOCKET), | 256 : socket_(INVALID_SOCKET), |
257 addr_family_(0), | 257 addr_family_(0), |
258 is_connected_(false), | |
258 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), | 259 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), |
259 multicast_interface_(0), | 260 multicast_interface_(0), |
260 multicast_time_to_live_(1), | 261 multicast_time_to_live_(1), |
261 bind_type_(bind_type), | 262 bind_type_(bind_type), |
262 rand_int_cb_(rand_int_cb), | 263 rand_int_cb_(rand_int_cb), |
263 recv_from_address_(NULL), | 264 recv_from_address_(NULL), |
264 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)), | 265 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)), |
265 qos_handle_(NULL), | 266 qos_handle_(NULL), |
266 qos_flow_id_(0) { | 267 qos_flow_id_(0) { |
267 EnsureWinsockInit(); | 268 EnsureWinsockInit(); |
268 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 269 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
269 source.ToEventParametersCallback()); | 270 source.ToEventParametersCallback()); |
270 if (bind_type == DatagramSocket::RANDOM_BIND) | 271 if (bind_type == DatagramSocket::RANDOM_BIND) |
271 DCHECK(!rand_int_cb.is_null()); | 272 DCHECK(!rand_int_cb.is_null()); |
272 } | 273 } |
273 | 274 |
274 UDPSocketWin::~UDPSocketWin() { | 275 UDPSocketWin::~UDPSocketWin() { |
275 Close(); | 276 Close(); |
276 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 277 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); |
277 } | 278 } |
278 | 279 |
280 int UDPSocketWin::Open(AddressFamily address_family) { | |
281 DCHECK(CalledOnValidThread()); | |
282 DCHECK(socket_ == INVALID_SOCKET); | |
rvargas (doing something else)
2014/12/02 23:28:10
DCHECK_EQ
hidehiko
2014/12/03 17:33:27
Done.
| |
283 return CreateSocket(ConvertAddressFamily(address_family)); | |
284 } | |
285 | |
279 void UDPSocketWin::Close() { | 286 void UDPSocketWin::Close() { |
280 DCHECK(CalledOnValidThread()); | 287 DCHECK(CalledOnValidThread()); |
281 | 288 |
282 if (!is_connected()) | 289 if (socket_ == INVALID_SOCKET) |
283 return; | 290 return; |
284 | 291 |
285 if (qos_handle_) { | 292 if (qos_handle_) { |
286 QwaveAPI::Get().CloseHandle(qos_handle_); | 293 QwaveAPI::Get().CloseHandle(qos_handle_); |
287 } | 294 } |
288 | 295 |
289 // Zero out any pending read/write callback state. | 296 // Zero out any pending read/write callback state. |
290 read_callback_.Reset(); | 297 read_callback_.Reset(); |
291 recv_from_address_ = NULL; | 298 recv_from_address_ = NULL; |
292 write_callback_.Reset(); | 299 write_callback_.Reset(); |
293 | 300 |
294 base::TimeTicks start_time = base::TimeTicks::Now(); | 301 base::TimeTicks start_time = base::TimeTicks::Now(); |
295 closesocket(socket_); | 302 closesocket(socket_); |
296 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose", | 303 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose", |
297 base::TimeTicks::Now() - start_time); | 304 base::TimeTicks::Now() - start_time); |
298 socket_ = INVALID_SOCKET; | 305 socket_ = INVALID_SOCKET; |
299 addr_family_ = 0; | 306 addr_family_ = 0; |
307 is_connected_ = false; | |
300 | 308 |
301 core_->Detach(); | 309 core_->Detach(); |
302 core_ = NULL; | 310 core_ = NULL; |
303 } | 311 } |
304 | 312 |
305 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { | 313 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { |
306 DCHECK(CalledOnValidThread()); | 314 DCHECK(CalledOnValidThread()); |
307 DCHECK(address); | 315 DCHECK(address); |
308 if (!is_connected()) | 316 if (!is_connected()) |
309 return ERR_SOCKET_NOT_CONNECTED; | 317 return ERR_SOCKET_NOT_CONNECTED; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
400 if (nwrite != ERR_IO_PENDING) | 408 if (nwrite != ERR_IO_PENDING) |
401 return nwrite; | 409 return nwrite; |
402 | 410 |
403 if (address) | 411 if (address) |
404 send_to_address_.reset(new IPEndPoint(*address)); | 412 send_to_address_.reset(new IPEndPoint(*address)); |
405 write_callback_ = callback; | 413 write_callback_ = callback; |
406 return ERR_IO_PENDING; | 414 return ERR_IO_PENDING; |
407 } | 415 } |
408 | 416 |
409 int UDPSocketWin::Connect(const IPEndPoint& address) { | 417 int UDPSocketWin::Connect(const IPEndPoint& address) { |
410 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, | 418 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, |
rvargas (doing something else)
2014/12/02 23:28:09
DCHECK_NE(socket_, invalid)
hidehiko
2014/12/03 17:33:28
Done.
| |
411 CreateNetLogUDPConnectCallback(&address)); | 419 CreateNetLogUDPConnectCallback(&address)); |
412 int rv = InternalConnect(address); | 420 int rv = InternalConnect(address); |
413 if (rv != OK) | |
414 Close(); | |
415 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); | 421 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); |
422 is_connected_ = (rv == OK); | |
416 return rv; | 423 return rv; |
417 } | 424 } |
418 | 425 |
419 int UDPSocketWin::InternalConnect(const IPEndPoint& address) { | 426 int UDPSocketWin::InternalConnect(const IPEndPoint& address) { |
420 DCHECK(!is_connected()); | 427 DCHECK(!is_connected()); |
421 DCHECK(!remote_address_.get()); | 428 DCHECK(!remote_address_.get()); |
422 int addr_family = address.GetSockAddrFamily(); | |
423 int rv = CreateSocket(addr_family); | |
424 if (rv < 0) | |
425 return rv; | |
426 | 429 |
430 int rv = 0; | |
427 if (bind_type_ == DatagramSocket::RANDOM_BIND) { | 431 if (bind_type_ == DatagramSocket::RANDOM_BIND) { |
428 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s, | 432 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s, |
429 // representing INADDR_ANY or in6addr_any. | 433 // representing INADDR_ANY or in6addr_any. |
430 size_t addr_size = | 434 size_t addr_size = (address.GetSockAddrFamily() == AF_INET) ? |
431 addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize; | 435 kIPv4AddressSize : kIPv6AddressSize; |
432 IPAddressNumber addr_any(addr_size); | 436 IPAddressNumber addr_any(addr_size); |
433 rv = RandomBind(addr_any); | 437 rv = RandomBind(addr_any); |
434 } | 438 } |
435 // else connect() does the DatagramSocket::DEFAULT_BIND | 439 // else connect() does the DatagramSocket::DEFAULT_BIND |
436 | 440 |
437 if (rv < 0) { | 441 if (rv < 0) { |
438 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); | 442 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); |
439 Close(); | |
440 return rv; | 443 return rv; |
441 } | 444 } |
442 | 445 |
443 SockaddrStorage storage; | 446 SockaddrStorage storage; |
444 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 447 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
445 return ERR_ADDRESS_INVALID; | 448 return ERR_ADDRESS_INVALID; |
446 | 449 |
447 rv = connect(socket_, storage.addr, storage.addr_len); | 450 rv = connect(socket_, storage.addr, storage.addr_len); |
448 if (rv < 0) { | 451 if (rv < 0) { |
449 // Close() may change the last error. Map it beforehand. | 452 // Close() may change the last error. Map it beforehand. |
rvargas (doing something else)
2014/12/02 23:28:09
The comment is stale
hidehiko
2014/12/03 17:33:28
Done.
| |
450 int result = MapSystemError(WSAGetLastError()); | 453 return MapSystemError(WSAGetLastError()); |
451 Close(); | |
452 return result; | |
453 } | 454 } |
454 | 455 |
455 remote_address_.reset(new IPEndPoint(address)); | 456 remote_address_.reset(new IPEndPoint(address)); |
456 return rv; | 457 return rv; |
457 } | 458 } |
458 | 459 |
459 int UDPSocketWin::Bind(const IPEndPoint& address) { | 460 int UDPSocketWin::Bind(const IPEndPoint& address) { |
rvargas (doing something else)
2014/12/02 23:28:09
DCHECK_NE(socket_, invalid)
hidehiko
2014/12/03 17:33:28
Done.
| |
460 DCHECK(!is_connected()); | 461 DCHECK(!is_connected()); |
461 int rv = CreateSocket(address.GetSockAddrFamily()); | 462 |
463 int rv = SetSocketOptions(); | |
462 if (rv < 0) | 464 if (rv < 0) |
463 return rv; | 465 return rv; |
464 rv = SetSocketOptions(); | 466 |
465 if (rv < 0) { | 467 rv = DoBind(address); |
466 Close(); | 468 if (rv < 0) |
467 return rv; | 469 return rv; |
468 } | 470 |
469 rv = DoBind(address); | |
470 if (rv < 0) { | |
471 Close(); | |
472 return rv; | |
473 } | |
474 local_address_.reset(); | 471 local_address_.reset(); |
472 is_connected_ = true; | |
475 return rv; | 473 return rv; |
476 } | 474 } |
477 | 475 |
478 int UDPSocketWin::CreateSocket(int addr_family) { | 476 int UDPSocketWin::CreateSocket(int addr_family) { |
rvargas (doing something else)
2014/12/02 23:28:10
we should move this implementation to Open()
hidehiko
2014/12/03 17:33:27
Done.
| |
479 addr_family_ = addr_family; | 477 addr_family_ = addr_family; |
480 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP); | 478 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP); |
481 if (socket_ == INVALID_SOCKET) | 479 if (socket_ == INVALID_SOCKET) |
482 return MapSystemError(WSAGetLastError()); | 480 return MapSystemError(WSAGetLastError()); |
483 core_ = new Core(this); | 481 core_ = new Core(this); |
484 return OK; | 482 return OK; |
485 } | 483 } |
486 | 484 |
487 int UDPSocketWin::SetReceiveBufferSize(int32 size) { | 485 int UDPSocketWin::SetReceiveBufferSize(int32 size) { |
rvargas (doing something else)
2014/12/02 23:28:09
DCHECK_NE(socket_, invalid) etc
hidehiko
2014/12/03 17:33:28
Done.
| |
488 DCHECK(CalledOnValidThread()); | 486 DCHECK(CalledOnValidThread()); |
489 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | 487 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
490 reinterpret_cast<const char*>(&size), sizeof(size)); | 488 reinterpret_cast<const char*>(&size), sizeof(size)); |
491 if (rv != 0) | 489 if (rv != 0) |
492 return MapSystemError(WSAGetLastError()); | 490 return MapSystemError(WSAGetLastError()); |
493 | 491 |
494 // According to documentation, setsockopt may succeed, but we need to check | 492 // According to documentation, setsockopt may succeed, but we need to check |
495 // the results via getsockopt to be sure it works on Windows. | 493 // the results via getsockopt to be sure it works on Windows. |
496 int32 actual_size = 0; | 494 int32 actual_size = 0; |
497 int option_size = sizeof(actual_size); | 495 int option_size = sizeof(actual_size); |
(...skipping 29 matching lines...) Expand all Loading... | |
527 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE; | 525 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE; |
528 } | 526 } |
529 | 527 |
530 void UDPSocketWin::AllowAddressReuse() { | 528 void UDPSocketWin::AllowAddressReuse() { |
531 DCHECK(CalledOnValidThread()); | 529 DCHECK(CalledOnValidThread()); |
532 DCHECK(!is_connected()); | 530 DCHECK(!is_connected()); |
533 | 531 |
534 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; | 532 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; |
535 } | 533 } |
536 | 534 |
537 void UDPSocketWin::AllowBroadcast() { | 535 int UDPSocketWin::SetBroadcast(bool broadcast) { |
538 DCHECK(CalledOnValidThread()); | 536 DCHECK(CalledOnValidThread()); |
539 DCHECK(!is_connected()); | |
540 | 537 |
541 socket_options_ |= SOCKET_OPTION_BROADCAST; | 538 BOOL value = broadcast ? TRUE : FALSE; |
539 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, | |
540 reinterpret_cast<const char*>(&value), sizeof(value)); | |
541 return rv == 0 ? OK : MapSystemError(WSAGetLastError()); | |
542 } | 542 } |
543 | 543 |
544 void UDPSocketWin::DoReadCallback(int rv) { | 544 void UDPSocketWin::DoReadCallback(int rv) { |
545 DCHECK_NE(rv, ERR_IO_PENDING); | 545 DCHECK_NE(rv, ERR_IO_PENDING); |
546 DCHECK(!read_callback_.is_null()); | 546 DCHECK(!read_callback_.is_null()); |
547 | 547 |
548 // since Run may result in Read being called, clear read_callback_ up front. | 548 // since Run may result in Read being called, clear read_callback_ up front. |
549 CompletionCallback c = read_callback_; | 549 CompletionCallback c = read_callback_; |
550 read_callback_.Reset(); | 550 read_callback_.Reset(); |
551 c.Run(rv); | 551 c.Run(rv); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
712 return result; | 712 return result; |
713 } | 713 } |
714 } | 714 } |
715 | 715 |
716 core_->WatchForWrite(); | 716 core_->WatchForWrite(); |
717 core_->write_iobuffer_ = buf; | 717 core_->write_iobuffer_ = buf; |
718 return ERR_IO_PENDING; | 718 return ERR_IO_PENDING; |
719 } | 719 } |
720 | 720 |
721 int UDPSocketWin::SetSocketOptions() { | 721 int UDPSocketWin::SetSocketOptions() { |
722 BOOL true_value = 1; | |
723 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { | 722 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { |
rvargas (doing something else)
2014/12/02 23:28:09
For consistency it looks like we should move this
hidehiko
2014/12/03 17:33:28
Done.
| |
723 BOOL true_value = TRUE; | |
724 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, | 724 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, |
725 reinterpret_cast<const char*>(&true_value), | 725 reinterpret_cast<const char*>(&true_value), |
726 sizeof(true_value)); | 726 sizeof(true_value)); |
727 if (rv < 0) | 727 if (rv < 0) |
728 return MapSystemError(WSAGetLastError()); | 728 return MapSystemError(WSAGetLastError()); |
729 } | 729 } |
730 if (socket_options_ & SOCKET_OPTION_BROADCAST) { | |
731 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, | |
732 reinterpret_cast<const char*>(&true_value), | |
733 sizeof(true_value)); | |
734 if (rv < 0) | |
735 return MapSystemError(WSAGetLastError()); | |
736 } | |
737 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { | 730 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { |
738 DWORD loop = 0; | 731 DWORD loop = 0; |
739 int protocol_level = | 732 int protocol_level = |
740 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 733 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
741 int option = | 734 int option = |
742 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP; | 735 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP; |
743 int rv = setsockopt(socket_, protocol_level, option, | 736 int rv = setsockopt(socket_, protocol_level, option, |
744 reinterpret_cast<const char*>(&loop), sizeof(loop)); | 737 reinterpret_cast<const char*>(&loop), sizeof(loop)); |
745 if (rv < 0) | 738 if (rv < 0) |
746 return MapSystemError(WSAGetLastError()); | 739 return MapSystemError(WSAGetLastError()); |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1020 NULL); | 1013 NULL); |
1021 | 1014 |
1022 return OK; | 1015 return OK; |
1023 } | 1016 } |
1024 | 1017 |
1025 void UDPSocketWin::DetachFromThread() { | 1018 void UDPSocketWin::DetachFromThread() { |
1026 base::NonThreadSafe::DetachFromThread(); | 1019 base::NonThreadSafe::DetachFromThread(); |
1027 } | 1020 } |
1028 | 1021 |
1029 } // namespace net | 1022 } // namespace net |
OLD | NEW |