Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: webrtc/p2p/base/transportcontroller.cc

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

Powered by Google App Engine
This is Rietveld 408576698