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