Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/protocol/webrtc_transport.h" | 5 #include "remoting/protocol/webrtc_transport.h" |
| 6 | 6 |
| 7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/single_thread_task_runner.h" | 8 #include "base/single_thread_task_runner.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/task_runner_util.h" | 10 #include "base/task_runner_util.h" |
| 11 #include "base/thread_task_runner_handle.h" | |
| 11 #include "jingle/glue/thread_wrapper.h" | 12 #include "jingle/glue/thread_wrapper.h" |
| 12 #include "third_party/libjingle/source/talk/app/webrtc/test/fakeconstraints.h" | 13 #include "third_party/libjingle/source/talk/app/webrtc/test/fakeconstraints.h" |
| 13 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" | 14 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" |
| 14 #include "third_party/webrtc/modules/audio_device/include/fake_audio_device.h" | 15 #include "third_party/webrtc/modules/audio_device/include/fake_audio_device.h" |
| 15 | 16 |
| 16 using buzz::QName; | 17 using buzz::QName; |
| 17 using buzz::XmlElement; | 18 using buzz::XmlElement; |
| 18 | 19 |
| 19 namespace remoting { | 20 namespace remoting { |
| 20 namespace protocol { | 21 namespace protocol { |
| 21 | 22 |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 24 // Delay after candidate creation before sending transport-info message to | 25 // Delay after candidate creation before sending transport-info message to |
| 25 // accumulate multiple candidates. This is an optimization to reduce number of | 26 // accumulate multiple candidates. This is an optimization to reduce number of |
| 26 // transport-info messages. | 27 // transport-info messages. |
| 27 const int kTransportInfoSendDelayMs = 20; | 28 const int kTransportInfoSendDelayMs = 20; |
| 28 | 29 |
| 29 // XML namespace for the transport elements. | 30 // XML namespace for the transport elements. |
| 30 const char kTransportNamespace[] = "google:remoting:webrtc"; | 31 const char kTransportNamespace[] = "google:remoting:webrtc"; |
| 31 | 32 |
| 32 rtc::Thread* InitAndGetRtcThread() { | |
| 33 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); | |
| 34 | |
| 35 // TODO(sergeyu): Investigate if it's possible to avoid Send(). | |
| 36 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true); | |
| 37 | |
| 38 return jingle_glue::JingleThreadWrapper::current(); | |
| 39 } | |
| 40 | |
| 41 // A webrtc::CreateSessionDescriptionObserver implementation used to receive the | 33 // A webrtc::CreateSessionDescriptionObserver implementation used to receive the |
| 42 // results of creating descriptions for this end of the PeerConnection. | 34 // results of creating descriptions for this end of the PeerConnection. |
| 43 class CreateSessionDescriptionObserver | 35 class CreateSessionDescriptionObserver |
| 44 : public webrtc::CreateSessionDescriptionObserver { | 36 : public webrtc::CreateSessionDescriptionObserver { |
| 45 public: | 37 public: |
| 46 typedef base::Callback<void( | 38 typedef base::Callback<void( |
| 47 scoped_ptr<webrtc::SessionDescriptionInterface> description, | 39 scoped_ptr<webrtc::SessionDescriptionInterface> description, |
| 48 const std::string& error)> ResultCallback; | 40 const std::string& error)> ResultCallback; |
| 49 | 41 |
| 50 static CreateSessionDescriptionObserver* Create( | 42 static CreateSessionDescriptionObserver* Create( |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 101 | 93 |
| 102 private: | 94 private: |
| 103 ResultCallback result_callback_; | 95 ResultCallback result_callback_; |
| 104 | 96 |
| 105 DISALLOW_COPY_AND_ASSIGN(SetSessionDescriptionObserver); | 97 DISALLOW_COPY_AND_ASSIGN(SetSessionDescriptionObserver); |
| 106 }; | 98 }; |
| 107 | 99 |
| 108 } // namespace | 100 } // namespace |
| 109 | 101 |
| 110 WebrtcTransport::WebrtcTransport( | 102 WebrtcTransport::WebrtcTransport( |
| 103 rtc::Thread* worker_thread, | |
| 111 rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface> | 104 rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface> |
| 112 port_allocator_factory, | 105 port_allocator_factory, |
| 113 TransportRole role, | 106 TransportRole role) |
| 114 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner) | |
| 115 : port_allocator_factory_(port_allocator_factory), | 107 : port_allocator_factory_(port_allocator_factory), |
| 116 role_(role), | 108 role_(role), |
| 117 worker_task_runner_(worker_task_runner), | 109 worker_thread_(worker_thread), |
| 118 weak_factory_(this) {} | 110 weak_factory_(this) {} |
| 119 | 111 |
| 120 WebrtcTransport::~WebrtcTransport() {} | 112 WebrtcTransport::~WebrtcTransport() {} |
| 121 | 113 |
| 122 void WebrtcTransport::Start(EventHandler* event_handler, | 114 void WebrtcTransport::Start(EventHandler* event_handler, |
| 123 Authenticator* authenticator) { | 115 Authenticator* authenticator) { |
| 124 DCHECK(thread_checker_.CalledOnValidThread()); | 116 DCHECK(thread_checker_.CalledOnValidThread()); |
| 125 | 117 |
| 126 event_handler_ = event_handler; | 118 event_handler_ = event_handler; |
| 127 | 119 |
| 128 // TODO(sergeyu): Use the |authenticator| to authenticate PeerConnection. | 120 // TODO(sergeyu): Use the |authenticator| to authenticate PeerConnection. |
| 121 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); | |
| 129 | 122 |
| 130 base::PostTaskAndReplyWithResult( | 123 // TODO(sergeyu): Investigate if it's possible to avoid Send(). |
| 131 worker_task_runner_.get(), FROM_HERE, base::Bind(&InitAndGetRtcThread), | 124 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true); |
| 132 base::Bind(&WebrtcTransport::DoStart, weak_factory_.GetWeakPtr())); | 125 |
| 126 fake_audio_device_module_.reset(new webrtc::FakeAudioDeviceModule()); | |
| 127 | |
| 128 peer_connection_factory_ = webrtc::CreatePeerConnectionFactory( | |
| 129 worker_thread_, rtc::Thread::Current(), | |
| 130 fake_audio_device_module_.get(), nullptr, nullptr); | |
| 131 | |
| 132 webrtc::PeerConnectionInterface::IceServer stun_server; | |
| 133 stun_server.urls.push_back("stun:stun.l.google.com:19302"); | |
| 134 webrtc::PeerConnectionInterface::RTCConfiguration rtc_config; | |
| 135 rtc_config.servers.push_back(stun_server); | |
| 136 | |
| 137 webrtc::FakeConstraints constraints; | |
|
Jamie
2015/12/09 19:42:22
Unrelated to this CL, but why are we using FakeCon
Sergey Ulanov
2015/12/09 19:57:06
PeerConnection gets MediaConstraintsInterface. Fak
| |
| 138 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, | |
| 139 webrtc::MediaConstraintsInterface::kValueTrue); | |
| 140 | |
| 141 peer_connection_ = peer_connection_factory_->CreatePeerConnection( | |
| 142 rtc_config, &constraints, port_allocator_factory_, nullptr, this); | |
| 143 | |
| 144 data_stream_adapter_.Initialize(peer_connection_, | |
| 145 role_ == TransportRole::SERVER); | |
| 146 | |
| 147 if (role_ == TransportRole::SERVER) | |
| 148 RequestNegotiation(); | |
| 133 } | 149 } |
| 134 | 150 |
| 135 bool WebrtcTransport::ProcessTransportInfo(XmlElement* transport_info) { | 151 bool WebrtcTransport::ProcessTransportInfo(XmlElement* transport_info) { |
| 136 DCHECK(thread_checker_.CalledOnValidThread()); | 152 DCHECK(thread_checker_.CalledOnValidThread()); |
| 137 | 153 |
| 138 if (transport_info->Name() != QName(kTransportNamespace, "transport")) | 154 if (transport_info->Name() != QName(kTransportNamespace, "transport")) |
| 139 return false; | 155 return false; |
| 140 | 156 |
| 141 if (!peer_connection_) | 157 if (!peer_connection_) |
| 142 return false; | 158 return false; |
| 143 | 159 |
| 144 XmlElement* session_description = transport_info->FirstNamed( | 160 XmlElement* session_description = transport_info->FirstNamed( |
| 145 QName(kTransportNamespace, "session-description")); | 161 QName(kTransportNamespace, "session-description")); |
| 146 if (session_description) { | 162 if (session_description) { |
| 147 webrtc::PeerConnectionInterface::SignalingState expected_state = | 163 webrtc::PeerConnectionInterface::SignalingState expected_state = |
| 148 role_ == TransportRole::SERVER | 164 role_ == TransportRole::CLIENT |
| 149 ? webrtc::PeerConnectionInterface::kStable | 165 ? webrtc::PeerConnectionInterface::kStable |
| 150 : webrtc::PeerConnectionInterface::kHaveLocalOffer; | 166 : webrtc::PeerConnectionInterface::kHaveLocalOffer; |
| 151 if (peer_connection_->signaling_state() != expected_state) { | 167 if (peer_connection_->signaling_state() != expected_state) { |
| 152 LOG(ERROR) << "Received unexpected WebRTC session_description. "; | 168 LOG(ERROR) << "Received unexpected WebRTC session_description. "; |
| 153 return false; | 169 return false; |
| 154 } | 170 } |
| 155 | 171 |
| 156 std::string type = session_description->Attr(QName(std::string(), "type")); | 172 std::string type = session_description->Attr(QName(std::string(), "type")); |
| 157 std::string sdp = session_description->BodyText(); | 173 std::string sdp = session_description->BodyText(); |
| 158 if (type.empty() || sdp.empty()) { | 174 if (type.empty() || sdp.empty()) { |
| 159 LOG(ERROR) << "Incorrect session_description format."; | 175 LOG(ERROR) << "Incorrect session description format."; |
| 160 return false; | 176 return false; |
| 161 } | 177 } |
| 162 | 178 |
| 163 webrtc::SdpParseError error; | 179 webrtc::SdpParseError error; |
| 164 scoped_ptr<webrtc::SessionDescriptionInterface> session_description( | 180 scoped_ptr<webrtc::SessionDescriptionInterface> session_description( |
| 165 webrtc::CreateSessionDescription(type, sdp, &error)); | 181 webrtc::CreateSessionDescription(type, sdp, &error)); |
| 166 if (!session_description) { | 182 if (!session_description) { |
| 167 LOG(ERROR) << "Failed to parse the offer: " << error.description | 183 LOG(ERROR) << "Failed to parse the session description: " |
| 168 << " line: " << error.line; | 184 << error.description << " line: " << error.line; |
| 169 return false; | 185 return false; |
| 170 } | 186 } |
| 171 | 187 |
| 172 peer_connection_->SetRemoteDescription( | 188 peer_connection_->SetRemoteDescription( |
| 173 SetSessionDescriptionObserver::Create( | 189 SetSessionDescriptionObserver::Create( |
| 174 base::Bind(&WebrtcTransport::OnRemoteDescriptionSet, | 190 base::Bind(&WebrtcTransport::OnRemoteDescriptionSet, |
| 175 weak_factory_.GetWeakPtr())), | 191 weak_factory_.GetWeakPtr(), |
| 192 type == webrtc::SessionDescriptionInterface::kOffer)), | |
| 176 session_description.release()); | 193 session_description.release()); |
| 177 } | 194 } |
| 178 | 195 |
| 179 XmlElement* candidate_element; | 196 XmlElement* candidate_element; |
| 180 QName candidate_qname(kTransportNamespace, "candidate"); | 197 QName candidate_qname(kTransportNamespace, "candidate"); |
| 181 for (candidate_element = transport_info->FirstNamed(candidate_qname); | 198 for (candidate_element = transport_info->FirstNamed(candidate_qname); |
| 182 candidate_element; | 199 candidate_element; |
| 183 candidate_element = candidate_element->NextNamed(candidate_qname)) { | 200 candidate_element = candidate_element->NextNamed(candidate_qname)) { |
| 184 std::string candidate_str = candidate_element->BodyText(); | 201 std::string candidate_str = candidate_element->BodyText(); |
| 185 std::string sdp_mid = | 202 std::string sdp_mid = |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 220 StreamChannelFactory* WebrtcTransport::GetStreamChannelFactory() { | 237 StreamChannelFactory* WebrtcTransport::GetStreamChannelFactory() { |
| 221 DCHECK(thread_checker_.CalledOnValidThread()); | 238 DCHECK(thread_checker_.CalledOnValidThread()); |
| 222 return &data_stream_adapter_; | 239 return &data_stream_adapter_; |
| 223 } | 240 } |
| 224 | 241 |
| 225 StreamChannelFactory* WebrtcTransport::GetMultiplexedChannelFactory() { | 242 StreamChannelFactory* WebrtcTransport::GetMultiplexedChannelFactory() { |
| 226 DCHECK(thread_checker_.CalledOnValidThread()); | 243 DCHECK(thread_checker_.CalledOnValidThread()); |
| 227 return GetStreamChannelFactory(); | 244 return GetStreamChannelFactory(); |
| 228 } | 245 } |
| 229 | 246 |
| 230 void WebrtcTransport::DoStart(rtc::Thread* worker_thread) { | |
| 231 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 232 | |
| 233 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); | |
| 234 | |
| 235 // TODO(sergeyu): Investigate if it's possible to avoid Send(). | |
| 236 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true); | |
| 237 | |
| 238 fake_audio_device_module_.reset(new webrtc::FakeAudioDeviceModule()); | |
| 239 | |
| 240 peer_connection_factory_ = webrtc::CreatePeerConnectionFactory( | |
| 241 worker_thread, rtc::Thread::Current(), | |
| 242 fake_audio_device_module_.get(), nullptr, nullptr); | |
| 243 | |
| 244 webrtc::PeerConnectionInterface::IceServer stun_server; | |
| 245 stun_server.urls.push_back("stun:stun.l.google.com:19302"); | |
| 246 webrtc::PeerConnectionInterface::RTCConfiguration rtc_config; | |
| 247 rtc_config.servers.push_back(stun_server); | |
| 248 | |
| 249 webrtc::FakeConstraints constraints; | |
| 250 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, | |
| 251 webrtc::MediaConstraintsInterface::kValueTrue); | |
| 252 | |
| 253 peer_connection_ = peer_connection_factory_->CreatePeerConnection( | |
| 254 rtc_config, &constraints, port_allocator_factory_, nullptr, this); | |
| 255 | |
| 256 data_stream_adapter_.Initialize(peer_connection_, | |
| 257 role_ == TransportRole::SERVER); | |
| 258 | |
| 259 if (role_ == TransportRole::CLIENT) { | |
| 260 webrtc::FakeConstraints offer_config; | |
| 261 offer_config.AddMandatory( | |
| 262 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo, | |
| 263 webrtc::MediaConstraintsInterface::kValueTrue); | |
| 264 offer_config.AddMandatory( | |
| 265 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio, | |
| 266 webrtc::MediaConstraintsInterface::kValueFalse); | |
| 267 offer_config.AddMandatory( | |
| 268 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, | |
| 269 webrtc::MediaConstraintsInterface::kValueTrue); | |
| 270 peer_connection_->CreateOffer( | |
| 271 CreateSessionDescriptionObserver::Create( | |
| 272 base::Bind(&WebrtcTransport::OnLocalSessionDescriptionCreated, | |
| 273 weak_factory_.GetWeakPtr())), | |
| 274 &offer_config); | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 void WebrtcTransport::OnLocalSessionDescriptionCreated( | 247 void WebrtcTransport::OnLocalSessionDescriptionCreated( |
| 279 scoped_ptr<webrtc::SessionDescriptionInterface> description, | 248 scoped_ptr<webrtc::SessionDescriptionInterface> description, |
| 280 const std::string& error) { | 249 const std::string& error) { |
| 281 DCHECK(thread_checker_.CalledOnValidThread()); | 250 DCHECK(thread_checker_.CalledOnValidThread()); |
| 282 | 251 |
| 283 if (!peer_connection_) | 252 if (!peer_connection_) |
| 284 return; | 253 return; |
| 285 | 254 |
| 286 if (!description) { | 255 if (!description) { |
| 287 LOG(ERROR) << "PeerConnection offer creation failed: " << error; | 256 LOG(ERROR) << "PeerConnection offer creation failed: " << error; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 | 291 |
| 323 if (!success) { | 292 if (!success) { |
| 324 LOG(ERROR) << "Failed to set local description: " << error; | 293 LOG(ERROR) << "Failed to set local description: " << error; |
| 325 Close(CHANNEL_CONNECTION_ERROR); | 294 Close(CHANNEL_CONNECTION_ERROR); |
| 326 return; | 295 return; |
| 327 } | 296 } |
| 328 | 297 |
| 329 AddPendingCandidatesIfPossible(); | 298 AddPendingCandidatesIfPossible(); |
| 330 } | 299 } |
| 331 | 300 |
| 332 void WebrtcTransport::OnRemoteDescriptionSet(bool success, | 301 void WebrtcTransport::OnRemoteDescriptionSet(bool send_answer, |
| 302 bool success, | |
| 333 const std::string& error) { | 303 const std::string& error) { |
| 334 DCHECK(thread_checker_.CalledOnValidThread()); | 304 DCHECK(thread_checker_.CalledOnValidThread()); |
| 335 | 305 |
| 336 if (!peer_connection_) | 306 if (!peer_connection_) |
| 337 return; | 307 return; |
| 338 | 308 |
| 339 if (!success) { | 309 if (!success) { |
| 340 LOG(ERROR) << "Failed to set local description: " << error; | 310 LOG(ERROR) << "Failed to set local description: " << error; |
| 341 Close(CHANNEL_CONNECTION_ERROR); | 311 Close(CHANNEL_CONNECTION_ERROR); |
| 342 return; | 312 return; |
| 343 } | 313 } |
| 344 | 314 |
| 345 // Create and send answer on the server. | 315 // Create and send answer on the server. |
| 346 if (role_ == TransportRole::SERVER) { | 316 if (send_answer) { |
| 347 peer_connection_->CreateAnswer( | 317 peer_connection_->CreateAnswer( |
| 348 CreateSessionDescriptionObserver::Create( | 318 CreateSessionDescriptionObserver::Create( |
| 349 base::Bind(&WebrtcTransport::OnLocalSessionDescriptionCreated, | 319 base::Bind(&WebrtcTransport::OnLocalSessionDescriptionCreated, |
| 350 weak_factory_.GetWeakPtr())), | 320 weak_factory_.GetWeakPtr())), |
| 351 nullptr); | 321 nullptr); |
| 352 } | 322 } |
| 353 | 323 |
| 354 AddPendingCandidatesIfPossible(); | 324 AddPendingCandidatesIfPossible(); |
| 355 } | 325 } |
| 356 | 326 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 382 } | 352 } |
| 383 | 353 |
| 384 void WebrtcTransport::OnDataChannel( | 354 void WebrtcTransport::OnDataChannel( |
| 385 webrtc::DataChannelInterface* data_channel) { | 355 webrtc::DataChannelInterface* data_channel) { |
| 386 DCHECK(thread_checker_.CalledOnValidThread()); | 356 DCHECK(thread_checker_.CalledOnValidThread()); |
| 387 data_stream_adapter_.OnIncomingDataChannel(data_channel); | 357 data_stream_adapter_.OnIncomingDataChannel(data_channel); |
| 388 } | 358 } |
| 389 | 359 |
| 390 void WebrtcTransport::OnRenegotiationNeeded() { | 360 void WebrtcTransport::OnRenegotiationNeeded() { |
| 391 DCHECK(thread_checker_.CalledOnValidThread()); | 361 DCHECK(thread_checker_.CalledOnValidThread()); |
| 392 // TODO(sergeyu): Figure out what needs to happen here. | 362 |
| 363 if (role_ == TransportRole::SERVER) { | |
| 364 RequestNegotiation(); | |
| 365 } else { | |
| 366 // TODO(sergeyu): Is it necessary to support renegotiation initiated by the | |
| 367 // client? | |
| 368 NOTIMPLEMENTED(); | |
| 369 } | |
| 370 } | |
| 371 | |
| 372 void WebrtcTransport::RequestNegotiation() { | |
| 373 DCHECK(role_ == TransportRole::SERVER); | |
| 374 | |
| 375 if (!negotiation_pending_) { | |
| 376 negotiation_pending_ = true; | |
| 377 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 378 FROM_HERE, | |
| 379 base::Bind(&WebrtcTransport::SendOffer, weak_factory_.GetWeakPtr())); | |
| 380 } | |
| 393 } | 381 } |
| 394 | 382 |
| 395 void WebrtcTransport::OnIceConnectionChange( | 383 void WebrtcTransport::OnIceConnectionChange( |
| 396 webrtc::PeerConnectionInterface::IceConnectionState new_state) { | 384 webrtc::PeerConnectionInterface::IceConnectionState new_state) { |
| 397 DCHECK(thread_checker_.CalledOnValidThread()); | 385 DCHECK(thread_checker_.CalledOnValidThread()); |
| 398 | 386 |
| 399 if (new_state == webrtc::PeerConnectionInterface::kIceConnectionConnected) | 387 if (new_state == webrtc::PeerConnectionInterface::kIceConnectionConnected) |
| 400 event_handler_->OnTransportConnected(); | 388 event_handler_->OnTransportConnected(); |
| 401 } | 389 } |
| 402 | 390 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 439 new XmlElement(QName(kTransportNamespace, "transport"), true)); | 427 new XmlElement(QName(kTransportNamespace, "transport"), true)); |
| 440 | 428 |
| 441 // Delay sending the new candidates in case we get more candidates | 429 // Delay sending the new candidates in case we get more candidates |
| 442 // that we can send in one message. | 430 // that we can send in one message. |
| 443 transport_info_timer_.Start( | 431 transport_info_timer_.Start( |
| 444 FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs), | 432 FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs), |
| 445 this, &WebrtcTransport::SendTransportInfo); | 433 this, &WebrtcTransport::SendTransportInfo); |
| 446 } | 434 } |
| 447 } | 435 } |
| 448 | 436 |
| 437 void WebrtcTransport::SendOffer() { | |
| 438 DCHECK(role_ == TransportRole::SERVER); | |
| 439 | |
| 440 DCHECK(negotiation_pending_); | |
| 441 negotiation_pending_ = false; | |
| 442 | |
| 443 webrtc::FakeConstraints offer_config; | |
| 444 offer_config.AddMandatory( | |
| 445 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo, | |
| 446 webrtc::MediaConstraintsInterface::kValueTrue); | |
| 447 offer_config.AddMandatory( | |
| 448 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio, | |
| 449 webrtc::MediaConstraintsInterface::kValueFalse); | |
| 450 offer_config.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, | |
| 451 webrtc::MediaConstraintsInterface::kValueTrue); | |
| 452 peer_connection_->CreateOffer( | |
| 453 CreateSessionDescriptionObserver::Create( | |
| 454 base::Bind(&WebrtcTransport::OnLocalSessionDescriptionCreated, | |
| 455 weak_factory_.GetWeakPtr())), | |
| 456 &offer_config); | |
| 457 } | |
| 458 | |
| 449 void WebrtcTransport::SendTransportInfo() { | 459 void WebrtcTransport::SendTransportInfo() { |
| 450 DCHECK(thread_checker_.CalledOnValidThread()); | 460 DCHECK(thread_checker_.CalledOnValidThread()); |
| 451 DCHECK(pending_transport_info_message_); | 461 DCHECK(pending_transport_info_message_); |
| 452 | 462 |
| 453 event_handler_->OnOutgoingTransportInfo( | 463 event_handler_->OnOutgoingTransportInfo( |
| 454 pending_transport_info_message_.Pass()); | 464 pending_transport_info_message_.Pass()); |
| 455 pending_transport_info_message_.reset(); | 465 pending_transport_info_message_.reset(); |
| 456 } | 466 } |
| 457 | 467 |
| 458 void WebrtcTransport::AddPendingCandidatesIfPossible() { | 468 void WebrtcTransport::AddPendingCandidatesIfPossible() { |
| 459 DCHECK(thread_checker_.CalledOnValidThread()); | 469 DCHECK(thread_checker_.CalledOnValidThread()); |
| 460 | 470 |
| 461 if (peer_connection_->signaling_state() == | 471 if (peer_connection_->signaling_state() == |
| 462 webrtc::PeerConnectionInterface::kStable) { | 472 webrtc::PeerConnectionInterface::kStable) { |
| 463 for (auto candidate : pending_incoming_candidates_) { | 473 for (auto candidate : pending_incoming_candidates_) { |
| 464 if (!peer_connection_->AddIceCandidate(candidate)) { | 474 if (!peer_connection_->AddIceCandidate(candidate)) { |
| 465 LOG(ERROR) << "Failed to add incoming candidate"; | 475 LOG(ERROR) << "Failed to add incoming candidate"; |
| 466 Close(INCOMPATIBLE_PROTOCOL); | 476 Close(INCOMPATIBLE_PROTOCOL); |
| 467 return; | 477 return; |
| 468 } | 478 } |
| 469 } | 479 } |
| 470 pending_incoming_candidates_.clear(); | 480 pending_incoming_candidates_.clear(); |
| 471 } | 481 } |
| 472 } | 482 } |
| 473 | 483 |
| 474 WebrtcTransportFactory::WebrtcTransportFactory( | 484 WebrtcTransportFactory::WebrtcTransportFactory( |
| 485 rtc::Thread* worker_thread, | |
| 475 SignalStrategy* signal_strategy, | 486 SignalStrategy* signal_strategy, |
| 476 rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface> | 487 rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface> |
| 477 port_allocator_factory, | 488 port_allocator_factory, |
| 478 TransportRole role) | 489 TransportRole role) |
| 479 : signal_strategy_(signal_strategy), | 490 : worker_thread_(worker_thread), |
| 491 signal_strategy_(signal_strategy), | |
| 480 port_allocator_factory_(port_allocator_factory), | 492 port_allocator_factory_(port_allocator_factory), |
| 481 role_(role), | 493 role_(role) {} |
| 482 worker_thread_("ChromotingWebrtcWorkerThread") { | |
| 483 worker_thread_.StartWithOptions( | |
| 484 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); | |
| 485 } | |
| 486 | 494 |
| 487 WebrtcTransportFactory::~WebrtcTransportFactory() {} | 495 WebrtcTransportFactory::~WebrtcTransportFactory() {} |
| 488 | 496 |
| 489 scoped_ptr<Transport> WebrtcTransportFactory::CreateTransport() { | 497 scoped_ptr<Transport> WebrtcTransportFactory::CreateTransport() { |
| 490 return make_scoped_ptr(new WebrtcTransport(port_allocator_factory_, role_, | 498 return make_scoped_ptr( |
| 491 worker_thread_.task_runner())); | 499 new WebrtcTransport(worker_thread_, port_allocator_factory_, role_)); |
| 492 } | 500 } |
| 493 | 501 |
| 494 } // namespace protocol | 502 } // namespace protocol |
| 495 } // namespace remoting | 503 } // namespace remoting |
| OLD | NEW |