1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/socket/udp_client_socket.h"
6 
7 #include "build/build_config.h"
8 #include "net/base/net_errors.h"
9 #include "net/traffic_annotation/network_traffic_annotation.h"
10 
11 namespace net {
12 
UDPClientSocket(DatagramSocket::BindType bind_type,net::NetLog * net_log,const net::NetLogSource & source)13 UDPClientSocket::UDPClientSocket(DatagramSocket::BindType bind_type,
14                                  net::NetLog* net_log,
15                                  const net::NetLogSource& source)
16     : socket_(bind_type, net_log, source),
17       network_(NetworkChangeNotifier::kInvalidNetworkHandle) {}
18 
19 UDPClientSocket::~UDPClientSocket() = default;
20 
Connect(const IPEndPoint & address)21 int UDPClientSocket::Connect(const IPEndPoint& address) {
22   int rv = socket_.Open(address.GetFamily());
23   if (rv != OK)
24     return rv;
25   return socket_.Connect(address);
26 }
27 
ConnectUsingNetwork(NetworkChangeNotifier::NetworkHandle network,const IPEndPoint & address)28 int UDPClientSocket::ConnectUsingNetwork(
29     NetworkChangeNotifier::NetworkHandle network,
30     const IPEndPoint& address) {
31   if (!NetworkChangeNotifier::AreNetworkHandlesSupported())
32     return ERR_NOT_IMPLEMENTED;
33   int rv = socket_.Open(address.GetFamily());
34   if (rv != OK)
35     return rv;
36   rv = socket_.BindToNetwork(network);
37   if (rv != OK)
38     return rv;
39   network_ = network;
40   return socket_.Connect(address);
41 }
42 
ConnectUsingDefaultNetwork(const IPEndPoint & address)43 int UDPClientSocket::ConnectUsingDefaultNetwork(const IPEndPoint& address) {
44   if (!NetworkChangeNotifier::AreNetworkHandlesSupported())
45     return ERR_NOT_IMPLEMENTED;
46   int rv;
47   rv = socket_.Open(address.GetFamily());
48   if (rv != OK)
49     return rv;
50   // Calling connect() will bind a socket to the default network, however there
51   // is no way to determine what network the socket got bound to.  The
52   // alternative is to query what the default network is and bind the socket to
53   // that network explicitly, however this is racy because the default network
54   // can change in between when we query it and when we bind to it.  This is
55   // rare but should be accounted for.  Since changes of the default network
56   // should not come in quick succession, we can simply try again.
57   NetworkChangeNotifier::NetworkHandle network;
58   for (int attempt = 0; attempt < 2; attempt++) {
59     network = NetworkChangeNotifier::GetDefaultNetwork();
60     if (network == NetworkChangeNotifier::kInvalidNetworkHandle)
61       return ERR_INTERNET_DISCONNECTED;
62     rv = socket_.BindToNetwork(network);
63     // |network| may have disconnected between the call to GetDefaultNetwork()
64     // and the call to BindToNetwork(). Loop only if this is the case (|rv| will
65     // be ERR_NETWORK_CHANGED).
66     if (rv != ERR_NETWORK_CHANGED)
67       break;
68   }
69   if (rv != OK)
70     return rv;
71   network_ = network;
72   return socket_.Connect(address);
73 }
74 
GetBoundNetwork() const75 NetworkChangeNotifier::NetworkHandle UDPClientSocket::GetBoundNetwork() const {
76   return network_;
77 }
78 
ApplySocketTag(const SocketTag & tag)79 void UDPClientSocket::ApplySocketTag(const SocketTag& tag) {
80   socket_.ApplySocketTag(tag);
81 }
82 
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)83 int UDPClientSocket::Read(IOBuffer* buf,
84                           int buf_len,
85                           CompletionOnceCallback callback) {
86   return socket_.Read(buf, buf_len, std::move(callback));
87 }
88 
Write(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)89 int UDPClientSocket::Write(
90     IOBuffer* buf,
91     int buf_len,
92     CompletionOnceCallback callback,
93     const NetworkTrafficAnnotationTag& traffic_annotation) {
94   return socket_.Write(buf, buf_len, std::move(callback), traffic_annotation);
95 }
96 
WriteAsync(const char * buffer,size_t buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)97 int UDPClientSocket::WriteAsync(
98     const char* buffer,
99     size_t buf_len,
100     CompletionOnceCallback callback,
101     const NetworkTrafficAnnotationTag& traffic_annotation) {
102   DCHECK(WriteAsyncEnabled());
103   return socket_.WriteAsync(buffer, buf_len, std::move(callback),
104                             traffic_annotation);
105 }
106 
WriteAsync(DatagramBuffers buffers,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)107 int UDPClientSocket::WriteAsync(
108     DatagramBuffers buffers,
109     CompletionOnceCallback callback,
110     const NetworkTrafficAnnotationTag& traffic_annotation) {
111   DCHECK(WriteAsyncEnabled());
112   return socket_.WriteAsync(std::move(buffers), std::move(callback),
113                             traffic_annotation);
114 }
115 
GetUnwrittenBuffers()116 DatagramBuffers UDPClientSocket::GetUnwrittenBuffers() {
117   return socket_.GetUnwrittenBuffers();
118 }
119 
Close()120 void UDPClientSocket::Close() {
121   socket_.Close();
122 }
123 
GetPeerAddress(IPEndPoint * address) const124 int UDPClientSocket::GetPeerAddress(IPEndPoint* address) const {
125   return socket_.GetPeerAddress(address);
126 }
127 
GetLocalAddress(IPEndPoint * address) const128 int UDPClientSocket::GetLocalAddress(IPEndPoint* address) const {
129   return socket_.GetLocalAddress(address);
130 }
131 
SetReceiveBufferSize(int32_t size)132 int UDPClientSocket::SetReceiveBufferSize(int32_t size) {
133   return socket_.SetReceiveBufferSize(size);
134 }
135 
SetSendBufferSize(int32_t size)136 int UDPClientSocket::SetSendBufferSize(int32_t size) {
137   return socket_.SetSendBufferSize(size);
138 }
139 
SetDoNotFragment()140 int UDPClientSocket::SetDoNotFragment() {
141   return socket_.SetDoNotFragment();
142 }
143 
SetMsgConfirm(bool confirm)144 void UDPClientSocket::SetMsgConfirm(bool confirm) {
145   socket_.SetMsgConfirm(confirm);
146 }
147 
NetLog() const148 const NetLogWithSource& UDPClientSocket::NetLog() const {
149   return socket_.NetLog();
150 }
151 
UseNonBlockingIO()152 void UDPClientSocket::UseNonBlockingIO() {
153 #if defined(OS_WIN)
154   socket_.UseNonBlockingIO();
155 #endif
156 }
157 
SetWriteAsyncEnabled(bool enabled)158 void UDPClientSocket::SetWriteAsyncEnabled(bool enabled) {
159   socket_.SetWriteAsyncEnabled(enabled);
160 }
161 
SetMaxPacketSize(size_t max_packet_size)162 void UDPClientSocket::SetMaxPacketSize(size_t max_packet_size) {
163   socket_.SetMaxPacketSize(max_packet_size);
164 }
165 
WriteAsyncEnabled()166 bool UDPClientSocket::WriteAsyncEnabled() {
167   return socket_.WriteAsyncEnabled();
168 }
169 
SetWriteMultiCoreEnabled(bool enabled)170 void UDPClientSocket::SetWriteMultiCoreEnabled(bool enabled) {
171   socket_.SetWriteMultiCoreEnabled(enabled);
172 }
173 
SetSendmmsgEnabled(bool enabled)174 void UDPClientSocket::SetSendmmsgEnabled(bool enabled) {
175   socket_.SetSendmmsgEnabled(enabled);
176 }
177 
SetWriteBatchingActive(bool active)178 void UDPClientSocket::SetWriteBatchingActive(bool active) {
179   socket_.SetWriteBatchingActive(active);
180 }
181 
SetMulticastInterface(uint32_t interface_index)182 int UDPClientSocket::SetMulticastInterface(uint32_t interface_index) {
183   return socket_.SetMulticastInterface(interface_index);
184 }
185 
EnableRecvOptimization()186 void UDPClientSocket::EnableRecvOptimization() {
187 #if defined(OS_POSIX)
188   socket_.enable_experimental_recv_optimization();
189 #endif
190 }
191 
192 }  // namespace net
193