OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | |
3 * | |
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 | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/p2p/base/transportcontroller.h" | |
12 | |
13 #include "webrtc/base/bind.h" | |
14 #include "webrtc/base/thread.h" | |
15 #include "webrtc/p2p/base/dtlstransport.h" | |
16 #include "webrtc/p2p/base/p2ptransport.h" | |
17 | |
18 namespace cricket { | |
19 | |
20 enum { | |
21 MSG_ICECONNECTIONSTATE, | |
22 MSG_RECEIVING, | |
23 MSG_ICEGATHERINGSTATE, | |
24 MSG_CANDIDATESGATHERED, | |
25 }; | |
26 | |
27 struct CandidatesData : public rtc::MessageData { | |
28 CandidatesData(const std::string& transport_name, | |
29 const Candidates& candidates) | |
30 : transport_name(transport_name), candidates(candidates) {} | |
31 | |
32 std::string transport_name; | |
33 Candidates candidates; | |
34 }; | |
35 | |
36 TransportController::TransportController(rtc::Thread* signaling_thread, | |
37 rtc::Thread* worker_thread, | |
38 PortAllocator* port_allocator) | |
39 : signaling_thread_(signaling_thread), | |
40 worker_thread_(worker_thread), | |
41 port_allocator_(port_allocator) {} | |
42 | |
43 TransportController::~TransportController() { | |
44 worker_thread_->Invoke<void>( | |
45 rtc::Bind(&TransportController::DestroyAllTransports_w, this)); | |
46 signaling_thread_->Clear(this); | |
47 } | |
48 | |
49 bool TransportController::SetSslMaxProtocolVersion( | |
50 rtc::SSLProtocolVersion version) { | |
51 return worker_thread_->Invoke<bool>(rtc::Bind( | |
52 &TransportController::SetSslMaxProtocolVersion_w, this, version)); | |
53 } | |
54 | |
55 void TransportController::SetIceConnectionReceivingTimeout(int timeout_ms) { | |
56 worker_thread_->Invoke<void>( | |
57 rtc::Bind(&TransportController::SetIceConnectionReceivingTimeout_w, this, | |
58 timeout_ms)); | |
59 } | |
60 | |
61 void TransportController::SetIceRole(IceRole ice_role) { | |
62 worker_thread_->Invoke<void>( | |
63 rtc::Bind(&TransportController::SetIceRole_w, this, ice_role)); | |
64 } | |
65 | |
66 bool TransportController::GetSslRole(rtc::SSLRole* role) { | |
67 return worker_thread_->Invoke<bool>( | |
68 rtc::Bind(&TransportController::GetSslRole_w, this, role)); | |
69 } | |
70 | |
71 bool TransportController::SetLocalCertificate( | |
72 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { | |
73 return worker_thread_->Invoke<bool>(rtc::Bind( | |
74 &TransportController::SetLocalCertificate_w, this, certificate)); | |
75 } | |
76 | |
77 bool TransportController::GetLocalCertificate( | |
78 const std::string& transport_name, | |
79 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) { | |
80 return worker_thread_->Invoke<bool>( | |
81 rtc::Bind(&TransportController::GetLocalCertificate_w, this, | |
82 transport_name, certificate)); | |
83 } | |
84 | |
85 bool TransportController::GetRemoteSSLCertificate( | |
86 const std::string& transport_name, | |
87 rtc::SSLCertificate** cert) { | |
88 return worker_thread_->Invoke<bool>( | |
89 rtc::Bind(&TransportController::GetRemoteSSLCertificate_w, this, | |
90 transport_name, cert)); | |
91 } | |
92 | |
93 bool TransportController::SetLocalTransportDescription( | |
94 const std::string& transport_name, | |
95 const TransportDescription& tdesc, | |
96 ContentAction action, | |
97 std::string* err) { | |
98 return worker_thread_->Invoke<bool>( | |
99 rtc::Bind(&TransportController::SetLocalTransportDescription_w, this, | |
100 transport_name, tdesc, action, err)); | |
101 } | |
102 | |
103 bool TransportController::SetRemoteTransportDescription( | |
104 const std::string& transport_name, | |
105 const TransportDescription& tdesc, | |
106 ContentAction action, | |
107 std::string* err) { | |
108 return worker_thread_->Invoke<bool>( | |
109 rtc::Bind(&TransportController::SetRemoteTransportDescription_w, this, | |
110 transport_name, tdesc, action, err)); | |
111 } | |
112 | |
113 bool TransportController::AddRemoteCandidates(const std::string& transport_name, | |
114 const Candidates& candidates, | |
115 std::string* err) { | |
116 return worker_thread_->Invoke<bool>( | |
117 rtc::Bind(&TransportController::AddRemoteCandidates_w, this, | |
118 transport_name, candidates, err)); | |
119 } | |
120 | |
121 bool TransportController::ReadyForRemoteCandidates( | |
122 const std::string& transport_name) { | |
123 return worker_thread_->Invoke<bool>(rtc::Bind( | |
124 &TransportController::ReadyForRemoteCandidates_w, this, transport_name)); | |
125 } | |
126 | |
127 bool TransportController::GetStats(const std::string& transport_name, | |
128 TransportStats* stats) { | |
129 return worker_thread_->Invoke<bool>( | |
130 rtc::Bind(&TransportController::GetStats_w, this, transport_name, stats)); | |
131 } | |
132 | |
133 TransportChannel* TransportController::CreateTransportChannel_w( | |
134 const std::string& transport_name, | |
135 int component) { | |
136 ASSERT(worker_thread_->IsCurrent()); | |
137 | |
138 Transport* transport = GetOrCreateTransport_w(transport_name); | |
139 return transport->CreateChannel(component); | |
140 } | |
141 | |
142 void TransportController::DestroyTransportChannel_w( | |
143 const std::string& transport_name, | |
144 int component) { | |
145 ASSERT(worker_thread_->IsCurrent()); | |
146 | |
147 Transport* transport = GetTransport_w(transport_name); | |
148 if (!transport) { | |
149 ASSERT(false); | |
150 return; | |
151 } | |
152 transport->DestroyChannel(component); | |
153 | |
154 // Just as we create a Transport when its first channel is created, | |
155 // we delete it when its last channel is deleted. | |
156 if (!transport->HasChannels()) { | |
157 DestroyTransport_w(transport_name); | |
158 } | |
159 } | |
160 | |
161 const rtc::scoped_refptr<rtc::RTCCertificate>& | |
162 TransportController::certificate_for_testing() { | |
163 return certificate_; | |
164 } | |
165 | |
166 Transport* TransportController::CreateTransport_w( | |
167 const std::string& transport_name) { | |
168 ASSERT(worker_thread_->IsCurrent()); | |
169 | |
170 Transport* transport = new DtlsTransport<P2PTransport>( | |
171 transport_name, port_allocator(), certificate_); | |
172 return transport; | |
173 } | |
174 | |
175 Transport* TransportController::GetTransport_w( | |
176 const std::string& transport_name) { | |
177 ASSERT(worker_thread_->IsCurrent()); | |
178 | |
179 auto iter = transports_.find(transport_name); | |
180 return (iter != transports_.end()) ? iter->second : nullptr; | |
181 } | |
182 | |
183 void TransportController::OnMessage(rtc::Message* pmsg) { | |
184 ASSERT(signaling_thread_->IsCurrent()); | |
185 | |
186 switch (pmsg->message_id) { | |
187 case MSG_ICECONNECTIONSTATE: { | |
188 rtc::TypedMessageData<IceConnectionState>* data = | |
189 static_cast<rtc::TypedMessageData<IceConnectionState>*>(pmsg->pdata); | |
190 SignalConnectionState(data->data()); | |
191 delete data; | |
192 break; | |
193 } | |
194 case MSG_RECEIVING: { | |
195 rtc::TypedMessageData<bool>* data = | |
196 static_cast<rtc::TypedMessageData<bool>*>(pmsg->pdata); | |
197 SignalReceiving(data->data()); | |
198 delete data; | |
199 break; | |
200 } | |
201 case MSG_ICEGATHERINGSTATE: { | |
202 rtc::TypedMessageData<IceGatheringState>* data = | |
203 static_cast<rtc::TypedMessageData<IceGatheringState>*>(pmsg->pdata); | |
204 SignalGatheringState(data->data()); | |
205 delete data; | |
206 break; | |
207 } | |
208 case MSG_CANDIDATESGATHERED: { | |
209 CandidatesData* data = static_cast<CandidatesData*>(pmsg->pdata); | |
210 SignalCandidatesGathered(data->transport_name, data->candidates); | |
211 delete data; | |
212 break; | |
213 } | |
214 default: | |
215 ASSERT(false); | |
216 } | |
217 } | |
218 | |
219 Transport* TransportController::GetOrCreateTransport_w( | |
220 const std::string& transport_name) { | |
221 ASSERT(worker_thread_->IsCurrent()); | |
222 | |
223 Transport* transport = GetTransport_w(transport_name); | |
224 if (transport) { | |
225 return transport; | |
226 } | |
227 | |
228 transport = CreateTransport_w(transport_name); | |
229 // The stuff below happens outside of CreateTransport_w so that unit tests | |
230 // can override CreateTransport_w to return a different type of transport. | |
231 transport->SetSslMaxProtocolVersion(ssl_max_version_); | |
232 transport->SetChannelReceivingTimeout(ice_receiving_timeout_ms_); | |
233 transport->SetIceRole(ice_role_); | |
234 transport->SetIceTiebreaker(ice_tiebreaker_); | |
235 if (certificate_) { | |
236 transport->SetLocalCertificate(certificate_); | |
237 } | |
238 transport->SignalConnecting.connect( | |
239 this, &TransportController::OnTransportConnecting_w); | |
240 transport->SignalWritableState.connect( | |
241 this, &TransportController::OnTransportWritableState_w); | |
242 transport->SignalReceivingState.connect( | |
243 this, &TransportController::OnTransportReceivingState_w); | |
244 transport->SignalCompleted.connect( | |
245 this, &TransportController::OnTransportCompleted_w); | |
246 transport->SignalFailed.connect(this, | |
247 &TransportController::OnTransportFailed_w); | |
248 transport->SignalGatheringState.connect( | |
249 this, &TransportController::OnTransportGatheringState_w); | |
250 transport->SignalCandidatesGathered.connect( | |
251 this, &TransportController::OnTransportCandidatesGathered_w); | |
252 transport->SignalRoleConflict.connect( | |
253 this, &TransportController::OnTransportRoleConflict_w); | |
254 transports_[transport_name] = transport; | |
255 | |
256 return transport; | |
257 } | |
258 | |
259 void TransportController::DestroyTransport_w( | |
260 const std::string& transport_name) { | |
261 ASSERT(worker_thread_->IsCurrent()); | |
262 | |
263 auto iter = transports_.find(transport_name); | |
264 if (iter != transports_.end()) { | |
265 delete iter->second; | |
266 transports_.erase(transport_name); | |
267 } | |
268 // Destroying a transport may cause aggregate state to change. | |
269 UpdateAggregateStates_w(); | |
270 } | |
271 | |
272 void TransportController::DestroyAllTransports_w() { | |
273 ASSERT(worker_thread_->IsCurrent()); | |
274 | |
275 for (const auto& kv : transports_) { | |
276 delete kv.second; | |
277 } | |
278 transports_.clear(); | |
279 } | |
280 | |
281 bool TransportController::SetSslMaxProtocolVersion_w( | |
282 rtc::SSLProtocolVersion version) { | |
283 ASSERT(worker_thread_->IsCurrent()); | |
284 | |
285 // Max SSL version can only be set before transports are created. | |
286 if (!transports_.empty()) { | |
287 return false; | |
288 } | |
289 | |
290 ssl_max_version_ = version; | |
291 return true; | |
292 } | |
293 | |
294 void TransportController::SetIceConnectionReceivingTimeout_w(int timeout_ms) { | |
295 ASSERT(worker_thread_->IsCurrent()); | |
296 ice_receiving_timeout_ms_ = timeout_ms; | |
297 for (const auto& kv : transports_) { | |
298 kv.second->SetChannelReceivingTimeout(timeout_ms); | |
299 } | |
300 } | |
301 | |
302 void TransportController::SetIceRole_w(IceRole ice_role) { | |
303 ASSERT(worker_thread_->IsCurrent()); | |
304 ice_role_ = ice_role; | |
305 for (const auto& kv : transports_) { | |
306 kv.second->SetIceRole(ice_role_); | |
307 } | |
308 } | |
309 | |
310 bool TransportController::GetSslRole_w(rtc::SSLRole* role) { | |
311 ASSERT(worker_thread()->IsCurrent()); | |
312 | |
313 if (transports_.empty()) { | |
314 return false; | |
315 } | |
316 return transports_.begin()->second->GetSslRole(role); | |
317 } | |
318 | |
319 bool TransportController::SetLocalCertificate_w( | |
320 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { | |
321 ASSERT(worker_thread_->IsCurrent()); | |
322 | |
323 if (certificate_) { | |
324 return false; | |
325 } | |
326 if (!certificate) { | |
327 return false; | |
328 } | |
329 certificate_ = certificate; | |
330 | |
331 for (const auto& kv : transports_) { | |
332 kv.second->SetLocalCertificate(certificate_); | |
333 } | |
334 return true; | |
335 } | |
336 | |
337 bool TransportController::GetLocalCertificate_w( | |
338 const std::string& transport_name, | |
339 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) { | |
340 ASSERT(worker_thread_->IsCurrent()); | |
341 | |
342 Transport* t = GetTransport_w(transport_name); | |
343 if (!t) { | |
344 return false; | |
345 } | |
346 | |
347 return t->GetLocalCertificate(certificate); | |
348 } | |
349 | |
350 bool TransportController::GetRemoteSSLCertificate_w( | |
351 const std::string& transport_name, | |
352 rtc::SSLCertificate** cert) { | |
353 ASSERT(worker_thread_->IsCurrent()); | |
354 | |
355 Transport* t = GetTransport_w(transport_name); | |
356 if (!t) { | |
357 return false; | |
358 } | |
359 | |
360 return t->GetRemoteSSLCertificate(cert); | |
361 } | |
362 | |
363 bool TransportController::SetLocalTransportDescription_w( | |
364 const std::string& transport_name, | |
365 const TransportDescription& tdesc, | |
366 ContentAction action, | |
367 std::string* err) { | |
368 ASSERT(worker_thread()->IsCurrent()); | |
369 | |
370 Transport* transport = GetTransport_w(transport_name); | |
371 if (!transport) { | |
372 // If we didn't find a transport, that's not an error; | |
373 // it could have been deleted as a result of bundling. | |
374 // TODO(deadbeef): Make callers smarter so they won't attempt to set a | |
375 // description on a deleted transport. | |
376 return true; | |
377 } | |
378 | |
379 return transport->SetLocalTransportDescription(tdesc, action, err); | |
380 } | |
381 | |
382 bool TransportController::SetRemoteTransportDescription_w( | |
383 const std::string& transport_name, | |
384 const TransportDescription& tdesc, | |
385 ContentAction action, | |
386 std::string* err) { | |
387 ASSERT(worker_thread()->IsCurrent()); | |
388 | |
389 Transport* transport = GetTransport_w(transport_name); | |
390 if (!transport) { | |
391 // If we didn't find a transport, that's not an error; | |
392 // it could have been deleted as a result of bundling. | |
393 // TODO(deadbeef): Make callers smarter so they won't attempt to set a | |
394 // description on a deleted transport. | |
395 return true; | |
396 } | |
397 | |
398 return transport->SetRemoteTransportDescription(tdesc, action, err); | |
399 } | |
400 | |
401 bool TransportController::AddRemoteCandidates_w( | |
402 const std::string& transport_name, | |
403 const Candidates& candidates, | |
404 std::string* err) { | |
405 ASSERT(worker_thread()->IsCurrent()); | |
406 | |
407 Transport* transport = GetTransport_w(transport_name); | |
408 if (!transport) { | |
409 // If we didn't find a transport, that's not an error; | |
410 // it could have been deleted as a result of bundling. | |
411 return true; | |
412 } | |
413 | |
414 return transport->AddRemoteCandidates(candidates, err); | |
415 } | |
416 | |
417 bool TransportController::ReadyForRemoteCandidates_w( | |
418 const std::string& transport_name) { | |
419 ASSERT(worker_thread()->IsCurrent()); | |
420 | |
421 Transport* transport = GetTransport_w(transport_name); | |
422 if (!transport) { | |
423 return false; | |
424 } | |
425 return transport->ready_for_remote_candidates(); | |
426 } | |
427 | |
428 bool TransportController::GetStats_w(const std::string& transport_name, | |
429 TransportStats* stats) { | |
430 ASSERT(worker_thread()->IsCurrent()); | |
431 | |
432 Transport* transport = GetTransport_w(transport_name); | |
433 if (!transport) { | |
434 return false; | |
435 } | |
436 return transport->GetStats(stats); | |
437 } | |
438 | |
439 void TransportController::OnTransportConnecting_w(Transport* transport) { | |
440 ASSERT(worker_thread_->IsCurrent()); | |
441 UpdateAggregateStates_w(); | |
442 } | |
443 | |
444 void TransportController::OnTransportWritableState_w(Transport* transport) { | |
445 ASSERT(worker_thread_->IsCurrent()); | |
446 UpdateAggregateStates_w(); | |
447 } | |
448 | |
449 void TransportController::OnTransportReceivingState_w(Transport* transport) { | |
450 ASSERT(worker_thread_->IsCurrent()); | |
451 UpdateAggregateStates_w(); | |
452 } | |
453 | |
454 void TransportController::OnTransportCompleted_w(Transport* transport) { | |
455 ASSERT(worker_thread_->IsCurrent()); | |
456 UpdateAggregateStates_w(); | |
457 } | |
458 | |
459 void TransportController::OnTransportFailed_w(Transport* transport) { | |
460 ASSERT(worker_thread_->IsCurrent()); | |
461 UpdateAggregateStates_w(); | |
462 } | |
463 | |
464 void TransportController::OnTransportGatheringState_w(Transport* transport) { | |
465 ASSERT(worker_thread_->IsCurrent()); | |
466 UpdateAggregateStates_w(); | |
467 } | |
468 | |
469 void TransportController::OnTransportCandidatesGathered_w( | |
470 Transport* transport, | |
471 const std::vector<Candidate>& candidates) { | |
472 ASSERT(worker_thread_->IsCurrent()); | |
473 CandidatesData* data = new CandidatesData(transport->name(), candidates); | |
474 signaling_thread_->Post(this, MSG_CANDIDATESGATHERED, data); | |
475 } | |
476 | |
477 void TransportController::OnTransportRoleConflict_w() { | |
478 ASSERT(worker_thread_->IsCurrent()); | |
479 | |
480 if (ice_role_switch_) { | |
481 LOG(LS_WARNING) << "Repeat of role conflict signal from Transport."; | |
482 return; | |
483 } | |
484 | |
485 ice_role_switch_ = true; | |
486 IceRole reversed_role = (ice_role_ == ICEROLE_CONTROLLING) | |
487 ? ICEROLE_CONTROLLED | |
488 : ICEROLE_CONTROLLING; | |
489 for (const auto& kv : transports_) { | |
490 kv.second->SetIceRole(reversed_role); | |
491 } | |
492 } | |
493 | |
494 void TransportController::UpdateAggregateStates_w() { | |
495 ASSERT(worker_thread_->IsCurrent()); | |
496 | |
497 IceConnectionState new_connection_state = kIceConnectionConnecting; | |
498 IceGatheringState new_gathering_state = kIceGatheringNew; | |
499 bool any_receiving = false; | |
500 bool any_failed = false; | |
501 bool all_connected = HasChannels_w(); | |
502 bool all_completed = HasChannels_w(); | |
503 bool any_gathering = false; | |
504 bool all_done_gathering = HasChannels_w(); | |
505 for (const auto& kv : transports_) { | |
506 // Ignore transports without channels since they're about to be deleted, | |
507 // and their state is meaningless. | |
508 if (!kv.second->HasChannels()) { | |
509 continue; | |
510 } | |
511 any_receiving = any_receiving || kv.second->any_channel_receiving(); | |
512 any_failed = any_failed || kv.second->AnyChannelFailed(); | |
513 all_connected = all_connected && kv.second->all_channels_writable(); | |
514 all_completed = all_completed && kv.second->AllChannelsCompleted(); | |
515 any_gathering = | |
516 any_gathering || kv.second->gathering_state() != kIceGatheringNew; | |
517 all_done_gathering = all_done_gathering && | |
518 kv.second->gathering_state() == kIceGatheringComplete; | |
519 } | |
520 | |
521 if (any_failed) { | |
522 new_connection_state = kIceConnectionFailed; | |
523 } else if (all_completed) { | |
524 new_connection_state = kIceConnectionCompleted; | |
525 } else if (all_connected) { | |
526 new_connection_state = kIceConnectionConnected; | |
527 } | |
pthatcher1
2015/09/09 06:47:52
Maybe we should say:
if (!HasChannels_w()) {
ne
Taylor Brandstetter
2015/09/10 01:17:48
That's similar to what I had initially, but we dec
| |
528 if (connection_state_ != new_connection_state) { | |
529 connection_state_ = new_connection_state; | |
530 signaling_thread_->Post( | |
531 this, MSG_ICECONNECTIONSTATE, | |
532 new rtc::TypedMessageData<IceConnectionState>(new_connection_state)); | |
533 } | |
534 | |
535 if (receiving_ != any_receiving) { | |
536 receiving_ = any_receiving; | |
537 signaling_thread_->Post(this, MSG_RECEIVING, | |
538 new rtc::TypedMessageData<bool>(any_receiving)); | |
539 } | |
540 | |
541 if (all_done_gathering) { | |
542 new_gathering_state = kIceGatheringComplete; | |
543 } else if (any_gathering) { | |
544 new_gathering_state = kIceGatheringGathering; | |
545 } | |
546 if (gathering_state_ != new_gathering_state) { | |
547 gathering_state_ = new_gathering_state; | |
548 signaling_thread_->Post( | |
549 this, MSG_ICEGATHERINGSTATE, | |
550 new rtc::TypedMessageData<IceGatheringState>(new_gathering_state)); | |
551 } | |
552 } | |
553 | |
554 bool TransportController::HasChannels_w() { | |
555 for (const auto& kv : transports_) { | |
556 if (kv.second->HasChannels()) { | |
557 return true; | |
558 } | |
559 } | |
560 return false; | |
561 } | |
562 | |
563 } // namespace cricket | |
OLD | NEW |