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_STREAMING_SENDER_SESSION_H_
6 #define CAST_STREAMING_SENDER_SESSION_H_
7 
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "cast/common/public/message_port.h"
14 #include "cast/streaming/answer_messages.h"
15 #include "cast/streaming/capture_configs.h"
16 #include "cast/streaming/offer_messages.h"
17 #include "cast/streaming/sender.h"
18 #include "cast/streaming/sender_packet_router.h"
19 #include "cast/streaming/session_config.h"
20 #include "cast/streaming/session_messager.h"
21 #include "json/value.h"
22 #include "util/json/json_serialization.h"
23 
24 namespace openscreen {
25 namespace cast {
26 
27 namespace capture_recommendations {
28 struct Recommendations;
29 }
30 
31 class Environment;
32 class Sender;
33 
34 class SenderSession final {
35  public:
36   // Upon successful negotiation, a set of configured senders is constructed
37   // for handling audio and video. Note that either sender may be null.
38   struct ConfiguredSenders {
39     // In practice, we may have 0, 1, or 2 senders configured, depending
40     // on if the device supports audio and video, and if we were able to
41     // successfully negotiate a sender configuration.
42 
43     // If the sender is audio- or video-only, either of the senders
44     // may be nullptr. However, in the majority of cases they will be populated.
45     Sender* audio_sender;
46     AudioCaptureConfig audio_config;
47 
48     Sender* video_sender;
49     VideoCaptureConfig video_config;
50   };
51 
52   // The embedder should provide a client for handling the negotiation.
53   // When the negotiation is complete, the OnNegotiated callback is called.
54   class Client {
55    public:
56     // Called when a new set of senders has been negotiated. This may be
57     // called multiple times during a session, once for every time Negotiate()
58     // is called on the SenderSession object. The negotation call also includes
59     // capture recommendations that can be used by the sender to provide
60     // an optimal video stream for the receiver.
61     virtual void OnNegotiated(
62         const SenderSession* session,
63         ConfiguredSenders senders,
64         capture_recommendations::Recommendations capture_recommendations) = 0;
65 
66     // Called whenever an error occurs. Ends the ongoing session, and the caller
67     // must call Negotiate() again if they wish to re-establish streaming.
68     virtual void OnError(const SenderSession* session, Error error) = 0;
69 
70    protected:
71     virtual ~Client();
72   };
73 
74   // The SenderSession assumes that the passed in client, environment, and
75   // message port persist for at least the lifetime of the SenderSession. If
76   // one of these classes needs to be reset, a new SenderSession should be
77   // created.
78   SenderSession(IPAddress remote_address,
79                 Client* const client,
80                 Environment* environment,
81                 MessagePort* message_port);
82   SenderSession(const SenderSession&) = delete;
83   SenderSession(SenderSession&&) = delete;
84   SenderSession& operator=(const SenderSession&) = delete;
85   SenderSession& operator=(SenderSession&&) = delete;
86   ~SenderSession();
87 
88   // Starts an OFFER/ANSWER exchange with the already configured receiver
89   // over the message port. The caller should assume any configured senders
90   // become invalid when calling this method.
91   Error Negotiate(std::vector<AudioCaptureConfig> audio_configs,
92                   std::vector<VideoCaptureConfig> video_configs);
93 
94  private:
95   // We store the current negotiation, so that when we get an answer from the
96   // receiver we can line up the selected streams with the original
97   // configuration.
98   struct Negotiation {
99     Offer offer;
100 
101     std::vector<AudioCaptureConfig> audio_configs;
102     std::vector<VideoCaptureConfig> video_configs;
103   };
104 
105   // Specific message type handler methods.
106   void OnAnswer(SessionMessager::Message message);
107 
108   // Used by SpawnSenders to generate a sender for a specific stream.
109   std::unique_ptr<Sender> CreateSender(Ssrc receiver_ssrc,
110                                        const Stream& stream,
111                                        RtpPayloadType type);
112 
113   // Helper methods for spawning specific senders from the Answer message.
114   void SpawnAudioSender(ConfiguredSenders* senders,
115                         Ssrc receiver_ssrc,
116                         int send_index,
117                         int config_index);
118   void SpawnVideoSender(ConfiguredSenders* senders,
119                         Ssrc receiver_ssrc,
120                         int send_index,
121                         int config_index);
122 
123   // Spawn a set of configured senders from the currently stored negotiation.
124   ConfiguredSenders SpawnSenders(const Answer& answer);
125 
126   // The sender ID of the Receiver for this session.
127   std::string receiver_sender_id_;
128 
129   // The remote address of the receiver we are communicating with. Used
130   // for both TLS and UDP traffic.
131   const IPAddress remote_address_;
132 
133   // The embedder is expected to provide us a client for notifications about
134   // negotiations and errors, a valid cast environment, and a messaging
135   // port for communicating to the Receiver over TLS.
136   Client* const client_;
137   Environment* const environment_;
138   SessionMessager messager_;
139 
140   // The packet router used for messaging across all senders.
141   SenderPacketRouter packet_router_;
142 
143   // Each negotiation has its own sequence number, and the receiver replies
144   // with the same sequence number that we send. Each message to the receiver
145   // advances our current sequence number.
146   int current_sequence_number_ = 0;
147 
148   // The current negotiation. If present, we are expected an ANSWER from
149   // the receiver. If not present, any provided ANSWERS are rejected.
150   std::unique_ptr<Negotiation> current_negotiation_;
151 
152   // If the negotiation has succeeded, we store the current audio and video
153   // senders used for this session. Either or both may be nullptr.
154   std::unique_ptr<Sender> current_audio_sender_;
155   std::unique_ptr<Sender> current_video_sender_;
156 };  // namespace cast
157 
158 }  // namespace cast
159 }  // namespace openscreen
160 
161 #endif  // CAST_STREAMING_SENDER_SESSION_H_
162