|  | // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "net/socket/udp_client_socket.h" | 
|  |  | 
|  | #include "build/build_config.h" | 
|  | #include "net/base/net_errors.h" | 
|  | #include "net/traffic_annotation/network_traffic_annotation.h" | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | UDPClientSocket::UDPClientSocket(DatagramSocket::BindType bind_type, | 
|  | net::NetLog* net_log, | 
|  | const net::NetLogSource& source) | 
|  | : socket_(bind_type, net_log, source), | 
|  | network_(NetworkChangeNotifier::kInvalidNetworkHandle) {} | 
|  |  | 
|  | UDPClientSocket::~UDPClientSocket() = default; | 
|  |  | 
|  | int UDPClientSocket::Connect(const IPEndPoint& address) { | 
|  | int rv = socket_.Open(address.GetFamily()); | 
|  | if (rv != OK) | 
|  | return rv; | 
|  | return socket_.Connect(address); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::ConnectUsingNetwork( | 
|  | NetworkChangeNotifier::NetworkHandle network, | 
|  | const IPEndPoint& address) { | 
|  | if (!NetworkChangeNotifier::AreNetworkHandlesSupported()) | 
|  | return ERR_NOT_IMPLEMENTED; | 
|  | int rv = socket_.Open(address.GetFamily()); | 
|  | if (rv != OK) | 
|  | return rv; | 
|  | rv = socket_.BindToNetwork(network); | 
|  | if (rv != OK) | 
|  | return rv; | 
|  | network_ = network; | 
|  | return socket_.Connect(address); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::ConnectUsingDefaultNetwork(const IPEndPoint& address) { | 
|  | if (!NetworkChangeNotifier::AreNetworkHandlesSupported()) | 
|  | return ERR_NOT_IMPLEMENTED; | 
|  | int rv; | 
|  | rv = socket_.Open(address.GetFamily()); | 
|  | if (rv != OK) | 
|  | return rv; | 
|  | // Calling connect() will bind a socket to the default network, however there | 
|  | // is no way to determine what network the socket got bound to.  The | 
|  | // alternative is to query what the default network is and bind the socket to | 
|  | // that network explicitly, however this is racy because the default network | 
|  | // can change in between when we query it and when we bind to it.  This is | 
|  | // rare but should be accounted for.  Since changes of the default network | 
|  | // should not come in quick succession, we can simply try again. | 
|  | NetworkChangeNotifier::NetworkHandle network; | 
|  | for (int attempt = 0; attempt < 2; attempt++) { | 
|  | network = NetworkChangeNotifier::GetDefaultNetwork(); | 
|  | if (network == NetworkChangeNotifier::kInvalidNetworkHandle) | 
|  | return ERR_INTERNET_DISCONNECTED; | 
|  | rv = socket_.BindToNetwork(network); | 
|  | // |network| may have disconnected between the call to GetDefaultNetwork() | 
|  | // and the call to BindToNetwork(). Loop only if this is the case (|rv| will | 
|  | // be ERR_NETWORK_CHANGED). | 
|  | if (rv != ERR_NETWORK_CHANGED) | 
|  | break; | 
|  | } | 
|  | if (rv != OK) | 
|  | return rv; | 
|  | network_ = network; | 
|  | return socket_.Connect(address); | 
|  | } | 
|  |  | 
|  | NetworkChangeNotifier::NetworkHandle UDPClientSocket::GetBoundNetwork() const { | 
|  | return network_; | 
|  | } | 
|  |  | 
|  | void UDPClientSocket::ApplySocketTag(const SocketTag& tag) { | 
|  | socket_.ApplySocketTag(tag); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::Read(IOBuffer* buf, | 
|  | int buf_len, | 
|  | CompletionOnceCallback callback) { | 
|  | return socket_.Read(buf, buf_len, std::move(callback)); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::Write( | 
|  | IOBuffer* buf, | 
|  | int buf_len, | 
|  | CompletionOnceCallback callback, | 
|  | const NetworkTrafficAnnotationTag& traffic_annotation) { | 
|  | return socket_.Write(buf, buf_len, std::move(callback), traffic_annotation); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::WriteAsync( | 
|  | const char* buffer, | 
|  | size_t buf_len, | 
|  | CompletionOnceCallback callback, | 
|  | const NetworkTrafficAnnotationTag& traffic_annotation) { | 
|  | DCHECK(WriteAsyncEnabled()); | 
|  | return socket_.WriteAsync(buffer, buf_len, std::move(callback), | 
|  | traffic_annotation); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::WriteAsync( | 
|  | DatagramBuffers buffers, | 
|  | CompletionOnceCallback callback, | 
|  | const NetworkTrafficAnnotationTag& traffic_annotation) { | 
|  | DCHECK(WriteAsyncEnabled()); | 
|  | return socket_.WriteAsync(std::move(buffers), std::move(callback), | 
|  | traffic_annotation); | 
|  | } | 
|  |  | 
|  | DatagramBuffers UDPClientSocket::GetUnwrittenBuffers() { | 
|  | return socket_.GetUnwrittenBuffers(); | 
|  | } | 
|  |  | 
|  | void UDPClientSocket::Close() { | 
|  | socket_.Close(); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::GetPeerAddress(IPEndPoint* address) const { | 
|  | return socket_.GetPeerAddress(address); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::GetLocalAddress(IPEndPoint* address) const { | 
|  | return socket_.GetLocalAddress(address); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::SetReceiveBufferSize(int32_t size) { | 
|  | return socket_.SetReceiveBufferSize(size); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::SetSendBufferSize(int32_t size) { | 
|  | return socket_.SetSendBufferSize(size); | 
|  | } | 
|  |  | 
|  | int UDPClientSocket::SetDoNotFragment() { | 
|  | return socket_.SetDoNotFragment(); | 
|  | } | 
|  |  | 
|  | void UDPClientSocket::SetMsgConfirm(bool confirm) { | 
|  | socket_.SetMsgConfirm(confirm); | 
|  | } | 
|  |  | 
|  | const NetLogWithSource& UDPClientSocket::NetLog() const { | 
|  | return socket_.NetLog(); | 
|  | } | 
|  |  | 
|  | void UDPClientSocket::UseNonBlockingIO() { | 
|  | #if defined(OS_WIN) | 
|  | socket_.UseNonBlockingIO(); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void UDPClientSocket::SetWriteAsyncEnabled(bool enabled) { | 
|  | socket_.SetWriteAsyncEnabled(enabled); | 
|  | } | 
|  |  | 
|  | void UDPClientSocket::SetMaxPacketSize(size_t max_packet_size) { | 
|  | socket_.SetMaxPacketSize(max_packet_size); | 
|  | } | 
|  |  | 
|  | bool UDPClientSocket::WriteAsyncEnabled() { | 
|  | return socket_.WriteAsyncEnabled(); | 
|  | } | 
|  |  | 
|  | void UDPClientSocket::SetWriteMultiCoreEnabled(bool enabled) { | 
|  | socket_.SetWriteMultiCoreEnabled(enabled); | 
|  | } | 
|  |  | 
|  | void UDPClientSocket::SetSendmmsgEnabled(bool enabled) { | 
|  | #if defined(STARBOARD) | 
|  | NOTIMPLEMENTED() << "Cobalt does not implement sendmmsg related functions!"; | 
|  | #else | 
|  | socket_.SetSendmmsgEnabled(enabled); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void UDPClientSocket::SetWriteBatchingActive(bool active) { | 
|  | socket_.SetWriteBatchingActive(active); | 
|  | } | 
|  |  | 
|  | void UDPClientSocket::EnableRecvOptimization() { | 
|  | #if defined(OS_POSIX) | 
|  | socket_.enable_experimental_recv_optimization(); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | }  // namespace net |