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