| // 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 |