blob: f5d462af7bf9922b6f773779bce0240234ba704f [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
Ryan Keane83050af2019-08-26 08:58:09 -07008#include <atomic>
Yuri Wiitala10dea9f2019-02-04 20:19:17 -08009#include <cstdint>
Ryan Keanedeb48b32019-06-28 16:24:40 -070010#include <functional>
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080011#include <memory>
Ryan Keane9222e042019-08-27 10:44:13 -070012#include <mutex>
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080013
Yuri Wiitala82edd202018-10-31 18:42:58 -070014#include "platform/api/network_interface.h"
Ryan Keane230920e2019-08-29 13:21:40 -070015#include "platform/api/udp_packet.h"
Jordan Baylesa26582d2019-07-10 14:44:58 -070016#include "platform/base/error.h"
17#include "platform/base/ip_address.h"
18#include "platform/base/macros.h"
btolsch9ccfa782018-07-26 00:16:08 -070019
20namespace openscreen {
21namespace platform {
22
Ryan Keanea4dfaa12019-08-19 10:30:20 -070023class TaskRunner;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080024class UdpSocket;
btolsch9ccfa782018-07-26 00:16:08 -070025
Ryan Keanedeb48b32019-06-28 16:24:40 -070026using UdpSocketUniquePtr = std::unique_ptr<UdpSocket>;
Yuri Wiitalab94f12e2018-10-31 18:28:53 -070027
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080028// An open UDP socket for sending/receiving datagrams to/from either specific
29// endpoints or over IP multicast.
30//
31// Usage: The socket is created and opened by calling the Create() method. This
32// returns a unique pointer that auto-closes/destroys the socket when it goes
33// out-of-scope.
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080034class UdpSocket {
35 public:
Ryan Keanea4dfaa12019-08-19 10:30:20 -070036 // Client for the UdpSocket class.
37 class Client {
38 public:
39 virtual ~Client() = default;
40
41 // Method called on socket configuration operations when an error occurs.
42 // These specific APIs are:
43 // UdpSocket::Bind()
44 // UdpSocket::SetMulticastOutboundInterface(...)
45 // UdpSocket::JoinMulticastGroup(...)
46 // UdpSocket::SetDscp(...)
47 virtual void OnError(UdpSocket* socket, Error error) = 0;
48
49 // Method called when an error occurs during a SendMessage call.
50 virtual void OnSendError(UdpSocket* socket, Error error) = 0;
51
52 // Method called when a packet is read.
53 virtual void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) = 0;
54 };
55
Ryan Keane8f1c9252019-05-06 11:03:38 -070056 // Constants used to specify how we want packets sent from this socket.
57 enum class DscpMode : uint8_t {
58 // Default value set by the system on creation of a new socket.
59 kUnspecified = 0x0,
60
61 // Mode for Audio only.
62 kAudioOnly = 0xb8,
63
64 // Mode for Audio + Video.
65 kAudioVideo = 0x88,
66
67 // Mode for low priority operations such as trace log data.
68 kLowPriority = 0x20
69 };
70
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080071 using Version = IPAddress::Version;
btolsch9ccfa782018-07-26 00:16:08 -070072
Yuri Wiitalade01e532019-08-06 18:12:02 -070073 // Creates a new, scoped UdpSocket within the IPv4 or IPv6 family.
74 // |local_endpoint| may be zero (see comments for Bind()). This method must be
Yuri Wiitalad697dfc2019-10-23 16:00:16 -070075 // defined in the platform-level implementation. All |client| methods called
76 // will be queued on the provided |task_runner|. For this reason, the provided
77 // TaskRunner and Client must exist for the duration of the created socket's
Ryan Keanea4dfaa12019-08-19 10:30:20 -070078 // lifetime.
79 static ErrorOr<UdpSocketUniquePtr> Create(TaskRunner* task_runner,
80 Client* client,
81 const IPEndpoint& local_endpoint);
btolsch9ccfa782018-07-26 00:16:08 -070082
Yuri Wiitalad697dfc2019-10-23 16:00:16 -070083 virtual ~UdpSocket();
84
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080085 // Returns true if |socket| belongs to the IPv4/IPv6 address family.
Ryan Keanedeb48b32019-06-28 16:24:40 -070086 virtual bool IsIPv4() const = 0;
87 virtual bool IsIPv6() const = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -080088
Yuri Wiitalade01e532019-08-06 18:12:02 -070089 // Returns the current local endpoint's address and port. Initially, this will
90 // be the same as the value that was passed into Create(). However, it can
91 // later change after certain operations, such as Bind(), are executed.
92 virtual IPEndpoint GetLocalEndpoint() const = 0;
93
94 // Binds to the address specified in the constructor. If the local endpoint's
95 // address is zero, the operating system will bind to all interfaces. If the
96 // local endpoint's port is zero, the operating system will automatically find
Yuri Wiitalad697dfc2019-10-23 16:00:16 -070097 // a free local port and bind to it. Future calls to GetLocalEndpoint() will
Yuri Wiitalade01e532019-08-06 18:12:02 -070098 // reflect the resolved port.
Ryan Keane83e68322019-08-23 14:54:38 -070099 virtual void Bind() = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800100
101 // Sets the device to use for outgoing multicast packets on the socket.
Ryan Keane7e74bdd2019-08-27 08:15:21 -0700102 virtual void SetMulticastOutboundInterface(NetworkInterfaceIndex ifindex) = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800103
104 // Joins to the multicast group at the given address, using the specified
105 // interface.
Ryan Keane7e74bdd2019-08-27 08:15:21 -0700106 virtual void JoinMulticastGroup(const IPAddress& address,
107 NetworkInterfaceIndex ifindex) = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800108
Yuri Wiitalad697dfc2019-10-23 16:00:16 -0700109 // Sends a message. If the message is not sent, Client::OnSendError() will be
110 // called to indicate this. Error::Code::kAgain indicates the operation would
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800111 // block, which can be expected during normal operation.
Ryan Keane71cacc22019-08-21 13:01:47 -0700112 virtual void SendMessage(const void* data,
113 size_t length,
114 const IPEndpoint& dest) = 0;
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800115
Ryan Keane8f1c9252019-05-06 11:03:38 -0700116 // Sets the DSCP value to use for all messages sent from this socket.
Ryan Keane7e74bdd2019-08-27 08:15:21 -0700117 virtual void SetDscp(DscpMode state) = 0;
Ryan Keanedeb48b32019-06-28 16:24:40 -0700118
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800119 protected:
Yuri Wiitalad697dfc2019-10-23 16:00:16 -0700120 UdpSocket();
Ryan Keane83050af2019-08-26 08:58:09 -0700121
Ryan Keane63fbedd2019-08-19 12:33:41 -0700122 private:
Jordan Baylesf1e4bb72019-05-01 12:38:39 -0700123 OSP_DISALLOW_COPY_AND_ASSIGN(UdpSocket);
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800124};
btolsch9ccfa782018-07-26 00:16:08 -0700125
126} // namespace platform
127} // namespace openscreen
128
Jordan Baylesad2d2cd2019-05-22 14:49:40 -0700129#endif // PLATFORM_API_UDP_SOCKET_H_