aboutsummaryrefslogtreecommitdiff
path: root/cast/standalone_sender/looping_file_cast_agent.h
blob: 895d13241d7d0425823d76827deefba4a1331775 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CAST_STANDALONE_SENDER_LOOPING_FILE_CAST_AGENT_H_
#define CAST_STANDALONE_SENDER_LOOPING_FILE_CAST_AGENT_H_

#include <openssl/x509.h>

#include <functional>
#include <memory>
#include <string>
#include <vector>

#include "absl/types/optional.h"
#include "cast/common/channel/cast_message_handler.h"
#include "cast/common/channel/cast_socket_message_port.h"
#include "cast/common/channel/connection_namespace_handler.h"
#include "cast/common/channel/virtual_connection_router.h"
#include "cast/common/public/cast_socket.h"
#include "cast/sender/public/sender_socket_factory.h"
#include "cast/standalone_sender/connection_settings.h"
#include "cast/standalone_sender/looping_file_sender.h"
#include "cast/standalone_sender/remoting_sender.h"
#include "cast/streaming/environment.h"
#include "cast/streaming/sender_session.h"
#include "platform/api/scoped_wake_lock.h"
#include "platform/api/serial_delete_ptr.h"
#include "platform/base/error.h"
#include "platform/base/interface_info.h"
#include "platform/impl/task_runner.h"

namespace Json {
class Value;
}

