1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/socket/udp_socket_win.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <winsock2.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <mstcpip.h>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include <memory>
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/lazy_instance.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_functions.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/rand_util.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/task/thread_pool.h"
23*6777b538SAndroid Build Coastguard Worker #include "net/base/io_buffer.h"
24*6777b538SAndroid Build Coastguard Worker #include "net/base/ip_address.h"
25*6777b538SAndroid Build Coastguard Worker #include "net/base/ip_endpoint.h"
26*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
27*6777b538SAndroid Build Coastguard Worker #include "net/base/network_activity_monitor.h"
28*6777b538SAndroid Build Coastguard Worker #include "net/base/network_change_notifier.h"
29*6777b538SAndroid Build Coastguard Worker #include "net/base/sockaddr_storage.h"
30*6777b538SAndroid Build Coastguard Worker #include "net/base/winsock_init.h"
31*6777b538SAndroid Build Coastguard Worker #include "net/base/winsock_util.h"
32*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log.h"
33*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_event_type.h"
34*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_source.h"
35*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_source_type.h"
36*6777b538SAndroid Build Coastguard Worker #include "net/socket/socket_descriptor.h"
37*6777b538SAndroid Build Coastguard Worker #include "net/socket/socket_options.h"
38*6777b538SAndroid Build Coastguard Worker #include "net/socket/socket_tag.h"
39*6777b538SAndroid Build Coastguard Worker #include "net/socket/udp_net_log_parameters.h"
40*6777b538SAndroid Build Coastguard Worker #include "net/traffic_annotation/network_traffic_annotation.h"
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker namespace net {
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker // This class encapsulates all the state that has to be preserved as long as
45*6777b538SAndroid Build Coastguard Worker // there is a network IO operation in progress. If the owner UDPSocketWin
46*6777b538SAndroid Build Coastguard Worker // is destroyed while an operation is in progress, the Core is detached and it
47*6777b538SAndroid Build Coastguard Worker // lives until the operation completes and the OS doesn't reference any resource
48*6777b538SAndroid Build Coastguard Worker // declared on this class anymore.
49*6777b538SAndroid Build Coastguard Worker class UDPSocketWin::Core : public base::RefCounted<Core> {
50*6777b538SAndroid Build Coastguard Worker public:
51*6777b538SAndroid Build Coastguard Worker explicit Core(UDPSocketWin* socket);
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker Core(const Core&) = delete;
54*6777b538SAndroid Build Coastguard Worker Core& operator=(const Core&) = delete;
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker // Start watching for the end of a read or write operation.
57*6777b538SAndroid Build Coastguard Worker void WatchForRead();
58*6777b538SAndroid Build Coastguard Worker void WatchForWrite();
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Worker // The UDPSocketWin is going away.
Detach()61*6777b538SAndroid Build Coastguard Worker void Detach() { socket_ = nullptr; }
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker // The separate OVERLAPPED variables for asynchronous operation.
64*6777b538SAndroid Build Coastguard Worker OVERLAPPED read_overlapped_;
65*6777b538SAndroid Build Coastguard Worker OVERLAPPED write_overlapped_;
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker // The buffers used in Read() and Write().
68*6777b538SAndroid Build Coastguard Worker scoped_refptr<IOBuffer> read_iobuffer_;
69*6777b538SAndroid Build Coastguard Worker scoped_refptr<IOBuffer> write_iobuffer_;
70*6777b538SAndroid Build Coastguard Worker // The struct for packet metadata passed to WSARecvMsg().
71*6777b538SAndroid Build Coastguard Worker std::unique_ptr<WSAMSG> read_message_ = nullptr;
72*6777b538SAndroid Build Coastguard Worker // Big enough for IP_ECN or IPV6_ECN, nothing more.
73*6777b538SAndroid Build Coastguard Worker char read_control_buffer_[WSA_CMSG_SPACE(sizeof(int))];
74*6777b538SAndroid Build Coastguard Worker
75*6777b538SAndroid Build Coastguard Worker // The address storage passed to WSARecvFrom().
76*6777b538SAndroid Build Coastguard Worker SockaddrStorage recv_addr_storage_;
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Worker private:
79*6777b538SAndroid Build Coastguard Worker friend class base::RefCounted<Core>;
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker class ReadDelegate : public base::win::ObjectWatcher::Delegate {
82*6777b538SAndroid Build Coastguard Worker public:
ReadDelegate(Core * core)83*6777b538SAndroid Build Coastguard Worker explicit ReadDelegate(Core* core) : core_(core) {}
84*6777b538SAndroid Build Coastguard Worker ~ReadDelegate() override = default;
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker // base::ObjectWatcher::Delegate methods:
87*6777b538SAndroid Build Coastguard Worker void OnObjectSignaled(HANDLE object) override;
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker private:
90*6777b538SAndroid Build Coastguard Worker const raw_ptr<Core> core_;
91*6777b538SAndroid Build Coastguard Worker };
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Worker class WriteDelegate : public base::win::ObjectWatcher::Delegate {
94*6777b538SAndroid Build Coastguard Worker public:
WriteDelegate(Core * core)95*6777b538SAndroid Build Coastguard Worker explicit WriteDelegate(Core* core) : core_(core) {}
96*6777b538SAndroid Build Coastguard Worker ~WriteDelegate() override = default;
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker // base::ObjectWatcher::Delegate methods:
99*6777b538SAndroid Build Coastguard Worker void OnObjectSignaled(HANDLE object) override;
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker private:
102*6777b538SAndroid Build Coastguard Worker const raw_ptr<Core> core_;
103*6777b538SAndroid Build Coastguard Worker };
104*6777b538SAndroid Build Coastguard Worker
105*6777b538SAndroid Build Coastguard Worker ~Core();
106*6777b538SAndroid Build Coastguard Worker
107*6777b538SAndroid Build Coastguard Worker // The socket that created this object.
108*6777b538SAndroid Build Coastguard Worker raw_ptr<UDPSocketWin> socket_;
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker // |reader_| handles the signals from |read_watcher_|.
111*6777b538SAndroid Build Coastguard Worker ReadDelegate reader_;
112*6777b538SAndroid Build Coastguard Worker // |writer_| handles the signals from |write_watcher_|.
113*6777b538SAndroid Build Coastguard Worker WriteDelegate writer_;
114*6777b538SAndroid Build Coastguard Worker
115*6777b538SAndroid Build Coastguard Worker // |read_watcher_| watches for events from Read().
116*6777b538SAndroid Build Coastguard Worker base::win::ObjectWatcher read_watcher_;
117*6777b538SAndroid Build Coastguard Worker // |write_watcher_| watches for events from Write();
118*6777b538SAndroid Build Coastguard Worker base::win::ObjectWatcher write_watcher_;
119*6777b538SAndroid Build Coastguard Worker };
120*6777b538SAndroid Build Coastguard Worker
Core(UDPSocketWin * socket)121*6777b538SAndroid Build Coastguard Worker UDPSocketWin::Core::Core(UDPSocketWin* socket)
122*6777b538SAndroid Build Coastguard Worker : socket_(socket),
123*6777b538SAndroid Build Coastguard Worker reader_(this),
124*6777b538SAndroid Build Coastguard Worker writer_(this) {
125*6777b538SAndroid Build Coastguard Worker memset(&read_overlapped_, 0, sizeof(read_overlapped_));
126*6777b538SAndroid Build Coastguard Worker memset(&write_overlapped_, 0, sizeof(write_overlapped_));
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Worker read_overlapped_.hEvent = WSACreateEvent();
129*6777b538SAndroid Build Coastguard Worker write_overlapped_.hEvent = WSACreateEvent();
130*6777b538SAndroid Build Coastguard Worker }
131*6777b538SAndroid Build Coastguard Worker
~Core()132*6777b538SAndroid Build Coastguard Worker UDPSocketWin::Core::~Core() {
133*6777b538SAndroid Build Coastguard Worker // Make sure the message loop is not watching this object anymore.
134*6777b538SAndroid Build Coastguard Worker read_watcher_.StopWatching();
135*6777b538SAndroid Build Coastguard Worker write_watcher_.StopWatching();
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker WSACloseEvent(read_overlapped_.hEvent);
138*6777b538SAndroid Build Coastguard Worker memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_));
139*6777b538SAndroid Build Coastguard Worker WSACloseEvent(write_overlapped_.hEvent);
140*6777b538SAndroid Build Coastguard Worker memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_));
141*6777b538SAndroid Build Coastguard Worker }
142*6777b538SAndroid Build Coastguard Worker
WatchForRead()143*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::Core::WatchForRead() {
144*6777b538SAndroid Build Coastguard Worker // We grab an extra reference because there is an IO operation in progress.
145*6777b538SAndroid Build Coastguard Worker // Balanced in ReadDelegate::OnObjectSignaled().
146*6777b538SAndroid Build Coastguard Worker AddRef();
147*6777b538SAndroid Build Coastguard Worker read_watcher_.StartWatchingOnce(read_overlapped_.hEvent, &reader_);
148*6777b538SAndroid Build Coastguard Worker }
149*6777b538SAndroid Build Coastguard Worker
WatchForWrite()150*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::Core::WatchForWrite() {
151*6777b538SAndroid Build Coastguard Worker // We grab an extra reference because there is an IO operation in progress.
152*6777b538SAndroid Build Coastguard Worker // Balanced in WriteDelegate::OnObjectSignaled().
153*6777b538SAndroid Build Coastguard Worker AddRef();
154*6777b538SAndroid Build Coastguard Worker write_watcher_.StartWatchingOnce(write_overlapped_.hEvent, &writer_);
155*6777b538SAndroid Build Coastguard Worker }
156*6777b538SAndroid Build Coastguard Worker
OnObjectSignaled(HANDLE object)157*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) {
158*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(object, core_->read_overlapped_.hEvent);
159*6777b538SAndroid Build Coastguard Worker if (core_->socket_)
160*6777b538SAndroid Build Coastguard Worker core_->socket_->DidCompleteRead();
161*6777b538SAndroid Build Coastguard Worker
162*6777b538SAndroid Build Coastguard Worker core_->Release();
163*6777b538SAndroid Build Coastguard Worker }
164*6777b538SAndroid Build Coastguard Worker
OnObjectSignaled(HANDLE object)165*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object) {
166*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(object, core_->write_overlapped_.hEvent);
167*6777b538SAndroid Build Coastguard Worker if (core_->socket_)
168*6777b538SAndroid Build Coastguard Worker core_->socket_->DidCompleteWrite();
169*6777b538SAndroid Build Coastguard Worker
170*6777b538SAndroid Build Coastguard Worker core_->Release();
171*6777b538SAndroid Build Coastguard Worker }
172*6777b538SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
173*6777b538SAndroid Build Coastguard Worker
QwaveApi()174*6777b538SAndroid Build Coastguard Worker QwaveApi::QwaveApi() {
175*6777b538SAndroid Build Coastguard Worker HMODULE qwave = LoadLibrary(L"qwave.dll");
176*6777b538SAndroid Build Coastguard Worker if (!qwave)
177*6777b538SAndroid Build Coastguard Worker return;
178*6777b538SAndroid Build Coastguard Worker create_handle_func_ =
179*6777b538SAndroid Build Coastguard Worker (CreateHandleFn)GetProcAddress(qwave, "QOSCreateHandle");
180*6777b538SAndroid Build Coastguard Worker close_handle_func_ =
181*6777b538SAndroid Build Coastguard Worker (CloseHandleFn)GetProcAddress(qwave, "QOSCloseHandle");
182*6777b538SAndroid Build Coastguard Worker add_socket_to_flow_func_ =
183*6777b538SAndroid Build Coastguard Worker (AddSocketToFlowFn)GetProcAddress(qwave, "QOSAddSocketToFlow");
184*6777b538SAndroid Build Coastguard Worker remove_socket_from_flow_func_ =
185*6777b538SAndroid Build Coastguard Worker (RemoveSocketFromFlowFn)GetProcAddress(qwave, "QOSRemoveSocketFromFlow");
186*6777b538SAndroid Build Coastguard Worker set_flow_func_ = (SetFlowFn)GetProcAddress(qwave, "QOSSetFlow");
187*6777b538SAndroid Build Coastguard Worker
188*6777b538SAndroid Build Coastguard Worker if (create_handle_func_ && close_handle_func_ &&
189*6777b538SAndroid Build Coastguard Worker add_socket_to_flow_func_ && remove_socket_from_flow_func_ &&
190*6777b538SAndroid Build Coastguard Worker set_flow_func_) {
191*6777b538SAndroid Build Coastguard Worker qwave_supported_ = true;
192*6777b538SAndroid Build Coastguard Worker }
193*6777b538SAndroid Build Coastguard Worker }
194*6777b538SAndroid Build Coastguard Worker
GetDefault()195*6777b538SAndroid Build Coastguard Worker QwaveApi* QwaveApi::GetDefault() {
196*6777b538SAndroid Build Coastguard Worker static base::LazyInstance<QwaveApi>::Leaky lazy_qwave =
197*6777b538SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
198*6777b538SAndroid Build Coastguard Worker return lazy_qwave.Pointer();
199*6777b538SAndroid Build Coastguard Worker }
200*6777b538SAndroid Build Coastguard Worker
qwave_supported() const201*6777b538SAndroid Build Coastguard Worker bool QwaveApi::qwave_supported() const {
202*6777b538SAndroid Build Coastguard Worker return qwave_supported_;
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker
OnFatalError()205*6777b538SAndroid Build Coastguard Worker void QwaveApi::OnFatalError() {
206*6777b538SAndroid Build Coastguard Worker // Disable everything moving forward.
207*6777b538SAndroid Build Coastguard Worker qwave_supported_ = false;
208*6777b538SAndroid Build Coastguard Worker }
209*6777b538SAndroid Build Coastguard Worker
CreateHandle(PQOS_VERSION version,PHANDLE handle)210*6777b538SAndroid Build Coastguard Worker BOOL QwaveApi::CreateHandle(PQOS_VERSION version, PHANDLE handle) {
211*6777b538SAndroid Build Coastguard Worker return create_handle_func_(version, handle);
212*6777b538SAndroid Build Coastguard Worker }
213*6777b538SAndroid Build Coastguard Worker
CloseHandle(HANDLE handle)214*6777b538SAndroid Build Coastguard Worker BOOL QwaveApi::CloseHandle(HANDLE handle) {
215*6777b538SAndroid Build Coastguard Worker return close_handle_func_(handle);
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker
AddSocketToFlow(HANDLE handle,SOCKET socket,PSOCKADDR addr,QOS_TRAFFIC_TYPE traffic_type,DWORD flags,PQOS_FLOWID flow_id)218*6777b538SAndroid Build Coastguard Worker BOOL QwaveApi::AddSocketToFlow(HANDLE handle,
219*6777b538SAndroid Build Coastguard Worker SOCKET socket,
220*6777b538SAndroid Build Coastguard Worker PSOCKADDR addr,
221*6777b538SAndroid Build Coastguard Worker QOS_TRAFFIC_TYPE traffic_type,
222*6777b538SAndroid Build Coastguard Worker DWORD flags,
223*6777b538SAndroid Build Coastguard Worker PQOS_FLOWID flow_id) {
224*6777b538SAndroid Build Coastguard Worker return add_socket_to_flow_func_(handle, socket, addr, traffic_type, flags,
225*6777b538SAndroid Build Coastguard Worker flow_id);
226*6777b538SAndroid Build Coastguard Worker }
227*6777b538SAndroid Build Coastguard Worker
RemoveSocketFromFlow(HANDLE handle,SOCKET socket,QOS_FLOWID flow_id,DWORD reserved)228*6777b538SAndroid Build Coastguard Worker BOOL QwaveApi::RemoveSocketFromFlow(HANDLE handle,
229*6777b538SAndroid Build Coastguard Worker SOCKET socket,
230*6777b538SAndroid Build Coastguard Worker QOS_FLOWID flow_id,
231*6777b538SAndroid Build Coastguard Worker DWORD reserved) {
232*6777b538SAndroid Build Coastguard Worker return remove_socket_from_flow_func_(handle, socket, flow_id, reserved);
233*6777b538SAndroid Build Coastguard Worker }
234*6777b538SAndroid Build Coastguard Worker
SetFlow(HANDLE handle,QOS_FLOWID flow_id,QOS_SET_FLOW op,ULONG size,PVOID data,DWORD reserved,LPOVERLAPPED overlapped)235*6777b538SAndroid Build Coastguard Worker BOOL QwaveApi::SetFlow(HANDLE handle,
236*6777b538SAndroid Build Coastguard Worker QOS_FLOWID flow_id,
237*6777b538SAndroid Build Coastguard Worker QOS_SET_FLOW op,
238*6777b538SAndroid Build Coastguard Worker ULONG size,
239*6777b538SAndroid Build Coastguard Worker PVOID data,
240*6777b538SAndroid Build Coastguard Worker DWORD reserved,
241*6777b538SAndroid Build Coastguard Worker LPOVERLAPPED overlapped) {
242*6777b538SAndroid Build Coastguard Worker return set_flow_func_(handle, flow_id, op, size, data, reserved, overlapped);
243*6777b538SAndroid Build Coastguard Worker }
244*6777b538SAndroid Build Coastguard Worker
245*6777b538SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
246*6777b538SAndroid Build Coastguard Worker
UDPSocketWin(DatagramSocket::BindType bind_type,net::NetLog * net_log,const net::NetLogSource & source)247*6777b538SAndroid Build Coastguard Worker UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type,
248*6777b538SAndroid Build Coastguard Worker net::NetLog* net_log,
249*6777b538SAndroid Build Coastguard Worker const net::NetLogSource& source)
250*6777b538SAndroid Build Coastguard Worker : socket_(INVALID_SOCKET),
251*6777b538SAndroid Build Coastguard Worker socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
252*6777b538SAndroid Build Coastguard Worker net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::UDP_SOCKET)) {
253*6777b538SAndroid Build Coastguard Worker EnsureWinsockInit();
254*6777b538SAndroid Build Coastguard Worker net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source);
255*6777b538SAndroid Build Coastguard Worker }
256*6777b538SAndroid Build Coastguard Worker
UDPSocketWin(DatagramSocket::BindType bind_type,NetLogWithSource source_net_log)257*6777b538SAndroid Build Coastguard Worker UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type,
258*6777b538SAndroid Build Coastguard Worker NetLogWithSource source_net_log)
259*6777b538SAndroid Build Coastguard Worker : socket_(INVALID_SOCKET),
260*6777b538SAndroid Build Coastguard Worker socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
261*6777b538SAndroid Build Coastguard Worker net_log_(source_net_log) {
262*6777b538SAndroid Build Coastguard Worker EnsureWinsockInit();
263*6777b538SAndroid Build Coastguard Worker net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE,
264*6777b538SAndroid Build Coastguard Worker net_log_.source());
265*6777b538SAndroid Build Coastguard Worker }
266*6777b538SAndroid Build Coastguard Worker
~UDPSocketWin()267*6777b538SAndroid Build Coastguard Worker UDPSocketWin::~UDPSocketWin() {
268*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
269*6777b538SAndroid Build Coastguard Worker Close();
270*6777b538SAndroid Build Coastguard Worker net_log_.EndEvent(NetLogEventType::SOCKET_ALIVE);
271*6777b538SAndroid Build Coastguard Worker }
272*6777b538SAndroid Build Coastguard Worker
Open(AddressFamily address_family)273*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::Open(AddressFamily address_family) {
274*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
275*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(socket_, INVALID_SOCKET);
276*6777b538SAndroid Build Coastguard Worker
277*6777b538SAndroid Build Coastguard Worker auto owned_socket_count = TryAcquireGlobalUDPSocketCount();
278*6777b538SAndroid Build Coastguard Worker if (owned_socket_count.empty())
279*6777b538SAndroid Build Coastguard Worker return ERR_INSUFFICIENT_RESOURCES;
280*6777b538SAndroid Build Coastguard Worker
281*6777b538SAndroid Build Coastguard Worker owned_socket_count_ = std::move(owned_socket_count);
282*6777b538SAndroid Build Coastguard Worker addr_family_ = ConvertAddressFamily(address_family);
283*6777b538SAndroid Build Coastguard Worker socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP);
284*6777b538SAndroid Build Coastguard Worker if (socket_ == INVALID_SOCKET) {
285*6777b538SAndroid Build Coastguard Worker owned_socket_count_.Reset();
286*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
287*6777b538SAndroid Build Coastguard Worker }
288*6777b538SAndroid Build Coastguard Worker ConfigureOpenedSocket();
289*6777b538SAndroid Build Coastguard Worker return OK;
290*6777b538SAndroid Build Coastguard Worker }
291*6777b538SAndroid Build Coastguard Worker
AdoptOpenedSocket(AddressFamily address_family,SOCKET socket)292*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::AdoptOpenedSocket(AddressFamily address_family,
293*6777b538SAndroid Build Coastguard Worker SOCKET socket) {
294*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
295*6777b538SAndroid Build Coastguard Worker auto owned_socket_count = TryAcquireGlobalUDPSocketCount();
296*6777b538SAndroid Build Coastguard Worker if (owned_socket_count.empty()) {
297*6777b538SAndroid Build Coastguard Worker return ERR_INSUFFICIENT_RESOURCES;
298*6777b538SAndroid Build Coastguard Worker }
299*6777b538SAndroid Build Coastguard Worker
300*6777b538SAndroid Build Coastguard Worker owned_socket_count_ = std::move(owned_socket_count);
301*6777b538SAndroid Build Coastguard Worker addr_family_ = ConvertAddressFamily(address_family);
302*6777b538SAndroid Build Coastguard Worker socket_ = socket;
303*6777b538SAndroid Build Coastguard Worker ConfigureOpenedSocket();
304*6777b538SAndroid Build Coastguard Worker return OK;
305*6777b538SAndroid Build Coastguard Worker }
306*6777b538SAndroid Build Coastguard Worker
ConfigureOpenedSocket()307*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::ConfigureOpenedSocket() {
308*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
309*6777b538SAndroid Build Coastguard Worker if (!use_non_blocking_io_) {
310*6777b538SAndroid Build Coastguard Worker core_ = base::MakeRefCounted<Core>(this);
311*6777b538SAndroid Build Coastguard Worker } else {
312*6777b538SAndroid Build Coastguard Worker read_write_event_.Set(WSACreateEvent());
313*6777b538SAndroid Build Coastguard Worker WSAEventSelect(socket_, read_write_event_.Get(), FD_READ | FD_WRITE);
314*6777b538SAndroid Build Coastguard Worker }
315*6777b538SAndroid Build Coastguard Worker }
316*6777b538SAndroid Build Coastguard Worker
Close()317*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::Close() {
318*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
319*6777b538SAndroid Build Coastguard Worker
320*6777b538SAndroid Build Coastguard Worker owned_socket_count_.Reset();
321*6777b538SAndroid Build Coastguard Worker
322*6777b538SAndroid Build Coastguard Worker if (socket_ == INVALID_SOCKET)
323*6777b538SAndroid Build Coastguard Worker return;
324*6777b538SAndroid Build Coastguard Worker
325*6777b538SAndroid Build Coastguard Worker // Remove socket_ from the QoS subsystem before we invalidate it.
326*6777b538SAndroid Build Coastguard Worker dscp_manager_ = nullptr;
327*6777b538SAndroid Build Coastguard Worker
328*6777b538SAndroid Build Coastguard Worker // Zero out any pending read/write callback state.
329*6777b538SAndroid Build Coastguard Worker read_callback_.Reset();
330*6777b538SAndroid Build Coastguard Worker recv_from_address_ = nullptr;
331*6777b538SAndroid Build Coastguard Worker write_callback_.Reset();
332*6777b538SAndroid Build Coastguard Worker
333*6777b538SAndroid Build Coastguard Worker base::TimeTicks start_time = base::TimeTicks::Now();
334*6777b538SAndroid Build Coastguard Worker closesocket(socket_);
335*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
336*6777b538SAndroid Build Coastguard Worker base::TimeTicks::Now() - start_time);
337*6777b538SAndroid Build Coastguard Worker socket_ = INVALID_SOCKET;
338*6777b538SAndroid Build Coastguard Worker addr_family_ = 0;
339*6777b538SAndroid Build Coastguard Worker is_connected_ = false;
340*6777b538SAndroid Build Coastguard Worker
341*6777b538SAndroid Build Coastguard Worker // Release buffers to free up memory.
342*6777b538SAndroid Build Coastguard Worker read_iobuffer_ = nullptr;
343*6777b538SAndroid Build Coastguard Worker read_iobuffer_len_ = 0;
344*6777b538SAndroid Build Coastguard Worker write_iobuffer_ = nullptr;
345*6777b538SAndroid Build Coastguard Worker write_iobuffer_len_ = 0;
346*6777b538SAndroid Build Coastguard Worker
347*6777b538SAndroid Build Coastguard Worker read_write_watcher_.StopWatching();
348*6777b538SAndroid Build Coastguard Worker read_write_event_.Close();
349*6777b538SAndroid Build Coastguard Worker
350*6777b538SAndroid Build Coastguard Worker event_pending_.InvalidateWeakPtrs();
351*6777b538SAndroid Build Coastguard Worker
352*6777b538SAndroid Build Coastguard Worker if (core_) {
353*6777b538SAndroid Build Coastguard Worker core_->Detach();
354*6777b538SAndroid Build Coastguard Worker core_ = nullptr;
355*6777b538SAndroid Build Coastguard Worker }
356*6777b538SAndroid Build Coastguard Worker }
357*6777b538SAndroid Build Coastguard Worker
GetPeerAddress(IPEndPoint * address) const358*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
359*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
360*6777b538SAndroid Build Coastguard Worker DCHECK(address);
361*6777b538SAndroid Build Coastguard Worker if (!is_connected())
362*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_NOT_CONNECTED;
363*6777b538SAndroid Build Coastguard Worker
364*6777b538SAndroid Build Coastguard Worker // TODO(szym): Simplify. http://crbug.com/126152
365*6777b538SAndroid Build Coastguard Worker if (!remote_address_.get()) {
366*6777b538SAndroid Build Coastguard Worker SockaddrStorage storage;
367*6777b538SAndroid Build Coastguard Worker if (getpeername(socket_, storage.addr, &storage.addr_len))
368*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
369*6777b538SAndroid Build Coastguard Worker auto remote_address = std::make_unique<IPEndPoint>();
370*6777b538SAndroid Build Coastguard Worker if (!remote_address->FromSockAddr(storage.addr, storage.addr_len))
371*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
372*6777b538SAndroid Build Coastguard Worker remote_address_ = std::move(remote_address);
373*6777b538SAndroid Build Coastguard Worker }
374*6777b538SAndroid Build Coastguard Worker
375*6777b538SAndroid Build Coastguard Worker *address = *remote_address_;
376*6777b538SAndroid Build Coastguard Worker return OK;
377*6777b538SAndroid Build Coastguard Worker }
378*6777b538SAndroid Build Coastguard Worker
GetLocalAddress(IPEndPoint * address) const379*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const {
380*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
381*6777b538SAndroid Build Coastguard Worker DCHECK(address);
382*6777b538SAndroid Build Coastguard Worker if (!is_connected())
383*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_NOT_CONNECTED;
384*6777b538SAndroid Build Coastguard Worker
385*6777b538SAndroid Build Coastguard Worker // TODO(szym): Simplify. http://crbug.com/126152
386*6777b538SAndroid Build Coastguard Worker if (!local_address_.get()) {
387*6777b538SAndroid Build Coastguard Worker SockaddrStorage storage;
388*6777b538SAndroid Build Coastguard Worker if (getsockname(socket_, storage.addr, &storage.addr_len))
389*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
390*6777b538SAndroid Build Coastguard Worker auto local_address = std::make_unique<IPEndPoint>();
391*6777b538SAndroid Build Coastguard Worker if (!local_address->FromSockAddr(storage.addr, storage.addr_len))
392*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
393*6777b538SAndroid Build Coastguard Worker local_address_ = std::move(local_address);
394*6777b538SAndroid Build Coastguard Worker net_log_.AddEvent(NetLogEventType::UDP_LOCAL_ADDRESS, [&] {
395*6777b538SAndroid Build Coastguard Worker return CreateNetLogUDPConnectParams(*local_address_,
396*6777b538SAndroid Build Coastguard Worker handles::kInvalidNetworkHandle);
397*6777b538SAndroid Build Coastguard Worker });
398*6777b538SAndroid Build Coastguard Worker }
399*6777b538SAndroid Build Coastguard Worker
400*6777b538SAndroid Build Coastguard Worker *address = *local_address_;
401*6777b538SAndroid Build Coastguard Worker return OK;
402*6777b538SAndroid Build Coastguard Worker }
403*6777b538SAndroid Build Coastguard Worker
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)404*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::Read(IOBuffer* buf,
405*6777b538SAndroid Build Coastguard Worker int buf_len,
406*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
407*6777b538SAndroid Build Coastguard Worker return RecvFrom(buf, buf_len, nullptr, std::move(callback));
408*6777b538SAndroid Build Coastguard Worker }
409*6777b538SAndroid Build Coastguard Worker
RecvFrom(IOBuffer * buf,int buf_len,IPEndPoint * address,CompletionOnceCallback callback)410*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::RecvFrom(IOBuffer* buf,
411*6777b538SAndroid Build Coastguard Worker int buf_len,
412*6777b538SAndroid Build Coastguard Worker IPEndPoint* address,
413*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
414*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
415*6777b538SAndroid Build Coastguard Worker DCHECK_NE(INVALID_SOCKET, socket_);
416*6777b538SAndroid Build Coastguard Worker CHECK(read_callback_.is_null());
417*6777b538SAndroid Build Coastguard Worker DCHECK(!recv_from_address_);
418*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null()); // Synchronous operation not supported.
419*6777b538SAndroid Build Coastguard Worker DCHECK_GT(buf_len, 0);
420*6777b538SAndroid Build Coastguard Worker
421*6777b538SAndroid Build Coastguard Worker int nread = core_ ? InternalRecvFromOverlapped(buf, buf_len, address)
422*6777b538SAndroid Build Coastguard Worker : InternalRecvFromNonBlocking(buf, buf_len, address);
423*6777b538SAndroid Build Coastguard Worker if (nread != ERR_IO_PENDING)
424*6777b538SAndroid Build Coastguard Worker return nread;
425*6777b538SAndroid Build Coastguard Worker
426*6777b538SAndroid Build Coastguard Worker read_callback_ = std::move(callback);
427*6777b538SAndroid Build Coastguard Worker recv_from_address_ = address;
428*6777b538SAndroid Build Coastguard Worker return ERR_IO_PENDING;
429*6777b538SAndroid Build Coastguard Worker }
430*6777b538SAndroid Build Coastguard Worker
Write(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag &)431*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::Write(
432*6777b538SAndroid Build Coastguard Worker IOBuffer* buf,
433*6777b538SAndroid Build Coastguard Worker int buf_len,
434*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback,
435*6777b538SAndroid Build Coastguard Worker const NetworkTrafficAnnotationTag& /* traffic_annotation */) {
436*6777b538SAndroid Build Coastguard Worker return SendToOrWrite(buf, buf_len, remote_address_.get(),
437*6777b538SAndroid Build Coastguard Worker std::move(callback));
438*6777b538SAndroid Build Coastguard Worker }
439*6777b538SAndroid Build Coastguard Worker
SendTo(IOBuffer * buf,int buf_len,const IPEndPoint & address,CompletionOnceCallback callback)440*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SendTo(IOBuffer* buf,
441*6777b538SAndroid Build Coastguard Worker int buf_len,
442*6777b538SAndroid Build Coastguard Worker const IPEndPoint& address,
443*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
444*6777b538SAndroid Build Coastguard Worker if (dscp_manager_) {
445*6777b538SAndroid Build Coastguard Worker // Alert DscpManager in case this is a new remote address. Failure to
446*6777b538SAndroid Build Coastguard Worker // apply Dscp code is never fatal.
447*6777b538SAndroid Build Coastguard Worker int rv = dscp_manager_->PrepareForSend(address);
448*6777b538SAndroid Build Coastguard Worker if (rv != OK)
449*6777b538SAndroid Build Coastguard Worker net_log_.AddEventWithNetErrorCode(NetLogEventType::UDP_SEND_ERROR, rv);
450*6777b538SAndroid Build Coastguard Worker }
451*6777b538SAndroid Build Coastguard Worker return SendToOrWrite(buf, buf_len, &address, std::move(callback));
452*6777b538SAndroid Build Coastguard Worker }
453*6777b538SAndroid Build Coastguard Worker
SendToOrWrite(IOBuffer * buf,int buf_len,const IPEndPoint * address,CompletionOnceCallback callback)454*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SendToOrWrite(IOBuffer* buf,
455*6777b538SAndroid Build Coastguard Worker int buf_len,
456*6777b538SAndroid Build Coastguard Worker const IPEndPoint* address,
457*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
458*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
459*6777b538SAndroid Build Coastguard Worker DCHECK_NE(INVALID_SOCKET, socket_);
460*6777b538SAndroid Build Coastguard Worker CHECK(write_callback_.is_null());
461*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null()); // Synchronous operation not supported.
462*6777b538SAndroid Build Coastguard Worker DCHECK_GT(buf_len, 0);
463*6777b538SAndroid Build Coastguard Worker DCHECK(!send_to_address_.get());
464*6777b538SAndroid Build Coastguard Worker
465*6777b538SAndroid Build Coastguard Worker int nwrite = core_ ? InternalSendToOverlapped(buf, buf_len, address)
466*6777b538SAndroid Build Coastguard Worker : InternalSendToNonBlocking(buf, buf_len, address);
467*6777b538SAndroid Build Coastguard Worker if (nwrite != ERR_IO_PENDING)
468*6777b538SAndroid Build Coastguard Worker return nwrite;
469*6777b538SAndroid Build Coastguard Worker
470*6777b538SAndroid Build Coastguard Worker if (address)
471*6777b538SAndroid Build Coastguard Worker send_to_address_ = std::make_unique<IPEndPoint>(*address);
472*6777b538SAndroid Build Coastguard Worker write_callback_ = std::move(callback);
473*6777b538SAndroid Build Coastguard Worker return ERR_IO_PENDING;
474*6777b538SAndroid Build Coastguard Worker }
475*6777b538SAndroid Build Coastguard Worker
Connect(const IPEndPoint & address)476*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::Connect(const IPEndPoint& address) {
477*6777b538SAndroid Build Coastguard Worker DCHECK_NE(socket_, INVALID_SOCKET);
478*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::UDP_CONNECT, [&] {
479*6777b538SAndroid Build Coastguard Worker return CreateNetLogUDPConnectParams(address,
480*6777b538SAndroid Build Coastguard Worker handles::kInvalidNetworkHandle);
481*6777b538SAndroid Build Coastguard Worker });
482*6777b538SAndroid Build Coastguard Worker int rv = SetMulticastOptions();
483*6777b538SAndroid Build Coastguard Worker if (rv != OK)
484*6777b538SAndroid Build Coastguard Worker return rv;
485*6777b538SAndroid Build Coastguard Worker rv = InternalConnect(address);
486*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::UDP_CONNECT, rv);
487*6777b538SAndroid Build Coastguard Worker is_connected_ = (rv == OK);
488*6777b538SAndroid Build Coastguard Worker return rv;
489*6777b538SAndroid Build Coastguard Worker }
490*6777b538SAndroid Build Coastguard Worker
InternalConnect(const IPEndPoint & address)491*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::InternalConnect(const IPEndPoint& address) {
492*6777b538SAndroid Build Coastguard Worker DCHECK(!is_connected());
493*6777b538SAndroid Build Coastguard Worker DCHECK(!remote_address_.get());
494*6777b538SAndroid Build Coastguard Worker
495*6777b538SAndroid Build Coastguard Worker // Always do a random bind.
496*6777b538SAndroid Build Coastguard Worker // Ignore failures, which may happen if the socket was already bound.
497*6777b538SAndroid Build Coastguard Worker DWORD randomize_port_value = 1;
498*6777b538SAndroid Build Coastguard Worker setsockopt(socket_, SOL_SOCKET, SO_RANDOMIZE_PORT,
499*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&randomize_port_value),
500*6777b538SAndroid Build Coastguard Worker sizeof(randomize_port_value));
501*6777b538SAndroid Build Coastguard Worker
502*6777b538SAndroid Build Coastguard Worker SockaddrStorage storage;
503*6777b538SAndroid Build Coastguard Worker if (!address.ToSockAddr(storage.addr, &storage.addr_len))
504*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
505*6777b538SAndroid Build Coastguard Worker
506*6777b538SAndroid Build Coastguard Worker int rv = connect(socket_, storage.addr, storage.addr_len);
507*6777b538SAndroid Build Coastguard Worker if (rv < 0)
508*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
509*6777b538SAndroid Build Coastguard Worker
510*6777b538SAndroid Build Coastguard Worker remote_address_ = std::make_unique<IPEndPoint>(address);
511*6777b538SAndroid Build Coastguard Worker
512*6777b538SAndroid Build Coastguard Worker if (dscp_manager_)
513*6777b538SAndroid Build Coastguard Worker dscp_manager_->PrepareForSend(*remote_address_.get());
514*6777b538SAndroid Build Coastguard Worker
515*6777b538SAndroid Build Coastguard Worker return rv;
516*6777b538SAndroid Build Coastguard Worker }
517*6777b538SAndroid Build Coastguard Worker
Bind(const IPEndPoint & address)518*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::Bind(const IPEndPoint& address) {
519*6777b538SAndroid Build Coastguard Worker DCHECK_NE(socket_, INVALID_SOCKET);
520*6777b538SAndroid Build Coastguard Worker DCHECK(!is_connected());
521*6777b538SAndroid Build Coastguard Worker
522*6777b538SAndroid Build Coastguard Worker int rv = SetMulticastOptions();
523*6777b538SAndroid Build Coastguard Worker if (rv < 0)
524*6777b538SAndroid Build Coastguard Worker return rv;
525*6777b538SAndroid Build Coastguard Worker
526*6777b538SAndroid Build Coastguard Worker rv = DoBind(address);
527*6777b538SAndroid Build Coastguard Worker if (rv < 0)
528*6777b538SAndroid Build Coastguard Worker return rv;
529*6777b538SAndroid Build Coastguard Worker
530*6777b538SAndroid Build Coastguard Worker local_address_.reset();
531*6777b538SAndroid Build Coastguard Worker is_connected_ = true;
532*6777b538SAndroid Build Coastguard Worker return rv;
533*6777b538SAndroid Build Coastguard Worker }
534*6777b538SAndroid Build Coastguard Worker
BindToNetwork(handles::NetworkHandle network)535*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::BindToNetwork(handles::NetworkHandle network) {
536*6777b538SAndroid Build Coastguard Worker NOTIMPLEMENTED();
537*6777b538SAndroid Build Coastguard Worker return ERR_NOT_IMPLEMENTED;
538*6777b538SAndroid Build Coastguard Worker }
539*6777b538SAndroid Build Coastguard Worker
SetReceiveBufferSize(int32_t size)540*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetReceiveBufferSize(int32_t size) {
541*6777b538SAndroid Build Coastguard Worker DCHECK_NE(socket_, INVALID_SOCKET);
542*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
543*6777b538SAndroid Build Coastguard Worker int rv = SetSocketReceiveBufferSize(socket_, size);
544*6777b538SAndroid Build Coastguard Worker
545*6777b538SAndroid Build Coastguard Worker if (rv != 0)
546*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
547*6777b538SAndroid Build Coastguard Worker
548*6777b538SAndroid Build Coastguard Worker // According to documentation, setsockopt may succeed, but we need to check
549*6777b538SAndroid Build Coastguard Worker // the results via getsockopt to be sure it works on Windows.
550*6777b538SAndroid Build Coastguard Worker int32_t actual_size = 0;
551*6777b538SAndroid Build Coastguard Worker int option_size = sizeof(actual_size);
552*6777b538SAndroid Build Coastguard Worker rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
553*6777b538SAndroid Build Coastguard Worker reinterpret_cast<char*>(&actual_size), &option_size);
554*6777b538SAndroid Build Coastguard Worker if (rv != 0)
555*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
556*6777b538SAndroid Build Coastguard Worker if (actual_size >= size)
557*6777b538SAndroid Build Coastguard Worker return OK;
558*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
559*6777b538SAndroid Build Coastguard Worker actual_size, 1000, 1000000, 50);
560*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE;
561*6777b538SAndroid Build Coastguard Worker }
562*6777b538SAndroid Build Coastguard Worker
SetSendBufferSize(int32_t size)563*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetSendBufferSize(int32_t size) {
564*6777b538SAndroid Build Coastguard Worker DCHECK_NE(socket_, INVALID_SOCKET);
565*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
566*6777b538SAndroid Build Coastguard Worker int rv = SetSocketSendBufferSize(socket_, size);
567*6777b538SAndroid Build Coastguard Worker if (rv != 0)
568*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
569*6777b538SAndroid Build Coastguard Worker // According to documentation, setsockopt may succeed, but we need to check
570*6777b538SAndroid Build Coastguard Worker // the results via getsockopt to be sure it works on Windows.
571*6777b538SAndroid Build Coastguard Worker int32_t actual_size = 0;
572*6777b538SAndroid Build Coastguard Worker int option_size = sizeof(actual_size);
573*6777b538SAndroid Build Coastguard Worker rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
574*6777b538SAndroid Build Coastguard Worker reinterpret_cast<char*>(&actual_size), &option_size);
575*6777b538SAndroid Build Coastguard Worker if (rv != 0)
576*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
577*6777b538SAndroid Build Coastguard Worker if (actual_size >= size)
578*6777b538SAndroid Build Coastguard Worker return OK;
579*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
580*6777b538SAndroid Build Coastguard Worker actual_size, 1000, 1000000, 50);
581*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE;
582*6777b538SAndroid Build Coastguard Worker }
583*6777b538SAndroid Build Coastguard Worker
SetDoNotFragment()584*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetDoNotFragment() {
585*6777b538SAndroid Build Coastguard Worker DCHECK_NE(socket_, INVALID_SOCKET);
586*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
587*6777b538SAndroid Build Coastguard Worker
588*6777b538SAndroid Build Coastguard Worker if (addr_family_ == AF_INET6)
589*6777b538SAndroid Build Coastguard Worker return OK;
590*6777b538SAndroid Build Coastguard Worker
591*6777b538SAndroid Build Coastguard Worker DWORD val = 1;
592*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, IPPROTO_IP, IP_DONTFRAGMENT,
593*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&val), sizeof(val));
594*6777b538SAndroid Build Coastguard Worker return rv == 0 ? OK : MapSystemError(WSAGetLastError());
595*6777b538SAndroid Build Coastguard Worker }
596*6777b538SAndroid Build Coastguard Worker
GetRecvMsgPointer()597*6777b538SAndroid Build Coastguard Worker LPFN_WSARECVMSG UDPSocketWin::GetRecvMsgPointer() {
598*6777b538SAndroid Build Coastguard Worker LPFN_WSARECVMSG rv;
599*6777b538SAndroid Build Coastguard Worker GUID message_code = WSAID_WSARECVMSG;
600*6777b538SAndroid Build Coastguard Worker DWORD size;
601*6777b538SAndroid Build Coastguard Worker if (WSAIoctl(socket_, SIO_GET_EXTENSION_FUNCTION_POINTER, &message_code,
602*6777b538SAndroid Build Coastguard Worker sizeof(message_code), &rv, sizeof(rv), &size, NULL,
603*6777b538SAndroid Build Coastguard Worker NULL) == SOCKET_ERROR) {
604*6777b538SAndroid Build Coastguard Worker return nullptr;
605*6777b538SAndroid Build Coastguard Worker }
606*6777b538SAndroid Build Coastguard Worker return rv;
607*6777b538SAndroid Build Coastguard Worker }
608*6777b538SAndroid Build Coastguard Worker
GetSendMsgPointer()609*6777b538SAndroid Build Coastguard Worker LPFN_WSASENDMSG UDPSocketWin::GetSendMsgPointer() {
610*6777b538SAndroid Build Coastguard Worker LPFN_WSASENDMSG rv;
611*6777b538SAndroid Build Coastguard Worker GUID message_code = WSAID_WSASENDMSG;
612*6777b538SAndroid Build Coastguard Worker DWORD size;
613*6777b538SAndroid Build Coastguard Worker if (WSAIoctl(socket_, SIO_GET_EXTENSION_FUNCTION_POINTER, &message_code,
614*6777b538SAndroid Build Coastguard Worker sizeof(message_code), &rv, sizeof(rv), &size, NULL,
615*6777b538SAndroid Build Coastguard Worker NULL) == SOCKET_ERROR) {
616*6777b538SAndroid Build Coastguard Worker return nullptr;
617*6777b538SAndroid Build Coastguard Worker }
618*6777b538SAndroid Build Coastguard Worker return rv;
619*6777b538SAndroid Build Coastguard Worker }
620*6777b538SAndroid Build Coastguard Worker
SetRecvTos()621*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetRecvTos() {
622*6777b538SAndroid Build Coastguard Worker DCHECK_NE(socket_, INVALID_SOCKET);
623*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
624*6777b538SAndroid Build Coastguard Worker int rv = WSASetRecvIPEcn(socket_, TRUE);
625*6777b538SAndroid Build Coastguard Worker if (rv != 0) {
626*6777b538SAndroid Build Coastguard Worker int os_error = WSAGetLastError();
627*6777b538SAndroid Build Coastguard Worker int result = MapSystemError(os_error);
628*6777b538SAndroid Build Coastguard Worker LogRead(result, nullptr, nullptr);
629*6777b538SAndroid Build Coastguard Worker return result;
630*6777b538SAndroid Build Coastguard Worker }
631*6777b538SAndroid Build Coastguard Worker wsa_recv_msg_ = GetRecvMsgPointer();
632*6777b538SAndroid Build Coastguard Worker if (wsa_recv_msg_ == nullptr) {
633*6777b538SAndroid Build Coastguard Worker int os_error = WSAGetLastError();
634*6777b538SAndroid Build Coastguard Worker int result = MapSystemError(os_error);
635*6777b538SAndroid Build Coastguard Worker LogRead(result, nullptr, nullptr);
636*6777b538SAndroid Build Coastguard Worker return result;
637*6777b538SAndroid Build Coastguard Worker }
638*6777b538SAndroid Build Coastguard Worker report_ecn_ = true;
639*6777b538SAndroid Build Coastguard Worker return 0;
640*6777b538SAndroid Build Coastguard Worker }
641*6777b538SAndroid Build Coastguard Worker
SetMsgConfirm(bool confirm)642*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::SetMsgConfirm(bool confirm) {}
643*6777b538SAndroid Build Coastguard Worker
AllowAddressReuse()644*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::AllowAddressReuse() {
645*6777b538SAndroid Build Coastguard Worker DCHECK_NE(socket_, INVALID_SOCKET);
646*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
647*6777b538SAndroid Build Coastguard Worker DCHECK(!is_connected());
648*6777b538SAndroid Build Coastguard Worker
649*6777b538SAndroid Build Coastguard Worker BOOL true_value = TRUE;
650*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
651*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&true_value),
652*6777b538SAndroid Build Coastguard Worker sizeof(true_value));
653*6777b538SAndroid Build Coastguard Worker return rv == 0 ? OK : MapSystemError(WSAGetLastError());
654*6777b538SAndroid Build Coastguard Worker }
655*6777b538SAndroid Build Coastguard Worker
SetBroadcast(bool broadcast)656*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetBroadcast(bool broadcast) {
657*6777b538SAndroid Build Coastguard Worker DCHECK_NE(socket_, INVALID_SOCKET);
658*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
659*6777b538SAndroid Build Coastguard Worker
660*6777b538SAndroid Build Coastguard Worker BOOL value = broadcast ? TRUE : FALSE;
661*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
662*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&value), sizeof(value));
663*6777b538SAndroid Build Coastguard Worker return rv == 0 ? OK : MapSystemError(WSAGetLastError());
664*6777b538SAndroid Build Coastguard Worker }
665*6777b538SAndroid Build Coastguard Worker
AllowAddressSharingForMulticast()666*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::AllowAddressSharingForMulticast() {
667*6777b538SAndroid Build Coastguard Worker // When proper multicast groups are used, Windows further defines the address
668*6777b538SAndroid Build Coastguard Worker // resuse option (SO_REUSEADDR) to ensure all listening sockets can receive
669*6777b538SAndroid Build Coastguard Worker // all incoming messages for the multicast group.
670*6777b538SAndroid Build Coastguard Worker return AllowAddressReuse();
671*6777b538SAndroid Build Coastguard Worker }
672*6777b538SAndroid Build Coastguard Worker
DoReadCallback(int rv)673*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::DoReadCallback(int rv) {
674*6777b538SAndroid Build Coastguard Worker DCHECK_NE(rv, ERR_IO_PENDING);
675*6777b538SAndroid Build Coastguard Worker DCHECK(!read_callback_.is_null());
676*6777b538SAndroid Build Coastguard Worker
677*6777b538SAndroid Build Coastguard Worker // since Run may result in Read being called, clear read_callback_ up front.
678*6777b538SAndroid Build Coastguard Worker std::move(read_callback_).Run(rv);
679*6777b538SAndroid Build Coastguard Worker }
680*6777b538SAndroid Build Coastguard Worker
DoWriteCallback(int rv)681*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::DoWriteCallback(int rv) {
682*6777b538SAndroid Build Coastguard Worker DCHECK_NE(rv, ERR_IO_PENDING);
683*6777b538SAndroid Build Coastguard Worker DCHECK(!write_callback_.is_null());
684*6777b538SAndroid Build Coastguard Worker
685*6777b538SAndroid Build Coastguard Worker // since Run may result in Write being called, clear write_callback_ up front.
686*6777b538SAndroid Build Coastguard Worker std::move(write_callback_).Run(rv);
687*6777b538SAndroid Build Coastguard Worker }
688*6777b538SAndroid Build Coastguard Worker
DidCompleteRead()689*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::DidCompleteRead() {
690*6777b538SAndroid Build Coastguard Worker DWORD num_bytes, flags;
691*6777b538SAndroid Build Coastguard Worker BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_,
692*6777b538SAndroid Build Coastguard Worker &num_bytes, FALSE, &flags);
693*6777b538SAndroid Build Coastguard Worker WSAResetEvent(core_->read_overlapped_.hEvent);
694*6777b538SAndroid Build Coastguard Worker int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
695*6777b538SAndroid Build Coastguard Worker // Convert address.
696*6777b538SAndroid Build Coastguard Worker IPEndPoint address;
697*6777b538SAndroid Build Coastguard Worker IPEndPoint* address_to_log = nullptr;
698*6777b538SAndroid Build Coastguard Worker if (result >= 0) {
699*6777b538SAndroid Build Coastguard Worker if (address.FromSockAddr(core_->recv_addr_storage_.addr,
700*6777b538SAndroid Build Coastguard Worker core_->recv_addr_storage_.addr_len)) {
701*6777b538SAndroid Build Coastguard Worker if (recv_from_address_)
702*6777b538SAndroid Build Coastguard Worker *recv_from_address_ = address;
703*6777b538SAndroid Build Coastguard Worker address_to_log = &address;
704*6777b538SAndroid Build Coastguard Worker } else {
705*6777b538SAndroid Build Coastguard Worker result = ERR_ADDRESS_INVALID;
706*6777b538SAndroid Build Coastguard Worker }
707*6777b538SAndroid Build Coastguard Worker if (core_->read_message_ != nullptr) {
708*6777b538SAndroid Build Coastguard Worker SetLastTosFromWSAMSG(*core_->read_message_);
709*6777b538SAndroid Build Coastguard Worker }
710*6777b538SAndroid Build Coastguard Worker }
711*6777b538SAndroid Build Coastguard Worker LogRead(result, core_->read_iobuffer_->data(), address_to_log);
712*6777b538SAndroid Build Coastguard Worker core_->read_iobuffer_ = nullptr;
713*6777b538SAndroid Build Coastguard Worker core_->read_message_ = nullptr;
714*6777b538SAndroid Build Coastguard Worker recv_from_address_ = nullptr;
715*6777b538SAndroid Build Coastguard Worker DoReadCallback(result);
716*6777b538SAndroid Build Coastguard Worker }
717*6777b538SAndroid Build Coastguard Worker
DidCompleteWrite()718*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::DidCompleteWrite() {
719*6777b538SAndroid Build Coastguard Worker DWORD num_bytes, flags;
720*6777b538SAndroid Build Coastguard Worker BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
721*6777b538SAndroid Build Coastguard Worker &num_bytes, FALSE, &flags);
722*6777b538SAndroid Build Coastguard Worker WSAResetEvent(core_->write_overlapped_.hEvent);
723*6777b538SAndroid Build Coastguard Worker int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
724*6777b538SAndroid Build Coastguard Worker LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get());
725*6777b538SAndroid Build Coastguard Worker
726*6777b538SAndroid Build Coastguard Worker send_to_address_.reset();
727*6777b538SAndroid Build Coastguard Worker core_->write_iobuffer_ = nullptr;
728*6777b538SAndroid Build Coastguard Worker DoWriteCallback(result);
729*6777b538SAndroid Build Coastguard Worker }
730*6777b538SAndroid Build Coastguard Worker
OnObjectSignaled(HANDLE object)731*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::OnObjectSignaled(HANDLE object) {
732*6777b538SAndroid Build Coastguard Worker DCHECK(object == read_write_event_.Get());
733*6777b538SAndroid Build Coastguard Worker WSANETWORKEVENTS network_events;
734*6777b538SAndroid Build Coastguard Worker int os_error = 0;
735*6777b538SAndroid Build Coastguard Worker int rv =
736*6777b538SAndroid Build Coastguard Worker WSAEnumNetworkEvents(socket_, read_write_event_.Get(), &network_events);
737*6777b538SAndroid Build Coastguard Worker // Protects against trying to call the write callback if the read callback
738*6777b538SAndroid Build Coastguard Worker // either closes or destroys |this|.
739*6777b538SAndroid Build Coastguard Worker base::WeakPtr<UDPSocketWin> event_pending = event_pending_.GetWeakPtr();
740*6777b538SAndroid Build Coastguard Worker if (rv == SOCKET_ERROR) {
741*6777b538SAndroid Build Coastguard Worker os_error = WSAGetLastError();
742*6777b538SAndroid Build Coastguard Worker rv = MapSystemError(os_error);
743*6777b538SAndroid Build Coastguard Worker
744*6777b538SAndroid Build Coastguard Worker if (read_iobuffer_) {
745*6777b538SAndroid Build Coastguard Worker read_iobuffer_ = nullptr;
746*6777b538SAndroid Build Coastguard Worker read_iobuffer_len_ = 0;
747*6777b538SAndroid Build Coastguard Worker recv_from_address_ = nullptr;
748*6777b538SAndroid Build Coastguard Worker DoReadCallback(rv);
749*6777b538SAndroid Build Coastguard Worker }
750*6777b538SAndroid Build Coastguard Worker
751*6777b538SAndroid Build Coastguard Worker // Socket may have been closed or destroyed here.
752*6777b538SAndroid Build Coastguard Worker if (event_pending && write_iobuffer_) {
753*6777b538SAndroid Build Coastguard Worker write_iobuffer_ = nullptr;
754*6777b538SAndroid Build Coastguard Worker write_iobuffer_len_ = 0;
755*6777b538SAndroid Build Coastguard Worker send_to_address_.reset();
756*6777b538SAndroid Build Coastguard Worker DoWriteCallback(rv);
757*6777b538SAndroid Build Coastguard Worker }
758*6777b538SAndroid Build Coastguard Worker return;
759*6777b538SAndroid Build Coastguard Worker }
760*6777b538SAndroid Build Coastguard Worker
761*6777b538SAndroid Build Coastguard Worker if ((network_events.lNetworkEvents & FD_READ) && read_iobuffer_)
762*6777b538SAndroid Build Coastguard Worker OnReadSignaled();
763*6777b538SAndroid Build Coastguard Worker if (!event_pending)
764*6777b538SAndroid Build Coastguard Worker return;
765*6777b538SAndroid Build Coastguard Worker
766*6777b538SAndroid Build Coastguard Worker if ((network_events.lNetworkEvents & FD_WRITE) && write_iobuffer_)
767*6777b538SAndroid Build Coastguard Worker OnWriteSignaled();
768*6777b538SAndroid Build Coastguard Worker if (!event_pending)
769*6777b538SAndroid Build Coastguard Worker return;
770*6777b538SAndroid Build Coastguard Worker
771*6777b538SAndroid Build Coastguard Worker // There's still pending read / write. Watch for further events.
772*6777b538SAndroid Build Coastguard Worker if (read_iobuffer_ || write_iobuffer_)
773*6777b538SAndroid Build Coastguard Worker WatchForReadWrite();
774*6777b538SAndroid Build Coastguard Worker }
775*6777b538SAndroid Build Coastguard Worker
OnReadSignaled()776*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::OnReadSignaled() {
777*6777b538SAndroid Build Coastguard Worker int rv = InternalRecvFromNonBlocking(read_iobuffer_.get(), read_iobuffer_len_,
778*6777b538SAndroid Build Coastguard Worker recv_from_address_);
779*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING)
780*6777b538SAndroid Build Coastguard Worker return;
781*6777b538SAndroid Build Coastguard Worker read_iobuffer_ = nullptr;
782*6777b538SAndroid Build Coastguard Worker read_iobuffer_len_ = 0;
783*6777b538SAndroid Build Coastguard Worker recv_from_address_ = nullptr;
784*6777b538SAndroid Build Coastguard Worker DoReadCallback(rv);
785*6777b538SAndroid Build Coastguard Worker }
786*6777b538SAndroid Build Coastguard Worker
OnWriteSignaled()787*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::OnWriteSignaled() {
788*6777b538SAndroid Build Coastguard Worker int rv = InternalSendToNonBlocking(write_iobuffer_.get(), write_iobuffer_len_,
789*6777b538SAndroid Build Coastguard Worker send_to_address_.get());
790*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING)
791*6777b538SAndroid Build Coastguard Worker return;
792*6777b538SAndroid Build Coastguard Worker write_iobuffer_ = nullptr;
793*6777b538SAndroid Build Coastguard Worker write_iobuffer_len_ = 0;
794*6777b538SAndroid Build Coastguard Worker send_to_address_.reset();
795*6777b538SAndroid Build Coastguard Worker DoWriteCallback(rv);
796*6777b538SAndroid Build Coastguard Worker }
797*6777b538SAndroid Build Coastguard Worker
WatchForReadWrite()798*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::WatchForReadWrite() {
799*6777b538SAndroid Build Coastguard Worker if (read_write_watcher_.IsWatching())
800*6777b538SAndroid Build Coastguard Worker return;
801*6777b538SAndroid Build Coastguard Worker bool watched =
802*6777b538SAndroid Build Coastguard Worker read_write_watcher_.StartWatchingOnce(read_write_event_.Get(), this);
803*6777b538SAndroid Build Coastguard Worker DCHECK(watched);
804*6777b538SAndroid Build Coastguard Worker }
805*6777b538SAndroid Build Coastguard Worker
LogRead(int result,const char * bytes,const IPEndPoint * address) const806*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::LogRead(int result,
807*6777b538SAndroid Build Coastguard Worker const char* bytes,
808*6777b538SAndroid Build Coastguard Worker const IPEndPoint* address) const {
809*6777b538SAndroid Build Coastguard Worker if (result < 0) {
810*6777b538SAndroid Build Coastguard Worker net_log_.AddEventWithNetErrorCode(NetLogEventType::UDP_RECEIVE_ERROR,
811*6777b538SAndroid Build Coastguard Worker result);
812*6777b538SAndroid Build Coastguard Worker return;
813*6777b538SAndroid Build Coastguard Worker }
814*6777b538SAndroid Build Coastguard Worker
815*6777b538SAndroid Build Coastguard Worker if (net_log_.IsCapturing()) {
816*6777b538SAndroid Build Coastguard Worker NetLogUDPDataTransfer(net_log_, NetLogEventType::UDP_BYTES_RECEIVED, result,
817*6777b538SAndroid Build Coastguard Worker bytes, address);
818*6777b538SAndroid Build Coastguard Worker }
819*6777b538SAndroid Build Coastguard Worker
820*6777b538SAndroid Build Coastguard Worker activity_monitor::IncrementBytesReceived(result);
821*6777b538SAndroid Build Coastguard Worker }
822*6777b538SAndroid Build Coastguard Worker
LogWrite(int result,const char * bytes,const IPEndPoint * address) const823*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::LogWrite(int result,
824*6777b538SAndroid Build Coastguard Worker const char* bytes,
825*6777b538SAndroid Build Coastguard Worker const IPEndPoint* address) const {
826*6777b538SAndroid Build Coastguard Worker if (result < 0) {
827*6777b538SAndroid Build Coastguard Worker net_log_.AddEventWithNetErrorCode(NetLogEventType::UDP_SEND_ERROR, result);
828*6777b538SAndroid Build Coastguard Worker return;
829*6777b538SAndroid Build Coastguard Worker }
830*6777b538SAndroid Build Coastguard Worker
831*6777b538SAndroid Build Coastguard Worker if (net_log_.IsCapturing()) {
832*6777b538SAndroid Build Coastguard Worker NetLogUDPDataTransfer(net_log_, NetLogEventType::UDP_BYTES_SENT, result,
833*6777b538SAndroid Build Coastguard Worker bytes, address);
834*6777b538SAndroid Build Coastguard Worker }
835*6777b538SAndroid Build Coastguard Worker }
836*6777b538SAndroid Build Coastguard Worker
PopulateWSAMSG(WSAMSG & message,SockaddrStorage & storage,WSABUF * data_buffer,WSABUF & control_buffer,bool send)837*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::PopulateWSAMSG(WSAMSG& message,
838*6777b538SAndroid Build Coastguard Worker SockaddrStorage& storage,
839*6777b538SAndroid Build Coastguard Worker WSABUF* data_buffer,
840*6777b538SAndroid Build Coastguard Worker WSABUF& control_buffer,
841*6777b538SAndroid Build Coastguard Worker bool send) {
842*6777b538SAndroid Build Coastguard Worker bool is_ipv6 = addr_family_ == AF_INET6;
843*6777b538SAndroid Build Coastguard Worker message.name = storage.addr;
844*6777b538SAndroid Build Coastguard Worker message.namelen = storage.addr_len;
845*6777b538SAndroid Build Coastguard Worker message.lpBuffers = data_buffer;
846*6777b538SAndroid Build Coastguard Worker message.dwBufferCount = 1;
847*6777b538SAndroid Build Coastguard Worker message.Control.buf = control_buffer.buf;
848*6777b538SAndroid Build Coastguard Worker message.dwFlags = 0;
849*6777b538SAndroid Build Coastguard Worker if (send) {
850*6777b538SAndroid Build Coastguard Worker message.Control.len = 0;
851*6777b538SAndroid Build Coastguard Worker WSACMSGHDR* cmsg;
852*6777b538SAndroid Build Coastguard Worker message.Control.len += WSA_CMSG_SPACE(sizeof(int));
853*6777b538SAndroid Build Coastguard Worker cmsg = WSA_CMSG_FIRSTHDR(&message);
854*6777b538SAndroid Build Coastguard Worker cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(int));
855*6777b538SAndroid Build Coastguard Worker cmsg->cmsg_level = is_ipv6 ? IPPROTO_IPV6 : IPPROTO_IP;
856*6777b538SAndroid Build Coastguard Worker cmsg->cmsg_type = is_ipv6 ? IPV6_ECN : IP_ECN;
857*6777b538SAndroid Build Coastguard Worker *(int*)WSA_CMSG_DATA(cmsg) = static_cast<int>(send_ecn_);
858*6777b538SAndroid Build Coastguard Worker } else {
859*6777b538SAndroid Build Coastguard Worker message.Control.len = control_buffer.len;
860*6777b538SAndroid Build Coastguard Worker }
861*6777b538SAndroid Build Coastguard Worker }
862*6777b538SAndroid Build Coastguard Worker
SetLastTosFromWSAMSG(WSAMSG & message)863*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::SetLastTosFromWSAMSG(WSAMSG& message) {
864*6777b538SAndroid Build Coastguard Worker int ecn = 0;
865*6777b538SAndroid Build Coastguard Worker for (WSACMSGHDR* cmsg = WSA_CMSG_FIRSTHDR(&message); cmsg != NULL;
866*6777b538SAndroid Build Coastguard Worker cmsg = WSA_CMSG_NXTHDR(&message, cmsg)) {
867*6777b538SAndroid Build Coastguard Worker if ((cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_ECN) ||
868*6777b538SAndroid Build Coastguard Worker (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_ECN)) {
869*6777b538SAndroid Build Coastguard Worker ecn = *(int*)WSA_CMSG_DATA(cmsg);
870*6777b538SAndroid Build Coastguard Worker break;
871*6777b538SAndroid Build Coastguard Worker }
872*6777b538SAndroid Build Coastguard Worker }
873*6777b538SAndroid Build Coastguard Worker last_tos_.ecn = static_cast<EcnCodePoint>(ecn);
874*6777b538SAndroid Build Coastguard Worker }
875*6777b538SAndroid Build Coastguard Worker
InternalRecvFromOverlapped(IOBuffer * buf,int buf_len,IPEndPoint * address)876*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::InternalRecvFromOverlapped(IOBuffer* buf,
877*6777b538SAndroid Build Coastguard Worker int buf_len,
878*6777b538SAndroid Build Coastguard Worker IPEndPoint* address) {
879*6777b538SAndroid Build Coastguard Worker DCHECK(!core_->read_iobuffer_.get());
880*6777b538SAndroid Build Coastguard Worker DCHECK(!core_->read_message_.get());
881*6777b538SAndroid Build Coastguard Worker SockaddrStorage& storage = core_->recv_addr_storage_;
882*6777b538SAndroid Build Coastguard Worker storage.addr_len = sizeof(storage.addr_storage);
883*6777b538SAndroid Build Coastguard Worker
884*6777b538SAndroid Build Coastguard Worker WSABUF read_buffer;
885*6777b538SAndroid Build Coastguard Worker read_buffer.buf = buf->data();
886*6777b538SAndroid Build Coastguard Worker read_buffer.len = buf_len;
887*6777b538SAndroid Build Coastguard Worker
888*6777b538SAndroid Build Coastguard Worker DWORD flags = 0;
889*6777b538SAndroid Build Coastguard Worker DWORD num;
890*6777b538SAndroid Build Coastguard Worker CHECK_NE(INVALID_SOCKET, socket_);
891*6777b538SAndroid Build Coastguard Worker int rv;
892*6777b538SAndroid Build Coastguard Worker std::unique_ptr<WSAMSG> message;
893*6777b538SAndroid Build Coastguard Worker if (report_ecn_) {
894*6777b538SAndroid Build Coastguard Worker WSABUF control_buffer;
895*6777b538SAndroid Build Coastguard Worker control_buffer.buf = core_->read_control_buffer_;
896*6777b538SAndroid Build Coastguard Worker control_buffer.len = sizeof(core_->read_control_buffer_);
897*6777b538SAndroid Build Coastguard Worker message = std::make_unique<WSAMSG>();
898*6777b538SAndroid Build Coastguard Worker if (message == nullptr) {
899*6777b538SAndroid Build Coastguard Worker return WSA_NOT_ENOUGH_MEMORY;
900*6777b538SAndroid Build Coastguard Worker }
901*6777b538SAndroid Build Coastguard Worker PopulateWSAMSG(*message, storage, &read_buffer, control_buffer, false);
902*6777b538SAndroid Build Coastguard Worker rv = wsa_recv_msg_(socket_, message.get(), &num, &core_->read_overlapped_,
903*6777b538SAndroid Build Coastguard Worker nullptr);
904*6777b538SAndroid Build Coastguard Worker if (rv == 0) {
905*6777b538SAndroid Build Coastguard Worker SetLastTosFromWSAMSG(*message);
906*6777b538SAndroid Build Coastguard Worker }
907*6777b538SAndroid Build Coastguard Worker } else {
908*6777b538SAndroid Build Coastguard Worker rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr,
909*6777b538SAndroid Build Coastguard Worker &storage.addr_len, &core_->read_overlapped_, nullptr);
910*6777b538SAndroid Build Coastguard Worker }
911*6777b538SAndroid Build Coastguard Worker if (rv == 0) {
912*6777b538SAndroid Build Coastguard Worker if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
913*6777b538SAndroid Build Coastguard Worker int result = num;
914*6777b538SAndroid Build Coastguard Worker // Convert address.
915*6777b538SAndroid Build Coastguard Worker IPEndPoint address_storage;
916*6777b538SAndroid Build Coastguard Worker IPEndPoint* address_to_log = nullptr;
917*6777b538SAndroid Build Coastguard Worker if (result >= 0) {
918*6777b538SAndroid Build Coastguard Worker if (address_storage.FromSockAddr(core_->recv_addr_storage_.addr,
919*6777b538SAndroid Build Coastguard Worker core_->recv_addr_storage_.addr_len)) {
920*6777b538SAndroid Build Coastguard Worker if (address)
921*6777b538SAndroid Build Coastguard Worker *address = address_storage;
922*6777b538SAndroid Build Coastguard Worker address_to_log = &address_storage;
923*6777b538SAndroid Build Coastguard Worker } else {
924*6777b538SAndroid Build Coastguard Worker result = ERR_ADDRESS_INVALID;
925*6777b538SAndroid Build Coastguard Worker }
926*6777b538SAndroid Build Coastguard Worker }
927*6777b538SAndroid Build Coastguard Worker LogRead(result, buf->data(), address_to_log);
928*6777b538SAndroid Build Coastguard Worker return result;
929*6777b538SAndroid Build Coastguard Worker }
930*6777b538SAndroid Build Coastguard Worker } else {
931*6777b538SAndroid Build Coastguard Worker int os_error = WSAGetLastError();
932*6777b538SAndroid Build Coastguard Worker if (os_error != WSA_IO_PENDING) {
933*6777b538SAndroid Build Coastguard Worker int result = MapSystemError(os_error);
934*6777b538SAndroid Build Coastguard Worker LogRead(result, nullptr, nullptr);
935*6777b538SAndroid Build Coastguard Worker return result;
936*6777b538SAndroid Build Coastguard Worker }
937*6777b538SAndroid Build Coastguard Worker }
938*6777b538SAndroid Build Coastguard Worker core_->WatchForRead();
939*6777b538SAndroid Build Coastguard Worker core_->read_iobuffer_ = buf;
940*6777b538SAndroid Build Coastguard Worker core_->read_message_ = std::move(message);
941*6777b538SAndroid Build Coastguard Worker return ERR_IO_PENDING;
942*6777b538SAndroid Build Coastguard Worker }
943*6777b538SAndroid Build Coastguard Worker
InternalSendToOverlapped(IOBuffer * buf,int buf_len,const IPEndPoint * address)944*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::InternalSendToOverlapped(IOBuffer* buf,
945*6777b538SAndroid Build Coastguard Worker int buf_len,
946*6777b538SAndroid Build Coastguard Worker const IPEndPoint* address) {
947*6777b538SAndroid Build Coastguard Worker DCHECK(!core_->write_iobuffer_.get());
948*6777b538SAndroid Build Coastguard Worker SockaddrStorage storage;
949*6777b538SAndroid Build Coastguard Worker struct sockaddr* addr = storage.addr;
950*6777b538SAndroid Build Coastguard Worker // Convert address.
951*6777b538SAndroid Build Coastguard Worker if (!address) {
952*6777b538SAndroid Build Coastguard Worker addr = nullptr;
953*6777b538SAndroid Build Coastguard Worker storage.addr_len = 0;
954*6777b538SAndroid Build Coastguard Worker } else {
955*6777b538SAndroid Build Coastguard Worker if (!address->ToSockAddr(addr, &storage.addr_len)) {
956*6777b538SAndroid Build Coastguard Worker int result = ERR_ADDRESS_INVALID;
957*6777b538SAndroid Build Coastguard Worker LogWrite(result, nullptr, nullptr);
958*6777b538SAndroid Build Coastguard Worker return result;
959*6777b538SAndroid Build Coastguard Worker }
960*6777b538SAndroid Build Coastguard Worker }
961*6777b538SAndroid Build Coastguard Worker
962*6777b538SAndroid Build Coastguard Worker WSABUF write_buffer;
963*6777b538SAndroid Build Coastguard Worker write_buffer.buf = buf->data();
964*6777b538SAndroid Build Coastguard Worker write_buffer.len = buf_len;
965*6777b538SAndroid Build Coastguard Worker
966*6777b538SAndroid Build Coastguard Worker DWORD flags = 0;
967*6777b538SAndroid Build Coastguard Worker DWORD num;
968*6777b538SAndroid Build Coastguard Worker int rv;
969*6777b538SAndroid Build Coastguard Worker if (send_ecn_ != ECN_NOT_ECT) {
970*6777b538SAndroid Build Coastguard Worker WSABUF control_buffer;
971*6777b538SAndroid Build Coastguard Worker char raw_control_buffer[WSA_CMSG_SPACE(sizeof(int))];
972*6777b538SAndroid Build Coastguard Worker control_buffer.buf = raw_control_buffer;
973*6777b538SAndroid Build Coastguard Worker control_buffer.len = sizeof(raw_control_buffer);
974*6777b538SAndroid Build Coastguard Worker WSAMSG message;
975*6777b538SAndroid Build Coastguard Worker PopulateWSAMSG(message, storage, &write_buffer, control_buffer, true);
976*6777b538SAndroid Build Coastguard Worker rv = wsa_send_msg_(socket_, &message, flags, &num,
977*6777b538SAndroid Build Coastguard Worker &core_->write_overlapped_, nullptr);
978*6777b538SAndroid Build Coastguard Worker } else {
979*6777b538SAndroid Build Coastguard Worker rv = WSASendTo(socket_, &write_buffer, 1, &num, flags, addr,
980*6777b538SAndroid Build Coastguard Worker storage.addr_len, &core_->write_overlapped_, nullptr);
981*6777b538SAndroid Build Coastguard Worker }
982*6777b538SAndroid Build Coastguard Worker if (rv == 0) {
983*6777b538SAndroid Build Coastguard Worker if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
984*6777b538SAndroid Build Coastguard Worker int result = num;
985*6777b538SAndroid Build Coastguard Worker LogWrite(result, buf->data(), address);
986*6777b538SAndroid Build Coastguard Worker return result;
987*6777b538SAndroid Build Coastguard Worker }
988*6777b538SAndroid Build Coastguard Worker } else {
989*6777b538SAndroid Build Coastguard Worker int os_error = WSAGetLastError();
990*6777b538SAndroid Build Coastguard Worker if (os_error != WSA_IO_PENDING) {
991*6777b538SAndroid Build Coastguard Worker int result = MapSystemError(os_error);
992*6777b538SAndroid Build Coastguard Worker LogWrite(result, nullptr, nullptr);
993*6777b538SAndroid Build Coastguard Worker return result;
994*6777b538SAndroid Build Coastguard Worker }
995*6777b538SAndroid Build Coastguard Worker }
996*6777b538SAndroid Build Coastguard Worker
997*6777b538SAndroid Build Coastguard Worker core_->WatchForWrite();
998*6777b538SAndroid Build Coastguard Worker core_->write_iobuffer_ = buf;
999*6777b538SAndroid Build Coastguard Worker return ERR_IO_PENDING;
1000*6777b538SAndroid Build Coastguard Worker }
1001*6777b538SAndroid Build Coastguard Worker
InternalRecvFromNonBlocking(IOBuffer * buf,int buf_len,IPEndPoint * address)1002*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::InternalRecvFromNonBlocking(IOBuffer* buf,
1003*6777b538SAndroid Build Coastguard Worker int buf_len,
1004*6777b538SAndroid Build Coastguard Worker IPEndPoint* address) {
1005*6777b538SAndroid Build Coastguard Worker DCHECK(!read_iobuffer_ || read_iobuffer_.get() == buf);
1006*6777b538SAndroid Build Coastguard Worker SockaddrStorage storage;
1007*6777b538SAndroid Build Coastguard Worker storage.addr_len = sizeof(storage.addr_storage);
1008*6777b538SAndroid Build Coastguard Worker
1009*6777b538SAndroid Build Coastguard Worker CHECK_NE(INVALID_SOCKET, socket_);
1010*6777b538SAndroid Build Coastguard Worker
1011*6777b538SAndroid Build Coastguard Worker int rv;
1012*6777b538SAndroid Build Coastguard Worker if (report_ecn_) {
1013*6777b538SAndroid Build Coastguard Worker WSABUF read_buffer;
1014*6777b538SAndroid Build Coastguard Worker read_buffer.buf = buf->data();
1015*6777b538SAndroid Build Coastguard Worker read_buffer.len = buf_len;
1016*6777b538SAndroid Build Coastguard Worker WSABUF control_buffer;
1017*6777b538SAndroid Build Coastguard Worker char raw_control_buffer[WSA_CMSG_SPACE(sizeof(INT))];
1018*6777b538SAndroid Build Coastguard Worker control_buffer.buf = raw_control_buffer;
1019*6777b538SAndroid Build Coastguard Worker control_buffer.len = sizeof(raw_control_buffer);
1020*6777b538SAndroid Build Coastguard Worker WSAMSG message;
1021*6777b538SAndroid Build Coastguard Worker DWORD bytes_read;
1022*6777b538SAndroid Build Coastguard Worker PopulateWSAMSG(message, storage, &read_buffer, control_buffer, false);
1023*6777b538SAndroid Build Coastguard Worker rv = wsa_recv_msg_(socket_, &message, &bytes_read, nullptr, nullptr);
1024*6777b538SAndroid Build Coastguard Worker SetLastTosFromWSAMSG(message);
1025*6777b538SAndroid Build Coastguard Worker if (rv == 0) {
1026*6777b538SAndroid Build Coastguard Worker rv = bytes_read; // WSARecvMsg() returns zero on delivery, but recvfrom
1027*6777b538SAndroid Build Coastguard Worker // returns the number of bytes received.
1028*6777b538SAndroid Build Coastguard Worker }
1029*6777b538SAndroid Build Coastguard Worker } else {
1030*6777b538SAndroid Build Coastguard Worker rv = recvfrom(socket_, buf->data(), buf_len, 0, storage.addr,
1031*6777b538SAndroid Build Coastguard Worker &storage.addr_len);
1032*6777b538SAndroid Build Coastguard Worker }
1033*6777b538SAndroid Build Coastguard Worker if (rv == SOCKET_ERROR) {
1034*6777b538SAndroid Build Coastguard Worker int os_error = WSAGetLastError();
1035*6777b538SAndroid Build Coastguard Worker if (os_error == WSAEWOULDBLOCK) {
1036*6777b538SAndroid Build Coastguard Worker read_iobuffer_ = buf;
1037*6777b538SAndroid Build Coastguard Worker read_iobuffer_len_ = buf_len;
1038*6777b538SAndroid Build Coastguard Worker WatchForReadWrite();
1039*6777b538SAndroid Build Coastguard Worker return ERR_IO_PENDING;
1040*6777b538SAndroid Build Coastguard Worker }
1041*6777b538SAndroid Build Coastguard Worker rv = MapSystemError(os_error);
1042*6777b538SAndroid Build Coastguard Worker LogRead(rv, nullptr, nullptr);
1043*6777b538SAndroid Build Coastguard Worker return rv;
1044*6777b538SAndroid Build Coastguard Worker }
1045*6777b538SAndroid Build Coastguard Worker IPEndPoint address_storage;
1046*6777b538SAndroid Build Coastguard Worker IPEndPoint* address_to_log = nullptr;
1047*6777b538SAndroid Build Coastguard Worker if (rv >= 0) {
1048*6777b538SAndroid Build Coastguard Worker if (address_storage.FromSockAddr(storage.addr, storage.addr_len)) {
1049*6777b538SAndroid Build Coastguard Worker if (address)
1050*6777b538SAndroid Build Coastguard Worker *address = address_storage;
1051*6777b538SAndroid Build Coastguard Worker address_to_log = &address_storage;
1052*6777b538SAndroid Build Coastguard Worker } else {
1053*6777b538SAndroid Build Coastguard Worker rv = ERR_ADDRESS_INVALID;
1054*6777b538SAndroid Build Coastguard Worker }
1055*6777b538SAndroid Build Coastguard Worker }
1056*6777b538SAndroid Build Coastguard Worker LogRead(rv, buf->data(), address_to_log);
1057*6777b538SAndroid Build Coastguard Worker return rv;
1058*6777b538SAndroid Build Coastguard Worker }
1059*6777b538SAndroid Build Coastguard Worker
InternalSendToNonBlocking(IOBuffer * buf,int buf_len,const IPEndPoint * address)1060*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::InternalSendToNonBlocking(IOBuffer* buf,
1061*6777b538SAndroid Build Coastguard Worker int buf_len,
1062*6777b538SAndroid Build Coastguard Worker const IPEndPoint* address) {
1063*6777b538SAndroid Build Coastguard Worker DCHECK(!write_iobuffer_ || write_iobuffer_.get() == buf);
1064*6777b538SAndroid Build Coastguard Worker SockaddrStorage storage;
1065*6777b538SAndroid Build Coastguard Worker struct sockaddr* addr = storage.addr;
1066*6777b538SAndroid Build Coastguard Worker // Convert address.
1067*6777b538SAndroid Build Coastguard Worker if (address) {
1068*6777b538SAndroid Build Coastguard Worker if (!address->ToSockAddr(addr, &storage.addr_len)) {
1069*6777b538SAndroid Build Coastguard Worker int result = ERR_ADDRESS_INVALID;
1070*6777b538SAndroid Build Coastguard Worker LogWrite(result, nullptr, nullptr);
1071*6777b538SAndroid Build Coastguard Worker return result;
1072*6777b538SAndroid Build Coastguard Worker }
1073*6777b538SAndroid Build Coastguard Worker } else {
1074*6777b538SAndroid Build Coastguard Worker addr = nullptr;
1075*6777b538SAndroid Build Coastguard Worker storage.addr_len = 0;
1076*6777b538SAndroid Build Coastguard Worker }
1077*6777b538SAndroid Build Coastguard Worker
1078*6777b538SAndroid Build Coastguard Worker int rv;
1079*6777b538SAndroid Build Coastguard Worker if (send_ecn_ != ECN_NOT_ECT) {
1080*6777b538SAndroid Build Coastguard Worker char raw_control_buffer[WSA_CMSG_SPACE(sizeof(INT))];
1081*6777b538SAndroid Build Coastguard Worker WSABUF write_buffer;
1082*6777b538SAndroid Build Coastguard Worker write_buffer.buf = buf->data();
1083*6777b538SAndroid Build Coastguard Worker write_buffer.len = buf_len;
1084*6777b538SAndroid Build Coastguard Worker WSABUF control_buffer;
1085*6777b538SAndroid Build Coastguard Worker control_buffer.buf = raw_control_buffer;
1086*6777b538SAndroid Build Coastguard Worker control_buffer.len = sizeof(raw_control_buffer);
1087*6777b538SAndroid Build Coastguard Worker WSAMSG message;
1088*6777b538SAndroid Build Coastguard Worker DWORD bytes_read;
1089*6777b538SAndroid Build Coastguard Worker PopulateWSAMSG(message, storage, &write_buffer, control_buffer, true);
1090*6777b538SAndroid Build Coastguard Worker rv = wsa_send_msg_(socket_, &message, 0, &bytes_read, nullptr, nullptr);
1091*6777b538SAndroid Build Coastguard Worker if (rv == 0) {
1092*6777b538SAndroid Build Coastguard Worker rv = bytes_read;
1093*6777b538SAndroid Build Coastguard Worker }
1094*6777b538SAndroid Build Coastguard Worker } else {
1095*6777b538SAndroid Build Coastguard Worker rv = sendto(socket_, buf->data(), buf_len, 0, addr, storage.addr_len);
1096*6777b538SAndroid Build Coastguard Worker }
1097*6777b538SAndroid Build Coastguard Worker if (rv == SOCKET_ERROR) {
1098*6777b538SAndroid Build Coastguard Worker int os_error = WSAGetLastError();
1099*6777b538SAndroid Build Coastguard Worker if (os_error == WSAEWOULDBLOCK) {
1100*6777b538SAndroid Build Coastguard Worker write_iobuffer_ = buf;
1101*6777b538SAndroid Build Coastguard Worker write_iobuffer_len_ = buf_len;
1102*6777b538SAndroid Build Coastguard Worker WatchForReadWrite();
1103*6777b538SAndroid Build Coastguard Worker return ERR_IO_PENDING;
1104*6777b538SAndroid Build Coastguard Worker }
1105*6777b538SAndroid Build Coastguard Worker rv = MapSystemError(os_error);
1106*6777b538SAndroid Build Coastguard Worker LogWrite(rv, nullptr, nullptr);
1107*6777b538SAndroid Build Coastguard Worker return rv;
1108*6777b538SAndroid Build Coastguard Worker }
1109*6777b538SAndroid Build Coastguard Worker LogWrite(rv, buf->data(), address);
1110*6777b538SAndroid Build Coastguard Worker return rv;
1111*6777b538SAndroid Build Coastguard Worker }
1112*6777b538SAndroid Build Coastguard Worker
SetMulticastOptions()1113*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetMulticastOptions() {
1114*6777b538SAndroid Build Coastguard Worker if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
1115*6777b538SAndroid Build Coastguard Worker DWORD loop = 0;
1116*6777b538SAndroid Build Coastguard Worker int protocol_level =
1117*6777b538SAndroid Build Coastguard Worker addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
1118*6777b538SAndroid Build Coastguard Worker int option =
1119*6777b538SAndroid Build Coastguard Worker addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP;
1120*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, protocol_level, option,
1121*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&loop), sizeof(loop));
1122*6777b538SAndroid Build Coastguard Worker if (rv < 0)
1123*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
1124*6777b538SAndroid Build Coastguard Worker }
1125*6777b538SAndroid Build Coastguard Worker if (multicast_time_to_live_ != 1) {
1126*6777b538SAndroid Build Coastguard Worker DWORD hops = multicast_time_to_live_;
1127*6777b538SAndroid Build Coastguard Worker int protocol_level =
1128*6777b538SAndroid Build Coastguard Worker addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
1129*6777b538SAndroid Build Coastguard Worker int option =
1130*6777b538SAndroid Build Coastguard Worker addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS;
1131*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, protocol_level, option,
1132*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&hops), sizeof(hops));
1133*6777b538SAndroid Build Coastguard Worker if (rv < 0)
1134*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
1135*6777b538SAndroid Build Coastguard Worker }
1136*6777b538SAndroid Build Coastguard Worker if (multicast_interface_ != 0) {
1137*6777b538SAndroid Build Coastguard Worker switch (addr_family_) {
1138*6777b538SAndroid Build Coastguard Worker case AF_INET: {
1139*6777b538SAndroid Build Coastguard Worker in_addr address;
1140*6777b538SAndroid Build Coastguard Worker address.s_addr = htonl(multicast_interface_);
1141*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
1142*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&address),
1143*6777b538SAndroid Build Coastguard Worker sizeof(address));
1144*6777b538SAndroid Build Coastguard Worker if (rv)
1145*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
1146*6777b538SAndroid Build Coastguard Worker break;
1147*6777b538SAndroid Build Coastguard Worker }
1148*6777b538SAndroid Build Coastguard Worker case AF_INET6: {
1149*6777b538SAndroid Build Coastguard Worker uint32_t interface_index = multicast_interface_;
1150*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1151*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&interface_index),
1152*6777b538SAndroid Build Coastguard Worker sizeof(interface_index));
1153*6777b538SAndroid Build Coastguard Worker if (rv)
1154*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
1155*6777b538SAndroid Build Coastguard Worker break;
1156*6777b538SAndroid Build Coastguard Worker }
1157*6777b538SAndroid Build Coastguard Worker default:
1158*6777b538SAndroid Build Coastguard Worker NOTREACHED() << "Invalid address family";
1159*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
1160*6777b538SAndroid Build Coastguard Worker }
1161*6777b538SAndroid Build Coastguard Worker }
1162*6777b538SAndroid Build Coastguard Worker return OK;
1163*6777b538SAndroid Build Coastguard Worker }
1164*6777b538SAndroid Build Coastguard Worker
DoBind(const IPEndPoint & address)1165*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::DoBind(const IPEndPoint& address) {
1166*6777b538SAndroid Build Coastguard Worker SockaddrStorage storage;
1167*6777b538SAndroid Build Coastguard Worker if (!address.ToSockAddr(storage.addr, &storage.addr_len))
1168*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
1169*6777b538SAndroid Build Coastguard Worker int rv = bind(socket_, storage.addr, storage.addr_len);
1170*6777b538SAndroid Build Coastguard Worker if (rv == 0)
1171*6777b538SAndroid Build Coastguard Worker return OK;
1172*6777b538SAndroid Build Coastguard Worker int last_error = WSAGetLastError();
1173*6777b538SAndroid Build Coastguard Worker // Map some codes that are special to bind() separately.
1174*6777b538SAndroid Build Coastguard Worker // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
1175*6777b538SAndroid Build Coastguard Worker // returned instead of WSAEADDRINUSE, depending on whether the socket
1176*6777b538SAndroid Build Coastguard Worker // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
1177*6777b538SAndroid Build Coastguard Worker // conflicting socket is owned by a different user account. See the MSDN
1178*6777b538SAndroid Build Coastguard Worker // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
1179*6777b538SAndroid Build Coastguard Worker if (last_error == WSAEACCES || last_error == WSAEADDRNOTAVAIL)
1180*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_IN_USE;
1181*6777b538SAndroid Build Coastguard Worker return MapSystemError(last_error);
1182*6777b538SAndroid Build Coastguard Worker }
1183*6777b538SAndroid Build Coastguard Worker
GetQwaveApi() const1184*6777b538SAndroid Build Coastguard Worker QwaveApi* UDPSocketWin::GetQwaveApi() const {
1185*6777b538SAndroid Build Coastguard Worker return QwaveApi::GetDefault();
1186*6777b538SAndroid Build Coastguard Worker }
1187*6777b538SAndroid Build Coastguard Worker
JoinGroup(const IPAddress & group_address) const1188*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::JoinGroup(const IPAddress& group_address) const {
1189*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1190*6777b538SAndroid Build Coastguard Worker if (!is_connected())
1191*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_NOT_CONNECTED;
1192*6777b538SAndroid Build Coastguard Worker
1193*6777b538SAndroid Build Coastguard Worker switch (group_address.size()) {
1194*6777b538SAndroid Build Coastguard Worker case IPAddress::kIPv4AddressSize: {
1195*6777b538SAndroid Build Coastguard Worker if (addr_family_ != AF_INET)
1196*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
1197*6777b538SAndroid Build Coastguard Worker ip_mreq mreq;
1198*6777b538SAndroid Build Coastguard Worker mreq.imr_interface.s_addr = htonl(multicast_interface_);
1199*6777b538SAndroid Build Coastguard Worker memcpy(&mreq.imr_multiaddr, group_address.bytes().data(),
1200*6777b538SAndroid Build Coastguard Worker IPAddress::kIPv4AddressSize);
1201*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1202*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&mreq),
1203*6777b538SAndroid Build Coastguard Worker sizeof(mreq));
1204*6777b538SAndroid Build Coastguard Worker if (rv)
1205*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
1206*6777b538SAndroid Build Coastguard Worker return OK;
1207*6777b538SAndroid Build Coastguard Worker }
1208*6777b538SAndroid Build Coastguard Worker case IPAddress::kIPv6AddressSize: {
1209*6777b538SAndroid Build Coastguard Worker if (addr_family_ != AF_INET6)
1210*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
1211*6777b538SAndroid Build Coastguard Worker ipv6_mreq mreq;
1212*6777b538SAndroid Build Coastguard Worker mreq.ipv6mr_interface = multicast_interface_;
1213*6777b538SAndroid Build Coastguard Worker memcpy(&mreq.ipv6mr_multiaddr, group_address.bytes().data(),
1214*6777b538SAndroid Build Coastguard Worker IPAddress::kIPv6AddressSize);
1215*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
1216*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&mreq),
1217*6777b538SAndroid Build Coastguard Worker sizeof(mreq));
1218*6777b538SAndroid Build Coastguard Worker if (rv)
1219*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
1220*6777b538SAndroid Build Coastguard Worker return OK;
1221*6777b538SAndroid Build Coastguard Worker }
1222*6777b538SAndroid Build Coastguard Worker default:
1223*6777b538SAndroid Build Coastguard Worker NOTREACHED() << "Invalid address family";
1224*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
1225*6777b538SAndroid Build Coastguard Worker }
1226*6777b538SAndroid Build Coastguard Worker }
1227*6777b538SAndroid Build Coastguard Worker
LeaveGroup(const IPAddress & group_address) const1228*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::LeaveGroup(const IPAddress& group_address) const {
1229*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1230*6777b538SAndroid Build Coastguard Worker if (!is_connected())
1231*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_NOT_CONNECTED;
1232*6777b538SAndroid Build Coastguard Worker
1233*6777b538SAndroid Build Coastguard Worker switch (group_address.size()) {
1234*6777b538SAndroid Build Coastguard Worker case IPAddress::kIPv4AddressSize: {
1235*6777b538SAndroid Build Coastguard Worker if (addr_family_ != AF_INET)
1236*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
1237*6777b538SAndroid Build Coastguard Worker ip_mreq mreq;
1238*6777b538SAndroid Build Coastguard Worker mreq.imr_interface.s_addr = htonl(multicast_interface_);
1239*6777b538SAndroid Build Coastguard Worker memcpy(&mreq.imr_multiaddr, group_address.bytes().data(),
1240*6777b538SAndroid Build Coastguard Worker IPAddress::kIPv4AddressSize);
1241*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
1242*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&mreq), sizeof(mreq));
1243*6777b538SAndroid Build Coastguard Worker if (rv)
1244*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
1245*6777b538SAndroid Build Coastguard Worker return OK;
1246*6777b538SAndroid Build Coastguard Worker }
1247*6777b538SAndroid Build Coastguard Worker case IPAddress::kIPv6AddressSize: {
1248*6777b538SAndroid Build Coastguard Worker if (addr_family_ != AF_INET6)
1249*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
1250*6777b538SAndroid Build Coastguard Worker ipv6_mreq mreq;
1251*6777b538SAndroid Build Coastguard Worker mreq.ipv6mr_interface = multicast_interface_;
1252*6777b538SAndroid Build Coastguard Worker memcpy(&mreq.ipv6mr_multiaddr, group_address.bytes().data(),
1253*6777b538SAndroid Build Coastguard Worker IPAddress::kIPv6AddressSize);
1254*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
1255*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&mreq), sizeof(mreq));
1256*6777b538SAndroid Build Coastguard Worker if (rv)
1257*6777b538SAndroid Build Coastguard Worker return MapSystemError(WSAGetLastError());
1258*6777b538SAndroid Build Coastguard Worker return OK;
1259*6777b538SAndroid Build Coastguard Worker }
1260*6777b538SAndroid Build Coastguard Worker default:
1261*6777b538SAndroid Build Coastguard Worker NOTREACHED() << "Invalid address family";
1262*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
1263*6777b538SAndroid Build Coastguard Worker }
1264*6777b538SAndroid Build Coastguard Worker }
1265*6777b538SAndroid Build Coastguard Worker
SetMulticastInterface(uint32_t interface_index)1266*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetMulticastInterface(uint32_t interface_index) {
1267*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1268*6777b538SAndroid Build Coastguard Worker if (is_connected())
1269*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_IS_CONNECTED;
1270*6777b538SAndroid Build Coastguard Worker multicast_interface_ = interface_index;
1271*6777b538SAndroid Build Coastguard Worker return OK;
1272*6777b538SAndroid Build Coastguard Worker }
1273*6777b538SAndroid Build Coastguard Worker
SetMulticastTimeToLive(int time_to_live)1274*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) {
1275*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1276*6777b538SAndroid Build Coastguard Worker if (is_connected())
1277*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_IS_CONNECTED;
1278*6777b538SAndroid Build Coastguard Worker
1279*6777b538SAndroid Build Coastguard Worker if (time_to_live < 0 || time_to_live > 255)
1280*6777b538SAndroid Build Coastguard Worker return ERR_INVALID_ARGUMENT;
1281*6777b538SAndroid Build Coastguard Worker multicast_time_to_live_ = time_to_live;
1282*6777b538SAndroid Build Coastguard Worker return OK;
1283*6777b538SAndroid Build Coastguard Worker }
1284*6777b538SAndroid Build Coastguard Worker
SetMulticastLoopbackMode(bool loopback)1285*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
1286*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1287*6777b538SAndroid Build Coastguard Worker if (is_connected())
1288*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_IS_CONNECTED;
1289*6777b538SAndroid Build Coastguard Worker
1290*6777b538SAndroid Build Coastguard Worker if (loopback)
1291*6777b538SAndroid Build Coastguard Worker socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
1292*6777b538SAndroid Build Coastguard Worker else
1293*6777b538SAndroid Build Coastguard Worker socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
1294*6777b538SAndroid Build Coastguard Worker return OK;
1295*6777b538SAndroid Build Coastguard Worker }
1296*6777b538SAndroid Build Coastguard Worker
DscpToTrafficType(DiffServCodePoint dscp)1297*6777b538SAndroid Build Coastguard Worker QOS_TRAFFIC_TYPE DscpToTrafficType(DiffServCodePoint dscp) {
1298*6777b538SAndroid Build Coastguard Worker QOS_TRAFFIC_TYPE traffic_type = QOSTrafficTypeBestEffort;
1299*6777b538SAndroid Build Coastguard Worker switch (dscp) {
1300*6777b538SAndroid Build Coastguard Worker case DSCP_CS0:
1301*6777b538SAndroid Build Coastguard Worker traffic_type = QOSTrafficTypeBestEffort;
1302*6777b538SAndroid Build Coastguard Worker break;
1303*6777b538SAndroid Build Coastguard Worker case DSCP_CS1:
1304*6777b538SAndroid Build Coastguard Worker traffic_type = QOSTrafficTypeBackground;
1305*6777b538SAndroid Build Coastguard Worker break;
1306*6777b538SAndroid Build Coastguard Worker case DSCP_AF11:
1307*6777b538SAndroid Build Coastguard Worker case DSCP_AF12:
1308*6777b538SAndroid Build Coastguard Worker case DSCP_AF13:
1309*6777b538SAndroid Build Coastguard Worker case DSCP_CS2:
1310*6777b538SAndroid Build Coastguard Worker case DSCP_AF21:
1311*6777b538SAndroid Build Coastguard Worker case DSCP_AF22:
1312*6777b538SAndroid Build Coastguard Worker case DSCP_AF23:
1313*6777b538SAndroid Build Coastguard Worker case DSCP_CS3:
1314*6777b538SAndroid Build Coastguard Worker case DSCP_AF31:
1315*6777b538SAndroid Build Coastguard Worker case DSCP_AF32:
1316*6777b538SAndroid Build Coastguard Worker case DSCP_AF33:
1317*6777b538SAndroid Build Coastguard Worker case DSCP_CS4:
1318*6777b538SAndroid Build Coastguard Worker traffic_type = QOSTrafficTypeExcellentEffort;
1319*6777b538SAndroid Build Coastguard Worker break;
1320*6777b538SAndroid Build Coastguard Worker case DSCP_AF41:
1321*6777b538SAndroid Build Coastguard Worker case DSCP_AF42:
1322*6777b538SAndroid Build Coastguard Worker case DSCP_AF43:
1323*6777b538SAndroid Build Coastguard Worker case DSCP_CS5:
1324*6777b538SAndroid Build Coastguard Worker traffic_type = QOSTrafficTypeAudioVideo;
1325*6777b538SAndroid Build Coastguard Worker break;
1326*6777b538SAndroid Build Coastguard Worker case DSCP_EF:
1327*6777b538SAndroid Build Coastguard Worker case DSCP_CS6:
1328*6777b538SAndroid Build Coastguard Worker traffic_type = QOSTrafficTypeVoice;
1329*6777b538SAndroid Build Coastguard Worker break;
1330*6777b538SAndroid Build Coastguard Worker case DSCP_CS7:
1331*6777b538SAndroid Build Coastguard Worker traffic_type = QOSTrafficTypeControl;
1332*6777b538SAndroid Build Coastguard Worker break;
1333*6777b538SAndroid Build Coastguard Worker case DSCP_NO_CHANGE:
1334*6777b538SAndroid Build Coastguard Worker NOTREACHED();
1335*6777b538SAndroid Build Coastguard Worker break;
1336*6777b538SAndroid Build Coastguard Worker }
1337*6777b538SAndroid Build Coastguard Worker return traffic_type;
1338*6777b538SAndroid Build Coastguard Worker }
1339*6777b538SAndroid Build Coastguard Worker
SetDiffServCodePoint(DiffServCodePoint dscp)1340*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) {
1341*6777b538SAndroid Build Coastguard Worker return SetTos(dscp, ECN_NO_CHANGE);
1342*6777b538SAndroid Build Coastguard Worker }
1343*6777b538SAndroid Build Coastguard Worker
SetTos(DiffServCodePoint dscp,EcnCodePoint ecn)1344*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) {
1345*6777b538SAndroid Build Coastguard Worker if (!is_connected())
1346*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_NOT_CONNECTED;
1347*6777b538SAndroid Build Coastguard Worker
1348*6777b538SAndroid Build Coastguard Worker if (dscp != DSCP_NO_CHANGE) {
1349*6777b538SAndroid Build Coastguard Worker QwaveApi* api = GetQwaveApi();
1350*6777b538SAndroid Build Coastguard Worker
1351*6777b538SAndroid Build Coastguard Worker if (!api->qwave_supported()) {
1352*6777b538SAndroid Build Coastguard Worker return ERR_NOT_IMPLEMENTED;
1353*6777b538SAndroid Build Coastguard Worker }
1354*6777b538SAndroid Build Coastguard Worker
1355*6777b538SAndroid Build Coastguard Worker if (!dscp_manager_) {
1356*6777b538SAndroid Build Coastguard Worker dscp_manager_ = std::make_unique<DscpManager>(api, socket_);
1357*6777b538SAndroid Build Coastguard Worker }
1358*6777b538SAndroid Build Coastguard Worker
1359*6777b538SAndroid Build Coastguard Worker dscp_manager_->Set(dscp);
1360*6777b538SAndroid Build Coastguard Worker if (remote_address_) {
1361*6777b538SAndroid Build Coastguard Worker int rv = dscp_manager_->PrepareForSend(*remote_address_.get());
1362*6777b538SAndroid Build Coastguard Worker if (rv != OK) {
1363*6777b538SAndroid Build Coastguard Worker return rv;
1364*6777b538SAndroid Build Coastguard Worker }
1365*6777b538SAndroid Build Coastguard Worker }
1366*6777b538SAndroid Build Coastguard Worker }
1367*6777b538SAndroid Build Coastguard Worker if (ecn == ECN_NO_CHANGE) {
1368*6777b538SAndroid Build Coastguard Worker return OK;
1369*6777b538SAndroid Build Coastguard Worker }
1370*6777b538SAndroid Build Coastguard Worker if (wsa_send_msg_ == nullptr) {
1371*6777b538SAndroid Build Coastguard Worker wsa_send_msg_ = GetSendMsgPointer();
1372*6777b538SAndroid Build Coastguard Worker }
1373*6777b538SAndroid Build Coastguard Worker send_ecn_ = ecn;
1374*6777b538SAndroid Build Coastguard Worker return OK;
1375*6777b538SAndroid Build Coastguard Worker }
1376*6777b538SAndroid Build Coastguard Worker
SetIPv6Only(bool ipv6_only)1377*6777b538SAndroid Build Coastguard Worker int UDPSocketWin::SetIPv6Only(bool ipv6_only) {
1378*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1379*6777b538SAndroid Build Coastguard Worker if (is_connected()) {
1380*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_IS_CONNECTED;
1381*6777b538SAndroid Build Coastguard Worker }
1382*6777b538SAndroid Build Coastguard Worker return net::SetIPv6Only(socket_, ipv6_only);
1383*6777b538SAndroid Build Coastguard Worker }
1384*6777b538SAndroid Build Coastguard Worker
DetachFromThread()1385*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::DetachFromThread() {
1386*6777b538SAndroid Build Coastguard Worker DETACH_FROM_THREAD(thread_checker_);
1387*6777b538SAndroid Build Coastguard Worker }
1388*6777b538SAndroid Build Coastguard Worker
UseNonBlockingIO()1389*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::UseNonBlockingIO() {
1390*6777b538SAndroid Build Coastguard Worker DCHECK(!core_);
1391*6777b538SAndroid Build Coastguard Worker use_non_blocking_io_ = true;
1392*6777b538SAndroid Build Coastguard Worker }
1393*6777b538SAndroid Build Coastguard Worker
ApplySocketTag(const SocketTag & tag)1394*6777b538SAndroid Build Coastguard Worker void UDPSocketWin::ApplySocketTag(const SocketTag& tag) {
1395*6777b538SAndroid Build Coastguard Worker // Windows does not support any specific SocketTags so fail if any non-default
1396*6777b538SAndroid Build Coastguard Worker // tag is applied.
1397*6777b538SAndroid Build Coastguard Worker CHECK(tag == SocketTag());
1398*6777b538SAndroid Build Coastguard Worker }
1399*6777b538SAndroid Build Coastguard Worker
DscpManager(QwaveApi * api,SOCKET socket)1400*6777b538SAndroid Build Coastguard Worker DscpManager::DscpManager(QwaveApi* api, SOCKET socket)
1401*6777b538SAndroid Build Coastguard Worker : api_(api), socket_(socket) {
1402*6777b538SAndroid Build Coastguard Worker RequestHandle();
1403*6777b538SAndroid Build Coastguard Worker }
1404*6777b538SAndroid Build Coastguard Worker
~DscpManager()1405*6777b538SAndroid Build Coastguard Worker DscpManager::~DscpManager() {
1406*6777b538SAndroid Build Coastguard Worker if (!qos_handle_)
1407*6777b538SAndroid Build Coastguard Worker return;
1408*6777b538SAndroid Build Coastguard Worker
1409*6777b538SAndroid Build Coastguard Worker if (flow_id_ != 0)
1410*6777b538SAndroid Build Coastguard Worker api_->RemoveSocketFromFlow(qos_handle_, NULL, flow_id_, 0);
1411*6777b538SAndroid Build Coastguard Worker
1412*6777b538SAndroid Build Coastguard Worker api_->CloseHandle(qos_handle_);
1413*6777b538SAndroid Build Coastguard Worker }
1414*6777b538SAndroid Build Coastguard Worker
Set(DiffServCodePoint dscp)1415*6777b538SAndroid Build Coastguard Worker void DscpManager::Set(DiffServCodePoint dscp) {
1416*6777b538SAndroid Build Coastguard Worker if (dscp == DSCP_NO_CHANGE || dscp == dscp_value_)
1417*6777b538SAndroid Build Coastguard Worker return;
1418*6777b538SAndroid Build Coastguard Worker
1419*6777b538SAndroid Build Coastguard Worker dscp_value_ = dscp;
1420*6777b538SAndroid Build Coastguard Worker
1421*6777b538SAndroid Build Coastguard Worker // TODO(zstein): We could reuse the flow when the value changes
1422*6777b538SAndroid Build Coastguard Worker // by calling QOSSetFlow with the new traffic type and dscp value.
1423*6777b538SAndroid Build Coastguard Worker if (flow_id_ != 0 && qos_handle_) {
1424*6777b538SAndroid Build Coastguard Worker api_->RemoveSocketFromFlow(qos_handle_, NULL, flow_id_, 0);
1425*6777b538SAndroid Build Coastguard Worker configured_.clear();
1426*6777b538SAndroid Build Coastguard Worker flow_id_ = 0;
1427*6777b538SAndroid Build Coastguard Worker }
1428*6777b538SAndroid Build Coastguard Worker }
1429*6777b538SAndroid Build Coastguard Worker
PrepareForSend(const IPEndPoint & remote_address)1430*6777b538SAndroid Build Coastguard Worker int DscpManager::PrepareForSend(const IPEndPoint& remote_address) {
1431*6777b538SAndroid Build Coastguard Worker if (dscp_value_ == DSCP_NO_CHANGE) {
1432*6777b538SAndroid Build Coastguard Worker // No DSCP value has been set.
1433*6777b538SAndroid Build Coastguard Worker return OK;
1434*6777b538SAndroid Build Coastguard Worker }
1435*6777b538SAndroid Build Coastguard Worker
1436*6777b538SAndroid Build Coastguard Worker if (!api_->qwave_supported())
1437*6777b538SAndroid Build Coastguard Worker return ERR_NOT_IMPLEMENTED;
1438*6777b538SAndroid Build Coastguard Worker
1439*6777b538SAndroid Build Coastguard Worker if (!qos_handle_)
1440*6777b538SAndroid Build Coastguard Worker return ERR_INVALID_HANDLE; // The closest net error to try again later.
1441*6777b538SAndroid Build Coastguard Worker
1442*6777b538SAndroid Build Coastguard Worker if (configured_.find(remote_address) != configured_.end())
1443*6777b538SAndroid Build Coastguard Worker return OK;
1444*6777b538SAndroid Build Coastguard Worker
1445*6777b538SAndroid Build Coastguard Worker SockaddrStorage storage;
1446*6777b538SAndroid Build Coastguard Worker if (!remote_address.ToSockAddr(storage.addr, &storage.addr_len))
1447*6777b538SAndroid Build Coastguard Worker return ERR_ADDRESS_INVALID;
1448*6777b538SAndroid Build Coastguard Worker
1449*6777b538SAndroid Build Coastguard Worker // We won't try this address again if we get an error.
1450*6777b538SAndroid Build Coastguard Worker configured_.emplace(remote_address);
1451*6777b538SAndroid Build Coastguard Worker
1452*6777b538SAndroid Build Coastguard Worker // We don't need to call SetFlow if we already have a qos flow.
1453*6777b538SAndroid Build Coastguard Worker bool new_flow = flow_id_ == 0;
1454*6777b538SAndroid Build Coastguard Worker
1455*6777b538SAndroid Build Coastguard Worker const QOS_TRAFFIC_TYPE traffic_type = DscpToTrafficType(dscp_value_);
1456*6777b538SAndroid Build Coastguard Worker
1457*6777b538SAndroid Build Coastguard Worker if (!api_->AddSocketToFlow(qos_handle_, socket_, storage.addr, traffic_type,
1458*6777b538SAndroid Build Coastguard Worker QOS_NON_ADAPTIVE_FLOW, &flow_id_)) {
1459*6777b538SAndroid Build Coastguard Worker DWORD err = ::GetLastError();
1460*6777b538SAndroid Build Coastguard Worker if (err == ERROR_DEVICE_REINITIALIZATION_NEEDED) {
1461*6777b538SAndroid Build Coastguard Worker // Reset. PrepareForSend is called for every packet. Once RequestHandle
1462*6777b538SAndroid Build Coastguard Worker // completes asynchronously the next PrepareForSend call will re-register
1463*6777b538SAndroid Build Coastguard Worker // the address with the new QoS Handle. In the meantime, sends will
1464*6777b538SAndroid Build Coastguard Worker // continue without DSCP.
1465*6777b538SAndroid Build Coastguard Worker RequestHandle();
1466*6777b538SAndroid Build Coastguard Worker configured_.clear();
1467*6777b538SAndroid Build Coastguard Worker flow_id_ = 0;
1468*6777b538SAndroid Build Coastguard Worker return ERR_INVALID_HANDLE;
1469*6777b538SAndroid Build Coastguard Worker }
1470*6777b538SAndroid Build Coastguard Worker return MapSystemError(err);
1471*6777b538SAndroid Build Coastguard Worker }
1472*6777b538SAndroid Build Coastguard Worker
1473*6777b538SAndroid Build Coastguard Worker if (new_flow) {
1474*6777b538SAndroid Build Coastguard Worker DWORD buf = dscp_value_;
1475*6777b538SAndroid Build Coastguard Worker // This requires admin rights, and may fail, if so we ignore it
1476*6777b538SAndroid Build Coastguard Worker // as AddSocketToFlow should still do *approximately* the right thing.
1477*6777b538SAndroid Build Coastguard Worker api_->SetFlow(qos_handle_, flow_id_, QOSSetOutgoingDSCPValue, sizeof(buf),
1478*6777b538SAndroid Build Coastguard Worker &buf, 0, nullptr);
1479*6777b538SAndroid Build Coastguard Worker }
1480*6777b538SAndroid Build Coastguard Worker
1481*6777b538SAndroid Build Coastguard Worker return OK;
1482*6777b538SAndroid Build Coastguard Worker }
1483*6777b538SAndroid Build Coastguard Worker
RequestHandle()1484*6777b538SAndroid Build Coastguard Worker void DscpManager::RequestHandle() {
1485*6777b538SAndroid Build Coastguard Worker if (handle_is_initializing_)
1486*6777b538SAndroid Build Coastguard Worker return;
1487*6777b538SAndroid Build Coastguard Worker
1488*6777b538SAndroid Build Coastguard Worker if (qos_handle_) {
1489*6777b538SAndroid Build Coastguard Worker api_->CloseHandle(qos_handle_);
1490*6777b538SAndroid Build Coastguard Worker qos_handle_ = nullptr;
1491*6777b538SAndroid Build Coastguard Worker }
1492*6777b538SAndroid Build Coastguard Worker
1493*6777b538SAndroid Build Coastguard Worker handle_is_initializing_ = true;
1494*6777b538SAndroid Build Coastguard Worker base::ThreadPool::PostTaskAndReplyWithResult(
1495*6777b538SAndroid Build Coastguard Worker FROM_HERE, {base::MayBlock()},
1496*6777b538SAndroid Build Coastguard Worker base::BindOnce(&DscpManager::DoCreateHandle, api_),
1497*6777b538SAndroid Build Coastguard Worker base::BindOnce(&DscpManager::OnHandleCreated, api_,
1498*6777b538SAndroid Build Coastguard Worker weak_ptr_factory_.GetWeakPtr()));
1499*6777b538SAndroid Build Coastguard Worker }
1500*6777b538SAndroid Build Coastguard Worker
DoCreateHandle(QwaveApi * api)1501*6777b538SAndroid Build Coastguard Worker HANDLE DscpManager::DoCreateHandle(QwaveApi* api) {
1502*6777b538SAndroid Build Coastguard Worker QOS_VERSION version;
1503*6777b538SAndroid Build Coastguard Worker version.MajorVersion = 1;
1504*6777b538SAndroid Build Coastguard Worker version.MinorVersion = 0;
1505*6777b538SAndroid Build Coastguard Worker
1506*6777b538SAndroid Build Coastguard Worker HANDLE handle = nullptr;
1507*6777b538SAndroid Build Coastguard Worker
1508*6777b538SAndroid Build Coastguard Worker // No access to net_log_ so swallow any errors here.
1509*6777b538SAndroid Build Coastguard Worker api->CreateHandle(&version, &handle);
1510*6777b538SAndroid Build Coastguard Worker return handle;
1511*6777b538SAndroid Build Coastguard Worker }
1512*6777b538SAndroid Build Coastguard Worker
OnHandleCreated(QwaveApi * api,base::WeakPtr<DscpManager> dscp_manager,HANDLE handle)1513*6777b538SAndroid Build Coastguard Worker void DscpManager::OnHandleCreated(QwaveApi* api,
1514*6777b538SAndroid Build Coastguard Worker base::WeakPtr<DscpManager> dscp_manager,
1515*6777b538SAndroid Build Coastguard Worker HANDLE handle) {
1516*6777b538SAndroid Build Coastguard Worker if (!handle)
1517*6777b538SAndroid Build Coastguard Worker api->OnFatalError();
1518*6777b538SAndroid Build Coastguard Worker
1519*6777b538SAndroid Build Coastguard Worker if (!dscp_manager) {
1520*6777b538SAndroid Build Coastguard Worker api->CloseHandle(handle);
1521*6777b538SAndroid Build Coastguard Worker return;
1522*6777b538SAndroid Build Coastguard Worker }
1523*6777b538SAndroid Build Coastguard Worker
1524*6777b538SAndroid Build Coastguard Worker DCHECK(dscp_manager->handle_is_initializing_);
1525*6777b538SAndroid Build Coastguard Worker DCHECK(!dscp_manager->qos_handle_);
1526*6777b538SAndroid Build Coastguard Worker
1527*6777b538SAndroid Build Coastguard Worker dscp_manager->qos_handle_ = handle;
1528*6777b538SAndroid Build Coastguard Worker dscp_manager->handle_is_initializing_ = false;
1529*6777b538SAndroid Build Coastguard Worker }
1530*6777b538SAndroid Build Coastguard Worker
1531*6777b538SAndroid Build Coastguard Worker } // namespace net
1532