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