blob: 64b2dbd3ff9cd579ad9f2c464a9c9ecd36e2f10b [file] [log] [blame]
btolsch9ccfa782018-07-26 00:16:08 -07001// Copyright 2018 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
Jordan Baylesad2d2cd2019-05-22 14:49:40 -07005#ifndef PLATFORM_API_UDP_SOCKET_H_
6#define PLATFORM_API_UDP_SOCKET_H_
btolsch9ccfa782018-07-26 00:16:08 -07007
Yuri Wiitala10dea9f2019-02-04 20:19:17 -08008#include <cstdint>
Ryan Keanedeb48b32019-06-28 16:24:40 -07009#include <functional>
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080010#include <memory>
11
Yuri Wiitala82edd202018-10-31 18:42:58 -070012#include "platform/api/network_interface.h"
Max Yakimakha04362e22019-07-22 17:54:45 -070013#include "platform/api/udp_read_callback.h"
Jordan Baylesa26582d2019-07-10 14:44:58 -070014#include "platform/base/error.h"
15#include "platform/base/ip_address.h"
16#include "platform/base/macros.h"
btolsch9ccfa782018-07-26 00:16:08 -070017
18namespace openscreen {
19namespace platform {
20
Ryan Keanea4dfaa12019-08-19 10:30:20 -070021class TaskRunner;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080022class UdpSocket;
btolsch9ccfa782018-07-26 00:16:08 -070023
Ryan Keanedeb48b32019-06-28 16:24:40 -070024using UdpSocketUniquePtr = std::unique_ptr<UdpSocket>;
Yuri Wiitalab94f12e2018-10-31 18:28:53 -070025
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080026// An open UDP socket for sending/receiving datagrams to/from either specific
27// endpoints or over IP multicast.
28//
29// Usage: The socket is created and opened by calling the Create() method. This
30// returns a unique pointer that auto-closes/destroys the socket when it goes
31// out-of-scope.
32//
33// Platform implementation note: There must only be one platform-specific
34// implementation of UdpSocket linked into the library/application. For that
35// reason, none of the methods here are declared virtual (i.e., the overhead is
36// pure waste). However, UdpSocket can be subclassed to include all extra
37// private state, such as OS-specific handles. See UdpSocketPosix for a
38// reference implementation.
39class UdpSocket {
40 public:
Ryan Keanedeb48b32019-06-28 16:24:40 -070041 virtual ~UdpSocket();
42
Ryan Keanea4dfaa12019-08-19 10:30:20 -070043 // Client for the UdpSocket class.
44 class Client {
45 public:
46 virtual ~Client() = default;
47
48 // Method called on socket configuration operations when an error occurs.
49 // These specific APIs are:
50 // UdpSocket::Bind()
51 // UdpSocket::SetMulticastOutboundInterface(...)
52 // UdpSocket::JoinMulticastGroup(...)
53 // UdpSocket::SetDscp(...)
54 virtual void OnError(UdpSocket* socket, Error error) = 0;
55
56 // Method called when an error occurs during a SendMessage call.
57 virtual void OnSendError(UdpSocket* socket, Error error) = 0;
58
59 // Method called when a packet is read.
60 virtual void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) = 0;
61 };
62
Ryan Keane8f1c9252019-05-06 11:03:38 -070063 // Constants used to specify how we want packets sent from this socket.
64 enum class DscpMode : uint8_t {
65 // Default value set by the system on creation of a new socket.
66 kUnspecified = 0x0,
67
68 // Mode for Audio only.
69 kAudioOnly = 0xb8,
70
71 // Mode for Audio + Video.
72 kAudioVideo = 0x88,
73
74 // Mode for low priority operations such as trace log data.
75 kLowPriority = 0x20
76 };
77
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080078 using Version = IPAddress::Version;
btolsch9ccfa782018-07-26 00:16:08 -070079
Yuri Wiitalade01e532019-08-06 18:12:02 -070080 // Creates a new, scoped UdpSocket within the IPv4 or IPv6 family.
81 // |local_endpoint| may be zero (see comments for Bind()). This method must be
Ryan Keanea4dfaa12019-08-19 10:30:20 -070082 // defined in the platform-level implementation. All client_ methods called
83 // will be queued on the provided task_runner. For this reason, the provided
84 // task_runner and client must exist for the duration of the created socket's
85 // lifetime.
86 static ErrorOr<UdpSocketUniquePtr> Create(TaskRunner* task_runner,
87 Client* client,
88 const IPEndpoint& local_endpoint);
btolsch9ccfa782018-07-26 00:16:08 -070089
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080090 // Returns true if |socket| belongs to the IPv4/IPv6 address family.
Ryan Keanedeb48b32019-06-28 16:24:40 -070091 virtual bool IsIPv4() const = 0;
92 virtual bool IsIPv6() const = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080093
Yuri Wiitalade01e532019-08-06 18:12:02 -070094 // Returns the current local endpoint's address and port. Initially, this will
95 // be the same as the value that was passed into Create(). However, it can
96 // later change after certain operations, such as Bind(), are executed.
97 virtual IPEndpoint GetLocalEndpoint() const = 0;
98
99 // Binds to the address specified in the constructor. If the local endpoint's
100 // address is zero, the operating system will bind to all interfaces. If the
101 // local endpoint's port is zero, the operating system will automatically find
102 // a free local port and bind to it. Future calls to local_endpoint() will
103 // reflect the resolved port.
Jordan Bayles5c473922019-07-26 12:44:15 -0700104 virtual Error Bind() = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800105
106 // Sets the device to use for outgoing multicast packets on the socket.
Ryan Keanedeb48b32019-06-28 16:24:40 -0700107 virtual Error SetMulticastOutboundInterface(
108 NetworkInterfaceIndex ifindex) = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800109
110 // Joins to the multicast group at the given address, using the specified
111 // interface.
Ryan Keanedeb48b32019-06-28 16:24:40 -0700112 virtual Error JoinMulticastGroup(const IPAddress& address,
113 NetworkInterfaceIndex ifindex) = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800114
115 // Performs a non-blocking read on the socket, returning the number of bytes
116 // received. Note that a non-Error return value of 0 is a valid result,
117 // indicating an empty message has been received. Also note that
118 // Error::Code::kAgain might be returned if there is no message currently
Max Yakimakha04362e22019-07-22 17:54:45 -0700119 // ready for receive, which can be expected during normal operation.
120 virtual ErrorOr<UdpPacket> ReceiveMessage() = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800121
122 // Sends a message and returns the number of bytes sent, on success.
123 // Error::Code::kAgain might be returned to indicate the operation would
124 // block, which can be expected during normal operation.
Ryan Keanedeb48b32019-06-28 16:24:40 -0700125 virtual Error SendMessage(const void* data,
126 size_t length,
127 const IPEndpoint& dest) = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800128
Ryan Keane8f1c9252019-05-06 11:03:38 -0700129 // Sets the DSCP value to use for all messages sent from this socket.
Ryan Keanedeb48b32019-06-28 16:24:40 -0700130 virtual Error SetDscp(DscpMode state) = 0;
131
132 // Sets the callback that should be called upon deletion of this socket. This
133 // allows other objects to observe the socket's destructor and act when it is
134 // called.
135 void SetDeletionCallback(std::function<void(UdpSocket*)> callback);
Ryan Keane8f1c9252019-05-06 11:03:38 -0700136
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800137 protected:
Ryan Keanea4dfaa12019-08-19 10:30:20 -0700138 // Creates a new UdpSocket. The provided client and task_runner must exist for
139 // the duration of this socket's lifetime.
140 UdpSocket(TaskRunner* task_runner, Client* client);
141
Ryan Keane63fbedd2019-08-19 12:33:41 -0700142 // Methods to take care of posting UdpSocket::Client callbacks for client_ to
143 // task_runner_.
144 void OnError(Error error);
145 void OnSendError(Error error);
146 void OnRead(ErrorOr<UdpPacket> read_data);
147
148 private:
149 // This callback allows other objects to observe the socket's destructor and
150 // act when it is called.
151 std::function<void(UdpSocket*)> deletion_callback_;
152
Ryan Keanea4dfaa12019-08-19 10:30:20 -0700153 // Client to use for callbacks.
154 // NOTE: client_ can be nullptr if the user does not want any callbacks (for
155 // example, in the send-only case).
156 Client* const client_;
157
158 // Task runner to use for queuing client_ callbacks.
159 TaskRunner* const task_runner_;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800160
Jordan Baylesf1e4bb72019-05-01 12:38:39 -0700161 OSP_DISALLOW_COPY_AND_ASSIGN(UdpSocket);
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800162};
btolsch9ccfa782018-07-26 00:16:08 -0700163
164} // namespace platform
165} // namespace openscreen
166
Jordan Baylesad2d2cd2019-05-22 14:49:40 -0700167#endif // PLATFORM_API_UDP_SOCKET_H_