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

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: minor cleanup Created 5 years, 4 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_CONNECTIONSTATE,
22 MSG_RECEIVING,
23 MSG_CANDIDATESALLOCATIONSTARTED,
24 MSG_CANDIDATESALLOCATIONDONE,
25 MSG_CANDIDATESREADY,
26 };
27
28 struct CandidatesData : public rtc::MessageData {
29 CandidatesData(const std::string& transport_name,
30 const Candidates& candidates)
31 : transport_name(transport_name),
32 candidates(candidates) {
33 }
34
35 std::string transport_name;
36 Candidates candidates;
37 };
38
39 TransportController::TransportController(rtc::Thread* signaling_thread,
40 rtc::Thread* worker_thread,
41 PortAllocator* port_allocator)
42 : signaling_thread_(signaling_thread),
43 worker_thread_(worker_thread),
44 port_allocator_(port_allocator),
45 ice_receiving_timeout_ms_(-1),
46 ice_role_(ICEROLE_CONTROLLING),
47 ssl_max_version_(rtc::SSL_PROTOCOL_DTLS_10),
48 ice_role_switch_(false),
49 ice_tiebreaker_(rtc::CreateRandomId64()),
50 connection_state_(kConnecting),
51 receiving_(false),
52 candidate_gathering_state_(Transport::kGatheringNew) {
53 ASSERT(signaling_thread_->IsCurrent());
54 }
55
56 TransportController::~TransportController() {
57 ASSERT(signaling_thread_->IsCurrent());
58 worker_thread_->Invoke<void>(
59 rtc::Bind(&TransportController::DestroyAllTransports_w, this));
60 signaling_thread_->Clear(this);
61 }
62
63 void TransportController::SetIceConnectionReceivingTimeout(int timeout_ms) {
64 ASSERT(signaling_thread_->IsCurrent());
65 worker_thread_->Invoke<void>(
66 rtc::Bind(&TransportController::SetIceConnectionReceivingTimeout_w, this,
67 timeout_ms));
68 }
69
70 void TransportController::SetIceRole(IceRole ice_role) {
71 ASSERT(signaling_thread_->IsCurrent());
72 worker_thread_->Invoke<void>(
73 rtc::Bind(&TransportController::SetIceRole_w, this, ice_role));
74 }
75
76 bool TransportController::SetIdentity(rtc::SSLIdentity* identity) {
77 ASSERT(signaling_thread_->IsCurrent());
78 return worker_thread_->Invoke<bool>(
79 rtc::Bind(&TransportController::SetIdentity_w, this, identity));
80 }
81
82 bool TransportController::GetIdentity(const std::string& transport_name,
83 rtc::SSLIdentity** identity) {
84 ASSERT(signaling_thread_->IsCurrent());
85 return worker_thread_->Invoke<bool>(
86 rtc::Bind(&TransportController::GetIdentity_w, this, transport_name,
87 identity));
88 }
89
90 bool TransportController::GetRemoteCertificate(
91 const std::string& transport_name,
92 rtc::SSLCertificate** cert) {
93 ASSERT(signaling_thread_->IsCurrent());
94 return worker_thread_->Invoke<bool>(
95 rtc::Bind(&TransportController::GetRemoteCertificate_w, this,
96 transport_name, cert));
97 }
98
99 bool TransportController::SetSslMaxProtocolVersion(
100 rtc::SSLProtocolVersion version) {
101 ASSERT(signaling_thread_->IsCurrent());
102 return worker_thread_->Invoke<bool>(
103 rtc::Bind(&TransportController::SetSslMaxProtocolVersion_w, this,
104 version));
105 }
106
107 bool TransportController::SetLocalTransportDescription(
108 const std::string& transport_name,
109 const TransportDescription& tdesc,
110 ContentAction action,
111 std::string* err) {
112 ASSERT(signaling_thread_->IsCurrent());
113 return worker_thread_->Invoke<bool>(
114 rtc::Bind(&TransportController::SetLocalTransportDescription_w, this,
115 transport_name, tdesc, action, err));
116 }
117
118 bool TransportController::SetRemoteTransportDescription(
119 const std::string& transport_name,
120 const TransportDescription& tdesc,
121 ContentAction action,
122 std::string* err) {
123 ASSERT(signaling_thread_->IsCurrent());
124 return worker_thread_->Invoke<bool>(
125 rtc::Bind(&TransportController::SetRemoteTransportDescription_w, this,
126 transport_name, tdesc, action, err));
127 }
128
129 bool TransportController::AddRemoteCandidates(
130 const std::string& transport_name,
131 const Candidates& candidates,
132 std::string* err) {
133 ASSERT(signaling_thread_->IsCurrent());
134 return worker_thread_->Invoke<bool>(
135 rtc::Bind(&TransportController::AddRemoteCandidates_w, this,
136 transport_name, candidates, err));
137 }
138
139 bool TransportController::ReadyForRemoteCandidates(
140 const std::string& transport_name) {
141 ASSERT(signaling_thread_->IsCurrent());
142 return worker_thread_->Invoke<bool>(
143 rtc::Bind(&TransportController::ReadyForRemoteCandidates_w, this,
144 transport_name));
145 }
146
147 bool TransportController::GetSslRole(rtc::SSLRole* role) {
148 ASSERT(signaling_thread_->IsCurrent());
149 return worker_thread_->Invoke<bool>(
150 rtc::Bind(&TransportController::GetSslRole_w, this, role));
151 }
152
153 bool TransportController::GetStats(
154 const std::string& transport_name,
155 TransportStats* stats) {
156 ASSERT(signaling_thread_->IsCurrent());
157 return worker_thread_->Invoke<bool>(
158 rtc::Bind(&TransportController::GetStats_w, this,
159 transport_name, stats));
160 }
161
162 TransportChannel* TransportController::CreateTransportChannel_w(
163 const std::string& transport_name, int component) {
164 ASSERT(worker_thread_->IsCurrent());
165
166 Transport* transport = GetOrCreateTransport_w(transport_name);
167 return transport->CreateChannel(component);
168 }
169
170 void TransportController::DestroyTransportChannel_w(
171 const std::string& transport_name, int component) {
172 ASSERT(worker_thread_->IsCurrent());
173
174 Transport* transport = GetTransport_w(transport_name);
175 ASSERT(transport != nullptr);
176 transport->DestroyChannel(component);
177
178 // Just as we create a Transport when its first channel is created,
179 // we delete it when its last channel is deleted.
180 if (!transport->HasChannels()) {
181 DestroyTransport_w(transport_name);
182 UpdateState_w();
183 CheckIfCandidatesAllocationDone_w();
184 }
185 }
186
187 void TransportController::OnMessage(rtc::Message* pmsg) {
188 ASSERT(signaling_thread_->IsCurrent());
189
190 switch (pmsg->message_id) {
191 case MSG_CONNECTIONSTATE: {
192 rtc::TypedMessageData<ConnectionState>* data =
193 static_cast<rtc::TypedMessageData<ConnectionState>*>(pmsg->pdata);
194 SignalConnectionStateChanged(data->data());
195 delete data;
196 break;
197 }
198 case MSG_RECEIVING: {
199 rtc::TypedMessageData<bool>* data =
200 static_cast<rtc::TypedMessageData<bool>*>(pmsg->pdata);
201 SignalReceiving(data->data());
202 delete data;
203 break;
204 }
205 case MSG_CANDIDATESALLOCATIONSTARTED:
206 SignalCandidatesAllocationStarted();
207 break;
208 case MSG_CANDIDATESALLOCATIONDONE:
209 SignalCandidatesAllocationDone();
210 break;
211 case MSG_CANDIDATESREADY: {
212 CandidatesData* data = static_cast<CandidatesData*>(pmsg->pdata);
213 SignalCandidatesReady(data->transport_name, data->candidates);
214 delete data;
215 break;
216 }
217 default:
218 ASSERT(false);
219 }
220 }
221
222 Transport* TransportController::CreateTransport_w(
223 const std::string& transport_name) {
224 ASSERT(worker_thread_->IsCurrent());
225
226 Transport* transport = new DtlsTransport<P2PTransport>(
227 transport_name, port_allocator(), identity_.get());
228 return transport;
229 }
230
231 Transport* TransportController::GetOrCreateTransport_w(
232 const std::string& transport_name) {
233 ASSERT(worker_thread_->IsCurrent());
234
235 Transport* transport = GetTransport_w(transport_name);
236 if (transport)
237 return transport;
238
239 transport = CreateTransport_w(transport_name);
240 transport->SetChannelReceivingTimeout(ice_receiving_timeout_ms_);
241 transport->SetIceRole(ice_role_);
242 transport->SetIceTiebreaker(ice_tiebreaker_);
243 transport->SetSslMaxProtocolVersion(ssl_max_version_);
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->SignalCandidatesAllocationStarted.connect(
251 this, &TransportController::OnTransportCandidatesAllocationStarted_w);
252 transport->SignalRouteChange.connect(
253 this, &TransportController::OnTransportRouteChange_w);
254 transport->SignalCandidatesAllocationDone.connect(
255 this, &TransportController::OnTransportCandidatesAllocationDone_w);
256 transport->SignalRoleConflict.connect(
257 this, &TransportController::OnTransportRoleConflict_w);
258 transport->SignalCompleted.connect(
259 this, &TransportController::OnTransportCompleted_w);
260 transport->SignalFailed.connect(
261 this, &TransportController::OnTransportFailed_w);
262 transport->SignalCandidatesReady.connect(
263 this, &TransportController::OnTransportCandidatesReady_w);
264 if (identity_)
265 transport->SetIdentity(identity_.get());
266 transports_[transport_name] = transport;
267
268 return transport;
269 }
270
271 Transport* TransportController::GetTransport_w(
272 const std::string& transport_name) {
273 ASSERT(worker_thread_->IsCurrent());
274
275 auto iter = transports_.find(transport_name);
276 return (iter != transports_.end()) ? iter->second : nullptr;
277 }
278
279 void TransportController::DestroyTransport_w(
280 const std::string& transport_name) {
281 ASSERT(worker_thread_->IsCurrent());
282
283 auto iter = transports_.find(transport_name);
284 if (iter != transports_.end()) {
285 delete iter->second;
286 transports_.erase(transport_name);
287 }
288 }
289
290 void TransportController::DestroyAllTransports_w() {
291 ASSERT(worker_thread_->IsCurrent());
292
293 for (const auto& kv : transports_) {
294 delete kv.second;
295 }
296 transports_.clear();
297 }
298
299 void TransportController::SetIceConnectionReceivingTimeout_w(int timeout_ms) {
300 ASSERT(worker_thread_->IsCurrent());
301 ice_receiving_timeout_ms_ = timeout_ms;
302 for (const auto& kv : transports_) {
303 kv.second->SetChannelReceivingTimeout(timeout_ms);
304 }
305 }
306
307 void TransportController::SetIceRole_w(IceRole ice_role) {
308 ASSERT(worker_thread_->IsCurrent());
309 ice_role_ = ice_role;
310 for (const auto& kv : transports_) {
311 kv.second->SetIceRole(ice_role_);
312 }
313 }
314
315 bool TransportController::SetIdentity_w(rtc::SSLIdentity* identity) {
316 ASSERT(worker_thread_->IsCurrent());
317
318 if (identity_)
319 return false;
320 identity_.reset(identity);
321
322 for (const auto& kv : transports_) {
323 kv.second->SetIdentity(identity_.get());
324 }
325 return true;
326 }
327
328 bool TransportController::GetIdentity_w(const std::string& transport_name,
329 rtc::SSLIdentity** identity) {
330 ASSERT(worker_thread_->IsCurrent());
331
332 Transport* t = GetTransport_w(transport_name);
333 if (!t) {
334 return false;
335 }
336
337 return t->GetIdentity(identity);
338 }
339
340 bool TransportController::GetRemoteCertificate_w(
341 const std::string& transport_name,
342 rtc::SSLCertificate** cert) {
343 ASSERT(worker_thread_->IsCurrent());
344
345 Transport* t = GetTransport_w(transport_name);
346 if (!t) {
347 return false;
348 }
349
350 return t->GetRemoteCertificate(cert);
351 }
352
353 bool TransportController::SetSslMaxProtocolVersion_w(
354 rtc::SSLProtocolVersion version) {
355 ASSERT(worker_thread_->IsCurrent());
356
357 // Max SSL version can only be set before transports are created
358 if (!transports_.empty()) {
359 return false;
360 }
361
362 ssl_max_version_ = version;
363 return true;
364 }
365
366 bool TransportController::SetLocalTransportDescription_w(
367 const std::string& transport_name,
368 const TransportDescription& tdesc,
369 ContentAction action,
370 std::string* err) {
371 ASSERT(worker_thread()->IsCurrent());
372
373 Transport* transport = GetTransport_w(transport_name);
374 if (!transport) {
375 // If we didn't find a transport, that's not an error;
376 // it could have been deleted as a result of bundling.
377 return true;
378 }
379
380 if (!transport->SetLocalTransportDescription(tdesc, action, err)) {
381 return false;
382 }
383 transport->ConnectChannels();
384 return true;
385 }
386
387 bool TransportController::SetRemoteTransportDescription_w(
388 const std::string& transport_name,
389 const TransportDescription& tdesc,
390 ContentAction action,
391 std::string* err) {
392 ASSERT(worker_thread()->IsCurrent());
393
394 Transport* transport = GetTransport_w(transport_name);
395 if (!transport) {
396 // If we didn't find a transport, that's not an error;
397 // it could have been deleted as a result of bundling.
398 return true;
399 }
400
401 return transport->SetRemoteTransportDescription(tdesc, action, err);
402 }
403
404 bool TransportController::AddRemoteCandidates_w(
405 const std::string& transport_name,
406 const Candidates& candidates,
407 std::string* err) {
408 ASSERT(worker_thread()->IsCurrent());
409
410 Transport* transport = GetTransport_w(transport_name);
411 if (!transport) {
412 // If we didn't find a transport, that's not an error;
413 // it could have been deleted as a result of bundling.
414 return true;
415 }
416
417 return transport->AddRemoteCandidates(candidates, err);
418 }
419
420 bool TransportController::ReadyForRemoteCandidates_w(
421 const std::string& transport_name) {
422 ASSERT(worker_thread()->IsCurrent());
423
424 Transport* transport = GetTransport_w(transport_name);
425 if (!transport) {
426 return false;
427 }
428 return transport->local_description_set() &&
429 transport->remote_description_set();
430 }
431
432 bool TransportController::GetSslRole_w(rtc::SSLRole* role) {
433 ASSERT(worker_thread()->IsCurrent());
434
435 // TODO(mallinath) - Return role of each transport, as role may differ from
436 // one another.
437 // In current implementaion we just return the role of first transport in the
438 // transport map.
439 for (const auto& kv : transports_) {
440 return kv.second->GetSslRole(role);
441 }
442 return false;
443 }
444
445 bool TransportController::GetStats_w(
446 const std::string& transport_name,
447 TransportStats* stats) {
448 ASSERT(worker_thread()->IsCurrent());
449
450 Transport* transport = GetTransport_w(transport_name);
451 if (!transport) {
452 return false;
453 }
454 return transport->GetStats(stats);
455 }
456
457 void TransportController::OnTransportConnecting_w(Transport* transport) {
458 ASSERT(worker_thread_->IsCurrent());
459 UpdateState_w();
460 }
461
462 void TransportController::OnTransportWritableState_w(Transport* transport) {
463 ASSERT(worker_thread_->IsCurrent());
464 UpdateState_w();
465 }
466
467 void TransportController::OnTransportReceivingState_w(Transport* transport) {
468 ASSERT(worker_thread_->IsCurrent());
469 UpdateState_w();
470 }
471
472 void TransportController::OnTransportCandidatesAllocationStarted_w(
473 Transport* transport) {
474 ASSERT(worker_thread_->IsCurrent());
475 if (candidate_gathering_state_ != Transport::kGatheringGathering) {
476 candidate_gathering_state_ = Transport::kGatheringGathering;
477 signaling_thread_->Post(this, MSG_CANDIDATESALLOCATIONSTARTED);
478 }
479 }
480
481 void TransportController::OnTransportRouteChange_w(Transport* transport,
482 int component,
483 const Candidate& candidate) {
484 ASSERT(worker_thread_->IsCurrent());
485 // This signal is not currently used for anything
486 }
487
488 void TransportController::OnTransportCandidatesAllocationDone_w(
489 Transport* transport) {
490 ASSERT(worker_thread_->IsCurrent());
491 CheckIfCandidatesAllocationDone_w();
492 }
493
494 void TransportController::OnTransportRoleConflict_w() {
495 ASSERT(worker_thread_->IsCurrent());
496
497 if (ice_role_switch_) {
498 LOG(LS_WARNING) << "Repeat of role conflic signal from Transport.";
499 return;
500 }
501
502 ice_role_switch_ = true;
503 IceRole reversed_role = (ice_role_ == ICEROLE_CONTROLLING)
504 ? ICEROLE_CONTROLLED
505 : ICEROLE_CONTROLLING;
506 for (const auto& kv : transports_) {
507 kv.second->SetIceRole(reversed_role);
508 }
509 }
510
511 void TransportController::OnTransportCompleted_w(Transport* transport) {
512 ASSERT(worker_thread_->IsCurrent());
513 UpdateState_w();
514 }
515
516 void TransportController::OnTransportFailed_w(Transport* transport) {
517 ASSERT(worker_thread_->IsCurrent());
518 UpdateState_w();
519 }
520
521 void TransportController::OnTransportCandidatesReady_w(Transport* transport,
522 const std::vector<Candidate>& candidates) {
523 ASSERT(worker_thread_->IsCurrent());
524 CandidatesData* data = new CandidatesData(transport->content_name(),
525 candidates);
526 signaling_thread_->Post(this, MSG_CANDIDATESREADY, data);
527 }
528
529 void TransportController::UpdateState_w() {
530 ASSERT(worker_thread_->IsCurrent());
531
532 ConnectionState new_state = kConnecting;
533 bool receiving = false;
534 // If we don't have ANY Transports, we shouldn't signal that we're completed
535 if (!transports_.empty()) {
536 bool failed = false;
537 bool connected = true;
538 bool completed = true;
539 for (const auto& kv : transports_) {
540 if (!kv.second->Completed()) {
541 completed = false;
542 }
543 if (!kv.second->all_channels_writable()) {
544 connected = false;
545 }
546 if (kv.second->any_channel_receiving()) {
547 // The connection is considered receiving if at least one transport is
548 // receiving on any channel.
549 receiving = true;
550 }
551 }
552
553 if (failed) {
554 new_state = kFailed;
555 } else if (completed) {
556 new_state = kCompleted;
557 } else if (connected) {
558 new_state = kConnected;
559 }
560 }
561
562 if (connection_state_ != new_state) {
563 connection_state_ = new_state;
564 signaling_thread_->Post(
565 this, MSG_CONNECTIONSTATE,
566 new rtc::TypedMessageData<ConnectionState>(new_state));
567 }
568
569 if (receiving_ != receiving) {
570 receiving_ = receiving;
571 signaling_thread_->Post(this, MSG_RECEIVING,
572 new rtc::TypedMessageData<bool>(receiving));
573 }
574 }
575
576 void TransportController::CheckIfCandidatesAllocationDone_w() {
577 ASSERT(worker_thread_->IsCurrent());
578
579 // If already allocated, no point in checking.
580 if (candidate_gathering_state_ == Transport::kGatheringDone) {
581 return;
582 }
583
584 if (transports_.empty()) {
585 return;
586 }
587
588 for (const auto& kv : transports_) {
589 if (kv.second->candidate_gathering_state() != Transport::kGatheringDone) {
590 return;
591 }
592 }
593
594 candidate_gathering_state_ = Transport::kGatheringDone;
595 signaling_thread_->Post(this, MSG_CANDIDATESALLOCATIONDONE);
596 }
597
598 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698