blob: 8b321913f1888443bb3d3a7740ebce975c57243d [file] [log] [blame]
wu@webrtc.org91053e72013-08-10 07:18:041/*
kjellanderb24317b2016-02-10 15:54:432 * Copyright 2013 The WebRTC project authors. All Rights Reserved.
wu@webrtc.org91053e72013-08-10 07:18:043 *
kjellanderb24317b2016-02-10 15:54:434 * 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.
wu@webrtc.org91053e72013-08-10 07:18:049 */
10
Steve Anton10542f22019-01-11 17:11:0011#include "pc/webrtc_session_description_factory.h"
wu@webrtc.org91053e72013-08-10 07:18:0412
Yves Gerey3e707812018-11-28 15:47:4913#include <stddef.h>
Harald Alvestrandc24a2182022-02-23 13:44:5914
Harald Alvestrandd153de62024-09-16 20:28:1415#include <cstdint>
16#include <functional>
17#include <memory>
Florent Castelli8037fc62024-08-29 13:00:4018#include <optional>
Danil Chapovalov97bdfa32022-08-22 17:45:4319#include <queue>
Steve Anton36b29d12017-10-30 16:57:4220#include <string>
kwiberg0eb15ed2015-12-17 11:04:1521#include <utility>
Steve Anton36b29d12017-10-30 16:57:4222#include <vector>
kwiberg0eb15ed2015-12-17 11:04:1523
Steve Anton64b626b2019-01-29 01:25:2624#include "absl/algorithm/container.h"
Harald Alvestrandd153de62024-09-16 20:28:1425#include "absl/functional/any_invocable.h"
26#include "api/field_trials_view.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3127#include "api/jsep.h"
Steve Anton10542f22019-01-11 17:11:0028#include "api/jsep_session_description.h"
Harald Alvestrandd153de62024-09-16 20:28:1429#include "api/peer_connection_interface.h"
Steve Anton10542f22019-01-11 17:11:0030#include "api/rtc_error.h"
Harald Alvestrandd153de62024-09-16 20:28:1431#include "api/scoped_refptr.h"
Harald Alvestrandc24a2182022-02-23 13:44:5932#include "api/sequence_checker.h"
Harald Alvestrandd153de62024-09-16 20:28:1433#include "call/payload_type.h"
Jonas Orelanded99dae2022-03-09 08:28:1034#include "pc/connection_context.h"
Harald Alvestrandd153de62024-09-16 20:28:1435#include "pc/media_session.h"
Harald Alvestrandf01bd6c2020-10-23 13:30:4636#include "pc/sdp_state_provider.h"
Steve Anton10542f22019-01-11 17:11:0037#include "pc/session_description.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3138#include "rtc_base/checks.h"
Yves Gerey3e707812018-11-28 15:47:4939#include "rtc_base/logging.h"
Harald Alvestrandd153de62024-09-16 20:28:1440#include "rtc_base/rtc_certificate.h"
41#include "rtc_base/rtc_certificate_generator.h"
Steve Anton10542f22019-01-11 17:11:0042#include "rtc_base/ssl_identity.h"
43#include "rtc_base/ssl_stream_adapter.h"
44#include "rtc_base/string_encode.h"
Harald Alvestrandc24a2182022-02-23 13:44:5945#include "rtc_base/unique_id_generator.h"
wu@webrtc.org91053e72013-08-10 07:18:0446
wu@webrtc.org364f2042013-11-20 21:49:4147using cricket::MediaSessionOptions;
Amit Hilbuchbcd39d42019-01-26 01:13:5648using rtc::UniqueRandomIdGenerator;
wu@webrtc.org364f2042013-11-20 21:49:4149
wu@webrtc.org91053e72013-08-10 07:18:0450namespace webrtc {
wu@webrtc.org91053e72013-08-10 07:18:0451namespace {
wu@webrtc.org91053e72013-08-10 07:18:0452static const char kFailedDueToIdentityFailed[] =
53 " failed because DTLS identity request failed";
tommi0f620f42015-07-09 10:25:0254static const char kFailedDueToSessionShutdown[] =
55 " failed because the session was shut down";
wu@webrtc.org91053e72013-08-10 07:18:0456
Peter Boström0c4e06b2015-10-07 10:23:2157static const uint64_t kInitSessionVersion = 2;
wu@webrtc.org91053e72013-08-10 07:18:0458
zhihuang1c378ed2017-08-17 21:10:5059// Check that each sender has a unique ID.
60static bool ValidMediaSessionOptions(
61 const cricket::MediaSessionOptions& session_options) {
62 std::vector<cricket::SenderOptions> sorted_senders;
63 for (const cricket::MediaDescriptionOptions& media_description_options :
64 session_options.media_description_options) {
65 sorted_senders.insert(sorted_senders.end(),
66 media_description_options.sender_options.begin(),
67 media_description_options.sender_options.end());
68 }
Steve Anton64b626b2019-01-29 01:25:2669 absl::c_sort(sorted_senders, [](const cricket::SenderOptions& sender1,
70 const cricket::SenderOptions& sender2) {
71 return sender1.track_id < sender2.track_id;
72 });
73 return absl::c_adjacent_find(sorted_senders,
74 [](const cricket::SenderOptions& sender1,
75 const cricket::SenderOptions& sender2) {
76 return sender1.track_id == sender2.track_id;
77 }) == sorted_senders.end();
wu@webrtc.org91053e72013-08-10 07:18:0478}
wu@webrtc.org91053e72013-08-10 07:18:0479} // namespace
80
81// static
82void WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
83 const SessionDescriptionInterface* source_desc,
deadbeef0ed85b22016-02-24 01:24:5284 const std::string& content_name,
wu@webrtc.org91053e72013-08-10 07:18:0485 SessionDescriptionInterface* dest_desc) {
deadbeef0ed85b22016-02-24 01:24:5286 if (!source_desc) {
wu@webrtc.org91053e72013-08-10 07:18:0487 return;
deadbeef0ed85b22016-02-24 01:24:5288 }
89 const cricket::ContentInfos& contents =
90 source_desc->description()->contents();
91 const cricket::ContentInfo* cinfo =
92 source_desc->description()->GetContentByName(content_name);
93 if (!cinfo) {
94 return;
95 }
96 size_t mediasection_index = static_cast<int>(cinfo - &contents[0]);
97 const IceCandidateCollection* source_candidates =
98 source_desc->candidates(mediasection_index);
99 const IceCandidateCollection* dest_candidates =
100 dest_desc->candidates(mediasection_index);
Taylor Brandstetter4eb1ddd2016-03-02 00:21:07101 if (!source_candidates || !dest_candidates) {
102 return;
103 }
deadbeef0ed85b22016-02-24 01:24:52104 for (size_t n = 0; n < source_candidates->count(); ++n) {
105 const IceCandidateInterface* new_candidate = source_candidates->at(n);
106 if (!dest_candidates->HasCandidate(new_candidate)) {
107 dest_desc->AddCandidate(source_candidates->at(n));
wu@webrtc.org91053e72013-08-10 07:18:04108 }
109 }
110}
111
112WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
Jonas Orelanded99dae2022-03-09 08:28:10113 ConnectionContext* context,
Harald Alvestrandf01bd6c2020-10-23 13:30:46114 const SdpStateProvider* sdp_info,
wu@webrtc.org91053e72013-08-10 07:18:04115 const std::string& session_id,
Harald Alvestrandd89ce532020-10-21 08:59:22116 bool dtls_enabled,
Henrik Boströmd03c23b2016-06-01 09:44:18117 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
Danil Chapovalovb7da8162022-08-22 14:39:34118 rtc::scoped_refptr<rtc::RTCCertificate> certificate,
Harald Alvestranda0947872020-11-09 14:15:00119 std::function<void(const rtc::scoped_refptr<rtc::RTCCertificate>&)>
Jonas Oreland6c7f9842022-04-19 15:24:10120 on_certificate_ready,
Harald Alvestrandd153de62024-09-16 20:28:14121 PayloadTypeSuggester* pt_suggester,
Jonas Oreland6c7f9842022-04-19 15:24:10122 const FieldTrialsView& field_trials)
Jonas Orelanded99dae2022-03-09 08:28:10123 : signaling_thread_(context->signaling_thread()),
Jonas Oreland6c7f9842022-04-19 15:24:10124 transport_desc_factory_(field_trials),
Harald Alvestrandc3fa7c32022-05-22 10:57:01125 session_desc_factory_(context->media_engine(),
126 context->use_rtx(),
127 context->ssrc_generator(),
Harald Alvestrandd153de62024-09-16 20:28:14128 &transport_desc_factory_,
129 pt_suggester),
wu@webrtc.org91053e72013-08-10 07:18:04130 // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp
131 // as the session id and session version. To simplify, it should be fine
132 // to just use a random number as session id and start version from
Artem Titov880fa812021-07-30 20:30:23133 // `kInitSessionVersion`.
wu@webrtc.org91053e72013-08-10 07:18:04134 session_version_(kInitSessionVersion),
Harald Alvestrandd89ce532020-10-21 08:59:22135 cert_generator_(dtls_enabled ? std::move(cert_generator) : nullptr),
Harald Alvestrandf01bd6c2020-10-23 13:30:46136 sdp_info_(sdp_info),
wu@webrtc.org91053e72013-08-10 07:18:04137 session_id_(session_id),
Harald Alvestranda0947872020-11-09 14:15:00138 certificate_request_state_(CERTIFICATE_NOT_NEEDED),
139 on_certificate_ready_(on_certificate_ready) {
Henrik Boströmd03c23b2016-06-01 09:44:18140 RTC_DCHECK(signaling_thread_);
Harald Alvestrandd89ce532020-10-21 08:59:22141
Henrik Boströmd03c23b2016-06-01 09:44:18142 if (!dtls_enabled) {
Harald Alvestrand974044e2024-02-08 13:15:51143 RTC_LOG(LS_INFO) << "DTLS-SRTP disabled";
144 transport_desc_factory_.SetInsecureForTesting();
Henrik Boströmd03c23b2016-06-01 09:44:18145 return;
146 }
Henrik Boströmd03c23b2016-06-01 09:44:18147 if (certificate) {
Artem Titov880fa812021-07-30 20:30:23148 // Use `certificate`.
Henrik Boströmd03c23b2016-06-01 09:44:18149 certificate_request_state_ = CERTIFICATE_WAITING;
150
Mirko Bonadei675513b2017-11-09 10:09:25151 RTC_LOG(LS_VERBOSE) << "DTLS-SRTP enabled; has certificate parameter.";
Danil Chapovalovb22f0c22022-08-19 12:03:54152 RTC_LOG(LS_INFO) << "Using certificate supplied to the constructor.";
153 SetCertificate(certificate);
Harald Alvestrand974044e2024-02-08 13:15:51154 return;
Henrik Boströmd03c23b2016-06-01 09:44:18155 }
Harald Alvestrand974044e2024-02-08 13:15:51156 // Generate certificate.
157 RTC_DCHECK(cert_generator_);
158 certificate_request_state_ = CERTIFICATE_WAITING;
159
160 auto callback = [weak_ptr = weak_factory_.GetWeakPtr()](
161 rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
162 if (!weak_ptr) {
163 return;
164 }
165 if (certificate) {
166 weak_ptr->SetCertificate(std::move(certificate));
167 } else {
168 weak_ptr->OnCertificateRequestFailed();
169 }
170 };
171
172 rtc::KeyParams key_params = rtc::KeyParams();
173 RTC_LOG(LS_VERBOSE)
174 << "DTLS-SRTP enabled; sending DTLS identity request (key type: "
175 << key_params.type() << ").";
176
177 // Request certificate. This happens asynchronously on a different thread.
Florent Castelli8037fc62024-08-29 13:00:40178 cert_generator_->GenerateCertificateAsync(key_params, std::nullopt,
Harald Alvestrand974044e2024-02-08 13:15:51179 std::move(callback));
Henrik Boström87713d02015-08-25 07:53:21180}
wu@webrtc.org91053e72013-08-10 07:18:04181
wu@webrtc.org91053e72013-08-10 07:18:04182WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() {
Tomas Gunnarsson20f74562021-02-04 09:22:50183 RTC_DCHECK_RUN_ON(signaling_thread_);
tommi0f620f42015-07-09 10:25:02184
185 // Fail any requests that were asked for before identity generation completed.
186 FailPendingRequests(kFailedDueToSessionShutdown);
187
Danil Chapovalov97bdfa32022-08-22 17:45:43188 // Process all pending notifications. If we don't do this, requests will
189 // linger and not know they succeeded or failed.
190 // All tasks that suppose to run them are protected with weak_factory_ and
191 // will be cancelled. If we don't protect them, they might trigger after peer
192 // connection is destroyed, which might be surprising.
193 while (!callbacks_.empty()) {
194 std::move(callbacks_.front())();
195 callbacks_.pop();
Henrik Boström87713d02015-08-25 07:53:21196 }
wu@webrtc.org91053e72013-08-10 07:18:04197}
198
199void WebRtcSessionDescriptionFactory::CreateOffer(
200 CreateSessionDescriptionObserver* observer,
deadbeefab9b2d12015-10-14 18:33:11201 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
202 const cricket::MediaSessionOptions& session_options) {
Tomas Gunnarsson20f74562021-02-04 09:22:50203 RTC_DCHECK_RUN_ON(signaling_thread_);
wu@webrtc.org91053e72013-08-10 07:18:04204 std::string error = "CreateOffer";
Henrik Boström87713d02015-08-25 07:53:21205 if (certificate_request_state_ == CERTIFICATE_FAILED) {
wu@webrtc.org91053e72013-08-10 07:18:04206 error += kFailedDueToIdentityFailed;
Philipp Hanckeb916a702023-09-18 11:06:24207 PostCreateSessionDescriptionFailed(
208 observer, RTCError(RTCErrorType::INTERNAL_ERROR, std::move(error)));
wu@webrtc.org91053e72013-08-10 07:18:04209 return;
210 }
211
zhihuang1c378ed2017-08-17 21:10:50212 if (!ValidMediaSessionOptions(session_options)) {
213 error += " called with invalid session options";
Philipp Hanckeb916a702023-09-18 11:06:24214 PostCreateSessionDescriptionFailed(
215 observer, RTCError(RTCErrorType::INTERNAL_ERROR, std::move(error)));
wu@webrtc.org91053e72013-08-10 07:18:04216 return;
217 }
218
wu@webrtc.org91053e72013-08-10 07:18:04219 CreateSessionDescriptionRequest request(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16220 CreateSessionDescriptionRequest::kOffer, observer, session_options);
Henrik Boström87713d02015-08-25 07:53:21221 if (certificate_request_state_ == CERTIFICATE_WAITING) {
wu@webrtc.org91053e72013-08-10 07:18:04222 create_session_description_requests_.push(request);
223 } else {
nisseede5da42017-01-12 13:15:36224 RTC_DCHECK(certificate_request_state_ == CERTIFICATE_SUCCEEDED ||
225 certificate_request_state_ == CERTIFICATE_NOT_NEEDED);
wu@webrtc.org91053e72013-08-10 07:18:04226 InternalCreateOffer(request);
227 }
228}
229
230void WebRtcSessionDescriptionFactory::CreateAnswer(
231 CreateSessionDescriptionObserver* observer,
deadbeefab9b2d12015-10-14 18:33:11232 const cricket::MediaSessionOptions& session_options) {
wu@webrtc.org91053e72013-08-10 07:18:04233 std::string error = "CreateAnswer";
Henrik Boström87713d02015-08-25 07:53:21234 if (certificate_request_state_ == CERTIFICATE_FAILED) {
wu@webrtc.org91053e72013-08-10 07:18:04235 error += kFailedDueToIdentityFailed;
Philipp Hanckeb916a702023-09-18 11:06:24236 PostCreateSessionDescriptionFailed(
237 observer, RTCError(RTCErrorType::INTERNAL_ERROR, std::move(error)));
wu@webrtc.org91053e72013-08-10 07:18:04238 return;
239 }
Harald Alvestrandf01bd6c2020-10-23 13:30:46240 if (!sdp_info_->remote_description()) {
wu@webrtc.org91053e72013-08-10 07:18:04241 error += " can't be called before SetRemoteDescription.";
Philipp Hanckeb916a702023-09-18 11:06:24242 PostCreateSessionDescriptionFailed(
243 observer, RTCError(RTCErrorType::INTERNAL_ERROR, std::move(error)));
wu@webrtc.org91053e72013-08-10 07:18:04244 return;
245 }
Harald Alvestrandf01bd6c2020-10-23 13:30:46246 if (sdp_info_->remote_description()->GetType() != SdpType::kOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04247 error += " failed because remote_description is not an offer.";
Philipp Hanckeb916a702023-09-18 11:06:24248 PostCreateSessionDescriptionFailed(
249 observer, RTCError(RTCErrorType::INTERNAL_ERROR, std::move(error)));
wu@webrtc.org91053e72013-08-10 07:18:04250 return;
251 }
252
zhihuang1c378ed2017-08-17 21:10:50253 if (!ValidMediaSessionOptions(session_options)) {
254 error += " called with invalid session options.";
Philipp Hanckeb916a702023-09-18 11:06:24255 PostCreateSessionDescriptionFailed(
256 observer, RTCError(RTCErrorType::INTERNAL_ERROR, std::move(error)));
wu@webrtc.org91053e72013-08-10 07:18:04257 return;
258 }
wu@webrtc.org91053e72013-08-10 07:18:04259
260 CreateSessionDescriptionRequest request(
deadbeefab9b2d12015-10-14 18:33:11261 CreateSessionDescriptionRequest::kAnswer, observer, session_options);
Henrik Boström87713d02015-08-25 07:53:21262 if (certificate_request_state_ == CERTIFICATE_WAITING) {
wu@webrtc.org91053e72013-08-10 07:18:04263 create_session_description_requests_.push(request);
264 } else {
nisseede5da42017-01-12 13:15:36265 RTC_DCHECK(certificate_request_state_ == CERTIFICATE_SUCCEEDED ||
266 certificate_request_state_ == CERTIFICATE_NOT_NEEDED);
wu@webrtc.org91053e72013-08-10 07:18:04267 InternalCreateAnswer(request);
268 }
269}
270
wu@webrtc.org91053e72013-08-10 07:18:04271void WebRtcSessionDescriptionFactory::InternalCreateOffer(
272 CreateSessionDescriptionRequest request) {
Harald Alvestrandf01bd6c2020-10-23 13:30:46273 if (sdp_info_->local_description()) {
zhihuang1c378ed2017-08-17 21:10:50274 // If the needs-ice-restart flag is set as described by JSEP, we should
275 // generate an offer with a new ufrag/password to trigger an ICE restart.
276 for (cricket::MediaDescriptionOptions& options :
277 request.options.media_description_options) {
Harald Alvestrandf01bd6c2020-10-23 13:30:46278 if (sdp_info_->NeedsIceRestart(options.mid)) {
zhihuang1c378ed2017-08-17 21:10:50279 options.transport_options.ice_restart = true;
deadbeefd1a38b52016-12-10 21:15:33280 }
281 }
282 }
283
Philipp Hancke2bf1b992023-09-26 07:04:46284 auto result = session_desc_factory_.CreateOfferOrError(
285 request.options, sdp_info_->local_description()
286 ? sdp_info_->local_description()->description()
287 : nullptr);
288 if (!result.ok()) {
289 PostCreateSessionDescriptionFailed(request.observer.get(), result.error());
Steve Anton6fe1fba2018-12-11 18:15:23290 return;
291 }
Philipp Hancke2bf1b992023-09-26 07:04:46292 std::unique_ptr<cricket::SessionDescription> desc = std::move(result.value());
293 RTC_CHECK(desc);
Steve Anton6fe1fba2018-12-11 18:15:23294
wu@webrtc.org91053e72013-08-10 07:18:04295 // RFC 3264
296 // When issuing an offer that modifies the session,
297 // the "o=" line of the new SDP MUST be identical to that in the
298 // previous SDP, except that the version in the origin field MUST
299 // increment by one from the previous SDP.
300
301 // Just increase the version number by one each time when a new offer
302 // is created regardless if it's identical to the previous one or not.
Artem Titov880fa812021-07-30 20:30:23303 // The `session_version_` is a uint64_t, the wrap around should not happen.
nisseede5da42017-01-12 13:15:36304 RTC_DCHECK(session_version_ + 1 > session_version_);
Mirko Bonadei317a1f02019-09-17 15:06:18305 auto offer = std::make_unique<JsepSessionDescription>(
Steve Anton6fe1fba2018-12-11 18:15:23306 SdpType::kOffer, std::move(desc), session_id_,
307 rtc::ToString(session_version_++));
Harald Alvestrandf01bd6c2020-10-23 13:30:46308 if (sdp_info_->local_description()) {
zhihuang1c378ed2017-08-17 21:10:50309 for (const cricket::MediaDescriptionOptions& options :
310 request.options.media_description_options) {
311 if (!options.transport_options.ice_restart) {
Harald Alvestrandf01bd6c2020-10-23 13:30:46312 CopyCandidatesFromSessionDescription(sdp_info_->local_description(),
Steve Antona3a92c22017-12-07 18:27:41313 options.mid, offer.get());
deadbeef0ed85b22016-02-24 01:24:52314 }
315 }
wu@webrtc.org91053e72013-08-10 07:18:04316 }
Niels Möllerafb246b2022-04-20 12:26:50317 PostCreateSessionDescriptionSucceeded(request.observer.get(),
318 std::move(offer));
wu@webrtc.org91053e72013-08-10 07:18:04319}
320
321void WebRtcSessionDescriptionFactory::InternalCreateAnswer(
322 CreateSessionDescriptionRequest request) {
Harald Alvestrandf01bd6c2020-10-23 13:30:46323 if (sdp_info_->remote_description()) {
zhihuang1c378ed2017-08-17 21:10:50324 for (cricket::MediaDescriptionOptions& options :
325 request.options.media_description_options) {
deadbeef0ed85b22016-02-24 01:24:52326 // According to http://tools.ietf.org/html/rfc5245#section-9.2.1.1
327 // an answer should also contain new ICE ufrag and password if an offer
328 // has been received with new ufrag and password.
zhihuang1c378ed2017-08-17 21:10:50329 options.transport_options.ice_restart =
Harald Alvestrandf01bd6c2020-10-23 13:30:46330 sdp_info_->IceRestartPending(options.mid);
Harald Alvestrandd89ce532020-10-21 08:59:22331 // We should pass the current DTLS role to the transport description
deadbeef0ed85b22016-02-24 01:24:52332 // factory, if there is already an existing ongoing session.
Florent Castelli8037fc62024-08-29 13:00:40333 std::optional<rtc::SSLRole> dtls_role =
Harald Alvestrandf01bd6c2020-10-23 13:30:46334 sdp_info_->GetDtlsRole(options.mid);
Harald Alvestrandd89ce532020-10-21 08:59:22335 if (dtls_role) {
zhihuang1c378ed2017-08-17 21:10:50336 options.transport_options.prefer_passive_role =
Harald Alvestrandd89ce532020-10-21 08:59:22337 (rtc::SSL_SERVER == *dtls_role);
deadbeef0ed85b22016-02-24 01:24:52338 }
339 }
sergeyu@chromium.org0be6aa02013-08-23 23:21:25340 }
wu@webrtc.org91053e72013-08-10 07:18:04341
Philipp Hancke2bf1b992023-09-26 07:04:46342 auto result = session_desc_factory_.CreateAnswerOrError(
343 sdp_info_->remote_description()
344 ? sdp_info_->remote_description()->description()
345 : nullptr,
346 request.options,
347 sdp_info_->local_description()
348 ? sdp_info_->local_description()->description()
349 : nullptr);
350 if (!result.ok()) {
351 PostCreateSessionDescriptionFailed(request.observer.get(), result.error());
Steve Anton6fe1fba2018-12-11 18:15:23352 return;
353 }
Philipp Hancke2bf1b992023-09-26 07:04:46354 std::unique_ptr<cricket::SessionDescription> desc = std::move(result.value());
355 RTC_CHECK(desc);
Steve Anton6fe1fba2018-12-11 18:15:23356
wu@webrtc.org91053e72013-08-10 07:18:04357 // RFC 3264
358 // If the answer is different from the offer in any way (different IP
359 // addresses, ports, etc.), the origin line MUST be different in the answer.
360 // In that case, the version number in the "o=" line of the answer is
361 // unrelated to the version number in the o line of the offer.
Artem Titov880fa812021-07-30 20:30:23362 // Get a new version number by increasing the `session_version_answer_`.
363 // The `session_version_` is a uint64_t, the wrap around should not happen.
nisseede5da42017-01-12 13:15:36364 RTC_DCHECK(session_version_ + 1 > session_version_);
Mirko Bonadei317a1f02019-09-17 15:06:18365 auto answer = std::make_unique<JsepSessionDescription>(
Steve Anton6fe1fba2018-12-11 18:15:23366 SdpType::kAnswer, std::move(desc), session_id_,
367 rtc::ToString(session_version_++));
Harald Alvestrandf01bd6c2020-10-23 13:30:46368 if (sdp_info_->local_description()) {
zhihuang1c378ed2017-08-17 21:10:50369 // Include all local ICE candidates in the SessionDescription unless
370 // the remote peer has requested an ICE restart.
371 for (const cricket::MediaDescriptionOptions& options :
372 request.options.media_description_options) {
373 if (!options.transport_options.ice_restart) {
Harald Alvestrandf01bd6c2020-10-23 13:30:46374 CopyCandidatesFromSessionDescription(sdp_info_->local_description(),
Steve Antona3a92c22017-12-07 18:27:41375 options.mid, answer.get());
deadbeef0ed85b22016-02-24 01:24:52376 }
377 }
wu@webrtc.org91053e72013-08-10 07:18:04378 }
Niels Möllerafb246b2022-04-20 12:26:50379 PostCreateSessionDescriptionSucceeded(request.observer.get(),
380 std::move(answer));
wu@webrtc.org91053e72013-08-10 07:18:04381}
382
tommi0f620f42015-07-09 10:25:02383void WebRtcSessionDescriptionFactory::FailPendingRequests(
384 const std::string& reason) {
Tomas Gunnarsson20f74562021-02-04 09:22:50385 RTC_DCHECK_RUN_ON(signaling_thread_);
tommi0f620f42015-07-09 10:25:02386 while (!create_session_description_requests_.empty()) {
387 const CreateSessionDescriptionRequest& request =
388 create_session_description_requests_.front();
Yves Gerey665174f2018-06-19 13:03:05389 PostCreateSessionDescriptionFailed(
Niels Möllerafb246b2022-04-20 12:26:50390 request.observer.get(),
Philipp Hanckeb916a702023-09-18 11:06:24391 RTCError(RTCErrorType::INTERNAL_ERROR,
392 ((request.type == CreateSessionDescriptionRequest::kOffer)
393 ? "CreateOffer"
394 : "CreateAnswer") +
395 reason));
tommi0f620f42015-07-09 10:25:02396 create_session_description_requests_.pop();
397 }
398}
399
wu@webrtc.org91053e72013-08-10 07:18:04400void WebRtcSessionDescriptionFactory::PostCreateSessionDescriptionFailed(
Yves Gerey665174f2018-06-19 13:03:05401 CreateSessionDescriptionObserver* observer,
Philipp Hanckeb916a702023-09-18 11:06:24402 RTCError error) {
Danil Chapovalov97bdfa32022-08-22 17:45:43403 Post([observer =
404 rtc::scoped_refptr<CreateSessionDescriptionObserver>(observer),
Philipp Hanckeb916a702023-09-18 11:06:24405 error]() mutable { observer->OnFailure(error); });
406 RTC_LOG(LS_ERROR) << "CreateSessionDescription failed: " << error.message();
wu@webrtc.org91053e72013-08-10 07:18:04407}
408
409void WebRtcSessionDescriptionFactory::PostCreateSessionDescriptionSucceeded(
410 CreateSessionDescriptionObserver* observer,
Steve Antona3a92c22017-12-07 18:27:41411 std::unique_ptr<SessionDescriptionInterface> description) {
Danil Chapovalov97bdfa32022-08-22 17:45:43412 Post([observer =
413 rtc::scoped_refptr<CreateSessionDescriptionObserver>(observer),
414 description = std::move(description)]() mutable {
415 observer->OnSuccess(description.release());
416 });
417}
418
419void WebRtcSessionDescriptionFactory::Post(
420 absl::AnyInvocable<void() &&> callback) {
421 RTC_DCHECK_RUN_ON(signaling_thread_);
422 callbacks_.push(std::move(callback));
423 signaling_thread_->PostTask([weak_ptr = weak_factory_.GetWeakPtr()] {
424 if (weak_ptr) {
425 auto& callbacks = weak_ptr->callbacks_;
426 // Callbacks are pushed from the same thread, thus this task should
427 // corresond to the first entry in the queue.
428 RTC_DCHECK(!callbacks.empty());
429 std::move(callbacks.front())();
430 callbacks.pop();
431 }
432 });
wu@webrtc.org91053e72013-08-10 07:18:04433}
434
Henrik Boströmd03c23b2016-06-01 09:44:18435void WebRtcSessionDescriptionFactory::OnCertificateRequestFailed() {
Tomas Gunnarsson20f74562021-02-04 09:22:50436 RTC_DCHECK_RUN_ON(signaling_thread_);
wu@webrtc.org91053e72013-08-10 07:18:04437
Mirko Bonadei675513b2017-11-09 10:09:25438 RTC_LOG(LS_ERROR) << "Asynchronous certificate generation request failed.";
Henrik Boström87713d02015-08-25 07:53:21439 certificate_request_state_ = CERTIFICATE_FAILED;
wu@webrtc.org91053e72013-08-10 07:18:04440
tommi0f620f42015-07-09 10:25:02441 FailPendingRequests(kFailedDueToIdentityFailed);
wu@webrtc.org91053e72013-08-10 07:18:04442}
443
Henrik Boströmd8281982015-08-27 08:12:24444void WebRtcSessionDescriptionFactory::SetCertificate(
Danil Chapovalovb7da8162022-08-22 14:39:34445 rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
henrikg91d6ede2015-09-17 07:24:34446 RTC_DCHECK(certificate);
Mirko Bonadei675513b2017-11-09 10:09:25447 RTC_LOG(LS_VERBOSE) << "Setting new certificate.";
jiayl@webrtc.org61e00b02015-03-04 22:17:38448
Henrik Boström87713d02015-08-25 07:53:21449 certificate_request_state_ = CERTIFICATE_SUCCEEDED;
Harald Alvestranda0947872020-11-09 14:15:00450
451 on_certificate_ready_(certificate);
wu@webrtc.org91053e72013-08-10 07:18:04452
Danil Chapovalovb7da8162022-08-22 14:39:34453 transport_desc_factory_.set_certificate(std::move(certificate));
wu@webrtc.org91053e72013-08-10 07:18:04454
455 while (!create_session_description_requests_.empty()) {
456 if (create_session_description_requests_.front().type ==
457 CreateSessionDescriptionRequest::kOffer) {
458 InternalCreateOffer(create_session_description_requests_.front());
459 } else {
460 InternalCreateAnswer(create_session_description_requests_.front());
461 }
462 create_session_description_requests_.pop();
463 }
464}
Harald Alvestrand974044e2024-02-08 13:15:51465
wu@webrtc.org91053e72013-08-10 07:18:04466} // namespace webrtc