namespace openscreen {
namespace cast {

// A single-use sender-side Cast Agent that manages the workflow for a mirroring
// session, casting the content from a local file indefinitely. After being
// constructed and having its Connect() method called, the LoopingFileCastAgent
// steps through the following workflow:
//
//   1. Waits for a CastSocket representing a successful connection to a remote
//      Cast Receiver's agent.
//   2. Sends a LAUNCH request to the Cast Receiver to start its Mirroring App.
//   3. Waits for a RECEIVER_STATUS message from the Receiver indicating launch
//      success, or a LAUNCH_ERROR.
//   4. Once launched, message routing (i.e., a VirtualConnection) is requested,
//      for messaging between the SenderSession (locally) and the remote
//      Mirroring App.
//   5. Once message routing is established, the local SenderSession is created
//      and begins the mirroring-specific OFFER/ANSWER messaging to negotiate
//      the streaming parameters.
//   6. Streaming commences.
//
// If at any point an error occurs, the LoopingFileCastAgent executes a clean
// shut-down (both locally, and with the remote Cast Receiver), and then invokes
// the ShutdownCallback that was passed to the constructor.
//
// Normal shutdown happens when either:
//
//   1. Receiver-side, the Mirroring App is shut down. This will cause the
//      ShutdownCallback passed to the constructor to be invoked.
//   2. This LoopingFileCastAgent is destroyed (automatic shutdown is part of
//      the destruction procedure).
class LoopingFileCastAgent final
    : public SenderSocketFactory::Client,
      public VirtualConnectionRouter::SocketErrorHandler,
      public ConnectionNamespaceHandler::VirtualConnectionPolicy,
      public CastMessageHandler,
      public SenderSession::Client {
 public:
  using ShutdownCallback = std::function<void()>;

  // |shutdown_callback| is invoked after normal shutdown, whether initiated
  // sender- or receiver-side; or, for any fatal error.
  LoopingFileCastAgent(TaskRunner* task_runner,
                       ShutdownCallback shutdown_callback);
  ~LoopingFileCastAgent();

  // Connect to a Cast Receiver, and start the workflow to establish a
  // mirroring/streaming session. Destroy the LoopingFileCastAgent to shutdown
  // and disconnect.
  void Connect(ConnectionSettings settings);

 private:
  // SenderSocketFactory::Client overrides.
  void OnConnected(SenderSocketFactory* factory,
                   const IPEndpoint& endpoint,
                   std::unique_ptr<CastSocket> socket) override;
  void OnError(SenderSocketFactory* factory,
               const IPEndpoint& endpoint,
               Error error) override;

  // VirtualConnectionRouter::SocketErrorHandler overrides.
  void OnClose(CastSocket* cast_socket) override;
  void OnError(CastSocket* socket, Error error) override;

  // ConnectionNamespaceHandler::VirtualConnectionPolicy overrides.
  bool IsConnectionAllowed(
      const VirtualConnection& virtual_conn) const override;

  // CastMessageHandler overrides.
  void OnMessage(VirtualConnectionRouter* router,
                 CastSocket* socket,
                 ::cast::channel::CastMessage message) override;

  // Returns the Cast application ID for either A/V mirroring or audio-only
  // mirroring, as configured by the ConnectionSettings.
  const char* GetMirroringAppId() const;

  // Called by OnMessage() to determine whether the Cast Receiver has launched
  // or unlaunched the Mirroring App. If the former, a VirtualConnection is
  // requested. Otherwise, the workflow is aborted and Shutdown() is called.
  void HandleReceiverStatus(const Json::Value& status);

  // Called by the |connection_handler_| after message routing to the Cast
  // Receiver's Mirroring App has been established (if |success| is true).
  void OnRemoteMessagingOpened(bool success);

  // Once we have a connection to the receiver we need to create and start
  // a sender session. This method results in the OFFER/ANSWER exchange
  // being completed and a session should be started.
  void CreateAndStartSession();

  // SenderSession::Client overrides.
  void OnNegotiated(const SenderSession* session,
                    SenderSession::ConfiguredSenders senders,
                    capture_recommendations::Recommendations
                        capture_recommendations) override;
  void OnRemotingNegotiated(
      const SenderSession* session,
      SenderSession::RemotingNegotiation negotiation) override;
  void OnError(const SenderSession* session, Error error) override;

  // Callback for when the RemotingSender indicates that the receiver
  // is ready.
  void OnRemotingReceiverReady();

  // Starts the remoting sender. This may occur when remoting is "ready" if the
  // session is already negotiated, or upon session negotiation if the receiver
  // is already ready.
  void StartRemotingSenders();

  // Helper for stopping the current session, and/or unwinding a remote
  // connection request (pre-session). This ensures LoopingFileCastAgent is in a
  // terminal shutdown state.
  void Shutdown();

  // Member variables set as part of construction.
  TaskRunner* const task_runner_;
  ShutdownCallback shutdown_callback_;
  VirtualConnectionRouter router_;
  ConnectionNamespaceHandler connection_handler_;
  SenderSocketFactory socket_factory_;
  std::unique_ptr<TlsConnectionFactory> connection_factory_;
  CastSocketMessagePort message_port_;

  // Counter for distinguishing request messages sent to the Cast Receiver.
  int next_request_id_ = 1;

  // Initialized by Connect().
  absl::optional<ConnectionSettings> connection_settings_;
  SerialDeletePtr<ScopedWakeLock> wake_lock_;

  // If non-empty, this is the sessionId associated with the Cast Receiver
  // application that this LoopingFileCastAgent launched.
  std::string app_session_id_;

  // This is set once LoopingFileCastAgent has requested to start messaging to
  // the mirroring app on a Cast Receiver.
  absl::optional<VirtualConnection> remote_connection_;

  // Member variables set while a streaming to the mirroring app on a Cast
  // Receiver.
  std::unique_ptr<Environment> environment_;
  std::unique_ptr<SenderSession> current_session_;
  std::unique_ptr<LoopingFileSender> file_sender_;

  // Remoting specific member variables.
  std::unique_ptr<RemotingSender> remoting_sender_;

  // Set when remoting is successfully negotiated. However, remoting streams
  // won't start until |is_ready_for_remoting_| is true.
  std::unique_ptr<SenderSession::RemotingNegotiation> current_negotiation_;

  // Set to true when the remoting receiver is ready.  However, remoting streams
  // won't start until remoting is successfully negotiated.
  bool is_ready_for_remoting_ = false;
};

}  // namespace cast
}  // namespace openscreen

#endif  // CAST_STANDALONE_SENDER_LOOPING_FILE_CAST_AGENT_H_