xref: /aosp_15_r20/external/cronet/net/socket/udp_socket_win.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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