OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2013 Google Inc. | 3 * Copyright 2013 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 13 matching lines...) Expand all Loading... |
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h" | 28 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h" |
29 | 29 |
30 #include "talk/app/webrtc/dtlsidentitystore.h" | 30 #include "talk/app/webrtc/dtlsidentitystore.h" |
31 #include "talk/app/webrtc/jsep.h" | 31 #include "talk/app/webrtc/jsep.h" |
32 #include "talk/app/webrtc/jsepsessiondescription.h" | 32 #include "talk/app/webrtc/jsepsessiondescription.h" |
33 #include "talk/app/webrtc/mediaconstraintsinterface.h" | 33 #include "talk/app/webrtc/mediaconstraintsinterface.h" |
34 #include "talk/app/webrtc/mediastreamsignaling.h" | |
35 #include "talk/app/webrtc/webrtcsession.h" | 34 #include "talk/app/webrtc/webrtcsession.h" |
36 #include "webrtc/base/sslidentity.h" | 35 #include "webrtc/base/sslidentity.h" |
37 | 36 |
38 using cricket::MediaSessionOptions; | 37 using cricket::MediaSessionOptions; |
39 | 38 |
40 namespace webrtc { | 39 namespace webrtc { |
41 namespace { | 40 namespace { |
42 static const char kFailedDueToIdentityFailed[] = | 41 static const char kFailedDueToIdentityFailed[] = |
43 " failed because DTLS identity request failed"; | 42 " failed because DTLS identity request failed"; |
44 static const char kFailedDueToSessionShutdown[] = | 43 static const char kFailedDueToSessionShutdown[] = |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 if (!dest_candidates->HasCandidate(new_candidate)) | 123 if (!dest_candidates->HasCandidate(new_candidate)) |
125 dest_desc->AddCandidate(source_candidates->at(n)); | 124 dest_desc->AddCandidate(source_candidates->at(n)); |
126 } | 125 } |
127 } | 126 } |
128 } | 127 } |
129 | 128 |
130 // Private constructor called by other constructors. | 129 // Private constructor called by other constructors. |
131 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 130 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
132 rtc::Thread* signaling_thread, | 131 rtc::Thread* signaling_thread, |
133 cricket::ChannelManager* channel_manager, | 132 cricket::ChannelManager* channel_manager, |
134 MediaStreamSignaling* mediastream_signaling, | |
135 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, | 133 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, |
136 const rtc::scoped_refptr<WebRtcIdentityRequestObserver>& | 134 const rtc::scoped_refptr<WebRtcIdentityRequestObserver>& |
137 identity_request_observer, | 135 identity_request_observer, |
138 WebRtcSession* session, | 136 WebRtcSession* session, |
139 const std::string& session_id, | 137 const std::string& session_id, |
140 cricket::DataChannelType dct, | |
141 bool dtls_enabled) | 138 bool dtls_enabled) |
142 : signaling_thread_(signaling_thread), | 139 : signaling_thread_(signaling_thread), |
143 mediastream_signaling_(mediastream_signaling), | |
144 session_desc_factory_(channel_manager, &transport_desc_factory_), | 140 session_desc_factory_(channel_manager, &transport_desc_factory_), |
145 // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp | 141 // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp |
146 // as the session id and session version. To simplify, it should be fine | 142 // as the session id and session version. To simplify, it should be fine |
147 // to just use a random number as session id and start version from | 143 // to just use a random number as session id and start version from |
148 // |kInitSessionVersion|. | 144 // |kInitSessionVersion|. |
149 session_version_(kInitSessionVersion), | 145 session_version_(kInitSessionVersion), |
150 dtls_identity_store_(dtls_identity_store.Pass()), | 146 dtls_identity_store_(dtls_identity_store.Pass()), |
151 identity_request_observer_(identity_request_observer), | 147 identity_request_observer_(identity_request_observer), |
152 session_(session), | 148 session_(session), |
153 session_id_(session_id), | 149 session_id_(session_id), |
154 data_channel_type_(dct), | |
155 certificate_request_state_(CERTIFICATE_NOT_NEEDED) { | 150 certificate_request_state_(CERTIFICATE_NOT_NEEDED) { |
156 session_desc_factory_.set_add_legacy_streams(false); | 151 session_desc_factory_.set_add_legacy_streams(false); |
157 // SRTP-SDES is disabled if DTLS is on. | 152 // SRTP-SDES is disabled if DTLS is on. |
158 SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED); | 153 SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED); |
159 } | 154 } |
160 | 155 |
161 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 156 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
162 rtc::Thread* signaling_thread, | 157 rtc::Thread* signaling_thread, |
163 cricket::ChannelManager* channel_manager, | 158 cricket::ChannelManager* channel_manager, |
164 MediaStreamSignaling* mediastream_signaling, | |
165 WebRtcSession* session, | 159 WebRtcSession* session, |
166 const std::string& session_id, | 160 const std::string& session_id) |
167 cricket::DataChannelType dct) | |
168 : WebRtcSessionDescriptionFactory(signaling_thread, | 161 : WebRtcSessionDescriptionFactory(signaling_thread, |
169 channel_manager, | 162 channel_manager, |
170 mediastream_signaling, | |
171 nullptr, | 163 nullptr, |
172 nullptr, | 164 nullptr, |
173 session, | 165 session, |
174 session_id, | 166 session_id, |
175 dct, | |
176 false) { | 167 false) { |
177 LOG(LS_VERBOSE) << "DTLS-SRTP disabled."; | 168 LOG(LS_VERBOSE) << "DTLS-SRTP disabled."; |
178 } | 169 } |
179 | 170 |
180 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 171 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
181 rtc::Thread* signaling_thread, | 172 rtc::Thread* signaling_thread, |
182 cricket::ChannelManager* channel_manager, | 173 cricket::ChannelManager* channel_manager, |
183 MediaStreamSignaling* mediastream_signaling, | |
184 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, | 174 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, |
185 WebRtcSession* session, | 175 WebRtcSession* session, |
186 const std::string& session_id, | 176 const std::string& session_id) |
187 cricket::DataChannelType dct) | |
188 : WebRtcSessionDescriptionFactory( | 177 : WebRtcSessionDescriptionFactory( |
189 signaling_thread, | 178 signaling_thread, |
190 channel_manager, | 179 channel_manager, |
191 mediastream_signaling, | 180 dtls_identity_store.Pass(), |
192 dtls_identity_store.Pass(), | 181 new rtc::RefCountedObject<WebRtcIdentityRequestObserver>(), |
193 new rtc::RefCountedObject<WebRtcIdentityRequestObserver>(), | 182 session, |
194 session, | 183 session_id, |
195 session_id, | 184 true) { |
196 dct, | |
197 true) { | |
198 RTC_DCHECK(dtls_identity_store_); | 185 RTC_DCHECK(dtls_identity_store_); |
199 | 186 |
200 certificate_request_state_ = CERTIFICATE_WAITING; | 187 certificate_request_state_ = CERTIFICATE_WAITING; |
201 | 188 |
202 identity_request_observer_->SignalRequestFailed.connect( | 189 identity_request_observer_->SignalRequestFailed.connect( |
203 this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed); | 190 this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed); |
204 identity_request_observer_->SignalCertificateReady.connect( | 191 identity_request_observer_->SignalCertificateReady.connect( |
205 this, &WebRtcSessionDescriptionFactory::SetCertificate); | 192 this, &WebRtcSessionDescriptionFactory::SetCertificate); |
206 | 193 |
207 rtc::KeyType key_type = rtc::KT_DEFAULT; | 194 rtc::KeyType key_type = rtc::KT_DEFAULT; |
208 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sending DTLS identity request (key " | 195 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sending DTLS identity request (key " |
209 << "type: " << key_type << ")."; | 196 << "type: " << key_type << ")."; |
210 | 197 |
211 // Request identity. This happens asynchronously, so the caller will have a | 198 // Request identity. This happens asynchronously, so the caller will have a |
212 // chance to connect to SignalIdentityReady. | 199 // chance to connect to SignalIdentityReady. |
213 dtls_identity_store_->RequestIdentity(key_type, identity_request_observer_); | 200 dtls_identity_store_->RequestIdentity(key_type, identity_request_observer_); |
214 } | 201 } |
215 | 202 |
216 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 203 WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
217 rtc::Thread* signaling_thread, | 204 rtc::Thread* signaling_thread, |
218 cricket::ChannelManager* channel_manager, | 205 cricket::ChannelManager* channel_manager, |
219 MediaStreamSignaling* mediastream_signaling, | |
220 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate, | 206 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate, |
221 WebRtcSession* session, | 207 WebRtcSession* session, |
222 const std::string& session_id, | 208 const std::string& session_id) |
223 cricket::DataChannelType dct) | 209 : WebRtcSessionDescriptionFactory(signaling_thread, |
224 : WebRtcSessionDescriptionFactory( | 210 channel_manager, |
225 signaling_thread, channel_manager, mediastream_signaling, nullptr, | 211 nullptr, |
226 nullptr, session, session_id, dct, true) { | 212 nullptr, |
| 213 session, |
| 214 session_id, |
| 215 true) { |
227 RTC_DCHECK(certificate); | 216 RTC_DCHECK(certificate); |
228 | 217 |
229 certificate_request_state_ = CERTIFICATE_WAITING; | 218 certificate_request_state_ = CERTIFICATE_WAITING; |
230 | 219 |
231 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; has certificate parameter."; | 220 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; has certificate parameter."; |
232 // We already have a certificate but we wait to do SetIdentity; if we do | 221 // We already have a certificate but we wait to do SetIdentity; if we do |
233 // it in the constructor then the caller has not had a chance to connect to | 222 // it in the constructor then the caller has not had a chance to connect to |
234 // SignalIdentityReady. | 223 // SignalIdentityReady. |
235 signaling_thread_->Post( | 224 signaling_thread_->Post( |
236 this, MSG_USE_CONSTRUCTOR_CERTIFICATE, | 225 this, MSG_USE_CONSTRUCTOR_CERTIFICATE, |
(...skipping 20 matching lines...) Expand all Loading... |
257 // destructor that caused WebRtcSessionDescriptionFactory's destruction. | 246 // destructor that caused WebRtcSessionDescriptionFactory's destruction. |
258 // The callback is then ignored, leaking memory allocated by OnMessage for | 247 // The callback is then ignored, leaking memory allocated by OnMessage for |
259 // MSG_USE_CONSTRUCTOR_CERTIFICATE. | 248 // MSG_USE_CONSTRUCTOR_CERTIFICATE. |
260 delete msg.pdata; | 249 delete msg.pdata; |
261 } | 250 } |
262 } | 251 } |
263 } | 252 } |
264 | 253 |
265 void WebRtcSessionDescriptionFactory::CreateOffer( | 254 void WebRtcSessionDescriptionFactory::CreateOffer( |
266 CreateSessionDescriptionObserver* observer, | 255 CreateSessionDescriptionObserver* observer, |
267 const PeerConnectionInterface::RTCOfferAnswerOptions& options) { | 256 const PeerConnectionInterface::RTCOfferAnswerOptions& options, |
268 cricket::MediaSessionOptions session_options; | 257 const cricket::MediaSessionOptions& session_options) { |
269 | |
270 std::string error = "CreateOffer"; | 258 std::string error = "CreateOffer"; |
271 if (certificate_request_state_ == CERTIFICATE_FAILED) { | 259 if (certificate_request_state_ == CERTIFICATE_FAILED) { |
272 error += kFailedDueToIdentityFailed; | 260 error += kFailedDueToIdentityFailed; |
273 LOG(LS_ERROR) << error; | 261 LOG(LS_ERROR) << error; |
274 PostCreateSessionDescriptionFailed(observer, error); | 262 PostCreateSessionDescriptionFailed(observer, error); |
275 return; | 263 return; |
276 } | 264 } |
277 | 265 |
278 if (!mediastream_signaling_->GetOptionsForOffer(options, | |
279 &session_options)) { | |
280 error += " called with invalid options."; | |
281 LOG(LS_ERROR) << error; | |
282 PostCreateSessionDescriptionFailed(observer, error); | |
283 return; | |
284 } | |
285 | |
286 if (!ValidStreams(session_options.streams)) { | 266 if (!ValidStreams(session_options.streams)) { |
287 error += " called with invalid media streams."; | 267 error += " called with invalid media streams."; |
288 LOG(LS_ERROR) << error; | 268 LOG(LS_ERROR) << error; |
289 PostCreateSessionDescriptionFailed(observer, error); | 269 PostCreateSessionDescriptionFailed(observer, error); |
290 return; | 270 return; |
291 } | 271 } |
292 | 272 |
293 if (data_channel_type_ == cricket::DCT_SCTP && | |
294 mediastream_signaling_->HasDataChannels()) { | |
295 session_options.data_channel_type = cricket::DCT_SCTP; | |
296 } | |
297 | |
298 CreateSessionDescriptionRequest request( | 273 CreateSessionDescriptionRequest request( |
299 CreateSessionDescriptionRequest::kOffer, observer, session_options); | 274 CreateSessionDescriptionRequest::kOffer, observer, session_options); |
300 if (certificate_request_state_ == CERTIFICATE_WAITING) { | 275 if (certificate_request_state_ == CERTIFICATE_WAITING) { |
301 create_session_description_requests_.push(request); | 276 create_session_description_requests_.push(request); |
302 } else { | 277 } else { |
303 ASSERT(certificate_request_state_ == CERTIFICATE_SUCCEEDED || | 278 ASSERT(certificate_request_state_ == CERTIFICATE_SUCCEEDED || |
304 certificate_request_state_ == CERTIFICATE_NOT_NEEDED); | 279 certificate_request_state_ == CERTIFICATE_NOT_NEEDED); |
305 InternalCreateOffer(request); | 280 InternalCreateOffer(request); |
306 } | 281 } |
307 } | 282 } |
308 | 283 |
309 void WebRtcSessionDescriptionFactory::CreateAnswer( | 284 void WebRtcSessionDescriptionFactory::CreateAnswer( |
310 CreateSessionDescriptionObserver* observer, | 285 CreateSessionDescriptionObserver* observer, |
311 const MediaConstraintsInterface* constraints) { | 286 const MediaConstraintsInterface* constraints, |
| 287 const cricket::MediaSessionOptions& session_options) { |
312 std::string error = "CreateAnswer"; | 288 std::string error = "CreateAnswer"; |
313 if (certificate_request_state_ == CERTIFICATE_FAILED) { | 289 if (certificate_request_state_ == CERTIFICATE_FAILED) { |
314 error += kFailedDueToIdentityFailed; | 290 error += kFailedDueToIdentityFailed; |
315 LOG(LS_ERROR) << error; | 291 LOG(LS_ERROR) << error; |
316 PostCreateSessionDescriptionFailed(observer, error); | 292 PostCreateSessionDescriptionFailed(observer, error); |
317 return; | 293 return; |
318 } | 294 } |
319 if (!session_->remote_description()) { | 295 if (!session_->remote_description()) { |
320 error += " can't be called before SetRemoteDescription."; | 296 error += " can't be called before SetRemoteDescription."; |
321 LOG(LS_ERROR) << error; | 297 LOG(LS_ERROR) << error; |
322 PostCreateSessionDescriptionFailed(observer, error); | 298 PostCreateSessionDescriptionFailed(observer, error); |
323 return; | 299 return; |
324 } | 300 } |
325 if (session_->remote_description()->type() != | 301 if (session_->remote_description()->type() != |
326 JsepSessionDescription::kOffer) { | 302 JsepSessionDescription::kOffer) { |
327 error += " failed because remote_description is not an offer."; | 303 error += " failed because remote_description is not an offer."; |
328 LOG(LS_ERROR) << error; | 304 LOG(LS_ERROR) << error; |
329 PostCreateSessionDescriptionFailed(observer, error); | 305 PostCreateSessionDescriptionFailed(observer, error); |
330 return; | 306 return; |
331 } | 307 } |
332 | 308 |
333 cricket::MediaSessionOptions options; | 309 if (!ValidStreams(session_options.streams)) { |
334 if (!mediastream_signaling_->GetOptionsForAnswer(constraints, &options)) { | |
335 error += " called with invalid constraints."; | |
336 LOG(LS_ERROR) << error; | |
337 PostCreateSessionDescriptionFailed(observer, error); | |
338 return; | |
339 } | |
340 if (!ValidStreams(options.streams)) { | |
341 error += " called with invalid media streams."; | 310 error += " called with invalid media streams."; |
342 LOG(LS_ERROR) << error; | 311 LOG(LS_ERROR) << error; |
343 PostCreateSessionDescriptionFailed(observer, error); | 312 PostCreateSessionDescriptionFailed(observer, error); |
344 return; | 313 return; |
345 } | 314 } |
346 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams | |
347 // are not signaled in the SDP so does not go through that path and must be | |
348 // handled here. | |
349 if (data_channel_type_ == cricket::DCT_SCTP) { | |
350 options.data_channel_type = cricket::DCT_SCTP; | |
351 } | |
352 | 315 |
353 CreateSessionDescriptionRequest request( | 316 CreateSessionDescriptionRequest request( |
354 CreateSessionDescriptionRequest::kAnswer, observer, options); | 317 CreateSessionDescriptionRequest::kAnswer, observer, session_options); |
355 if (certificate_request_state_ == CERTIFICATE_WAITING) { | 318 if (certificate_request_state_ == CERTIFICATE_WAITING) { |
356 create_session_description_requests_.push(request); | 319 create_session_description_requests_.push(request); |
357 } else { | 320 } else { |
358 ASSERT(certificate_request_state_ == CERTIFICATE_SUCCEEDED || | 321 ASSERT(certificate_request_state_ == CERTIFICATE_SUCCEEDED || |
359 certificate_request_state_ == CERTIFICATE_NOT_NEEDED); | 322 certificate_request_state_ == CERTIFICATE_NOT_NEEDED); |
360 InternalCreateAnswer(request); | 323 InternalCreateAnswer(request); |
361 } | 324 } |
362 } | 325 } |
363 | 326 |
364 void WebRtcSessionDescriptionFactory::SetSdesPolicy( | 327 void WebRtcSessionDescriptionFactory::SetSdesPolicy( |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 if (create_session_description_requests_.front().type == | 496 if (create_session_description_requests_.front().type == |
534 CreateSessionDescriptionRequest::kOffer) { | 497 CreateSessionDescriptionRequest::kOffer) { |
535 InternalCreateOffer(create_session_description_requests_.front()); | 498 InternalCreateOffer(create_session_description_requests_.front()); |
536 } else { | 499 } else { |
537 InternalCreateAnswer(create_session_description_requests_.front()); | 500 InternalCreateAnswer(create_session_description_requests_.front()); |
538 } | 501 } |
539 create_session_description_requests_.pop(); | 502 create_session_description_requests_.pop(); |
540 } | 503 } |
541 } | 504 } |
542 } // namespace webrtc | 505 } // namespace webrtc |
OLD | NEW |