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