blob: b84c8bd3fee07a02ce96c32b24a2aefcc79f2482 [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();
133
Harald Alvestrandc06e3742020-10-01 10:23:33 +0000134 // Returns the media section in the given session description that is
135 // associated with the RtpTransceiver. Returns null if none found or this
136 // RtpTransceiver is not associated. Logic varies depending on the
137 // SdpSemantics specified in the configuration.
138 const cricket::ContentInfo* FindMediaSectionForTransceiver(
139 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
140 transceiver,
141 const SessionDescriptionInterface* sdesc) const;
142
Harald Alvestrandcdcfab02020-09-28 13:02:07 +0000143 private:
144 class ImplicitCreateSessionDescriptionObserver;
145 friend class ImplicitCreateSessionDescriptionObserver;
146 class SetSessionDescriptionObserverAdapter;
147 friend class SetSessionDescriptionObserverAdapter;
148
149 // Represents the [[LocalIceCredentialsToReplace]] internal slot in the spec.
150 // It makes the next CreateOffer() produce new ICE credentials even if
151 // RTCOfferAnswerOptions::ice_restart is false.
152 // https://w3c.github.io/webrtc-pc/#dfn-localufragstoreplace
153 // TODO(hbos): When JsepTransportController/JsepTransport supports rollback,
154 // move this type of logic to JsepTransportController/JsepTransport.
155 class LocalIceCredentialsToReplace;
156
157 rtc::Thread* signaling_thread() const;
158 // Non-const versions of local_description()/remote_description(), for use
159 // internally.
160 SessionDescriptionInterface* mutable_local_description()
161 RTC_RUN_ON(signaling_thread()) {
162 return pending_local_description_ ? pending_local_description_.get()
163 : current_local_description_.get();
164 }
165 SessionDescriptionInterface* mutable_remote_description()
166 RTC_RUN_ON(signaling_thread()) {
167 return pending_remote_description_ ? pending_remote_description_.get()
168 : current_remote_description_.get();
169 }
170
171 // Synchronous implementations of SetLocalDescription/SetRemoteDescription
172 // that return an RTCError instead of invoking a callback.
173 RTCError ApplyLocalDescription(
174 std::unique_ptr<SessionDescriptionInterface> desc);
175 RTCError ApplyRemoteDescription(
176 std::unique_ptr<SessionDescriptionInterface> desc);
177
178 // Implementation of the offer/answer exchange operations. These are chained
179 // onto the |operations_chain_| when the public CreateOffer(), CreateAnswer(),
180 // SetLocalDescription() and SetRemoteDescription() methods are invoked.
181 void DoCreateOffer(
182 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
183 rtc::scoped_refptr<CreateSessionDescriptionObserver> observer);
184 void DoCreateAnswer(
185 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
186 rtc::scoped_refptr<CreateSessionDescriptionObserver> observer);
187 void DoSetLocalDescription(
188 std::unique_ptr<SessionDescriptionInterface> desc,
189 rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer);
190 void DoSetRemoteDescription(
191 std::unique_ptr<SessionDescriptionInterface> desc,
192 rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer);
193
194 // Update the state, signaling if necessary.
195 void ChangeSignalingState(
196 PeerConnectionInterface::SignalingState signaling_state);
197
198 RTCError UpdateSessionState(SdpType type,
199 cricket::ContentSource source,
200 const cricket::SessionDescription* description);
201
202 bool IsUnifiedPlan() const RTC_RUN_ON(signaling_thread());
203
204 // | desc_type | is the type of the description that caused the rollback.
205 RTCError Rollback(SdpType desc_type);
206 void OnOperationsChainEmpty();
207
208 // Runs the algorithm **set the associated remote streams** specified in
209 // https://w3c.github.io/webrtc-pc/#set-associated-remote-streams.
210 void SetAssociatedRemoteStreams(
211 rtc::scoped_refptr<RtpReceiverInternal> receiver,
212 const std::vector<std::string>& stream_ids,
213 std::vector<rtc::scoped_refptr<MediaStreamInterface>>* added_streams,
214 std::vector<rtc::scoped_refptr<MediaStreamInterface>>* removed_streams);
215
216 bool CheckIfNegotiationIsNeeded();
217 void GenerateNegotiationNeededEvent();
218 // Helper method which verifies SDP.
219 RTCError ValidateSessionDescription(const SessionDescriptionInterface* sdesc,
220 cricket::ContentSource source)
221 RTC_RUN_ON(signaling_thread());
222
223 // Updates the local RtpTransceivers according to the JSEP rules. Called as
224 // part of setting the local/remote description.
225 RTCError UpdateTransceiversAndDataChannels(
226 cricket::ContentSource source,
227 const SessionDescriptionInterface& new_session,
228 const SessionDescriptionInterface* old_local_description,
229 const SessionDescriptionInterface* old_remote_description);
230
231 // Associate the given transceiver according to the JSEP rules.
232 RTCErrorOr<
233 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
234 AssociateTransceiver(cricket::ContentSource source,
235 SdpType type,
236 size_t mline_index,
237 const cricket::ContentInfo& content,
238 const cricket::ContentInfo* old_local_content,
239 const cricket::ContentInfo* old_remote_content)
240 RTC_RUN_ON(signaling_thread());
241
242 // If the BUNDLE policy is max-bundle, then we know for sure that all
243 // transports will be bundled from the start. This method returns the BUNDLE
244 // group if that's the case, or null if BUNDLE will be negotiated later. An
245 // error is returned if max-bundle is specified but the session description
246 // does not have a BUNDLE group.
247 RTCErrorOr<const cricket::ContentGroup*> GetEarlyBundleGroup(
248 const cricket::SessionDescription& desc) const
249 RTC_RUN_ON(signaling_thread());
250
251 // Either creates or destroys the transceiver's BaseChannel according to the
252 // given media section.
253 RTCError UpdateTransceiverChannel(
254 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
255 transceiver,
256 const cricket::ContentInfo& content,
257 const cricket::ContentGroup* bundle_group) RTC_RUN_ON(signaling_thread());
258
259 // Either creates or destroys the local data channel according to the given
260 // media section.
261 RTCError UpdateDataChannel(cricket::ContentSource source,
262 const cricket::ContentInfo& content,
263 const cricket::ContentGroup* bundle_group)
264 RTC_RUN_ON(signaling_thread());
Harald Alvestrandc06e3742020-10-01 10:23:33 +0000265 // Check if a call to SetLocalDescription is acceptable with a session
266 // description of the given type.
267 bool ExpectSetLocalDescription(SdpType type);
268 // Check if a call to SetRemoteDescription is acceptable with a session
269 // description of the given type.
270 bool ExpectSetRemoteDescription(SdpType type);
271
272 // The offer/answer machinery assumes the media section MID is present and
273 // unique. To support legacy end points that do not supply a=mid lines, this
274 // method will modify the session description to add MIDs generated according
275 // to the SDP semantics.
276 void FillInMissingRemoteMids(cricket::SessionDescription* remote_description);
277
278 // Returns an RtpTransciever, if available, that can be used to receive the
279 // given media type according to JSEP rules.
280 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
281 FindAvailableTransceiverToReceive(cricket::MediaType media_type) const;
282
283 // Returns a MediaSessionOptions struct with options decided by |options|,
284 // the local MediaStreams and DataChannels.
285 void GetOptionsForOffer(const PeerConnectionInterface::RTCOfferAnswerOptions&
286 offer_answer_options,
287 cricket::MediaSessionOptions* session_options);
288 void GetOptionsForPlanBOffer(
289 const PeerConnectionInterface::RTCOfferAnswerOptions&
290 offer_answer_options,
291 cricket::MediaSessionOptions* session_options)
292 RTC_RUN_ON(signaling_thread());
293 void GetOptionsForUnifiedPlanOffer(
294 const PeerConnectionInterface::RTCOfferAnswerOptions&
295 offer_answer_options,
296 cricket::MediaSessionOptions* session_options)
297 RTC_RUN_ON(signaling_thread());
298
299 // Returns a MediaSessionOptions struct with options decided by
300 // |constraints|, the local MediaStreams and DataChannels.
301 void GetOptionsForAnswer(const PeerConnectionInterface::RTCOfferAnswerOptions&
302 offer_answer_options,
303 cricket::MediaSessionOptions* session_options);
304 void GetOptionsForPlanBAnswer(
305 const PeerConnectionInterface::RTCOfferAnswerOptions&
306 offer_answer_options,
307 cricket::MediaSessionOptions* session_options)
308 RTC_RUN_ON(signaling_thread());
309 void GetOptionsForUnifiedPlanAnswer(
310 const PeerConnectionInterface::RTCOfferAnswerOptions&
311 offer_answer_options,
312 cricket::MediaSessionOptions* session_options)
313 RTC_RUN_ON(signaling_thread());
Harald Alvestrandcdcfab02020-09-28 13:02:07 +0000314
315 // ===================================================================
316
317 PeerConnection* const pc_;
318
319 std::unique_ptr<WebRtcSessionDescriptionFactory> webrtc_session_desc_factory_
320 RTC_GUARDED_BY(signaling_thread());
321
322 std::unique_ptr<SessionDescriptionInterface> current_local_description_
323 RTC_GUARDED_BY(signaling_thread());
324 std::unique_ptr<SessionDescriptionInterface> pending_local_description_
325 RTC_GUARDED_BY(signaling_thread());
326 std::unique_ptr<SessionDescriptionInterface> current_remote_description_
327 RTC_GUARDED_BY(signaling_thread());
328 std::unique_ptr<SessionDescriptionInterface> pending_remote_description_
329 RTC_GUARDED_BY(signaling_thread());
330
331 PeerConnectionInterface::SignalingState signaling_state_
332 RTC_GUARDED_BY(signaling_thread()) = PeerConnectionInterface::kStable;
333
334 // Whether this peer is the caller. Set when the local description is applied.
335 absl::optional<bool> is_caller_ RTC_GUARDED_BY(signaling_thread());
336
337 // The operations chain is used by the offer/answer exchange methods to ensure
338 // they are executed in the right order. For example, if
339 // SetRemoteDescription() is invoked while CreateOffer() is still pending, the
340 // SRD operation will not start until CreateOffer() has completed. See
341 // https://w3c.github.io/webrtc-pc/#dfn-operations-chain.
342 rtc::scoped_refptr<rtc::OperationsChain> operations_chain_
343 RTC_GUARDED_BY(signaling_thread());
344
345 // List of content names for which the remote side triggered an ICE restart.
346 std::set<std::string> pending_ice_restarts_
347 RTC_GUARDED_BY(signaling_thread());
348
349 std::unique_ptr<LocalIceCredentialsToReplace>
350 local_ice_credentials_to_replace_ RTC_GUARDED_BY(signaling_thread());
351
352 bool remote_peer_supports_msid_ RTC_GUARDED_BY(signaling_thread()) = false;
353 bool is_negotiation_needed_ RTC_GUARDED_BY(signaling_thread()) = false;
354 uint32_t negotiation_needed_event_id_ = 0;
355 bool update_negotiation_needed_on_empty_chain_
356 RTC_GUARDED_BY(signaling_thread()) = false;
357
358 // In Unified Plan, if we encounter remote SDP that does not contain an a=msid
359 // line we create and use a stream with a random ID for our receivers. This is
360 // to support legacy endpoints that do not support the a=msid attribute (as
361 // opposed to streamless tracks with "a=msid:-").
362 rtc::scoped_refptr<MediaStreamInterface> missing_msid_default_stream_
363 RTC_GUARDED_BY(signaling_thread());
364
365 rtc::WeakPtrFactory<SdpOfferAnswerHandler> weak_ptr_factory_
366 RTC_GUARDED_BY(signaling_thread());
367};
368
369} // namespace webrtc
370
371#endif // PC_SDP_OFFER_ANSWER_H_