blob: f08520230c122e4ca7a37610f12ea9734cf7de05 [file] [log] [blame]
// Copyright 2018 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.
#ifndef SERVICES_NETWORK_UDP_SOCKET_H_
#define SERVICES_NETWORK_UDP_SOCKET_H_
#include <deque>
#include <memory>
#include <vector>
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "net/base/address_family.h"
#include "net/base/completion_once_callback.h"
#include "net/base/ip_endpoint.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/mojom/address_family.mojom.h"
#include "services/network/public/mojom/ip_endpoint.mojom.h"
#include "services/network/public/mojom/udp_socket.mojom.h"
namespace net {
class IOBuffer;
class IOBufferWithSize;
class NetLog;
} // namespace net
namespace network {
class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket {
public:
// Number of Send()/SendTo() requests that are queued internally. Public for
// testing.
static const uint32_t kMaxPendingSendRequests = 32;
// A socket wrapper class that allows tests to substitute the default
// implementation (implemented using net::UDPSocket) with a test
// implementation.
class SocketWrapper {
public:
virtual ~SocketWrapper() {}
// This wrapper class forwards the functions to a concrete udp socket
// implementation. Please refer to udp_socket_posix.h/udp_socket_win.h for
// definitions.
virtual int Connect(const net::IPEndPoint& remote_addr,
mojom::UDPSocketOptionsPtr options,
net::IPEndPoint* local_addr_out) = 0;
virtual int Bind(const net::IPEndPoint& local_addr,
mojom::UDPSocketOptionsPtr options,
net::IPEndPoint* local_addr_out) = 0;
virtual int SendTo(
net::IOBuffer* buf,
int buf_len,
const net::IPEndPoint& dest_addr,
net::CompletionOnceCallback callback,
const net::NetworkTrafficAnnotationTag& traffic_annotation) = 0;
virtual int Write(
net::IOBuffer* buf,
int buf_len,
net::CompletionOnceCallback callback,
const net::NetworkTrafficAnnotationTag& traffic_annotation) = 0;
virtual int SetBroadcast(bool broadcast) = 0;
virtual int SetSendBufferSize(int send_buffer_size) = 0;
virtual int SetReceiveBufferSize(int receive_buffer_size) = 0;
virtual int JoinGroup(const net::IPAddress& group_address) = 0;
virtual int LeaveGroup(const net::IPAddress& group_address) = 0;
virtual int RecvFrom(net::IOBuffer* buf,
int buf_len,
net::IPEndPoint* address,
net::CompletionOnceCallback callback) = 0;
};
UDPSocket(mojom::UDPSocketReceiverPtr receiver, net::NetLog* net_log);
~UDPSocket() override;
// UDPSocket implementation.
void Connect(const net::IPEndPoint& remote_addr,
mojom::UDPSocketOptionsPtr options,
ConnectCallback callback) override;
void Bind(const net::IPEndPoint& local_addr,
mojom::UDPSocketOptionsPtr options,
BindCallback callback) override;
void SetBroadcast(bool broadcast, SetBroadcastCallback callback) override;
void SetSendBufferSize(int32_t send_buffer_size,
SetSendBufferSizeCallback callback) override;
void SetReceiveBufferSize(int32_t receive_buffer_size,
SetSendBufferSizeCallback callback) override;
void JoinGroup(const net::IPAddress& group_address,
JoinGroupCallback callback) override;
void LeaveGroup(const net::IPAddress& group_address,
LeaveGroupCallback callback) override;
void ReceiveMore(uint32_t num_additional_datagrams) override;
void ReceiveMoreWithBufferSize(uint32_t num_additional_datagrams,
uint32_t buffer_size) override;
void SendTo(const net::IPEndPoint& dest_addr,
base::span<const uint8_t> data,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
SendToCallback callback) override;
void Send(base::span<const uint8_t> data,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
SendCallback callback) override;
void Close() override;
private:
friend class UDPSocketTest;
// Represents a pending Send()/SendTo() request that is yet to be sent to the
// |socket_|. In the case of Send(), |addr| will be not filled in.
struct PendingSendRequest {
PendingSendRequest();
~PendingSendRequest();
std::unique_ptr<net::IPEndPoint> addr;
net::MutableNetworkTrafficAnnotationTag traffic_annotation;
scoped_refptr<net::IOBufferWithSize> data;
SendToCallback callback;
};
// Helper method to create a new SocketWrapper.
std::unique_ptr<UDPSocket::SocketWrapper> CreateSocketWrapper() const;
// Returns whether a successful Connect() or Bind() has been executed.
bool IsConnectedOrBound() const;
void DoRecvFrom(uint32_t buffer_size);
void DoSendToOrWrite(
const net::IPEndPoint* dest_addr,
const base::span<const uint8_t>& data,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
SendToCallback callback);
void DoSendToOrWriteBuffer(
const net::IPEndPoint* dest_addr,
scoped_refptr<net::IOBufferWithSize> buffer,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
SendToCallback callback);
void OnRecvFromCompleted(uint32_t buffer_size, int net_result);
void OnSendToCompleted(int net_result);
net::NetLog* net_log_;
// Whether a Bind() has been successfully executed.
bool is_bound_;
// Whether a Connect() has been successfully executed.
bool is_connected_;
// The interface which gets data from fulfilled receive requests.
mojom::UDPSocketReceiverPtr receiver_;
std::unique_ptr<SocketWrapper> wrapped_socket_;
// Non-null when there is a pending RecvFrom operation on socket.
scoped_refptr<net::IOBuffer> recvfrom_buffer_;
// Non-null when there is a pending Send/SendTo operation on socket.
scoped_refptr<net::IOBufferWithSize> send_buffer_;
SendToCallback send_callback_;
// The address of the sender of a received packet. This address might not be
// filled if an error occurred during the receiving of the packet.
net::IPEndPoint recvfrom_address_;
// How many more packets the client side expects to receive.
uint32_t remaining_recv_slots_;
// The queue owns the PendingSendRequest instances.
base::circular_deque<std::unique_ptr<PendingSendRequest>>
pending_send_requests_;
DISALLOW_COPY_AND_ASSIGN(UDPSocket);
};
} // namespace network
#endif // SERVICES_NETWORK_UDP_SOCKET_H_