OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2013 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 12 matching lines...) Expand all Loading... |
23 | 23 |
24 namespace webrtc { | 24 namespace webrtc { |
25 namespace { | 25 namespace { |
26 static const char kFailedDueToIdentityFailed[] = | 26 static const char kFailedDueToIdentityFailed[] = |
27 " failed because DTLS identity request failed"; | 27 " failed because DTLS identity request failed"; |
28 static const char kFailedDueToSessionShutdown[] = | 28 static const char kFailedDueToSessionShutdown[] = |
29 " failed because the session was shut down"; | 29 " failed because the session was shut down"; |
30 | 30 |
31 static const uint64_t kInitSessionVersion = 2; | 31 static const uint64_t kInitSessionVersion = 2; |
32 | 32 |
33 static bool CompareStream(const MediaSessionOptions::Stream& stream1, | 33 static bool CompareSenderOptions(const cricket::SenderOptions& sender1, |
34 const MediaSessionOptions::Stream& stream2) { | 34 const cricket::SenderOptions& sender2) { |
35 return stream1.id < stream2.id; | 35 return sender1.track_id < sender2.track_id; |
36 } | 36 } |
37 | 37 |
38 static bool SameId(const MediaSessionOptions::Stream& stream1, | 38 static bool SameId(const cricket::SenderOptions& sender1, |
39 const MediaSessionOptions::Stream& stream2) { | 39 const cricket::SenderOptions& sender2) { |
40 return stream1.id == stream2.id; | 40 return sender1.track_id == sender2.track_id; |
41 } | 41 } |
42 | 42 |
43 // Checks if each Stream within the |streams| has unique id. | 43 // Check that each sender has a unique ID. |
44 static bool ValidStreams(const MediaSessionOptions::Streams& streams) { | 44 static bool ValidMediaSessionOptions( |
45 MediaSessionOptions::Streams sorted_streams = streams; | 45 const cricket::MediaSessionOptions& session_options) { |
46 std::sort(sorted_streams.begin(), sorted_streams.end(), CompareStream); | 46 std::vector<cricket::SenderOptions> sorted_senders; |
47 MediaSessionOptions::Streams::iterator it = | 47 for (const cricket::MediaDescriptionOptions& media_description_options : |
48 std::adjacent_find(sorted_streams.begin(), sorted_streams.end(), | 48 session_options.media_description_options) { |
49 SameId); | 49 sorted_senders.insert(sorted_senders.end(), |
50 return it == sorted_streams.end(); | 50 media_description_options.sender_options.begin(), |
| 51 media_description_options.sender_options.end()); |
| 52 } |
| 53 std::sort(sorted_senders.begin(), sorted_senders.end(), CompareSenderOptions); |
| 54 std::vector<cricket::SenderOptions>::iterator it = |
| 55 std::adjacent_find(sorted_senders.begin(), sorted_senders.end(), SameId); |
| 56 return it == sorted_senders.end(); |
51 } | 57 } |
52 | 58 |
53 enum { | 59 enum { |
54 MSG_CREATE_SESSIONDESCRIPTION_SUCCESS, | 60 MSG_CREATE_SESSIONDESCRIPTION_SUCCESS, |
55 MSG_CREATE_SESSIONDESCRIPTION_FAILED, | 61 MSG_CREATE_SESSIONDESCRIPTION_FAILED, |
56 MSG_USE_CONSTRUCTOR_CERTIFICATE | 62 MSG_USE_CONSTRUCTOR_CERTIFICATE |
57 }; | 63 }; |
58 | 64 |
59 struct CreateSessionDescriptionMsg : public rtc::MessageData { | 65 struct CreateSessionDescriptionMsg : public rtc::MessageData { |
60 explicit CreateSessionDescriptionMsg( | 66 explicit CreateSessionDescriptionMsg( |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp | 127 // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp |
122 // as the session id and session version. To simplify, it should be fine | 128 // as the session id and session version. To simplify, it should be fine |
123 // to just use a random number as session id and start version from | 129 // to just use a random number as session id and start version from |
124 // |kInitSessionVersion|. | 130 // |kInitSessionVersion|. |
125 session_version_(kInitSessionVersion), | 131 session_version_(kInitSessionVersion), |
126 cert_generator_(std::move(cert_generator)), | 132 cert_generator_(std::move(cert_generator)), |
127 session_(session), | 133 session_(session), |
128 session_id_(session_id), | 134 session_id_(session_id), |
129 certificate_request_state_(CERTIFICATE_NOT_NEEDED) { | 135 certificate_request_state_(CERTIFICATE_NOT_NEEDED) { |
130 RTC_DCHECK(signaling_thread_); | 136 RTC_DCHECK(signaling_thread_); |
131 session_desc_factory_.set_add_legacy_streams(false); | |
132 bool dtls_enabled = cert_generator_ || certificate; | 137 bool dtls_enabled = cert_generator_ || certificate; |
133 // SRTP-SDES is disabled if DTLS is on. | 138 // SRTP-SDES is disabled if DTLS is on. |
134 SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED); | 139 SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED); |
135 if (!dtls_enabled) { | 140 if (!dtls_enabled) { |
136 LOG(LS_VERBOSE) << "DTLS-SRTP disabled."; | 141 LOG(LS_VERBOSE) << "DTLS-SRTP disabled."; |
137 return; | 142 return; |
138 } | 143 } |
139 | 144 |
140 if (certificate) { | 145 if (certificate) { |
141 // Use |certificate|. | 146 // Use |certificate|. |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 const PeerConnectionInterface::RTCOfferAnswerOptions& options, | 235 const PeerConnectionInterface::RTCOfferAnswerOptions& options, |
231 const cricket::MediaSessionOptions& session_options) { | 236 const cricket::MediaSessionOptions& session_options) { |
232 std::string error = "CreateOffer"; | 237 std::string error = "CreateOffer"; |
233 if (certificate_request_state_ == CERTIFICATE_FAILED) { | 238 if (certificate_request_state_ == CERTIFICATE_FAILED) { |
234 error += kFailedDueToIdentityFailed; | 239 error += kFailedDueToIdentityFailed; |
235 LOG(LS_ERROR) << error; | 240 LOG(LS_ERROR) << error; |
236 PostCreateSessionDescriptionFailed(observer, error); | 241 PostCreateSessionDescriptionFailed(observer, error); |
237 return; | 242 return; |
238 } | 243 } |
239 | 244 |
240 if (!ValidStreams(session_options.streams)) { | 245 if (!ValidMediaSessionOptions(session_options)) { |
241 error += " called with invalid media streams."; | 246 error += " called with invalid session options"; |
242 LOG(LS_ERROR) << error; | 247 LOG(LS_ERROR) << error; |
243 PostCreateSessionDescriptionFailed(observer, error); | 248 PostCreateSessionDescriptionFailed(observer, error); |
244 return; | 249 return; |
245 } | 250 } |
246 | 251 |
247 CreateSessionDescriptionRequest request( | 252 CreateSessionDescriptionRequest request( |
248 CreateSessionDescriptionRequest::kOffer, observer, session_options); | 253 CreateSessionDescriptionRequest::kOffer, observer, session_options); |
249 if (certificate_request_state_ == CERTIFICATE_WAITING) { | 254 if (certificate_request_state_ == CERTIFICATE_WAITING) { |
250 create_session_description_requests_.push(request); | 255 create_session_description_requests_.push(request); |
251 } else { | 256 } else { |
(...skipping 20 matching lines...) Expand all Loading... |
272 return; | 277 return; |
273 } | 278 } |
274 if (session_->remote_description()->type() != | 279 if (session_->remote_description()->type() != |
275 JsepSessionDescription::kOffer) { | 280 JsepSessionDescription::kOffer) { |
276 error += " failed because remote_description is not an offer."; | 281 error += " failed because remote_description is not an offer."; |
277 LOG(LS_ERROR) << error; | 282 LOG(LS_ERROR) << error; |
278 PostCreateSessionDescriptionFailed(observer, error); | 283 PostCreateSessionDescriptionFailed(observer, error); |
279 return; | 284 return; |
280 } | 285 } |
281 | 286 |
282 if (!ValidStreams(session_options.streams)) { | 287 if (!ValidMediaSessionOptions(session_options)) { |
283 error += " called with invalid media streams."; | 288 error += " called with invalid session options."; |
284 LOG(LS_ERROR) << error; | 289 LOG(LS_ERROR) << error; |
285 PostCreateSessionDescriptionFailed(observer, error); | 290 PostCreateSessionDescriptionFailed(observer, error); |
286 return; | 291 return; |
287 } | 292 } |
288 | 293 |
289 CreateSessionDescriptionRequest request( | 294 CreateSessionDescriptionRequest request( |
290 CreateSessionDescriptionRequest::kAnswer, observer, session_options); | 295 CreateSessionDescriptionRequest::kAnswer, observer, session_options); |
291 if (certificate_request_state_ == CERTIFICATE_WAITING) { | 296 if (certificate_request_state_ == CERTIFICATE_WAITING) { |
292 create_session_description_requests_.push(request); | 297 create_session_description_requests_.push(request); |
293 } else { | 298 } else { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 } | 338 } |
334 default: | 339 default: |
335 RTC_NOTREACHED(); | 340 RTC_NOTREACHED(); |
336 break; | 341 break; |
337 } | 342 } |
338 } | 343 } |
339 | 344 |
340 void WebRtcSessionDescriptionFactory::InternalCreateOffer( | 345 void WebRtcSessionDescriptionFactory::InternalCreateOffer( |
341 CreateSessionDescriptionRequest request) { | 346 CreateSessionDescriptionRequest request) { |
342 if (session_->local_description()) { | 347 if (session_->local_description()) { |
343 for (const cricket::TransportInfo& transport : | 348 // If the needs-ice-restart flag is set as described by JSEP, we should |
344 session_->local_description()->description()->transport_infos()) { | 349 // generate an offer with a new ufrag/password to trigger an ICE restart. |
345 // If the needs-ice-restart flag is set as described by JSEP, we should | 350 for (cricket::MediaDescriptionOptions& options : |
346 // generate an offer with a new ufrag/password to trigger an ICE restart. | 351 request.options.media_description_options) { |
347 if (session_->NeedsIceRestart(transport.content_name)) { | 352 if (session_->NeedsIceRestart(options.mid)) { |
348 request.options.transport_options[transport.content_name].ice_restart = | 353 options.transport_options.ice_restart = true; |
349 true; | |
350 } | 354 } |
351 } | 355 } |
352 } | 356 } |
353 | 357 |
354 cricket::SessionDescription* desc(session_desc_factory_.CreateOffer( | 358 cricket::SessionDescription* desc(session_desc_factory_.CreateOffer( |
355 request.options, session_->local_description() | 359 request.options, session_->local_description() |
356 ? session_->local_description()->description() | 360 ? session_->local_description()->description() |
357 : nullptr)); | 361 : nullptr)); |
358 // RFC 3264 | 362 // RFC 3264 |
359 // When issuing an offer that modifies the session, | 363 // When issuing an offer that modifies the session, |
360 // the "o=" line of the new SDP MUST be identical to that in the | 364 // the "o=" line of the new SDP MUST be identical to that in the |
361 // previous SDP, except that the version in the origin field MUST | 365 // previous SDP, except that the version in the origin field MUST |
362 // increment by one from the previous SDP. | 366 // increment by one from the previous SDP. |
363 | 367 |
364 // Just increase the version number by one each time when a new offer | 368 // Just increase the version number by one each time when a new offer |
365 // is created regardless if it's identical to the previous one or not. | 369 // is created regardless if it's identical to the previous one or not. |
366 // The |session_version_| is a uint64_t, the wrap around should not happen. | 370 // The |session_version_| is a uint64_t, the wrap around should not happen. |
367 RTC_DCHECK(session_version_ + 1 > session_version_); | 371 RTC_DCHECK(session_version_ + 1 > session_version_); |
368 JsepSessionDescription* offer(new JsepSessionDescription( | 372 JsepSessionDescription* offer(new JsepSessionDescription( |
369 JsepSessionDescription::kOffer)); | 373 JsepSessionDescription::kOffer)); |
370 if (!offer->Initialize(desc, session_id_, | 374 if (!offer->Initialize(desc, session_id_, |
371 rtc::ToString(session_version_++))) { | 375 rtc::ToString(session_version_++))) { |
372 delete offer; | 376 delete offer; |
373 PostCreateSessionDescriptionFailed(request.observer, | 377 PostCreateSessionDescriptionFailed(request.observer, |
374 "Failed to initialize the offer."); | 378 "Failed to initialize the offer."); |
375 return; | 379 return; |
376 } | 380 } |
377 if (session_->local_description()) { | 381 if (session_->local_description()) { |
378 for (const cricket::ContentInfo& content : | 382 for (const cricket::MediaDescriptionOptions& options : |
379 session_->local_description()->description()->contents()) { | 383 request.options.media_description_options) { |
380 // Include all local ICE candidates in the SessionDescription unless | 384 if (!options.transport_options.ice_restart) { |
381 // an ICE restart was requested. | |
382 if (!request.options.transport_options[content.name].ice_restart) { | |
383 CopyCandidatesFromSessionDescription(session_->local_description(), | 385 CopyCandidatesFromSessionDescription(session_->local_description(), |
384 content.name, offer); | 386 options.mid, offer); |
385 } | 387 } |
386 } | 388 } |
387 } | 389 } |
388 PostCreateSessionDescriptionSucceeded(request.observer, offer); | 390 PostCreateSessionDescriptionSucceeded(request.observer, offer); |
389 } | 391 } |
390 | 392 |
391 void WebRtcSessionDescriptionFactory::InternalCreateAnswer( | 393 void WebRtcSessionDescriptionFactory::InternalCreateAnswer( |
392 CreateSessionDescriptionRequest request) { | 394 CreateSessionDescriptionRequest request) { |
393 if (session_->remote_description()) { | 395 if (session_->remote_description()) { |
394 for (const cricket::ContentInfo& content : | 396 for (cricket::MediaDescriptionOptions& options : |
395 session_->remote_description()->description()->contents()) { | 397 request.options.media_description_options) { |
396 // According to http://tools.ietf.org/html/rfc5245#section-9.2.1.1 | 398 // According to http://tools.ietf.org/html/rfc5245#section-9.2.1.1 |
397 // an answer should also contain new ICE ufrag and password if an offer | 399 // an answer should also contain new ICE ufrag and password if an offer |
398 // has been received with new ufrag and password. | 400 // has been received with new ufrag and password. |
399 request.options.transport_options[content.name].ice_restart = | 401 options.transport_options.ice_restart = |
400 session_->IceRestartPending(content.name); | 402 session_->IceRestartPending(options.mid); |
401 // We should pass the current SSL role to the transport description | 403 // We should pass the current SSL role to the transport description |
402 // factory, if there is already an existing ongoing session. | 404 // factory, if there is already an existing ongoing session. |
403 rtc::SSLRole ssl_role; | 405 rtc::SSLRole ssl_role; |
404 if (session_->GetSslRole(content.name, &ssl_role)) { | 406 if (session_->GetSslRole(options.mid, &ssl_role)) { |
405 request.options.transport_options[content.name].prefer_passive_role = | 407 options.transport_options.prefer_passive_role = |
406 (rtc::SSL_SERVER == ssl_role); | 408 (rtc::SSL_SERVER == ssl_role); |
407 } | 409 } |
408 } | 410 } |
409 } | 411 } |
410 | 412 |
411 cricket::SessionDescription* desc(session_desc_factory_.CreateAnswer( | 413 cricket::SessionDescription* desc(session_desc_factory_.CreateAnswer( |
412 session_->remote_description() | 414 session_->remote_description() |
413 ? session_->remote_description()->description() | 415 ? session_->remote_description()->description() |
414 : nullptr, | 416 : nullptr, |
415 request.options, session_->local_description() | 417 request.options, session_->local_description() |
(...skipping 10 matching lines...) Expand all Loading... |
426 JsepSessionDescription* answer(new JsepSessionDescription( | 428 JsepSessionDescription* answer(new JsepSessionDescription( |
427 JsepSessionDescription::kAnswer)); | 429 JsepSessionDescription::kAnswer)); |
428 if (!answer->Initialize(desc, session_id_, | 430 if (!answer->Initialize(desc, session_id_, |
429 rtc::ToString(session_version_++))) { | 431 rtc::ToString(session_version_++))) { |
430 delete answer; | 432 delete answer; |
431 PostCreateSessionDescriptionFailed(request.observer, | 433 PostCreateSessionDescriptionFailed(request.observer, |
432 "Failed to initialize the answer."); | 434 "Failed to initialize the answer."); |
433 return; | 435 return; |
434 } | 436 } |
435 if (session_->local_description()) { | 437 if (session_->local_description()) { |
436 for (const cricket::ContentInfo& content : | 438 // Include all local ICE candidates in the SessionDescription unless |
437 session_->local_description()->description()->contents()) { | 439 // the remote peer has requested an ICE restart. |
438 // Include all local ICE candidates in the SessionDescription unless | 440 for (const cricket::MediaDescriptionOptions& options : |
439 // the remote peer has requested an ICE restart. | 441 request.options.media_description_options) { |
440 if (!request.options.transport_options[content.name].ice_restart) { | 442 if (!options.transport_options.ice_restart) { |
441 CopyCandidatesFromSessionDescription(session_->local_description(), | 443 CopyCandidatesFromSessionDescription(session_->local_description(), |
442 content.name, answer); | 444 options.mid, answer); |
443 } | 445 } |
444 } | 446 } |
445 } | 447 } |
446 PostCreateSessionDescriptionSucceeded(request.observer, answer); | 448 PostCreateSessionDescriptionSucceeded(request.observer, answer); |
447 } | 449 } |
448 | 450 |
449 void WebRtcSessionDescriptionFactory::FailPendingRequests( | 451 void WebRtcSessionDescriptionFactory::FailPendingRequests( |
450 const std::string& reason) { | 452 const std::string& reason) { |
451 RTC_DCHECK(signaling_thread_->IsCurrent()); | 453 RTC_DCHECK(signaling_thread_->IsCurrent()); |
452 while (!create_session_description_requests_.empty()) { | 454 while (!create_session_description_requests_.empty()) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 if (create_session_description_requests_.front().type == | 503 if (create_session_description_requests_.front().type == |
502 CreateSessionDescriptionRequest::kOffer) { | 504 CreateSessionDescriptionRequest::kOffer) { |
503 InternalCreateOffer(create_session_description_requests_.front()); | 505 InternalCreateOffer(create_session_description_requests_.front()); |
504 } else { | 506 } else { |
505 InternalCreateAnswer(create_session_description_requests_.front()); | 507 InternalCreateAnswer(create_session_description_requests_.front()); |
506 } | 508 } |
507 create_session_description_requests_.pop(); | 509 create_session_description_requests_.pop(); |
508 } | 510 } |
509 } | 511 } |
510 } // namespace webrtc | 512 } // namespace webrtc |
OLD | NEW |