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 |