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

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: Use "EXPECT_TRUE" instead of "EXPECT_EQ(true...", etc. 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
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/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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698