xref: /aosp_15_r20/external/openscreen/cast/streaming/environment.h (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #ifndef CAST_STREAMING_ENVIRONMENT_H_
6*3f982cf4SFabien Sanglard #define CAST_STREAMING_ENVIRONMENT_H_
7*3f982cf4SFabien Sanglard 
8*3f982cf4SFabien Sanglard #include <stdint.h>
9*3f982cf4SFabien Sanglard 
10*3f982cf4SFabien Sanglard #include <functional>
11*3f982cf4SFabien Sanglard #include <memory>
12*3f982cf4SFabien Sanglard #include <vector>
13*3f982cf4SFabien Sanglard 
14*3f982cf4SFabien Sanglard #include "absl/types/span.h"
15*3f982cf4SFabien Sanglard #include "platform/api/time.h"
16*3f982cf4SFabien Sanglard #include "platform/api/udp_socket.h"
17*3f982cf4SFabien Sanglard #include "platform/base/ip_address.h"
18*3f982cf4SFabien Sanglard 
19*3f982cf4SFabien Sanglard namespace openscreen {
20*3f982cf4SFabien Sanglard namespace cast {
21*3f982cf4SFabien Sanglard 
22*3f982cf4SFabien Sanglard // Provides the common environment for operating system resources shared by
23*3f982cf4SFabien Sanglard // multiple components.
24*3f982cf4SFabien Sanglard class Environment : public UdpSocket::Client {
25*3f982cf4SFabien Sanglard  public:
26*3f982cf4SFabien Sanglard   class PacketConsumer {
27*3f982cf4SFabien Sanglard    public:
28*3f982cf4SFabien Sanglard     virtual void OnReceivedPacket(const IPEndpoint& source,
29*3f982cf4SFabien Sanglard                                   Clock::time_point arrival_time,
30*3f982cf4SFabien Sanglard                                   std::vector<uint8_t> packet) = 0;
31*3f982cf4SFabien Sanglard 
32*3f982cf4SFabien Sanglard    protected:
33*3f982cf4SFabien Sanglard     virtual ~PacketConsumer();
34*3f982cf4SFabien Sanglard   };
35*3f982cf4SFabien Sanglard 
36*3f982cf4SFabien Sanglard   // Consumers of the environment's UDP socket should be careful to check the
37*3f982cf4SFabien Sanglard   // socket's state before accessing its methods, especially
38*3f982cf4SFabien Sanglard   // GetBoundLocalEndpoint(). If the environment is |kStarting|, the
39*3f982cf4SFabien Sanglard   // local endpoint may not be set yet and will be zero initialized.
40*3f982cf4SFabien Sanglard   enum class SocketState {
41*3f982cf4SFabien Sanglard     // Socket is still initializing. Usually the UDP socket bind is
42*3f982cf4SFabien Sanglard     // the last piece.
43*3f982cf4SFabien Sanglard     kStarting,
44*3f982cf4SFabien Sanglard 
45*3f982cf4SFabien Sanglard     // The socket is ready for use and has been bound.
46*3f982cf4SFabien Sanglard     kReady,
47*3f982cf4SFabien Sanglard 
48*3f982cf4SFabien Sanglard     // The socket is either closed (normally or due to an error) or in an
49*3f982cf4SFabien Sanglard     // invalid state. Currently the environment does not create a new socket
50*3f982cf4SFabien Sanglard     // in this case, so to be used again the environment itself needs to be
51*3f982cf4SFabien Sanglard     // recreated.
52*3f982cf4SFabien Sanglard     kInvalid
53*3f982cf4SFabien Sanglard   };
54*3f982cf4SFabien Sanglard 
55*3f982cf4SFabien Sanglard   // Classes concerned with the Environment's UDP socket state may inherit from
56*3f982cf4SFabien Sanglard   // |Subscriber| and then |Subscribe|.
57*3f982cf4SFabien Sanglard   class SocketSubscriber {
58*3f982cf4SFabien Sanglard    public:
59*3f982cf4SFabien Sanglard     // Event that occurs when the environment is ready for use.
60*3f982cf4SFabien Sanglard     virtual void OnSocketReady() = 0;
61*3f982cf4SFabien Sanglard 
62*3f982cf4SFabien Sanglard     // Event that occurs when the environment has experienced a fatal error.
63*3f982cf4SFabien Sanglard     virtual void OnSocketInvalid(Error error) = 0;
64*3f982cf4SFabien Sanglard   };
65*3f982cf4SFabien Sanglard 
66*3f982cf4SFabien Sanglard   // Construct with the given clock source and TaskRunner. Creates and
67*3f982cf4SFabien Sanglard   // internally-owns a UdpSocket, and immediately binds it to the given
68*3f982cf4SFabien Sanglard   // |local_endpoint|. If embedders do not care what interface/address the UDP
69*3f982cf4SFabien Sanglard   // socket is bound on, they may omit that argument.
70*3f982cf4SFabien Sanglard   Environment(ClockNowFunctionPtr now_function,
71*3f982cf4SFabien Sanglard               TaskRunner* task_runner,
72*3f982cf4SFabien Sanglard               const IPEndpoint& local_endpoint = IPEndpoint::kAnyV6());
73*3f982cf4SFabien Sanglard 
74*3f982cf4SFabien Sanglard   ~Environment() override;
75*3f982cf4SFabien Sanglard 
now_function()76*3f982cf4SFabien Sanglard   ClockNowFunctionPtr now_function() const { return now_function_; }
now()77*3f982cf4SFabien Sanglard   Clock::time_point now() const { return now_function_(); }
task_runner()78*3f982cf4SFabien Sanglard   TaskRunner* task_runner() const { return task_runner_; }
79*3f982cf4SFabien Sanglard 
80*3f982cf4SFabien Sanglard   // Returns the local endpoint the socket is bound to, or the zero IPEndpoint
81*3f982cf4SFabien Sanglard   // if socket creation/binding failed.
82*3f982cf4SFabien Sanglard   //
83*3f982cf4SFabien Sanglard   // Note: This method is virtual to allow unit tests to fake that there really
84*3f982cf4SFabien Sanglard   // is a bound socket.
85*3f982cf4SFabien Sanglard   virtual IPEndpoint GetBoundLocalEndpoint() const;
86*3f982cf4SFabien Sanglard 
87*3f982cf4SFabien Sanglard   // Get/Set the remote endpoint. This is separate from the constructor because
88*3f982cf4SFabien Sanglard   // the remote endpoint is, in some cases, discovered only after receiving a
89*3f982cf4SFabien Sanglard   // packet.
remote_endpoint()90*3f982cf4SFabien Sanglard   const IPEndpoint& remote_endpoint() const { return remote_endpoint_; }
set_remote_endpoint(const IPEndpoint & endpoint)91*3f982cf4SFabien Sanglard   void set_remote_endpoint(const IPEndpoint& endpoint) {
92*3f982cf4SFabien Sanglard     remote_endpoint_ = endpoint;
93*3f982cf4SFabien Sanglard   }
94*3f982cf4SFabien Sanglard 
95*3f982cf4SFabien Sanglard   // Returns the current state of the UDP socket. This method is virtual
96*3f982cf4SFabien Sanglard   // to allow tests to simulate socket state.
socket_state()97*3f982cf4SFabien Sanglard   SocketState socket_state() const { return state_; }
set_socket_state_for_testing(SocketState state)98*3f982cf4SFabien Sanglard   void set_socket_state_for_testing(SocketState state) { state_ = state; }
99*3f982cf4SFabien Sanglard 
100*3f982cf4SFabien Sanglard   // Subscribe to socket changes. Callers can unsubscribe by passing
101*3f982cf4SFabien Sanglard   // nullptr.
102*3f982cf4SFabien Sanglard   void SetSocketSubscriber(SocketSubscriber* subscriber);
103*3f982cf4SFabien Sanglard 
104*3f982cf4SFabien Sanglard   // Start/Resume delivery of incoming packets to the given |packet_consumer|.
105*3f982cf4SFabien Sanglard   // Delivery will continue until DropIncomingPackets() is called.
106*3f982cf4SFabien Sanglard   void ConsumeIncomingPackets(PacketConsumer* packet_consumer);
107*3f982cf4SFabien Sanglard 
108*3f982cf4SFabien Sanglard   // Stop delivery of incoming packets, dropping any that do come in. All
109*3f982cf4SFabien Sanglard   // internal references to the PacketConsumer that was provided in the last
110*3f982cf4SFabien Sanglard   // call to ConsumeIncomingPackets() are cleared.
111*3f982cf4SFabien Sanglard   void DropIncomingPackets();
112*3f982cf4SFabien Sanglard 
113*3f982cf4SFabien Sanglard   // Returns the maximum packet size for the network. This will always return a
114*3f982cf4SFabien Sanglard   // value of at least kRequiredNetworkPacketSize.
115*3f982cf4SFabien Sanglard   int GetMaxPacketSize() const;
116*3f982cf4SFabien Sanglard 
117*3f982cf4SFabien Sanglard   // Sends the given |packet| to the remote endpoint, best-effort.
118*3f982cf4SFabien Sanglard   // set_remote_endpoint() must be called beforehand with a valid IPEndpoint.
119*3f982cf4SFabien Sanglard   //
120*3f982cf4SFabien Sanglard   // Note: This method is virtual to allow unit tests to intercept packets
121*3f982cf4SFabien Sanglard   // before they actually head-out through the socket.
122*3f982cf4SFabien Sanglard   virtual void SendPacket(absl::Span<const uint8_t> packet);
123*3f982cf4SFabien Sanglard 
124*3f982cf4SFabien Sanglard  protected:
Environment()125*3f982cf4SFabien Sanglard   Environment() : now_function_(nullptr), task_runner_(nullptr) {}
126*3f982cf4SFabien Sanglard 
127*3f982cf4SFabien Sanglard   // Protected so that they can be set by the MockEnvironment for testing.
128*3f982cf4SFabien Sanglard   ClockNowFunctionPtr now_function_;
129*3f982cf4SFabien Sanglard   TaskRunner* task_runner_;
130*3f982cf4SFabien Sanglard 
131*3f982cf4SFabien Sanglard  private:
132*3f982cf4SFabien Sanglard   // UdpSocket::Client implementation.
133*3f982cf4SFabien Sanglard   void OnBound(UdpSocket* socket) final;
134*3f982cf4SFabien Sanglard   void OnError(UdpSocket* socket, Error error) final;
135*3f982cf4SFabien Sanglard   void OnSendError(UdpSocket* socket, Error error) final;
136*3f982cf4SFabien Sanglard   void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet_or_error) final;
137*3f982cf4SFabien Sanglard 
138*3f982cf4SFabien Sanglard   // The UDP socket bound to the local endpoint that was passed into the
139*3f982cf4SFabien Sanglard   // constructor, or null if socket creation failed.
140*3f982cf4SFabien Sanglard   const std::unique_ptr<UdpSocket> socket_;
141*3f982cf4SFabien Sanglard 
142*3f982cf4SFabien Sanglard   // These are externally set/cleared. Behaviors are described in getter/setter
143*3f982cf4SFabien Sanglard   // method comments above.
144*3f982cf4SFabien Sanglard   IPEndpoint local_endpoint_{};
145*3f982cf4SFabien Sanglard   IPEndpoint remote_endpoint_{};
146*3f982cf4SFabien Sanglard   PacketConsumer* packet_consumer_ = nullptr;
147*3f982cf4SFabien Sanglard   SocketState state_ = SocketState::kStarting;
148*3f982cf4SFabien Sanglard   SocketSubscriber* socket_subscriber_ = nullptr;
149*3f982cf4SFabien Sanglard };
150*3f982cf4SFabien Sanglard 
151*3f982cf4SFabien Sanglard }  // namespace cast
152*3f982cf4SFabien Sanglard }  // namespace openscreen
153*3f982cf4SFabien Sanglard 
154*3f982cf4SFabien Sanglard #endif  // CAST_STREAMING_ENVIRONMENT_H_
155