15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/udp/udp_socket_win.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mstcpip.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/lazy_instance.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/sparse_histogram.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_init.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_util.h" 24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/socket/socket_descriptor.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/udp/udp_net_log_parameters.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst int kBindRetries = 10; 307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst int kPortStart = 1024; 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst int kPortEnd = 65535; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class encapsulates all the state that has to be preserved as long as 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// there is a network IO operation in progress. If the owner UDPSocketWin 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is destroyed while an operation is in progress, the Core is detached and it 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lives until the operation completes and the OS doesn't reference any resource 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// declared on this class anymore. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UDPSocketWin::Core : public base::RefCounted<Core> { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit Core(UDPSocketWin* socket); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start watching for the end of a read or write operation. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void WatchForRead(); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void WatchForWrite(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The UDPSocketWin is going away. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Detach() { socket_ = NULL; } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The separate OVERLAPPED variables for asynchronous operation. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OVERLAPPED read_overlapped_; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OVERLAPPED write_overlapped_; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The buffers used in Read() and Write(). 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<IOBuffer> read_iobuffer_; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<IOBuffer> write_iobuffer_; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The address storage passed to WSARecvFrom(). 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage recv_addr_storage_; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCounted<Core>; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class ReadDelegate : public base::win::ObjectWatcher::Delegate { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ReadDelegate(Core* core) : core_(core) {} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ReadDelegate() {} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // base::ObjectWatcher::Delegate methods: 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnObjectSignaled(HANDLE object); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Core* const core_; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class WriteDelegate : public base::win::ObjectWatcher::Delegate { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit WriteDelegate(Core* core) : core_(core) {} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~WriteDelegate() {} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // base::ObjectWatcher::Delegate methods: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnObjectSignaled(HANDLE object); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Core* const core_; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~Core(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The socket that created this object. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UDPSocketWin* socket_; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |reader_| handles the signals from |read_watcher_|. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReadDelegate reader_; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |writer_| handles the signals from |write_watcher_|. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteDelegate writer_; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |read_watcher_| watches for events from Read(). 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ObjectWatcher read_watcher_; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |write_watcher_| watches for events from Write(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ObjectWatcher write_watcher_; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Core); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UDPSocketWin::Core::Core(UDPSocketWin* socket) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : socket_(socket), 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reader_(this), 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) writer_(this) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&read_overlapped_, 0, sizeof(read_overlapped_)); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&write_overlapped_, 0, sizeof(write_overlapped_)); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_overlapped_.hEvent = WSACreateEvent(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_overlapped_.hEvent = WSACreateEvent(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UDPSocketWin::Core::~Core() { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the message loop is not watching this object anymore. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_watcher_.StopWatching(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_watcher_.StopWatching(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSACloseEvent(read_overlapped_.hEvent); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_)); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSACloseEvent(write_overlapped_.hEvent); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::Core::WatchForRead() { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We grab an extra reference because there is an IO operation in progress. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Balanced in ReadDelegate::OnObjectSignaled(). 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddRef(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::Core::WatchForWrite() { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We grab an extra reference because there is an IO operation in progress. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Balanced in WriteDelegate::OnObjectSignaled(). 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddRef(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(object, core_->read_overlapped_.hEvent); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (core_->socket_) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->socket_->DidCompleteRead(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->Release(); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(object, core_->write_overlapped_.hEvent); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (core_->socket_) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->socket_->DidCompleteWrite(); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->Release(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//----------------------------------------------------------------------------- 1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)QwaveAPI::QwaveAPI() : qwave_supported_(false) { 1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) HMODULE qwave = LoadLibrary(L"qwave.dll"); 1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!qwave) 1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) create_handle_func_ = 1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (CreateHandleFn)GetProcAddress(qwave, "QOSCreateHandle"); 1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) close_handle_func_ = 1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (CloseHandleFn)GetProcAddress(qwave, "QOSCloseHandle"); 1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) add_socket_to_flow_func_ = 1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (AddSocketToFlowFn)GetProcAddress(qwave, "QOSAddSocketToFlow"); 1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) remove_socket_from_flow_func_ = 1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (RemoveSocketFromFlowFn)GetProcAddress(qwave, "QOSRemoveSocketFromFlow"); 1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_flow_func_ = (SetFlowFn)GetProcAddress(qwave, "QOSSetFlow"); 1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (create_handle_func_ && close_handle_func_ && 1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) add_socket_to_flow_func_ && remove_socket_from_flow_func_ && 1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_flow_func_) { 1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qwave_supported_ = true; 1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)QwaveAPI& QwaveAPI::Get() { 1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static base::LazyInstance<QwaveAPI>::Leaky lazy_qwave = 1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return lazy_qwave.Get(); 1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool QwaveAPI::qwave_supported() const { 1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return qwave_supported_; 1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)BOOL QwaveAPI::CreateHandle(PQOS_VERSION version, PHANDLE handle) { 1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return create_handle_func_(version, handle); 1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)BOOL QwaveAPI::CloseHandle(HANDLE handle) { 1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return close_handle_func_(handle); 1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)BOOL QwaveAPI::AddSocketToFlow(HANDLE handle, 2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SOCKET socket, 2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) PSOCKADDR addr, 2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QOS_TRAFFIC_TYPE traffic_type, 2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DWORD flags, 2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) PQOS_FLOWID flow_id) { 2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return add_socket_to_flow_func_(handle, 2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) socket, 2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) addr, 2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) traffic_type, 2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) flags, 2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) flow_id); 2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)BOOL QwaveAPI::RemoveSocketFromFlow(HANDLE handle, 2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SOCKET socket, 2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QOS_FLOWID flow_id, 2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DWORD reserved) { 2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return remove_socket_from_flow_func_(handle, socket, flow_id, reserved); 2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)BOOL QwaveAPI::SetFlow(HANDLE handle, 2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QOS_FLOWID flow_id, 2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QOS_SET_FLOW op, 2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ULONG size, 2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) PVOID data, 2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DWORD reserved, 2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LPOVERLAPPED overlapped) { 2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return set_flow_func_(handle, 2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) flow_id, 2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) op, 2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) size, 2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) data, 2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) reserved, 2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) overlapped); 2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RandIntCallback& rand_int_cb, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::NetLog* net_log, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::NetLog::Source& source) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : socket_(INVALID_SOCKET), 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) addr_family_(0), 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) socket_options_(SOCKET_OPTION_MULTICAST_LOOP), 246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) multicast_interface_(0), 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) multicast_time_to_live_(1), 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bind_type_(bind_type), 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rand_int_cb_(rand_int_cb), 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recv_from_address_(NULL), 2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)), 2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qos_handle_(NULL), 2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qos_flow_id_(0) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureWinsockInit(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.ToEventParametersCallback()); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bind_type == DatagramSocket::RANDOM_BIND) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!rand_int_cb.is_null()); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UDPSocketWin::~UDPSocketWin() { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::Close() { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_connected()) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (qos_handle_) { 2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QwaveAPI::Get().CloseHandle(qos_handle_); 2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Zero out any pending read/write callback state. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recv_from_address_ = NULL; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_.Reset(); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks start_time = base::TimeTicks::Now(); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closesocket(socket_); 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose", 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks::Now() - start_time); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_ = INVALID_SOCKET; 2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch addr_family_ = 0; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->Detach(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_ = NULL; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(address); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_connected()) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(szym): Simplify. http://crbug.com/126152 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!remote_address_.get()) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (getpeername(socket_, storage.addr, &storage.addr_len)) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(WSAGetLastError()); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<IPEndPoint> address(new IPEndPoint()); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address->FromSockAddr(storage.addr, storage.addr_len)) 3057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return ERR_ADDRESS_INVALID; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remote_address_.reset(address.release()); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *address = *remote_address_; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(address); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_connected()) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(szym): Simplify. http://crbug.com/126152 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!local_address_.get()) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (getsockname(socket_, storage.addr, &storage.addr_len)) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(WSAGetLastError()); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<IPEndPoint> address(new IPEndPoint()); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address->FromSockAddr(storage.addr, storage.addr_len)) 3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return ERR_ADDRESS_INVALID; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_address_.reset(address.release()); 328a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch net_log_.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS, 329a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch CreateNetLogUDPConnectCallback(local_address_.get())); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *address = *local_address_; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::Read(IOBuffer* buf, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buf_len, 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RecvFrom(buf, buf_len, NULL, callback); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::RecvFrom(IOBuffer* buf, 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buf_len, 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPEndPoint* address, 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(INVALID_SOCKET, socket_); 3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(read_callback_.is_null()); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!recv_from_address_); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); // Synchronous operation not supported. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(buf_len, 0); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nread = InternalRecvFrom(buf, buf_len, address); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nread != ERR_IO_PENDING) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nread; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_ = callback; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recv_from_address_ = address; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::Write(IOBuffer* buf, 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buf_len, 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SendToOrWrite(buf, buf_len, NULL, callback); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::SendTo(IOBuffer* buf, 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buf_len, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPEndPoint& address, 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SendToOrWrite(buf, buf_len, &address, callback); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::SendToOrWrite(IOBuffer* buf, 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buf_len, 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPEndPoint* address, 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(INVALID_SOCKET, socket_); 3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(write_callback_.is_null()); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); // Synchronous operation not supported. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(buf_len, 0); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!send_to_address_.get()); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nwrite = InternalSendTo(buf, buf_len, address); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nwrite != ERR_IO_PENDING) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nwrite; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (address) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) send_to_address_.reset(new IPEndPoint(*address)); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_ = callback; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::Connect(const IPEndPoint& address) { 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogUDPConnectCallback(&address)); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = InternalConnect(address); 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != OK) 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Close(); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::InternalConnect(const IPEndPoint& address) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!is_connected()); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!remote_address_.get()); 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int addr_family = address.GetSockAddrFamily(); 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int rv = CreateSocket(addr_family); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv < 0) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (bind_type_ == DatagramSocket::RANDOM_BIND) { 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s, 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // representing INADDR_ANY or in6addr_any. 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t addr_size = 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize; 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IPAddressNumber addr_any(addr_size); 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rv = RandomBind(addr_any); 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else connect() does the DatagramSocket::DEFAULT_BIND 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (rv < 0) { 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); 4267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Close(); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 4327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return ERR_ADDRESS_INVALID; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = connect(socket_, storage.addr, storage.addr_len); 4357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (rv < 0) { 4367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Close() may change the last error. Map it beforehand. 4377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int result = MapSystemError(WSAGetLastError()); 4387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Close(); 4397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return result; 4407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remote_address_.reset(new IPEndPoint(address)); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::Bind(const IPEndPoint& address) { 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!is_connected()); 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int rv = CreateSocket(address.GetSockAddrFamily()); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv < 0) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = SetSocketOptions(); 4527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (rv < 0) { 4537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Close(); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoBind(address); 4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (rv < 0) { 4587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Close(); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_address_.reset(); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int UDPSocketWin::CreateSocket(int addr_family) { 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) addr_family_ = addr_family; 467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_ == INVALID_SOCKET) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(WSAGetLastError()); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_ = new Core(this); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 474c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint UDPSocketWin::SetReceiveBufferSize(int32 size) { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 476c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 477c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch reinterpret_cast<const char*>(&size), sizeof(size)); 478c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (rv != 0) 479c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return MapSystemError(WSAGetLastError()); 480c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 481c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // According to documentation, setsockopt may succeed, but we need to check 482c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // the results via getsockopt to be sure it works on Windows. 483effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int32 actual_size = 0; 484effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int option_size = sizeof(actual_size); 485c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 486c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch reinterpret_cast<char*>(&actual_size), &option_size); 487effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (rv != 0) 488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return MapSystemError(WSAGetLastError()); 489c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (actual_size >= size) 490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return OK; 491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer", 492c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch actual_size, 1000, 1000000, 50); 493c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 496c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint UDPSocketWin::SetSendBufferSize(int32 size) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 498c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 499c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch reinterpret_cast<const char*>(&size), sizeof(size)); 500c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (rv != 0) 501c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return MapSystemError(WSAGetLastError()); 502c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // According to documentation, setsockopt may succeed, but we need to check 503c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // the results via getsockopt to be sure it works on Windows. 504effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int32 actual_size = 0; 505effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int option_size = sizeof(actual_size); 506c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 507c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch reinterpret_cast<char*>(&actual_size), &option_size); 508effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (rv != 0) 509c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return MapSystemError(WSAGetLastError()); 510c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (actual_size >= size) 511c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return OK; 512c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer", 513c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch actual_size, 1000, 1000000, 50); 514c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::AllowAddressReuse() { 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!is_connected()); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::AllowBroadcast() { 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!is_connected()); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_options_ |= SOCKET_OPTION_BROADCAST; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::DoReadCallback(int rv) { 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(rv, ERR_IO_PENDING); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!read_callback_.is_null()); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since Run may result in Read being called, clear read_callback_ up front. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback c = read_callback_; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Run(rv); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::DoWriteCallback(int rv) { 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(rv, ERR_IO_PENDING); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!write_callback_.is_null()); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since Run may result in Write being called, clear write_callback_ up front. 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback c = write_callback_; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_.Reset(); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Run(rv); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::DidCompleteRead() { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD num_bytes, flags; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_, 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &num_bytes, FALSE, &flags); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSAResetEvent(core_->read_overlapped_.hEvent); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert address. 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (recv_from_address_ && result >= 0) { 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReceiveAddressToIPEndpoint(recv_from_address_)) 5607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result = ERR_ADDRESS_INVALID; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogRead(result, core_->read_iobuffer_->data()); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->read_iobuffer_ = NULL; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recv_from_address_ = NULL; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoReadCallback(result); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::LogRead(int result, const char* bytes) const { 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 574a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (net_log_.IsLogging()) { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get address for logging, if |address| is NULL. 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPEndPoint address; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_address_valid = ReceiveAddressToIPEndpoint(&address); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_UDP_BYTES_RECEIVED, 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogUDPDataTranferCallback( 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result, bytes, 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_address_valid ? &address : NULL)); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter read_bytes("udp.read_bytes"); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_bytes.Add(result); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::DidCompleteWrite() { 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD num_bytes, flags; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &num_bytes, FALSE, &flags); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSAResetEvent(core_->write_overlapped_.hEvent); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get()); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) send_to_address_.reset(); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->write_iobuffer_ = NULL; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoWriteCallback(result); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::LogWrite(int result, 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* bytes, 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPEndPoint* address) const { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) { 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 610a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (net_log_.IsLogging()) { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_UDP_BYTES_SENT, 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogUDPDataTranferCallback(result, bytes, address)); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter write_bytes("udp.write_bytes"); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_bytes.Add(result); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len, 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPEndPoint* address) { 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!core_->read_iobuffer_); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage& storage = core_->recv_addr_storage_; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage.addr_len = sizeof(storage.addr_storage); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSABUF read_buffer; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer.buf = buf->data(); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer.len = buf_len; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD flags = 0; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD num; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_NE(INVALID_SOCKET, socket_); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertEventNotSignaled(core_->read_overlapped_.hEvent); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr, 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &storage.addr_len, &core_->read_overlapped_, NULL); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == 0) { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = num; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert address. 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (address && result >= 0) { 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReceiveAddressToIPEndpoint(address)) 642effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch result = ERR_ADDRESS_INVALID; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogRead(result, buf->data()); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int os_error = WSAGetLastError(); 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (os_error != WSA_IO_PENDING) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = MapSystemError(os_error); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogRead(result, NULL); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->WatchForRead(); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->read_iobuffer_ = buf; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len, 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPEndPoint* address) { 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!core_->write_iobuffer_); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr* addr = storage.addr; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert address. 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address) { 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr = NULL; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage.addr_len = 0; 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address->ToSockAddr(addr, &storage.addr_len)) { 671effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int result = ERR_ADDRESS_INVALID; 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogWrite(result, NULL, NULL); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSABUF write_buffer; 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer.buf = buf->data(); 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer.len = buf_len; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD flags = 0; 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD num; 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertEventNotSignaled(core_->write_overlapped_.hEvent); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags, 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr, storage.addr_len, &core_->write_overlapped_, NULL); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == 0) { 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = num; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogWrite(result, buf->data(), address); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int os_error = WSAGetLastError(); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (os_error != WSA_IO_PENDING) { 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = MapSystemError(os_error); 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogWrite(result, NULL, NULL); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->WatchForWrite(); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_->write_iobuffer_ = buf; 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::SetSocketOptions() { 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL true_value = 1; 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(&true_value), 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(true_value)); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv < 0) 713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_options_ & SOCKET_OPTION_BROADCAST) { 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(&true_value), 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(true_value)); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv < 0) 720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { 723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DWORD loop = 0; 724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int protocol_level = 725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int option = 727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP; 728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int rv = setsockopt(socket_, protocol_level, option, 729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<const char*>(&loop), sizeof(loop)); 730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (rv < 0) 731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (multicast_time_to_live_ != 1) { 734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DWORD hops = multicast_time_to_live_; 735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int protocol_level = 736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int option = 738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS; 739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int rv = setsockopt(socket_, protocol_level, option, 740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<const char*>(&hops), sizeof(hops)); 741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (rv < 0) 742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 744a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (multicast_interface_ != 0) { 745a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) switch (addr_family_) { 746a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case AF_INET: { 747a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) in_addr address; 748a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) address.s_addr = htonl(multicast_interface_); 749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, 750a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reinterpret_cast<const char*>(&address), 751a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sizeof(address)); 752a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (rv) 753a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return MapSystemError(WSAGetLastError()); 754a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 755a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 756a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case AF_INET6: { 757a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint32 interface_index = multicast_interface_; 758a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF, 759a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reinterpret_cast<const char*>(&interface_index), 760a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sizeof(interface_index)); 761a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (rv) 762a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return MapSystemError(WSAGetLastError()); 763a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 764a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 765a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) default: 766a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTREACHED() << "Invalid address family"; 767a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return ERR_ADDRESS_INVALID; 768a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 769a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::DoBind(const IPEndPoint& address) { 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_ADDRESS_INVALID; 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = bind(socket_, storage.addr, storage.addr_len); 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (rv == 0) 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return OK; 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int last_error = WSAGetLastError(); 7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error); 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Map some codes that are special to bind() separately. 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // returned instead of WSAEADDRINUSE, depending on whether the socket 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // conflicting socket is owned by a different user account. See the MSDN 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details. 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (last_error == WSAEACCES || last_error == WSAEADDRNOTAVAIL) 7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ERR_ADDRESS_IN_USE; 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return MapSystemError(last_error); 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int UDPSocketWin::RandomBind(const IPAddressNumber& address) { 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kBindRetries; ++i) { 7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int rv = DoBind(IPEndPoint(address, 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rand_int_cb_.Run(kPortStart, kPortEnd))); 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == OK || rv != ERR_ADDRESS_IN_USE) 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return DoBind(IPEndPoint(address, 0)); 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage& storage = core_->recv_addr_storage_; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return address->FromSockAddr(storage.addr, storage.addr_len); 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocketWin::JoinGroup( 811c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const IPAddressNumber& group_address) const { 812c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 813c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_connected()) 814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 815c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (group_address.size()) { 817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case kIPv4AddressSize: { 818c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (addr_family_ != AF_INET) 819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_ADDRESS_INVALID; 820c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ip_mreq mreq; 821a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) mreq.imr_interface.s_addr = htonl(multicast_interface_); 822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); 823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, 824c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<const char*>(&mreq), 825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sizeof(mreq)); 826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (rv) 827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 828c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return OK; 829c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case kIPv6AddressSize: { 831c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (addr_family_ != AF_INET6) 832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_ADDRESS_INVALID; 833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ipv6_mreq mreq; 834a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) mreq.ipv6mr_interface = multicast_interface_; 835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); 836c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, 837c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<const char*>(&mreq), 838c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sizeof(mreq)); 839c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (rv) 840c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 841c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return OK; 842c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 843c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 844c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED() << "Invalid address family"; 845c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_ADDRESS_INVALID; 846c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 847c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocketWin::LeaveGroup( 850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const IPAddressNumber& group_address) const { 851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_connected()) 853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 854c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (group_address.size()) { 856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case kIPv4AddressSize: { 857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (addr_family_ != AF_INET) 858c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_ADDRESS_INVALID; 859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ip_mreq mreq; 860a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) mreq.imr_interface.s_addr = htonl(multicast_interface_); 861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); 862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP, 863a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reinterpret_cast<const char*>(&mreq), sizeof(mreq)); 864c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (rv) 865c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 866c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return OK; 867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case kIPv6AddressSize: { 869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (addr_family_ != AF_INET6) 870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_ADDRESS_INVALID; 871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ipv6_mreq mreq; 872a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) mreq.ipv6mr_interface = multicast_interface_; 873c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); 874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP, 875a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reinterpret_cast<const char*>(&mreq), sizeof(mreq)); 876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (rv) 877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return OK; 879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED() << "Invalid address family"; 882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_ADDRESS_INVALID; 883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 884c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 886a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int UDPSocketWin::SetMulticastInterface(uint32 interface_index) { 887a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(CalledOnValidThread()); 888a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (is_connected()) 889a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return ERR_SOCKET_IS_CONNECTED; 890a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) multicast_interface_ = interface_index; 891a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return OK; 892a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 893a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) { 895c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_connected()) 897c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_SOCKET_IS_CONNECTED; 898c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (time_to_live < 0 || time_to_live > 255) 900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_INVALID_ARGUMENT; 901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) multicast_time_to_live_ = time_to_live; 902c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return OK; 903c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) { 906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_connected()) 908c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_SOCKET_IS_CONNECTED; 909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (loopback) 911c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP; 912c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else 913c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP; 914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return OK; 915c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 916c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) { 9186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (dscp == DSCP_NO_CHANGE) { 9196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return OK; 9206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 9216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!is_connected()) 9236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 9246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QwaveAPI& qos(QwaveAPI::Get()); 9266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!qos.qwave_supported()) 9286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ERROR_NOT_SUPPORTED; 9296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (qos_handle_ == NULL) { 9316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QOS_VERSION version; 9326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) version.MajorVersion = 1; 9336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) version.MinorVersion = 0; 9346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qos.CreateHandle(&version, &qos_handle_); 9356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (qos_handle_ == NULL) 9366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ERROR_NOT_SUPPORTED; 9376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 9386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QOS_TRAFFIC_TYPE traffic_type = QOSTrafficTypeBestEffort; 9406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) switch (dscp) { 9416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_CS0: 9426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) traffic_type = QOSTrafficTypeBestEffort; 9436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 9446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_CS1: 9456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) traffic_type = QOSTrafficTypeBackground; 9466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 9476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF11: 9486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF12: 9496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF13: 9506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_CS2: 9516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF21: 9526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF22: 9536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF23: 9546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_CS3: 9556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF31: 9566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF32: 9576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF33: 9586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_CS4: 9596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) traffic_type = QOSTrafficTypeExcellentEffort; 9606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 9616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF41: 9626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF42: 9636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_AF43: 9646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_CS5: 9656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) traffic_type = QOSTrafficTypeAudioVideo; 9666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 9676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_EF: 9686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_CS6: 9696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) traffic_type = QOSTrafficTypeVoice; 9706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 9716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_CS7: 9726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) traffic_type = QOSTrafficTypeControl; 9736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 9746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DSCP_NO_CHANGE: 9756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 9766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 9776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 9786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (qos_flow_id_ != 0) { 9796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qos.RemoveSocketFromFlow(qos_handle_, NULL, qos_flow_id_, 0); 9806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qos_flow_id_ = 0; 9816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 9826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!qos.AddSocketToFlow(qos_handle_, 9836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) socket_, 9846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NULL, 9856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) traffic_type, 9866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QOS_NON_ADAPTIVE_FLOW, 9876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &qos_flow_id_)) { 9886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DWORD err = GetLastError(); 9896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (err == ERROR_DEVICE_REINITIALIZATION_NEEDED) { 9906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qos.CloseHandle(qos_handle_); 9916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qos_flow_id_ = 0; 9926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qos_handle_ = 0; 9936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 9946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return MapSystemError(err); 9956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 9966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // This requires admin rights, and may fail, if so we ignore it 9976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // as AddSocketToFlow should still do *approximately* the right thing. 9986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DWORD buf = dscp; 9996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qos.SetFlow(qos_handle_, 10006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) qos_flow_id_, 10016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QOSSetOutgoingDSCPValue, 10026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sizeof(buf), 10036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &buf, 10046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 0, 10056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NULL); 10066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 10076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return OK; 10088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 10098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1010a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void UDPSocketWin::DetachFromThread() { 1011a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::NonThreadSafe::DetachFromThread(); 1012a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 1013a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 1015