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