| 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 |
| 11 #include "webrtc/api/webrtcsessiondescriptionfactory.h" | 11 #include "webrtc/api/webrtcsessiondescriptionfactory.h" |
| 12 | 12 |
| 13 #include <utility> | 13 #include <utility> |
| 14 | 14 |
| 15 #include "webrtc/api/dtlsidentitystore.h" |
| 15 #include "webrtc/api/jsep.h" | 16 #include "webrtc/api/jsep.h" |
| 16 #include "webrtc/api/jsepsessiondescription.h" | 17 #include "webrtc/api/jsepsessiondescription.h" |
| 17 #include "webrtc/api/mediaconstraintsinterface.h" | 18 #include "webrtc/api/mediaconstraintsinterface.h" |
| 18 #include "webrtc/api/webrtcsession.h" | 19 #include "webrtc/api/webrtcsession.h" |
| 19 #include "webrtc/base/sslidentity.h" | 20 #include "webrtc/base/sslidentity.h" |
| 20 | 21 |
| 21 using cricket::MediaSessionOptions; | 22 using cricket::MediaSessionOptions; |
| 22 | 23 |
| 23 namespace webrtc { | 24 namespace webrtc { |
| 24 namespace { | 25 namespace { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 webrtc::CreateSessionDescriptionObserver* observer) | 61 webrtc::CreateSessionDescriptionObserver* observer) |
| 61 : observer(observer) { | 62 : observer(observer) { |
| 62 } | 63 } |
| 63 | 64 |
| 64 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer; | 65 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer; |
| 65 std::string error; | 66 std::string error; |
| 66 std::unique_ptr<webrtc::SessionDescriptionInterface> description; | 67 std::unique_ptr<webrtc::SessionDescriptionInterface> description; |
| 67 }; | 68 }; |
| 68 } // namespace | 69 } // namespace |
| 69 | 70 |
| 70 void WebRtcCertificateGeneratorCallback::OnFailure() { | 71 void WebRtcIdentityRequestObserver::OnFailure(int error) { |
| 71 SignalRequestFailed(); | 72 SignalRequestFailed(error); |
| 72 } | 73 } |
| 73 | 74 |
| 74 void WebRtcCertificateGeneratorCallback::OnSuccess( | 75 void WebRtcIdentityRequestObserver::OnSuccess( |
| 75 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { | 76 const std::string& der_cert, const std::string& der_private_key) { |
| 76 SignalCertificateReady(certificate); | 77 std::string pem_cert = rtc::SSLIdentity::DerToPem( |
| 78 rtc::kPemTypeCertificate, |
| 79 reinterpret_cast<const unsigned char*>(der_cert.data()), |
| 80 der_cert.length()); |
| 81 std::string pem_key = rtc::SSLIdentity::DerToPem( |
| 82 rtc::kPemTypeRsaPrivateKey, |
| 83 reinterpret_cast<const unsigned char*>(der_private_key.data()), |
| 84 der_private_key.length()); |
| 85 std::unique_ptr<rtc::SSLIdentity> identity( |
| 86 rtc::SSLIdentity::FromPEMStrings(pem_key, pem_cert)); |
| 87 SignalCertificateReady(rtc::RTCCertificate::Create(std::move(identity))); |
| 88 } |
| 89 |
| 90 void WebRtcIdentityRequestObserver::OnSuccess( |
| 91 std::unique_ptr<rtc::SSLIdentity> identity) { |
| 92 SignalCertificateReady(rtc::RTCCertificate::Create(std::move(identity))); |
| 77 } | 93 } |
| 78 | 94 |
| 79 // static | 95 // static |
| 80 void WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( | 96 void WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( |
| 81 const SessionDescriptionInterface* source_desc, | 97 const SessionDescriptionInterface* source_desc, |
| 82 const std::string& content_name, | 98 const std::string& content_name, |
| 83 SessionDescriptionInterface* dest_desc) { | 99 SessionDescriptionInterface* dest_desc) { |
| 84 if (!source_desc) { | 100 if (!source_desc) { |
| 85 return; | 101 return; |
| 86 } | 102 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 104 if (!dest_candidates->HasCandidate(new_candidate)) { | 120 if (!dest_candidates->HasCandidate(new_candidate)) { |
| 105 dest_desc->AddCandidate(source_candidates->at(n)); | 121 dest_desc->AddCandidate(source_candidates->at(n)); |
| 106 } | 122 } |
| 107 } | 123 } |
| 108 } | 124 } |
| 109 | 125 |
| 110 // Private constructor called by other constructors. | 126 // Private constructor called by other constructors. |
| 111 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 127 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
| 112 rtc::Thread* signaling_thread, | 128 rtc::Thread* signaling_thread, |
| 113 cricket::ChannelManager* channel_manager, | 129 cricket::ChannelManager* channel_manager, |
| 130 std::unique_ptr<DtlsIdentityStoreInterface> dtls_identity_store, |
| 131 const rtc::scoped_refptr<WebRtcIdentityRequestObserver>& |
| 132 identity_request_observer, |
| 114 WebRtcSession* session, | 133 WebRtcSession* session, |
| 115 const std::string& session_id, | 134 const std::string& session_id, |
| 116 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator, | 135 bool dtls_enabled) |
| 117 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) | |
| 118 : signaling_thread_(signaling_thread), | 136 : signaling_thread_(signaling_thread), |
| 119 session_desc_factory_(channel_manager, &transport_desc_factory_), | 137 session_desc_factory_(channel_manager, &transport_desc_factory_), |
| 120 // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp | 138 // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp |
| 121 // as the session id and session version. To simplify, it should be fine | 139 // 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 | 140 // to just use a random number as session id and start version from |
| 123 // |kInitSessionVersion|. | 141 // |kInitSessionVersion|. |
| 124 session_version_(kInitSessionVersion), | 142 session_version_(kInitSessionVersion), |
| 125 cert_generator_(std::move(cert_generator)), | 143 dtls_identity_store_(std::move(dtls_identity_store)), |
| 144 identity_request_observer_(identity_request_observer), |
| 126 session_(session), | 145 session_(session), |
| 127 session_id_(session_id), | 146 session_id_(session_id), |
| 128 certificate_request_state_(CERTIFICATE_NOT_NEEDED) { | 147 certificate_request_state_(CERTIFICATE_NOT_NEEDED) { |
| 129 RTC_DCHECK(signaling_thread_); | |
| 130 session_desc_factory_.set_add_legacy_streams(false); | 148 session_desc_factory_.set_add_legacy_streams(false); |
| 131 bool dtls_enabled = cert_generator_ || certificate; | |
| 132 // SRTP-SDES is disabled if DTLS is on. | 149 // SRTP-SDES is disabled if DTLS is on. |
| 133 SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED); | 150 SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED); |
| 134 if (!dtls_enabled) { | |
| 135 LOG(LS_VERBOSE) << "DTLS-SRTP disabled."; | |
| 136 return; | |
| 137 } | |
| 138 | |
| 139 if (certificate) { | |
| 140 // Use |certificate|. | |
| 141 certificate_request_state_ = CERTIFICATE_WAITING; | |
| 142 | |
| 143 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; has certificate parameter."; | |
| 144 // We already have a certificate but we wait to do |SetIdentity|; if we do | |
| 145 // it in the constructor then the caller has not had a chance to connect to | |
| 146 // |SignalCertificateReady|. | |
| 147 signaling_thread_->Post( | |
| 148 this, MSG_USE_CONSTRUCTOR_CERTIFICATE, | |
| 149 new rtc::ScopedRefMessageData<rtc::RTCCertificate>(certificate)); | |
| 150 } else { | |
| 151 // Generate certificate. | |
| 152 certificate_request_state_ = CERTIFICATE_WAITING; | |
| 153 | |
| 154 rtc::scoped_refptr<WebRtcCertificateGeneratorCallback> callback( | |
| 155 new rtc::RefCountedObject<WebRtcCertificateGeneratorCallback>()); | |
| 156 callback->SignalRequestFailed.connect( | |
| 157 this, &WebRtcSessionDescriptionFactory::OnCertificateRequestFailed); | |
| 158 callback->SignalCertificateReady.connect( | |
| 159 this, &WebRtcSessionDescriptionFactory::SetCertificate); | |
| 160 | |
| 161 rtc::KeyParams key_params = rtc::KeyParams(); | |
| 162 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sending DTLS identity request (key " | |
| 163 << "type: " << key_params.type() << ")."; | |
| 164 | |
| 165 // Request certificate. This happens asynchronously, so that the caller gets | |
| 166 // a chance to connect to |SignalCertificateReady|. | |
| 167 cert_generator_->GenerateCertificateAsync( | |
| 168 key_params, rtc::Optional<uint64_t>(), callback); | |
| 169 } | |
| 170 } | 151 } |
| 171 | 152 |
| 172 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 153 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
| 173 rtc::Thread* signaling_thread, | 154 rtc::Thread* signaling_thread, |
| 174 cricket::ChannelManager* channel_manager, | 155 cricket::ChannelManager* channel_manager, |
| 175 WebRtcSession* session, | 156 WebRtcSession* session, |
| 176 const std::string& session_id, | 157 const std::string& session_id) |
| 177 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator) | 158 : WebRtcSessionDescriptionFactory(signaling_thread, |
| 178 : WebRtcSessionDescriptionFactory( | 159 channel_manager, |
| 179 signaling_thread, | 160 nullptr, |
| 180 channel_manager, | 161 nullptr, |
| 181 session, | 162 session, |
| 182 session_id, | 163 session_id, |
| 183 std::move(cert_generator), | 164 false) { |
| 184 nullptr) { | 165 LOG(LS_VERBOSE) << "DTLS-SRTP disabled."; |
| 185 } | 166 } |
| 186 | 167 |
| 187 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 168 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
| 188 rtc::Thread* signaling_thread, | 169 rtc::Thread* signaling_thread, |
| 189 cricket::ChannelManager* channel_manager, | 170 cricket::ChannelManager* channel_manager, |
| 171 std::unique_ptr<DtlsIdentityStoreInterface> dtls_identity_store, |
| 190 WebRtcSession* session, | 172 WebRtcSession* session, |
| 191 const std::string& session_id, | 173 const std::string& session_id) |
| 192 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) | 174 : WebRtcSessionDescriptionFactory( |
| 175 signaling_thread, |
| 176 channel_manager, |
| 177 std::move(dtls_identity_store), |
| 178 new rtc::RefCountedObject<WebRtcIdentityRequestObserver>(), |
| 179 session, |
| 180 session_id, |
| 181 true) { |
| 182 RTC_DCHECK(dtls_identity_store_); |
| 183 |
| 184 certificate_request_state_ = CERTIFICATE_WAITING; |
| 185 |
| 186 identity_request_observer_->SignalRequestFailed.connect( |
| 187 this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed); |
| 188 identity_request_observer_->SignalCertificateReady.connect( |
| 189 this, &WebRtcSessionDescriptionFactory::SetCertificate); |
| 190 |
| 191 rtc::KeyParams key_params = rtc::KeyParams(); |
| 192 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sending DTLS identity request (key " |
| 193 << "type: " << key_params.type() << ")."; |
| 194 |
| 195 // Request identity. This happens asynchronously, so the caller will have a |
| 196 // chance to connect to SignalIdentityReady. |
| 197 dtls_identity_store_->RequestIdentity(key_params, |
| 198 rtc::Optional<uint64_t>(), |
| 199 identity_request_observer_); |
| 200 } |
| 201 |
| 202 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
| 203 rtc::Thread* signaling_thread, |
| 204 cricket::ChannelManager* channel_manager, |
| 205 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate, |
| 206 WebRtcSession* session, |
| 207 const std::string& session_id) |
| 193 : WebRtcSessionDescriptionFactory(signaling_thread, | 208 : WebRtcSessionDescriptionFactory(signaling_thread, |
| 194 channel_manager, | 209 channel_manager, |
| 210 nullptr, |
| 211 nullptr, |
| 195 session, | 212 session, |
| 196 session_id, | 213 session_id, |
| 197 nullptr, | 214 true) { |
| 198 certificate) { | |
| 199 RTC_DCHECK(certificate); | 215 RTC_DCHECK(certificate); |
| 216 |
| 217 certificate_request_state_ = CERTIFICATE_WAITING; |
| 218 |
| 219 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; has certificate parameter."; |
| 220 // We already have a certificate but we wait to do SetIdentity; if we do |
| 221 // it in the constructor then the caller has not had a chance to connect to |
| 222 // SignalIdentityReady. |
| 223 signaling_thread_->Post( |
| 224 this, MSG_USE_CONSTRUCTOR_CERTIFICATE, |
| 225 new rtc::ScopedRefMessageData<rtc::RTCCertificate>(certificate)); |
| 200 } | 226 } |
| 201 | 227 |
| 202 WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() { | 228 WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() { |
| 203 ASSERT(signaling_thread_->IsCurrent()); | 229 ASSERT(signaling_thread_->IsCurrent()); |
| 204 | 230 |
| 205 // Fail any requests that were asked for before identity generation completed. | 231 // Fail any requests that were asked for before identity generation completed. |
| 206 FailPendingRequests(kFailedDueToSessionShutdown); | 232 FailPendingRequests(kFailedDueToSessionShutdown); |
| 207 | 233 |
| 208 // Process all pending notifications in the message queue. If we don't do | 234 // Process all pending notifications in the message queue. If we don't do |
| 209 // this, requests will linger and not know they succeeded or failed. | 235 // this, requests will linger and not know they succeeded or failed. |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 } | 481 } |
| 456 | 482 |
| 457 void WebRtcSessionDescriptionFactory::PostCreateSessionDescriptionSucceeded( | 483 void WebRtcSessionDescriptionFactory::PostCreateSessionDescriptionSucceeded( |
| 458 CreateSessionDescriptionObserver* observer, | 484 CreateSessionDescriptionObserver* observer, |
| 459 SessionDescriptionInterface* description) { | 485 SessionDescriptionInterface* description) { |
| 460 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); | 486 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); |
| 461 msg->description.reset(description); | 487 msg->description.reset(description); |
| 462 signaling_thread_->Post(this, MSG_CREATE_SESSIONDESCRIPTION_SUCCESS, msg); | 488 signaling_thread_->Post(this, MSG_CREATE_SESSIONDESCRIPTION_SUCCESS, msg); |
| 463 } | 489 } |
| 464 | 490 |
| 465 void WebRtcSessionDescriptionFactory::OnCertificateRequestFailed() { | 491 void WebRtcSessionDescriptionFactory::OnIdentityRequestFailed(int error) { |
| 466 ASSERT(signaling_thread_->IsCurrent()); | 492 ASSERT(signaling_thread_->IsCurrent()); |
| 467 | 493 |
| 468 LOG(LS_ERROR) << "Asynchronous certificate generation request failed."; | 494 LOG(LS_ERROR) << "Async identity request failed: error = " << error; |
| 469 certificate_request_state_ = CERTIFICATE_FAILED; | 495 certificate_request_state_ = CERTIFICATE_FAILED; |
| 470 | 496 |
| 471 FailPendingRequests(kFailedDueToIdentityFailed); | 497 FailPendingRequests(kFailedDueToIdentityFailed); |
| 472 } | 498 } |
| 473 | 499 |
| 474 void WebRtcSessionDescriptionFactory::SetCertificate( | 500 void WebRtcSessionDescriptionFactory::SetCertificate( |
| 475 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { | 501 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { |
| 476 RTC_DCHECK(certificate); | 502 RTC_DCHECK(certificate); |
| 477 LOG(LS_VERBOSE) << "Setting new certificate."; | 503 LOG(LS_VERBOSE) << "Setting new certificate"; |
| 478 | 504 |
| 479 certificate_request_state_ = CERTIFICATE_SUCCEEDED; | 505 certificate_request_state_ = CERTIFICATE_SUCCEEDED; |
| 480 SignalCertificateReady(certificate); | 506 SignalCertificateReady(certificate); |
| 481 | 507 |
| 482 transport_desc_factory_.set_certificate(certificate); | 508 transport_desc_factory_.set_certificate(certificate); |
| 483 transport_desc_factory_.set_secure(cricket::SEC_ENABLED); | 509 transport_desc_factory_.set_secure(cricket::SEC_ENABLED); |
| 484 | 510 |
| 485 while (!create_session_description_requests_.empty()) { | 511 while (!create_session_description_requests_.empty()) { |
| 486 if (create_session_description_requests_.front().type == | 512 if (create_session_description_requests_.front().type == |
| 487 CreateSessionDescriptionRequest::kOffer) { | 513 CreateSessionDescriptionRequest::kOffer) { |
| 488 InternalCreateOffer(create_session_description_requests_.front()); | 514 InternalCreateOffer(create_session_description_requests_.front()); |
| 489 } else { | 515 } else { |
| 490 InternalCreateAnswer(create_session_description_requests_.front()); | 516 InternalCreateAnswer(create_session_description_requests_.front()); |
| 491 } | 517 } |
| 492 create_session_description_requests_.pop(); | 518 create_session_description_requests_.pop(); |
| 493 } | 519 } |
| 494 } | 520 } |
| 495 } // namespace webrtc | 521 } // namespace webrtc |
| OLD | NEW |