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 |