blob: 92ecbdfc3c97adf244f1ddfc1f8a84a0b1aa9ab2 [file] [log] [blame]
Harald Alvestrandcdcfab02020-09-28 13:02:07 +00001/*
2 * Copyright 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef PC_SDP_OFFER_ANSWER_H_
12#define PC_SDP_OFFER_ANSWER_H_
13
14#include <map>
15#include <memory>
16#include <set>
17#include <string>
18#include <utility>
19#include <vector>
20
21#include "api/jsep_ice_candidate.h"
22#include "api/peer_connection_interface.h"
23#include "api/transport/data_channel_transport_interface.h"
24#include "api/turn_customizer.h"
25#include "pc/data_channel_controller.h"
26#include "pc/ice_server_parsing.h"
27#include "pc/jsep_transport_controller.h"
28#include "pc/peer_connection_factory.h"
29#include "pc/peer_connection_internal.h"
30#include "pc/rtc_stats_collector.h"
31#include "pc/rtp_sender.h"
32#include "pc/rtp_transceiver.h"
33#include "pc/sctp_transport.h"
34#include "pc/stats_collector.h"
35#include "pc/stream_collection.h"
36#include "pc/webrtc_session_description_factory.h"
37#include "rtc_base/experiments/field_trial_parser.h"
38#include "rtc_base/operations_chain.h"
39#include "rtc_base/race_checker.h"
40#include "rtc_base/unique_id_generator.h"
41#include "rtc_base/weak_ptr.h"
42
43namespace webrtc {
44
45class MediaStreamObserver;
46class PeerConnection;
47class VideoRtpReceiver;
48class RtcEventLog;
49
50// SdpOfferAnswerHandler is a component
51// of the PeerConnection object as defined
52// by the PeerConnectionInterface API surface.
53// The class is responsible for the following:
54// - Parsing and interpreting SDP.
55// - Generating offers and answers based on the current state.
56// This class lives on the signaling thread.
57class SdpOfferAnswerHandler {
58 public:
59 explicit SdpOfferAnswerHandler(PeerConnection* pc);
60 ~SdpOfferAnswerHandler();
61
62 void SetSessionDescFactory(
63 std::unique_ptr<WebRtcSessionDescriptionFactory> factory) {
64 RTC_DCHECK_RUN_ON(signaling_thread());
65 webrtc_session_desc_factory_ = std::move(factory);
66 }
67 void ResetSessionDescFactory() {
68 RTC_DCHECK_RUN_ON(signaling_thread());
69 webrtc_session_desc_factory_.reset();
70 }
71 const WebRtcSessionDescriptionFactory* webrtc_session_desc_factory() const {
72 RTC_DCHECK_RUN_ON(signaling_thread());
73 return webrtc_session_desc_factory_.get();
74 }
75
76 // Change signaling state to Closed, and perform appropriate actions.
77 void Close();
78
79 // Called as part of destroying the owning PeerConnection.
80 void PrepareForShutdown();
81
82 PeerConnectionInterface::SignalingState signaling_state() const;
83
84 const SessionDescriptionInterface* local_description() const;
85 const SessionDescriptionInterface* remote_description() const;
86 const SessionDescriptionInterface* current_local_description() const;
87 const SessionDescriptionInterface* current_remote_description() const;
88 const SessionDescriptionInterface* pending_local_description() const;
89 const SessionDescriptionInterface* pending_remote_description() const;
90
91 void RestartIce();
92
93 // JSEP01
94 void CreateOffer(
95 CreateSessionDescriptionObserver* observer,
96 const PeerConnectionInterface::RTCOfferAnswerOptions& options);
97 void CreateAnswer(
98 CreateSessionDescriptionObserver* observer,
99 const PeerConnectionInterface::RTCOfferAnswerOptions& options);
100
101 void SetLocalDescription(
102 std::unique_ptr<SessionDescriptionInterface> desc,
103 rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer);
104 void SetLocalDescription(
105 rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer);
106 void SetLocalDescription(SetSessionDescriptionObserver* observer,
107 SessionDescriptionInterface* desc);
108 void SetLocalDescription(SetSessionDescriptionObserver* observer);
109
110 void SetRemoteDescription(
111 std::unique_ptr<SessionDescriptionInterface> desc,
112 rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer);
113 void SetRemoteDescription(SetSessionDescriptionObserver* observer,
114 SessionDescriptionInterface* desc);
115
116 PeerConnectionInterface::RTCConfiguration GetConfiguration();
117 RTCError SetConfiguration(
118 const PeerConnectionInterface::RTCConfiguration& configuration);
119 bool AddIceCandidate(const IceCandidateInterface* candidate);
120 void AddIceCandidate(std::unique_ptr<IceCandidateInterface> candidate,
121 std::function<void(RTCError)> callback);
122 bool RemoveIceCandidates(const std::vector<cricket::Candidate>& candidates);
123 // Adds a locally generated candidate to the local description.
124 void AddLocalIceCandidate(const JsepIceCandidate* candidate);
125 void RemoveLocalIceCandidates(
126 const std::vector<cricket::Candidate>& candidates);
127 bool ShouldFireNegotiationNeededEvent(uint32_t event_id);
128
129 absl::optional<bool> is_caller();
130 bool HasNewIceCredentials();
131 bool IceRestartPending(const std::string& content_name) const;
132 void UpdateNegotiationNeeded();
Harald Alvestrand75b9ab62020-09-30 22:17:18 +0000133 void SetHavePendingRtpDataChannel() {
134 RTC_DCHECK_RUN_ON(signaling_thread());
135 have_pending_rtp_data_channel_ = true;
136 }
Harald Alvestrandcdcfab02020-09-28 13:02:07 +0000137
Harald Alvestrandc06e3742020-10-01 10:23:33 +0000138 // Returns the media section in the given session description that is
139 // associated with the RtpTransceiver. Returns null if none found or this
140 // RtpTransceiver is not associated. Logic varies depending on the
141 // SdpSemantics specified in the configuration.
142 const cricket::ContentInfo* FindMediaSectionForTransceiver(
143 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
144 transceiver,
145 const SessionDescriptionInterface* sdesc) const;
146
Harald Alvestrandcdcfab02020-09-28 13:02:07 +0000147 private:
148 class ImplicitCreateSessionDescriptionObserver;
149 friend class ImplicitCreateSessionDescriptionObserver;
150 class SetSessionDescriptionObserverAdapter;
151 friend class SetSessionDescriptionObserverAdapter;
152
153 // Represents the [[LocalIceCredentialsToReplace]] internal slot in the spec.
154 // It makes the next CreateOffer() produce new ICE credentials even if
155 // RTCOfferAnswerOptions::ice_restart is false.
156 // https://w3c.github.io/webrtc-pc/#dfn-localufragstoreplace
157 // TODO(hbos): When JsepTransportController/JsepTransport supports rollback,
158 // move this type of logic to JsepTransportController/JsepTransport.
159 class LocalIceCredentialsToReplace;
160
161 rtc::Thread* signaling_thread() const;
162 // Non-const versions of local_description()/remote_description(), for use
163 // internally.
164 SessionDescriptionInterface* mutable_local_description()
165 RTC_RUN_ON(signaling_thread()) {
166 return pending_local_description_ ? pending_local_description_.get()
167 : current_local_description_.get();
168 }
169 SessionDescriptionInterface* mutable_remote_description()
170 RTC_RUN_ON(signaling_thread()) {
171 return pending_remote_description_ ? pending_remote_description_.get()
172 : current_remote_description_.get();
173 }
174
175 // Synchronous implementations of SetLocalDescription/SetRemoteDescription
176 // that return an RTCError instead of invoking a callback.
177 RTCError ApplyLocalDescription(
178 std::unique_ptr<SessionDescriptionInterface> desc);
179 RTCError ApplyRemoteDescription(
180 std::unique_ptr<SessionDescriptionInterface> desc);
181
182 // Implementation of the offer/answer exchange operations. These are chained
183 // onto the |operations_chain_| when the public CreateOffer(), CreateAnswer(),
184 // SetLocalDescription() and SetRemoteDescription() methods are invoked.
185 void DoCreateOffer(
186 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
187 rtc::scoped_refptr<CreateSessionDescriptionObserver> observer);
188 void DoCreateAnswer(
189 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
190 rtc::scoped_refptr<CreateSessionDescriptionObserver> observer);
191 void DoSetLocalDescription(
192 std::unique_ptr<SessionDescriptionInterface> desc,
193 rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer);
194 void DoSetRemoteDescription(
195 std::unique_ptr<SessionDescriptionInterface> desc,
196 rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer);
197
198 // Update the state, signaling if necessary.
199 void ChangeSignalingState(
200 PeerConnectionInterface::SignalingState signaling_state);
201
202 RTCError UpdateSessionState(SdpType type,
203 cricket::ContentSource source,
204 const cricket::SessionDescription* description);
205
206 bool IsUnifiedPlan() const RTC_RUN_ON(signaling_thread());
207
208 // | desc_type | is the type of the description that caused the rollback.
209 RTCError Rollback(SdpType desc_type);
210 void OnOperationsChainEmpty();
211
212 // Runs the algorithm **set the associated remote streams** specified in
213 // https://w3c.github.io/webrtc-pc/#set-associated-remote-streams.
214 void SetAssociatedRemoteStreams(
215 rtc::scoped_refptr<RtpReceiverInternal> receiver,
216 const std::vector<std::string>& stream_ids,
217 std::vector<rtc::scoped_refptr<MediaStreamInterface>>* added_streams,
218 std::vector<rtc::scoped_refptr<MediaStreamInterface>>* removed_streams);
219
220 bool CheckIfNegotiationIsNeeded();
221 void GenerateNegotiationNeededEvent();
222 // Helper method which verifies SDP.
223 RTCError ValidateSessionDescription(const SessionDescriptionInterface* sdesc,
224 cricket::ContentSource source)
225 RTC_RUN_ON(signaling_thread());
226
227 // Updates the local RtpTransceivers according to the JSEP rules. Called as
228 // part of setting the local/remote description.
229 RTCError UpdateTransceiversAndDataChannels(
230 cricket::ContentSource source,
231 const SessionDescriptionInterface& new_session,
232 const SessionDescriptionInterface* old_local_description,
233 const SessionDescriptionInterface* old_remote_description);
234
235 // Associate the given transceiver according to the JSEP rules.
236 RTCErrorOr<
237 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
238 AssociateTransceiver(cricket::ContentSource source,
239 SdpType type,
240 size_t mline_index,
241 const cricket::ContentInfo& content,
242 const cricket::ContentInfo* old_local_content,
243 const cricket::ContentInfo* old_remote_content)
244 RTC_RUN_ON(signaling_thread());
245
246 // If the BUNDLE policy is max-bundle, then we know for sure that all
247 // transports will be bundled from the start. This method returns the BUNDLE
248 // group if that's the case, or null if BUNDLE will be negotiated later. An
249 // error is returned if max-bundle is specified but the session description
250 // does not have a BUNDLE group.
251 RTCErrorOr<const cricket::ContentGroup*> GetEarlyBundleGroup(
252 const cricket::SessionDescription& desc) const
253 RTC_RUN_ON(signaling_thread());
254
255 // Either creates or destroys the transceiver's BaseChannel according to the
256 // given media section.
257 RTCError UpdateTransceiverChannel(
258 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
259 transceiver,
260 const cricket::ContentInfo& content,
261 const cricket::ContentGroup* bundle_group) RTC_RUN_ON(signaling_thread());
262
263 // Either creates or destroys the local data channel according to the given
264 // media section.
265 RTCError UpdateDataChannel(cricket::ContentSource source,
266 const cricket::ContentInfo& content,
267 const cricket::ContentGroup* bundle_group)
268 RTC_RUN_ON(signaling_thread());
Harald Alvestrandc06e3742020-10-01 10:23:33 +0000269 // Check if a call to SetLocalDescription is acceptable with a session
270 // description of the given type.
271 bool ExpectSetLocalDescription(SdpType type);
272 // Check if a call to SetRemoteDescription is acceptable with a session
273 // description of the given type.
274 bool ExpectSetRemoteDescription(SdpType type);
275
276 // The offer/answer machinery assumes the media section MID is present and
277 // unique. To support legacy end points that do not supply a=mid lines, this
278 // method will modify the session description to add MIDs generated according
279 // to the SDP semantics.
280 void FillInMissingRemoteMids(cricket::SessionDescription* remote_description);
281
282 // Returns an RtpTransciever, if available, that can be used to receive the
283 // given media type according to JSEP rules.
284 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
285 FindAvailableTransceiverToReceive(cricket::MediaType media_type) const;
286
287 // Returns a MediaSessionOptions struct with options decided by |options|,
288 // the local MediaStreams and DataChannels.
289 void GetOptionsForOffer(const PeerConnectionInterface::RTCOfferAnswerOptions&
290 offer_answer_options,
291 cricket::MediaSessionOptions* session_options);
292 void GetOptionsForPlanBOffer(
293 const PeerConnectionInterface::RTCOfferAnswerOptions&
294 offer_answer_options,
295 cricket::MediaSessionOptions* session_options)
296 RTC_RUN_ON(signaling_thread());
297 void GetOptionsForUnifiedPlanOffer(
298 const PeerConnectionInterface::RTCOfferAnswerOptions&
299 offer_answer_options,
300 cricket::MediaSessionOptions* session_options)
301 RTC_RUN_ON(signaling_thread());
302
303 // Returns a MediaSessionOptions struct with options decided by
304 // |constraints|, the local MediaStreams and DataChannels.
305 void GetOptionsForAnswer(const PeerConnectionInterface::RTCOfferAnswerOptions&
306 offer_answer_options,
307 cricket::MediaSessionOptions* session_options);
308 void GetOptionsForPlanBAnswer(
309 const PeerConnectionInterface::RTCOfferAnswerOptions&
310 offer_answer_options,
311 cricket::MediaSessionOptions* session_options)
312 RTC_RUN_ON(signaling_thread());
313 void GetOptionsForUnifiedPlanAnswer(
314 const PeerConnectionInterface::RTCOfferAnswerOptions&
315 offer_answer_options,
316 cricket::MediaSessionOptions* session_options)
317 RTC_RUN_ON(signaling_thread());
Harald Alvestrandcdcfab02020-09-28 13:02:07 +0000318
319 // ===================================================================
320
321 PeerConnection* const pc_;
322
323 std::unique_ptr<WebRtcSessionDescriptionFactory> webrtc_session_desc_factory_
324 RTC_GUARDED_BY(signaling_thread());
325
326 std::unique_ptr<SessionDescriptionInterface> current_local_description_
327 RTC_GUARDED_BY(signaling_thread());
328 std::unique_ptr<SessionDescriptionInterface> pending_local_description_
329 RTC_GUARDED_BY(signaling_thread());
330 std::unique_ptr<SessionDescriptionInterface> current_remote_description_
331 RTC_GUARDED_BY(signaling_thread());
332 std::unique_ptr<SessionDescriptionInterface> pending_remote_description_
333 RTC_GUARDED_BY(signaling_thread());
334
335 PeerConnectionInterface::SignalingState signaling_state_
336 RTC_GUARDED_BY(signaling_thread()) = PeerConnectionInterface::kStable;
337
338 // Whether this peer is the caller. Set when the local description is applied.
339 absl::optional<bool> is_caller_ RTC_GUARDED_BY(signaling_thread());
340
341 // The operations chain is used by the offer/answer exchange methods to ensure
342 // they are executed in the right order. For example, if
343 // SetRemoteDescription() is invoked while CreateOffer() is still pending, the
344 // SRD operation will not start until CreateOffer() has completed. See
345 // https://w3c.github.io/webrtc-pc/#dfn-operations-chain.
346 rtc::scoped_refptr<rtc::OperationsChain> operations_chain_
347 RTC_GUARDED_BY(signaling_thread());
348
349 // List of content names for which the remote side triggered an ICE restart.
350 std::set<std::string> pending_ice_restarts_
351 RTC_GUARDED_BY(signaling_thread());
352
353 std::unique_ptr<LocalIceCredentialsToReplace>
354 local_ice_credentials_to_replace_ RTC_GUARDED_BY(signaling_thread());
355
356 bool remote_peer_supports_msid_ RTC_GUARDED_BY(signaling_thread()) = false;
357 bool is_negotiation_needed_ RTC_GUARDED_BY(signaling_thread()) = false;
358 uint32_t negotiation_needed_event_id_ = 0;
359 bool update_negotiation_needed_on_empty_chain_
360 RTC_GUARDED_BY(signaling_thread()) = false;
361
362 // In Unified Plan, if we encounter remote SDP that does not contain an a=msid
363 // line we create and use a stream with a random ID for our receivers. This is
364 // to support legacy endpoints that do not support the a=msid attribute (as
365 // opposed to streamless tracks with "a=msid:-").
366 rtc::scoped_refptr<MediaStreamInterface> missing_msid_default_stream_
367 RTC_GUARDED_BY(signaling_thread());
368
Harald Alvestrand75b9ab62020-09-30 22:17:18 +0000369 // Used when rolling back RTP data channels.
370 bool have_pending_rtp_data_channel_ RTC_GUARDED_BY(signaling_thread()) =
371 false;
372
Harald Alvestrandcdcfab02020-09-28 13:02:07 +0000373 rtc::WeakPtrFactory<SdpOfferAnswerHandler> weak_ptr_factory_
374 RTC_GUARDED_BY(signaling_thread());
375};
376
377} // namespace webrtc
378
379#endif // PC_SDP_OFFER_ANSWER_H_