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

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

Issue 1246913005: TransportController refactoring (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: 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 bool TransportController::AddRemoteCandidates(const std::string& transport_name,
115 const Candidates& candidates,
116 std::string* err) {
117 return worker_thread_->Invoke<bool>(
118 rtc::Bind(&TransportController::AddRemoteCandidates_w, this,
119 transport_name, candidates, err));
120 }
121
122 bool TransportController::ReadyForRemoteCandidates(
123 const std::string& transport_name) {
124 return worker_thread_->Invoke<bool>(rtc::Bind(
125 &TransportController::ReadyForRemoteCandidates_w, this, transport_name));
126 }
127
128 bool TransportController::GetStats(const std::string& transport_name,
129 TransportStats* stats) {
130 return worker_thread_->Invoke<bool>(
131 rtc::Bind(&TransportController::GetStats_w, this, transport_name, stats));
132 }
133
134 TransportChannel* TransportController::CreateTransportChannel_w(
135 const std::string& transport_name,
136 int component) {
137 RTC_DCHECK(worker_thread_->IsCurrent());
138
139 Transport* transport = GetOrCreateTransport_w(transport_name);
140 return transport->CreateChannel(component);
141 }
142
143 void TransportController::DestroyTransportChannel_w(
144 const std::string& transport_name,
145 int component) {
146 RTC_DCHECK(worker_thread_->IsCurrent());
147
148 Transport* transport = GetTransport_w(transport_name);
149 if (!transport) {
150 ASSERT(false);
151 return;
152 }
153 transport->DestroyChannel(component);
154
155 // Just as we create a Transport when its first channel is created,
156 // we delete it when its last channel is deleted.
157 if (!transport->HasChannels()) {
158 DestroyTransport_w(transport_name);
159 }
160 }
161
162 const rtc::scoped_refptr<rtc::RTCCertificate>&
163 TransportController::certificate_for_testing() {
164 return certificate_;
165 }
166
167 Transport* TransportController::CreateTransport_w(
168 const std::string& transport_name) {
169 RTC_DCHECK(worker_thread_->IsCurrent());
170
171 Transport* transport = new DtlsTransport<P2PTransport>(
172 transport_name, port_allocator(), certificate_);
173 return transport;
174 }
175
176 Transport* TransportController::GetTransport_w(
177 const std::string& transport_name) {
178 RTC_DCHECK(worker_thread_->IsCurrent());
179
180 auto iter = transports_.find(transport_name);
181 return (iter != transports_.end()) ? iter->second : nullptr;
182 }
183
184 void TransportController::OnMessage(rtc::Message* pmsg) {
185 RTC_DCHECK(signaling_thread_->IsCurrent());
186
187 switch (pmsg->message_id) {
188 case MSG_ICECONNECTIONSTATE: {
189 rtc::TypedMessageData<IceConnectionState>* data =
190 static_cast<rtc::TypedMessageData<IceConnectionState>*>(pmsg->pdata);
191 SignalConnectionState(data->data());
192 delete data;
193 break;
194 }
195 case MSG_RECEIVING: {
196 rtc::TypedMessageData<bool>* data =
197 static_cast<rtc::TypedMessageData<bool>*>(pmsg->pdata);
198 SignalReceiving(data->data());
199 delete data;
200 break;
201 }
202 case MSG_ICEGATHERINGSTATE: {
203 rtc::TypedMessageData<IceGatheringState>* data =
204 static_cast<rtc::TypedMessageData<IceGatheringState>*>(pmsg->pdata);
205 SignalGatheringState(data->data());
206 delete data;
207 break;
208 }
209 case MSG_CANDIDATESGATHERED: {
210 CandidatesData* data = static_cast<CandidatesData*>(pmsg->pdata);
211 SignalCandidatesGathered(data->transport_name, data->candidates);
212 delete data;
213 break;
214 }
215 default:
216 ASSERT(false);
217 }
218 }
219
220 Transport* TransportController::GetOrCreateTransport_w(
221 const std::string& transport_name) {
222 RTC_DCHECK(worker_thread_->IsCurrent());
223
224 Transport* transport = GetTransport_w(transport_name);
225 if (transport) {
226 return transport;
227 }
228
229 transport = CreateTransport_w(transport_name);
230 // The stuff below happens outside of CreateTransport_w so that unit tests
231 // can override CreateTransport_w to return a different type of transport.
232 transport->SetSslMaxProtocolVersion(ssl_max_version_);
233 transport->SetChannelReceivingTimeout(ice_receiving_timeout_ms_);
234 transport->SetIceRole(ice_role_);
235 transport->SetIceTiebreaker(ice_tiebreaker_);
236 if (certificate_) {
237 transport->SetLocalCertificate(certificate_);
238 }
239 transport->SignalConnecting.connect(
240 this, &TransportController::OnTransportConnecting_w);
241 transport->SignalWritableState.connect(
242 this, &TransportController::OnTransportWritableState_w);
243 transport->SignalReceivingState.connect(
244 this, &TransportController::OnTransportReceivingState_w);
245 transport->SignalCompleted.connect(
246 this, &TransportController::OnTransportCompleted_w);
247 transport->SignalFailed.connect(this,
248 &TransportController::OnTransportFailed_w);
249 transport->SignalGatheringState.connect(
250 this, &TransportController::OnTransportGatheringState_w);
251 transport->SignalCandidatesGathered.connect(
252 this, &TransportController::OnTransportCandidatesGathered_w);
253 transport->SignalRoleConflict.connect(
254 this, &TransportController::OnTransportRoleConflict_w);
255 transports_[transport_name] = transport;
256
257 return transport;
258 }
259
260 void TransportController::DestroyTransport_w(
261 const std::string& transport_name) {
262 RTC_DCHECK(worker_thread_->IsCurrent());
263
264 auto iter = transports_.find(transport_name);
265 if (iter != transports_.end()) {
266 delete iter->second;
267 transports_.erase(transport_name);
268 }
269 // Destroying a transport may cause aggregate state to change.
270 UpdateAggregateStates_w();
271 }
272
273 void TransportController::DestroyAllTransports_w() {
274 RTC_DCHECK(worker_thread_->IsCurrent());
275
276 for (const auto& kv : transports_) {
277 delete kv.second;
278 }
279 transports_.clear();
280 }
281
282 bool TransportController::SetSslMaxProtocolVersion_w(
283 rtc::SSLProtocolVersion version) {
284 RTC_DCHECK(worker_thread_->IsCurrent());
285
286 // Max SSL version can only be set before transports are created.
287 if (!transports_.empty()) {
288 return false;
289 }
290
291 ssl_max_version_ = version;
292 return true;
293 }
294
295 void TransportController::SetIceConnectionReceivingTimeout_w(int timeout_ms) {
296 RTC_DCHECK(worker_thread_->IsCurrent());
297 ice_receiving_timeout_ms_ = timeout_ms;
298 for (const auto& kv : transports_) {
299 kv.second->SetChannelReceivingTimeout(timeout_ms);
300 }
301 }
302
303 void TransportController::SetIceRole_w(IceRole ice_role) {
304 RTC_DCHECK(worker_thread_->IsCurrent());
305 ice_role_ = ice_role;
306 for (const auto& kv : transports_) {
307 kv.second->SetIceRole(ice_role_);
308 }
309 }
310
311 bool TransportController::GetSslRole_w(rtc::SSLRole* role) {
312 RTC_DCHECK(worker_thread()->IsCurrent());
313
314 if (transports_.empty()) {
315 return false;
316 }
317 return transports_.begin()->second->GetSslRole(role);
318 }
319
320 bool TransportController::SetLocalCertificate_w(
321 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
322 RTC_DCHECK(worker_thread_->IsCurrent());
323
324 if (certificate_) {
325 return false;
326 }
327 if (!certificate) {
328 return false;
329 }
330 certificate_ = certificate;
331
332 for (const auto& kv : transports_) {
333 kv.second->SetLocalCertificate(certificate_);
334 }
335 return true;
336 }
337
338 bool TransportController::GetLocalCertificate_w(
339 const std::string& transport_name,
340 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
341 RTC_DCHECK(worker_thread_->IsCurrent());
342
343 Transport* t = GetTransport_w(transport_name);
344 if (!t) {
345 return false;
346 }
347
348 return t->GetLocalCertificate(certificate);
349 }
350
351 bool TransportController::GetRemoteSSLCertificate_w(
352 const std::string& transport_name,
353 rtc::SSLCertificate** cert) {
354 RTC_DCHECK(worker_thread_->IsCurrent());
355
356 Transport* t = GetTransport_w(transport_name);
357 if (!t) {
358 return false;
359 }
360
361 return t->GetRemoteSSLCertificate(cert);
362 }
363
364 bool TransportController::SetLocalTransportDescription_w(
365 const std::string& transport_name,
366 const TransportDescription& tdesc,
367 ContentAction action,
368 std::string* err) {
369 RTC_DCHECK(worker_thread()->IsCurrent());
370
371 Transport* transport = GetTransport_w(transport_name);
372 if (!transport) {
373 // If we didn't find a transport, that's not an error;
374 // it could have been deleted as a result of bundling.
375 // TODO(deadbeef): Make callers smarter so they won't attempt to set a
376 // description on a deleted transport.
377 return true;
378 }
379
380 return transport->SetLocalTransportDescription(tdesc, action, err);
381 }
382
383 bool TransportController::SetRemoteTransportDescription_w(
384 const std::string& transport_name,
385 const TransportDescription& tdesc,
386 ContentAction action,
387 std::string* err) {
388 RTC_DCHECK(worker_thread()->IsCurrent());
389
390 Transport* transport = GetTransport_w(transport_name);
391 if (!transport) {
392 // If we didn't find a transport, that's not an error;
393 // it could have been deleted as a result of bundling.
394 // TODO(deadbeef): Make callers smarter so they won't attempt to set a
395 // description on a deleted transport.
396 return true;
397 }
398
399 return transport->SetRemoteTransportDescription(tdesc, action, err);
400 }
401
402 bool TransportController::AddRemoteCandidates_w(
403 const std::string& transport_name,
404 const Candidates& candidates,
405 std::string* err) {
406 RTC_DCHECK(worker_thread()->IsCurrent());
407
408 Transport* transport = GetTransport_w(transport_name);
409 if (!transport) {
410 // If we didn't find a transport, that's not an error;
411 // it could have been deleted as a result of bundling.
412 return true;
413 }
414
415 return transport->AddRemoteCandidates(candidates, err);
416 }
417
418 bool TransportController::ReadyForRemoteCandidates_w(
419 const std::string& transport_name) {
420 RTC_DCHECK(worker_thread()->IsCurrent());
421
422 Transport* transport = GetTransport_w(transport_name);
423 if (!transport) {
424 return false;
425 }
426 return transport->ready_for_remote_candidates();
427 }
428
429 bool TransportController::GetStats_w(const std::string& transport_name,
430 TransportStats* stats) {
431 RTC_DCHECK(worker_thread()->IsCurrent());
432
433 Transport* transport = GetTransport_w(transport_name);
434 if (!transport) {
435 return false;
436 }
437 return transport->GetStats(stats);
438 }
439
440 void TransportController::OnTransportConnecting_w(Transport* transport) {
441 RTC_DCHECK(worker_thread_->IsCurrent());
442 UpdateAggregateStates_w();
443 }
444
445 void TransportController::OnTransportWritableState_w(Transport* transport) {
446 RTC_DCHECK(worker_thread_->IsCurrent());
447 UpdateAggregateStates_w();
448 }
449
450 void TransportController::OnTransportReceivingState_w(Transport* transport) {
451 RTC_DCHECK(worker_thread_->IsCurrent());
452 UpdateAggregateStates_w();
453 }
454
455 void TransportController::OnTransportCompleted_w(Transport* transport) {
456 RTC_DCHECK(worker_thread_->IsCurrent());
457 UpdateAggregateStates_w();
458 }
459
460 void TransportController::OnTransportFailed_w(Transport* transport) {
461 RTC_DCHECK(worker_thread_->IsCurrent());
462 UpdateAggregateStates_w();
463 }
464
465 void TransportController::OnTransportGatheringState_w(Transport* transport) {
466 RTC_DCHECK(worker_thread_->IsCurrent());
467 UpdateAggregateStates_w();
468 }
469
470 void TransportController::OnTransportCandidatesGathered_w(
471 Transport* transport,
472 const std::vector<Candidate>& candidates) {
473 RTC_DCHECK(worker_thread_->IsCurrent());
474 CandidatesData* data = new CandidatesData(transport->name(), candidates);
475 signaling_thread_->Post(this, MSG_CANDIDATESGATHERED, data);
476 }
477
478 void TransportController::OnTransportRoleConflict_w() {
479 RTC_DCHECK(worker_thread_->IsCurrent());
480
481 if (ice_role_switch_) {
482 LOG(LS_WARNING) << "Repeat of role conflict signal from Transport.";
483 return;
484 }
485
486 ice_role_switch_ = true;
487 IceRole reversed_role = (ice_role_ == ICEROLE_CONTROLLING)
488 ? ICEROLE_CONTROLLED
489 : ICEROLE_CONTROLLING;
490 for (const auto& kv : transports_) {
491 kv.second->SetIceRole(reversed_role);
492 }
493 }
494
495 void TransportController::UpdateAggregateStates_w() {
496 RTC_DCHECK(worker_thread_->IsCurrent());
497
498 IceConnectionState new_connection_state = kIceConnectionConnecting;
499 IceGatheringState new_gathering_state = kIceGatheringNew;
500 bool any_receiving = false;
501 bool any_failed = false;
502 bool all_connected = HasChannels_w();
503 bool all_completed = HasChannels_w();
504 bool any_gathering = false;
505 bool all_done_gathering = HasChannels_w();
506 for (const auto& kv : transports_) {
507 // Ignore transports without channels since they're about to be deleted,
508 // and their state is meaningless.
509 if (!kv.second->HasChannels()) {
510 continue;
511 }
512 any_receiving = any_receiving || kv.second->any_channel_receiving();
513 any_failed = any_failed || kv.second->AnyChannelFailed();
514 all_connected = all_connected && kv.second->all_channels_writable();
515 all_completed = all_completed && kv.second->AllChannelsCompleted();
516 any_gathering =
517 any_gathering || kv.second->gathering_state() != kIceGatheringNew;
518 all_done_gathering = all_done_gathering &&
519 kv.second->gathering_state() == kIceGatheringComplete;
520 }
521
522 if (any_failed) {
523 new_connection_state = kIceConnectionFailed;
524 } else if (all_completed) {
525 new_connection_state = kIceConnectionCompleted;
526 } else if (all_connected) {
527 new_connection_state = kIceConnectionConnected;
528 }
529 if (connection_state_ != new_connection_state) {
530 connection_state_ = new_connection_state;
531 signaling_thread_->Post(
532 this, MSG_ICECONNECTIONSTATE,
533 new rtc::TypedMessageData<IceConnectionState>(new_connection_state));
534 }
535
536 if (receiving_ != any_receiving) {
537 receiving_ = any_receiving;
538 signaling_thread_->Post(this, MSG_RECEIVING,
539 new rtc::TypedMessageData<bool>(any_receiving));
540 }
541
542 if (all_done_gathering) {
543 new_gathering_state = kIceGatheringComplete;
544 } else if (any_gathering) {
545 new_gathering_state = kIceGatheringGathering;
546 }
547 if (gathering_state_ != new_gathering_state) {
548 gathering_state_ = new_gathering_state;
549 signaling_thread_->Post(
550 this, MSG_ICEGATHERINGSTATE,
551 new rtc::TypedMessageData<IceGatheringState>(new_gathering_state));
552 }
553 }
554
555 bool TransportController::HasChannels_w() {
556 for (const auto& kv : transports_) {
557 if (kv.second->HasChannels()) {
558 return true;
559 }
560 }
561 return false;
562 }
563
564 } // 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