Chromium Code Reviews| 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/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 477 addr_family_ = addr_family; | 477 addr_family_ = addr_family; |
| 478 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP); | 478 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP); |
| 479 if (socket_ == INVALID_SOCKET) | 479 if (socket_ == INVALID_SOCKET) |
| 480 return MapSystemError(WSAGetLastError()); | 480 return MapSystemError(WSAGetLastError()); |
| 481 core_ = new Core(this); | 481 core_ = new Core(this); |
| 482 return OK; | 482 return OK; |
| 483 } | 483 } |
| 484 | 484 |
| 485 int UDPSocketWin::SetReceiveBufferSize(int32 size) { | 485 int UDPSocketWin::SetReceiveBufferSize(int32 size) { |
| 486 DCHECK(CalledOnValidThread()); | 486 DCHECK(CalledOnValidThread()); |
| 487 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | 487 if (is_connected()) { |
|
rvargas (doing something else)
2014/11/14 02:44:43
As I mentioned on the other review, I don't really
hidehiko
2014/11/19 06:11:24
This is to address mmenke@'s comment
https://coder
rvargas (doing something else)
2014/11/19 22:18:56
Both? I Agree with Matt in that rebinding is a wei
hidehiko
2014/12/01 16:06:24
Ok, Done both.
Note: along the change, now UDPServ
| |
| 488 reinterpret_cast<const char*>(&size), sizeof(size)); | 488 int result = SetReceiveBufferSizeInternal(size); |
| 489 if (rv != 0) | 489 if (result != OK) |
| 490 return MapSystemError(WSAGetLastError()); | 490 return result; |
| 491 | 491 } |
| 492 // According to documentation, setsockopt may succeed, but we need to check | 492 socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE; |
| 493 // the results via getsockopt to be sure it works on Windows. | 493 rcvbuf_size_ = size; |
| 494 int32 actual_size = 0; | 494 return OK; |
| 495 int option_size = sizeof(actual_size); | |
| 496 rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | |
| 497 reinterpret_cast<char*>(&actual_size), &option_size); | |
| 498 if (rv != 0) | |
| 499 return MapSystemError(WSAGetLastError()); | |
| 500 if (actual_size >= size) | |
| 501 return OK; | |
| 502 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer", | |
| 503 actual_size, 1000, 1000000, 50); | |
| 504 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE; | |
| 505 } | 495 } |
| 506 | 496 |
| 507 int UDPSocketWin::SetSendBufferSize(int32 size) { | 497 int UDPSocketWin::SetSendBufferSize(int32 size) { |
| 508 DCHECK(CalledOnValidThread()); | 498 DCHECK(CalledOnValidThread()); |
| 509 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 499 if (is_connected()) { |
| 510 reinterpret_cast<const char*>(&size), sizeof(size)); | 500 int result = SetSendBufferSizeInternal(size); |
| 511 if (rv != 0) | 501 if (result != OK) |
| 512 return MapSystemError(WSAGetLastError()); | 502 return result; |
| 513 // According to documentation, setsockopt may succeed, but we need to check | 503 } |
| 514 // the results via getsockopt to be sure it works on Windows. | 504 socket_options_ |= SOCKET_OPTION_SNDBUF_SIZE; |
| 515 int32 actual_size = 0; | 505 sndbuf_size_ = size; |
| 516 int option_size = sizeof(actual_size); | 506 return OK; |
| 517 rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | |
| 518 reinterpret_cast<char*>(&actual_size), &option_size); | |
| 519 if (rv != 0) | |
| 520 return MapSystemError(WSAGetLastError()); | |
| 521 if (actual_size >= size) | |
| 522 return OK; | |
| 523 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer", | |
| 524 actual_size, 1000, 1000000, 50); | |
| 525 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE; | |
| 526 } | 507 } |
| 527 | 508 |
| 528 void UDPSocketWin::AllowAddressReuse() { | 509 void UDPSocketWin::AllowAddressReuse() { |
| 529 DCHECK(CalledOnValidThread()); | 510 DCHECK(CalledOnValidThread()); |
| 530 DCHECK(!is_connected()); | 511 DCHECK(!is_connected()); |
| 531 | 512 |
| 532 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; | 513 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; |
| 533 } | 514 } |
| 534 | 515 |
| 535 void UDPSocketWin::AllowBroadcast() { | 516 int UDPSocketWin::SetBroadcast(bool broadcast) { |
| 536 DCHECK(CalledOnValidThread()); | 517 DCHECK(CalledOnValidThread()); |
| 537 DCHECK(!is_connected()); | 518 if (is_connected()) { |
| 538 | 519 int result = SetBroadcastInternal(broadcast); |
| 539 socket_options_ |= SOCKET_OPTION_BROADCAST; | 520 if (result != OK) |
| 521 return result; | |
| 522 } | |
| 523 if (broadcast) | |
| 524 socket_options_ |= SOCKET_OPTION_BROADCAST; | |
| 525 else | |
| 526 socket_options_ &= ~SOCKET_OPTION_BROADCAST; | |
| 527 return OK; | |
| 540 } | 528 } |
| 541 | 529 |
| 542 void UDPSocketWin::DoReadCallback(int rv) { | 530 void UDPSocketWin::DoReadCallback(int rv) { |
| 543 DCHECK_NE(rv, ERR_IO_PENDING); | 531 DCHECK_NE(rv, ERR_IO_PENDING); |
| 544 DCHECK(!read_callback_.is_null()); | 532 DCHECK(!read_callback_.is_null()); |
| 545 | 533 |
| 546 // since Run may result in Read being called, clear read_callback_ up front. | 534 // since Run may result in Read being called, clear read_callback_ up front. |
| 547 CompletionCallback c = read_callback_; | 535 CompletionCallback c = read_callback_; |
| 548 read_callback_.Reset(); | 536 read_callback_.Reset(); |
| 549 c.Run(rv); | 537 c.Run(rv); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 710 } | 698 } |
| 711 | 699 |
| 712 core_->WatchForWrite(); | 700 core_->WatchForWrite(); |
| 713 core_->write_iobuffer_ = buf; | 701 core_->write_iobuffer_ = buf; |
| 714 return ERR_IO_PENDING; | 702 return ERR_IO_PENDING; |
| 715 } | 703 } |
| 716 | 704 |
| 717 int UDPSocketWin::SetSocketOptions() { | 705 int UDPSocketWin::SetSocketOptions() { |
| 718 BOOL true_value = 1; | 706 BOOL true_value = 1; |
| 719 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { | 707 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { |
| 720 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, | 708 int rv = AllowAddressReuseInternal(); |
| 721 reinterpret_cast<const char*>(&true_value), | 709 if (rv != OK) |
| 722 sizeof(true_value)); | 710 return rv; |
| 723 if (rv < 0) | |
| 724 return MapSystemError(WSAGetLastError()); | |
| 725 } | 711 } |
| 726 if (socket_options_ & SOCKET_OPTION_BROADCAST) { | 712 if (socket_options_ & SOCKET_OPTION_BROADCAST) { |
| 727 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, | 713 int rv = SetBroadcastInternal(true); |
| 728 reinterpret_cast<const char*>(&true_value), | 714 if (rv != OK) |
| 729 sizeof(true_value)); | 715 return rv; |
| 730 if (rv < 0) | |
| 731 return MapSystemError(WSAGetLastError()); | |
| 732 } | 716 } |
| 733 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { | 717 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { |
| 734 DWORD loop = 0; | 718 DWORD loop = 0; |
| 735 int protocol_level = | 719 int protocol_level = |
| 736 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 720 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
| 737 int option = | 721 int option = |
| 738 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP; | 722 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP; |
| 739 int rv = setsockopt(socket_, protocol_level, option, | 723 int rv = setsockopt(socket_, protocol_level, option, |
| 740 reinterpret_cast<const char*>(&loop), sizeof(loop)); | 724 reinterpret_cast<const char*>(&loop), sizeof(loop)); |
| 741 if (rv < 0) | 725 if (rv < 0) |
| 742 return MapSystemError(WSAGetLastError()); | 726 return MapSystemError(WSAGetLastError()); |
| 743 } | 727 } |
| 728 if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE) { | |
| 729 int rv = SetReceiveBufferSizeInternal(rcvbuf_size_); | |
| 730 if (rv != OK) | |
| 731 return rv; | |
| 732 } | |
| 733 if (socket_options_ & SOCKET_OPTION_SNDBUF_SIZE) { | |
| 734 int rv = SetSendBufferSizeInternal(sndbuf_size_); | |
| 735 if (rv != OK) | |
| 736 return rv; | |
| 737 } | |
| 738 | |
| 744 if (multicast_time_to_live_ != 1) { | 739 if (multicast_time_to_live_ != 1) { |
| 745 DWORD hops = multicast_time_to_live_; | 740 DWORD hops = multicast_time_to_live_; |
| 746 int protocol_level = | 741 int protocol_level = |
| 747 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 742 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
| 748 int option = | 743 int option = |
| 749 addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS; | 744 addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS; |
| 750 int rv = setsockopt(socket_, protocol_level, option, | 745 int rv = setsockopt(socket_, protocol_level, option, |
| 751 reinterpret_cast<const char*>(&hops), sizeof(hops)); | 746 reinterpret_cast<const char*>(&hops), sizeof(hops)); |
| 752 if (rv < 0) | 747 if (rv < 0) |
| 753 return MapSystemError(WSAGetLastError()); | 748 return MapSystemError(WSAGetLastError()); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 774 break; | 769 break; |
| 775 } | 770 } |
| 776 default: | 771 default: |
| 777 NOTREACHED() << "Invalid address family"; | 772 NOTREACHED() << "Invalid address family"; |
| 778 return ERR_ADDRESS_INVALID; | 773 return ERR_ADDRESS_INVALID; |
| 779 } | 774 } |
| 780 } | 775 } |
| 781 return OK; | 776 return OK; |
| 782 } | 777 } |
| 783 | 778 |
| 779 int UDPSocketWin::AllowAddressReuseInternal() { | |
| 780 DCHECK(CalledOnValidThread()); | |
| 781 DCHECK(is_connected()); | |
| 782 | |
| 783 BOOL opt_value = TRUE; | |
| 784 int rv = setsockopt( | |
| 785 socket_, SOL_SOCKET, SO_REUSEADDR, | |
| 786 reinterpret_cast<const char*>(&opt_value), sizeof(opt_value)); | |
| 787 return rv == 0 ? OK : MapSystemError(WSAGetLastError()); | |
| 788 } | |
| 789 | |
| 790 int UDPSocketWin::SetBroadcastInternal(bool broadcast) { | |
| 791 DCHECK(CalledOnValidThread()); | |
| 792 DCHECK(is_connected()); | |
| 793 | |
| 794 BOOL opt_value = broadcast ? TRUE : FALSE; | |
| 795 int rv = setsockopt( | |
| 796 socket_, SOL_SOCKET, SO_BROADCAST, | |
| 797 reinterpret_cast<const char*>(&opt_value), sizeof(opt_value)); | |
| 798 return rv == 0 ? OK : MapSystemError(WSAGetLastError()); | |
| 799 } | |
| 800 | |
| 801 int UDPSocketWin::SetReceiveBufferSizeInternal(int32 size) { | |
| 802 DCHECK(CalledOnValidThread()); | |
| 803 DCHECK(is_connected()); | |
| 804 | |
| 805 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | |
| 806 reinterpret_cast<const char*>(&size), sizeof(size)); | |
| 807 if (rv != 0) | |
| 808 return MapSystemError(WSAGetLastError()); | |
| 809 | |
| 810 // According to documentation, setsockopt may succeed, but we need to check | |
| 811 // the results via getsockopt to be sure it works on Windows. | |
| 812 int32 actual_size = 0; | |
| 813 int option_size = sizeof(actual_size); | |
| 814 rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | |
| 815 reinterpret_cast<char*>(&actual_size), &option_size); | |
| 816 if (rv != 0) | |
| 817 return MapSystemError(WSAGetLastError()); | |
| 818 if (actual_size >= size) | |
| 819 return OK; | |
| 820 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer", | |
| 821 actual_size, 1000, 1000000, 50); | |
| 822 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE; | |
| 823 } | |
| 824 | |
| 825 int UDPSocketWin::SetSendBufferSizeInternal(int32 size) { | |
| 826 DCHECK(CalledOnValidThread()); | |
| 827 DCHECK(is_connected()); | |
| 828 | |
| 829 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | |
| 830 reinterpret_cast<const char*>(&size), sizeof(size)); | |
| 831 if (rv != 0) | |
| 832 return MapSystemError(WSAGetLastError()); | |
| 833 // According to documentation, setsockopt may succeed, but we need to check | |
| 834 // the results via getsockopt to be sure it works on Windows. | |
| 835 int32 actual_size = 0; | |
| 836 int option_size = sizeof(actual_size); | |
| 837 rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | |
| 838 reinterpret_cast<char*>(&actual_size), &option_size); | |
| 839 if (rv != 0) | |
| 840 return MapSystemError(WSAGetLastError()); | |
| 841 if (actual_size >= size) | |
| 842 return OK; | |
| 843 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer", | |
| 844 actual_size, 1000, 1000000, 50); | |
| 845 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE; | |
| 846 } | |
| 847 | |
| 784 int UDPSocketWin::DoBind(const IPEndPoint& address) { | 848 int UDPSocketWin::DoBind(const IPEndPoint& address) { |
| 785 SockaddrStorage storage; | 849 SockaddrStorage storage; |
| 786 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 850 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 787 return ERR_ADDRESS_INVALID; | 851 return ERR_ADDRESS_INVALID; |
| 788 int rv = bind(socket_, storage.addr, storage.addr_len); | 852 int rv = bind(socket_, storage.addr, storage.addr_len); |
| 789 if (rv == 0) | 853 if (rv == 0) |
| 790 return OK; | 854 return OK; |
| 791 int last_error = WSAGetLastError(); | 855 int last_error = WSAGetLastError(); |
| 792 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error); | 856 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error); |
| 793 // Map some codes that are special to bind() separately. | 857 // Map some codes that are special to bind() separately. |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1016 NULL); | 1080 NULL); |
| 1017 | 1081 |
| 1018 return OK; | 1082 return OK; |
| 1019 } | 1083 } |
| 1020 | 1084 |
| 1021 void UDPSocketWin::DetachFromThread() { | 1085 void UDPSocketWin::DetachFromThread() { |
| 1022 base::NonThreadSafe::DetachFromThread(); | 1086 base::NonThreadSafe::DetachFromThread(); |
| 1023 } | 1087 } |
| 1024 | 1088 |
| 1025 } // namespace net | 1089 } // namespace net |
| OLD | NEW |