blob: abd25c4d98a2b59065e32e18731dfa0a0d7f5ed4 [file] [log] [blame]
Harald Alvestrandcdcfab02020-09-28 13:02:071/*
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:18133 void SetHavePendingRtpDataChannel() {
134 RTC_DCHECK_RUN_ON(signaling_thread());
135 have_pending_rtp_data_channel_ = true;
136 }
Harald Alvestrandcdcfab02020-09-28 13:02:07137
Harald Alvestrandc06e3742020-10-01 10:23:33138 // 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:07147 private:
148 class ImplicitCreateSessionDescriptionObserver;
149 friend class ImplicitCreateSessionDescriptionObserver;
150 class SetSessionDescriptionObserverAdapter;
151 friend class SetSessionDescriptionObserverAdapter;
152
Harald Alvestranda474fbf2020-10-01 16:47:23153 enum class SessionError {
154 kNone, // No error.
155 kContent, // Error in BaseChannel SetLocalContent/SetRemoteContent.
156 kTransport, // Error from the underlying transport.
157 };
158
Harald Alvestrandcdcfab02020-09-28 13:02:07159 // Represents the [[LocalIceCredentialsToReplace]] internal slot in the spec.
160 // It makes the next CreateOffer() produce new ICE credentials even if
161 // RTCOfferAnswerOptions::ice_restart is false.
162 // https://w3c.github.io/webrtc-pc/#dfn-localufragstoreplace
163 // TODO(hbos): When JsepTransportController/JsepTransport supports rollback,
164 // move this type of logic to JsepTransportController/JsepTransport.
165 class LocalIceCredentialsToReplace;
166
167 rtc::Thread* signaling_thread() const;
168 // Non-const versions of local_description()/remote_description(), for use
169 // internally.
170 SessionDescriptionInterface* mutable_local_description()
171 RTC_RUN_ON(signaling_thread()) {
172 return pending_local_description_ ? pending_local_description_.get()
173 : current_local_description_.get();
174 }
175 SessionDescriptionInterface* mutable_remote_description()
176 RTC_RUN_ON(signaling_thread()) {
177 return pending_remote_description_ ? pending_remote_description_.get()
178 : current_remote_description_.get();
179 }
180
181 // Synchronous implementations of SetLocalDescription/SetRemoteDescription
182 // that return an RTCError instead of invoking a callback.
183 RTCError ApplyLocalDescription(
184 std::unique_ptr<SessionDescriptionInterface> desc);
185 RTCError ApplyRemoteDescription(
186 std::unique_ptr<SessionDescriptionInterface> desc);
187
188 // Implementation of the offer/answer exchange operations. These are chained
189 // onto the |operations_chain_| when the public CreateOffer(), CreateAnswer(),
190 // SetLocalDescription() and SetRemoteDescription() methods are invoked.
191 void DoCreateOffer(
192 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
193 rtc::scoped_refptr<CreateSessionDescriptionObserver> observer);
194 void DoCreateAnswer(
195 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
196 rtc::scoped_refptr<CreateSessionDescriptionObserver> observer);
197 void DoSetLocalDescription(
198 std::unique_ptr<SessionDescriptionInterface> desc,
199 rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer);
200 void DoSetRemoteDescription(
201 std::unique_ptr<SessionDescriptionInterface> desc,
202 rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer);
203
204 // Update the state, signaling if necessary.
205 void ChangeSignalingState(
206 PeerConnectionInterface::SignalingState signaling_state);
207
208 RTCError UpdateSessionState(SdpType type,
209 cricket::ContentSource source,
210 const cricket::SessionDescription* description);
211
212 bool IsUnifiedPlan() const RTC_RUN_ON(signaling_thread());
213
214 // | desc_type | is the type of the description that caused the rollback.
215 RTCError Rollback(SdpType desc_type);
216 void OnOperationsChainEmpty();
217
218 // Runs the algorithm **set the associated remote streams** specified in
219 // https://w3c.github.io/webrtc-pc/#set-associated-remote-streams.
220 void SetAssociatedRemoteStreams(
221 rtc::scoped_refptr<RtpReceiverInternal> receiver,
222 const std::vector<std::string>& stream_ids,
223 std::vector<rtc::scoped_refptr<MediaStreamInterface>>* added_streams,
224 std::vector<rtc::scoped_refptr<MediaStreamInterface>>* removed_streams);
225
226 bool CheckIfNegotiationIsNeeded();
227 void GenerateNegotiationNeededEvent();
228 // Helper method which verifies SDP.
229 RTCError ValidateSessionDescription(const SessionDescriptionInterface* sdesc,
230 cricket::ContentSource source)
231 RTC_RUN_ON(signaling_thread());
232
233 // Updates the local RtpTransceivers according to the JSEP rules. Called as
234 // part of setting the local/remote description.
235 RTCError UpdateTransceiversAndDataChannels(
236 cricket::ContentSource source,
237 const SessionDescriptionInterface& new_session,
238 const SessionDescriptionInterface* old_local_description,
239 const SessionDescriptionInterface* old_remote_description);
240
241 // Associate the given transceiver according to the JSEP rules.
242 RTCErrorOr<
243 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
244 AssociateTransceiver(cricket::ContentSource source,
245 SdpType type,
246 size_t mline_index,
247 const cricket::ContentInfo& content,
248 const cricket::ContentInfo* old_local_content,
249 const cricket::ContentInfo* old_remote_content)
250 RTC_RUN_ON(signaling_thread());
251
252 // If the BUNDLE policy is max-bundle, then we know for sure that all
253 // transports will be bundled from the start. This method returns the BUNDLE
254 // group if that's the case, or null if BUNDLE will be negotiated later. An
255 // error is returned if max-bundle is specified but the session description
256 // does not have a BUNDLE group.
257 RTCErrorOr<const cricket::ContentGroup*> GetEarlyBundleGroup(
258 const cricket::SessionDescription& desc) const
259 RTC_RUN_ON(signaling_thread());
260
261 // Either creates or destroys the transceiver's BaseChannel according to the
262 // given media section.
263 RTCError UpdateTransceiverChannel(
264 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
265 transceiver,
266 const cricket::ContentInfo& content,
267 const cricket::ContentGroup* bundle_group) RTC_RUN_ON(signaling_thread());
268
269 // Either creates or destroys the local data channel according to the given
270 // media section.
271 RTCError UpdateDataChannel(cricket::ContentSource source,
272 const cricket::ContentInfo& content,
273 const cricket::ContentGroup* bundle_group)
274 RTC_RUN_ON(signaling_thread());
Harald Alvestrandc06e3742020-10-01 10:23:33275 // Check if a call to SetLocalDescription is acceptable with a session
276 // description of the given type.
277 bool ExpectSetLocalDescription(SdpType type);
278 // Check if a call to SetRemoteDescription is acceptable with a session
279 // description of the given type.
280 bool ExpectSetRemoteDescription(SdpType type);
281
282 // The offer/answer machinery assumes the media section MID is present and
283 // unique. To support legacy end points that do not supply a=mid lines, this
284 // method will modify the session description to add MIDs generated according
285 // to the SDP semantics.
286 void FillInMissingRemoteMids(cricket::SessionDescription* remote_description);
287
288 // Returns an RtpTransciever, if available, that can be used to receive the
289 // given media type according to JSEP rules.
290 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
291 FindAvailableTransceiverToReceive(cricket::MediaType media_type) const;
292
293 // Returns a MediaSessionOptions struct with options decided by |options|,
294 // the local MediaStreams and DataChannels.
295 void GetOptionsForOffer(const PeerConnectionInterface::RTCOfferAnswerOptions&
296 offer_answer_options,
297 cricket::MediaSessionOptions* session_options);
298 void GetOptionsForPlanBOffer(
299 const PeerConnectionInterface::RTCOfferAnswerOptions&
300 offer_answer_options,
301 cricket::MediaSessionOptions* session_options)
302 RTC_RUN_ON(signaling_thread());
303 void GetOptionsForUnifiedPlanOffer(
304 const PeerConnectionInterface::RTCOfferAnswerOptions&
305 offer_answer_options,
306 cricket::MediaSessionOptions* session_options)
307 RTC_RUN_ON(signaling_thread());
308
309 // Returns a MediaSessionOptions struct with options decided by
310 // |constraints|, the local MediaStreams and DataChannels.
311 void GetOptionsForAnswer(const PeerConnectionInterface::RTCOfferAnswerOptions&
312 offer_answer_options,
313 cricket::MediaSessionOptions* session_options);
314 void GetOptionsForPlanBAnswer(
315 const PeerConnectionInterface::RTCOfferAnswerOptions&
316 offer_answer_options,
317 cricket::MediaSessionOptions* session_options)
318 RTC_RUN_ON(signaling_thread());
319 void GetOptionsForUnifiedPlanAnswer(
320 const PeerConnectionInterface::RTCOfferAnswerOptions&
321 offer_answer_options,
322 cricket::MediaSessionOptions* session_options)
323 RTC_RUN_ON(signaling_thread());
Harald Alvestrandcdcfab02020-09-28 13:02:07324
Harald Alvestranda474fbf2020-10-01 16:47:23325 const char* SessionErrorToString(SessionError error) const;
326 std::string GetSessionErrorMsg();
327 // Returns the last error in the session. See the enum above for details.
328 SessionError session_error() const {
329 RTC_DCHECK_RUN_ON(signaling_thread());
330 return session_error_;
331 }
332 const std::string& session_error_desc() const { return session_error_desc_; }
333
334 RTCError HandleLegacyOfferOptions(
335 const PeerConnectionInterface::RTCOfferAnswerOptions& options);
336 void RemoveRecvDirectionFromReceivingTransceiversOfType(
337 cricket::MediaType media_type) RTC_RUN_ON(signaling_thread());
338 void AddUpToOneReceivingTransceiverOfType(cricket::MediaType media_type);
339
340 std::vector<
341 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
342 GetReceivingTransceiversOfType(cricket::MediaType media_type)
343 RTC_RUN_ON(signaling_thread());
344
345 // Runs the algorithm **process the removal of a remote track** specified in
346 // the WebRTC specification.
347 // This method will update the following lists:
348 // |remove_list| is the list of transceivers for which the receiving track is
349 // being removed.
350 // |removed_streams| is the list of streams which no longer have a receiving
351 // track so should be removed.
352 // https://w3c.github.io/webrtc-pc/#process-remote-track-removal
353 void ProcessRemovalOfRemoteTrack(
354 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
355 transceiver,
356 std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>* remove_list,
357 std::vector<rtc::scoped_refptr<MediaStreamInterface>>* removed_streams);
358
359 void RemoveRemoteStreamsIfEmpty(
360 const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
361 remote_streams,
362 std::vector<rtc::scoped_refptr<MediaStreamInterface>>* removed_streams);
363
364 // Remove all local and remote senders of type |media_type|.
365 // Called when a media type is rejected (m-line set to port 0).
366 void RemoveSenders(cricket::MediaType media_type);
367
368 // Loops through the vector of |streams| and finds added and removed
369 // StreamParams since last time this method was called.
370 // For each new or removed StreamParam, OnLocalSenderSeen or
371 // OnLocalSenderRemoved is invoked.
372 void UpdateLocalSenders(const std::vector<cricket::StreamParams>& streams,
373 cricket::MediaType media_type);
374
375 // Makes sure a MediaStreamTrack is created for each StreamParam in |streams|,
376 // and existing MediaStreamTracks are removed if there is no corresponding
377 // StreamParam. If |default_track_needed| is true, a default MediaStreamTrack
378 // is created if it doesn't exist; if false, it's removed if it exists.
379 // |media_type| is the type of the |streams| and can be either audio or video.
380 // If a new MediaStream is created it is added to |new_streams|.
381 void UpdateRemoteSendersList(
382 const std::vector<cricket::StreamParams>& streams,
383 bool default_track_needed,
384 cricket::MediaType media_type,
385 StreamCollection* new_streams);
386
387 // Enables media channels to allow sending of media.
388 // This enables media to flow on all configured audio/video channels and the
389 // RtpDataChannel.
390 void EnableSending();
391 // Push the media parts of the local or remote session description
392 // down to all of the channels.
393 RTCError PushdownMediaDescription(SdpType type,
394 cricket::ContentSource source);
395
396 RTCError PushdownTransportDescription(cricket::ContentSource source,
397 SdpType type);
398 // Helper function to remove stopped transceivers.
399 void RemoveStoppedTransceivers();
400 // Deletes the corresponding channel of contents that don't exist in |desc|.
401 // |desc| can be null. This means that all channels are deleted.
402 void RemoveUnusedChannels(const cricket::SessionDescription* desc);
403
404 // Report inferred negotiated SDP semantics from a local/remote answer to the
405 // UMA observer.
406 void ReportNegotiatedSdpSemantics(const SessionDescriptionInterface& answer);
407
Harald Alvestrandcdcfab02020-09-28 13:02:07408 // ===================================================================
409
410 PeerConnection* const pc_;
411
412 std::unique_ptr<WebRtcSessionDescriptionFactory> webrtc_session_desc_factory_
413 RTC_GUARDED_BY(signaling_thread());
414
415 std::unique_ptr<SessionDescriptionInterface> current_local_description_
416 RTC_GUARDED_BY(signaling_thread());
417 std::unique_ptr<SessionDescriptionInterface> pending_local_description_
418 RTC_GUARDED_BY(signaling_thread());
419 std::unique_ptr<SessionDescriptionInterface> current_remote_description_
420 RTC_GUARDED_BY(signaling_thread());
421 std::unique_ptr<SessionDescriptionInterface> pending_remote_description_
422 RTC_GUARDED_BY(signaling_thread());
423
424 PeerConnectionInterface::SignalingState signaling_state_
425 RTC_GUARDED_BY(signaling_thread()) = PeerConnectionInterface::kStable;
426
427 // Whether this peer is the caller. Set when the local description is applied.
428 absl::optional<bool> is_caller_ RTC_GUARDED_BY(signaling_thread());
429
430 // The operations chain is used by the offer/answer exchange methods to ensure
431 // they are executed in the right order. For example, if
432 // SetRemoteDescription() is invoked while CreateOffer() is still pending, the
433 // SRD operation will not start until CreateOffer() has completed. See
434 // https://w3c.github.io/webrtc-pc/#dfn-operations-chain.
435 rtc::scoped_refptr<rtc::OperationsChain> operations_chain_
436 RTC_GUARDED_BY(signaling_thread());
437
438 // List of content names for which the remote side triggered an ICE restart.
439 std::set<std::string> pending_ice_restarts_
440 RTC_GUARDED_BY(signaling_thread());
441
442 std::unique_ptr<LocalIceCredentialsToReplace>
443 local_ice_credentials_to_replace_ RTC_GUARDED_BY(signaling_thread());
444
445 bool remote_peer_supports_msid_ RTC_GUARDED_BY(signaling_thread()) = false;
446 bool is_negotiation_needed_ RTC_GUARDED_BY(signaling_thread()) = false;
447 uint32_t negotiation_needed_event_id_ = 0;
448 bool update_negotiation_needed_on_empty_chain_
449 RTC_GUARDED_BY(signaling_thread()) = false;
450
451 // In Unified Plan, if we encounter remote SDP that does not contain an a=msid
452 // line we create and use a stream with a random ID for our receivers. This is
453 // to support legacy endpoints that do not support the a=msid attribute (as
454 // opposed to streamless tracks with "a=msid:-").
455 rtc::scoped_refptr<MediaStreamInterface> missing_msid_default_stream_
456 RTC_GUARDED_BY(signaling_thread());
457
Harald Alvestrand75b9ab62020-09-30 22:17:18458 // Used when rolling back RTP data channels.
459 bool have_pending_rtp_data_channel_ RTC_GUARDED_BY(signaling_thread()) =
460 false;
461
Harald Alvestranda474fbf2020-10-01 16:47:23462 // Updates the error state, signaling if necessary.
463 void SetSessionError(SessionError error, const std::string& error_desc);
464
465 SessionError session_error_ RTC_GUARDED_BY(signaling_thread()) =
466 SessionError::kNone;
467 std::string session_error_desc_ RTC_GUARDED_BY(signaling_thread());
468
Harald Alvestrandcdcfab02020-09-28 13:02:07469 rtc::WeakPtrFactory<SdpOfferAnswerHandler> weak_ptr_factory_
470 RTC_GUARDED_BY(signaling_thread());
471};
472
473} // namespace webrtc
474
475#endif // PC_SDP_OFFER_ANSWER_H_