1 // Copyright 2020 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 5 #ifndef CAST_STANDALONE_SENDER_LOOPING_FILE_CAST_AGENT_H_ 6 #define CAST_STANDALONE_SENDER_LOOPING_FILE_CAST_AGENT_H_ 7 8 #include <openssl/x509.h> 9 10 #include <functional> 11 #include <memory> 12 #include <string> 13 #include <vector> 14 15 #include "absl/types/optional.h" 16 #include "cast/common/channel/cast_message_handler.h" 17 #include "cast/common/channel/cast_socket_message_port.h" 18 #include "cast/common/channel/connection_namespace_handler.h" 19 #include "cast/common/channel/virtual_connection_router.h" 20 #include "cast/common/public/cast_socket.h" 21 #include "cast/sender/public/sender_socket_factory.h" 22 #include "cast/standalone_sender/connection_settings.h" 23 #include "cast/standalone_sender/looping_file_sender.h" 24 #include "cast/standalone_sender/remoting_sender.h" 25 #include "cast/streaming/environment.h" 26 #include "cast/streaming/sender_session.h" 27 #include "platform/api/scoped_wake_lock.h" 28 #include "platform/api/serial_delete_ptr.h" 29 #include "platform/base/error.h" 30 #include "platform/base/interface_info.h" 31 #include "platform/impl/task_runner.h" 32 33 namespace Json { 34 class Value; 35 } 36 37 namespace openscreen { 38 namespace cast { 39 40 // A single-use sender-side Cast Agent that manages the workflow for a mirroring 41 // session, casting the content from a local file indefinitely. After being 42 // constructed and having its Connect() method called, the LoopingFileCastAgent 43 // steps through the following workflow: 44 // 45 // 1. Waits for a CastSocket representing a successful connection to a remote 46 // Cast Receiver's agent. 47 // 2. Sends a LAUNCH request to the Cast Receiver to start its Mirroring App. 48 // 3. Waits for a RECEIVER_STATUS message from the Receiver indicating launch 49 // success, or a LAUNCH_ERROR. 50 // 4. Once launched, message routing (i.e., a VirtualConnection) is requested, 51 // for messaging between the SenderSession (locally) and the remote 52 // Mirroring App. 53 // 5. Once message routing is established, the local SenderSession is created 54 // and begins the mirroring-specific OFFER/ANSWER messaging to negotiate 55 // the streaming parameters. 56 // 6. Streaming commences. 57 // 58 // If at any point an error occurs, the LoopingFileCastAgent executes a clean 59 // shut-down (both locally, and with the remote Cast Receiver), and then invokes 60 // the ShutdownCallback that was passed to the constructor. 61 // 62 // Normal shutdown happens when either: 63 // 64 // 1. Receiver-side, the Mirroring App is shut down. This will cause the 65 // ShutdownCallback passed to the constructor to be invoked. 66 // 2. This LoopingFileCastAgent is destroyed (automatic shutdown is part of 67 // the destruction procedure). 68 class LoopingFileCastAgent final 69 : public SenderSocketFactory::Client, 70 public VirtualConnectionRouter::SocketErrorHandler, 71 public ConnectionNamespaceHandler::VirtualConnectionPolicy, 72 public CastMessageHandler, 73 public SenderSession::Client, 74 public RemotingSender::Client { 75 public: 76 using ShutdownCallback = std::function<void()>; 77 78 // |shutdown_callback| is invoked after normal shutdown, whether initiated 79 // sender- or receiver-side; or, for any fatal error. 80 LoopingFileCastAgent(TaskRunner* task_runner, 81 ShutdownCallback shutdown_callback); 82 ~LoopingFileCastAgent(); 83 84 // Connect to a Cast Receiver, and start the workflow to establish a 85 // mirroring/streaming session. Destroy the LoopingFileCastAgent to shutdown 86 // and disconnect. 87 void Connect(ConnectionSettings settings); 88 89 private: 90 // SenderSocketFactory::Client overrides. 91 void OnConnected(SenderSocketFactory* factory, 92 const IPEndpoint& endpoint, 93 std::unique_ptr<CastSocket> socket) override; 94 void OnError(SenderSocketFactory* factory, 95 const IPEndpoint& endpoint, 96 Error error) override; 97 98 // VirtualConnectionRouter::SocketErrorHandler overrides. 99 void OnClose(CastSocket* cast_socket) override; 100 void OnError(CastSocket* socket, Error error) override; 101 102 // ConnectionNamespaceHandler::VirtualConnectionPolicy overrides. 103 bool IsConnectionAllowed( 104 const VirtualConnection& virtual_conn) const override; 105 106 // CastMessageHandler overrides. 107 void OnMessage(VirtualConnectionRouter* router, 108 CastSocket* socket, 109 ::cast::channel::CastMessage message) override; 110 111 // RemotingSender::Client overrides. 112 void OnReady() override; 113 void OnPlaybackRateChange(double rate) override; 114 115 // Returns the Cast application ID for either A/V mirroring or audio-only 116 // mirroring, as configured by the ConnectionSettings. 117 const char* GetMirroringAppId() const; 118 119 // Called by OnMessage() to determine whether the Cast Receiver has launched 120 // or unlaunched the Mirroring App. If the former, a VirtualConnection is 121 // requested. Otherwise, the workflow is aborted and Shutdown() is called. 122 void HandleReceiverStatus(const Json::Value& status); 123 124 // Called by the |connection_handler_| after message routing to the Cast 125 // Receiver's Mirroring App has been established (if |success| is true). 126 void OnRemoteMessagingOpened(bool success); 127 128 // Once we have a connection to the receiver we need to create and start 129 // a sender session. This method results in the OFFER/ANSWER exchange 130 // being completed and a session should be started. 131 void CreateAndStartSession(); 132 133 // SenderSession::Client overrides. 134 void OnNegotiated(const SenderSession* session, 135 SenderSession::ConfiguredSenders senders, 136 capture_recommendations::Recommendations 137 capture_recommendations) override; 138 void OnRemotingNegotiated( 139 const SenderSession* session, 140 SenderSession::RemotingNegotiation negotiation) override; 141 void OnError(const SenderSession* session, Error error) override; 142 143 // Starts the remoting sender. This may occur when remoting is "ready" if the 144 // session is already negotiated, or upon session negotiation if the receiver 145 // is already ready. 146 void StartRemotingSenders(); 147 148 // Helper for stopping the current session, and/or unwinding a remote 149 // connection request (pre-session). This ensures LoopingFileCastAgent is in a 150 // terminal shutdown state. 151 void Shutdown(); 152 153 // Member variables set as part of construction. 154 TaskRunner* const task_runner_; 155 ShutdownCallback shutdown_callback_; 156 VirtualConnectionRouter router_; 157 ConnectionNamespaceHandler connection_handler_; 158 SenderSocketFactory socket_factory_; 159 std::unique_ptr<TlsConnectionFactory> connection_factory_; 160 CastSocketMessagePort message_port_; 161 162 // Counter for distinguishing request messages sent to the Cast Receiver. 163 int next_request_id_ = 1; 164 165 // Initialized by Connect(). 166 absl::optional<ConnectionSettings> connection_settings_; 167 SerialDeletePtr<ScopedWakeLock> wake_lock_; 168 169 // If non-empty, this is the sessionId associated with the Cast Receiver 170 // application that this LoopingFileCastAgent launched. 171 std::string app_session_id_; 172 173 // This is set once LoopingFileCastAgent has requested to start messaging to 174 // the mirroring app on a Cast Receiver. 175 absl::optional<VirtualConnection> remote_connection_; 176 177 // Member variables set while a streaming to the mirroring app on a Cast 178 // Receiver. 179 std::unique_ptr<Environment> environment_; 180 std::unique_ptr<SenderSession> current_session_; 181 std::unique_ptr<LoopingFileSender> file_sender_; 182 183 // Remoting specific member variables. 184 std::unique_ptr<RemotingSender> remoting_sender_; 185 186 // Set when remoting is successfully negotiated. However, remoting streams 187 // won't start until |is_ready_for_remoting_| is true. 188 std::unique_ptr<SenderSession::RemotingNegotiation> current_negotiation_; 189 190 // Set to true when the remoting receiver is ready. However, remoting streams 191 // won't start until remoting is successfully negotiated. 192 bool is_ready_for_remoting_ = false; 193 }; 194 195 } // namespace cast 196 } // namespace openscreen 197 198 #endif // CAST_STANDALONE_SENDER_LOOPING_FILE_CAST_AGENT_H_ 199