blob: 708c60f9df5471f4efad73a6d259a0dd39210162 [file] [log] [blame]
deadbeefcbecd352015-09-23 11:50:27 -07001/*
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
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -070013#include <algorithm>
14
deadbeefcbecd352015-09-23 11:50:27 -070015#include "webrtc/base/bind.h"
16#include "webrtc/base/checks.h"
17#include "webrtc/base/thread.h"
18#include "webrtc/p2p/base/dtlstransport.h"
19#include "webrtc/p2p/base/p2ptransport.h"
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -070020#include "webrtc/p2p/base/port.h"
deadbeefcbecd352015-09-23 11:50:27 -070021
22namespace cricket {
23
24enum {
25 MSG_ICECONNECTIONSTATE,
26 MSG_RECEIVING,
27 MSG_ICEGATHERINGSTATE,
28 MSG_CANDIDATESGATHERED,
29};
30
31struct CandidatesData : public rtc::MessageData {
32 CandidatesData(const std::string& transport_name,
33 const Candidates& candidates)
34 : transport_name(transport_name), candidates(candidates) {}
35
36 std::string transport_name;
37 Candidates candidates;
38};
39
40TransportController::TransportController(rtc::Thread* signaling_thread,
41 rtc::Thread* worker_thread,
42 PortAllocator* port_allocator)
43 : signaling_thread_(signaling_thread),
44 worker_thread_(worker_thread),
45 port_allocator_(port_allocator) {}
46
47TransportController::~TransportController() {
48 worker_thread_->Invoke<void>(
49 rtc::Bind(&TransportController::DestroyAllTransports_w, this));
50 signaling_thread_->Clear(this);
51}
52
53bool TransportController::SetSslMaxProtocolVersion(
54 rtc::SSLProtocolVersion version) {
55 return worker_thread_->Invoke<bool>(rtc::Bind(
56 &TransportController::SetSslMaxProtocolVersion_w, this, version));
57}
58
honghaiz1f429e32015-09-28 07:57:34 -070059void TransportController::SetIceConfig(const IceConfig& config) {
deadbeefcbecd352015-09-23 11:50:27 -070060 worker_thread_->Invoke<void>(
honghaiz1f429e32015-09-28 07:57:34 -070061 rtc::Bind(&TransportController::SetIceConfig_w, this, config));
deadbeefcbecd352015-09-23 11:50:27 -070062}
63
64void TransportController::SetIceRole(IceRole ice_role) {
65 worker_thread_->Invoke<void>(
66 rtc::Bind(&TransportController::SetIceRole_w, this, ice_role));
67}
68
Taylor Brandstetterf475d362016-01-08 15:35:57 -080069bool TransportController::GetSslRole(const std::string& transport_name,
70 rtc::SSLRole* role) {
71 return worker_thread_->Invoke<bool>(rtc::Bind(
72 &TransportController::GetSslRole_w, this, transport_name, role));
deadbeefcbecd352015-09-23 11:50:27 -070073}
74
75bool TransportController::SetLocalCertificate(
76 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
77 return worker_thread_->Invoke<bool>(rtc::Bind(
78 &TransportController::SetLocalCertificate_w, this, certificate));
79}
80
81bool TransportController::GetLocalCertificate(
82 const std::string& transport_name,
83 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
84 return worker_thread_->Invoke<bool>(
85 rtc::Bind(&TransportController::GetLocalCertificate_w, this,
86 transport_name, certificate));
87}
88
kwibergb4d01c42016-04-06 05:15:06 -070089rtc::scoped_ptr<rtc::SSLCertificate>
90TransportController::GetRemoteSSLCertificate(
91 const std::string& transport_name) {
92 return worker_thread_->Invoke<rtc::scoped_ptr<rtc::SSLCertificate>>(rtc::Bind(
93 &TransportController::GetRemoteSSLCertificate_w, this, transport_name));
deadbeefcbecd352015-09-23 11:50:27 -070094}
95
96bool TransportController::SetLocalTransportDescription(
97 const std::string& transport_name,
98 const TransportDescription& tdesc,
99 ContentAction action,
100 std::string* err) {
101 return worker_thread_->Invoke<bool>(
102 rtc::Bind(&TransportController::SetLocalTransportDescription_w, this,
103 transport_name, tdesc, action, err));
104}
105
106bool TransportController::SetRemoteTransportDescription(
107 const std::string& transport_name,
108 const TransportDescription& tdesc,
109 ContentAction action,
110 std::string* err) {
111 return worker_thread_->Invoke<bool>(
112 rtc::Bind(&TransportController::SetRemoteTransportDescription_w, this,
113 transport_name, tdesc, action, err));
114}
115
116void TransportController::MaybeStartGathering() {
117 worker_thread_->Invoke<void>(
118 rtc::Bind(&TransportController::MaybeStartGathering_w, this));
119}
120
121bool TransportController::AddRemoteCandidates(const std::string& transport_name,
122 const Candidates& candidates,
123 std::string* err) {
124 return worker_thread_->Invoke<bool>(
125 rtc::Bind(&TransportController::AddRemoteCandidates_w, this,
126 transport_name, candidates, err));
127}
128
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700129bool TransportController::RemoveRemoteCandidates(const Candidates& candidates,
130 std::string* err) {
131 return worker_thread_->Invoke<bool>(rtc::Bind(
132 &TransportController::RemoveRemoteCandidates_w, this, candidates, err));
133}
134
deadbeefcbecd352015-09-23 11:50:27 -0700135bool TransportController::ReadyForRemoteCandidates(
136 const std::string& transport_name) {
137 return worker_thread_->Invoke<bool>(rtc::Bind(
138 &TransportController::ReadyForRemoteCandidates_w, this, transport_name));
139}
140
141bool TransportController::GetStats(const std::string& transport_name,
142 TransportStats* stats) {
143 return worker_thread_->Invoke<bool>(
144 rtc::Bind(&TransportController::GetStats_w, this, transport_name, stats));
145}
146
147TransportChannel* TransportController::CreateTransportChannel_w(
148 const std::string& transport_name,
149 int component) {
150 RTC_DCHECK(worker_thread_->IsCurrent());
151
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700152 auto it = FindChannel_w(transport_name, component);
153 if (it != channels_.end()) {
154 // Channel already exists; increment reference count and return.
155 it->AddRef();
156 return it->get();
157 }
158
159 // Need to create a new channel.
deadbeefcbecd352015-09-23 11:50:27 -0700160 Transport* transport = GetOrCreateTransport_w(transport_name);
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700161 TransportChannelImpl* channel = transport->CreateChannel(component);
162 channel->SignalWritableState.connect(
163 this, &TransportController::OnChannelWritableState_w);
164 channel->SignalReceivingState.connect(
165 this, &TransportController::OnChannelReceivingState_w);
166 channel->SignalGatheringState.connect(
167 this, &TransportController::OnChannelGatheringState_w);
168 channel->SignalCandidateGathered.connect(
169 this, &TransportController::OnChannelCandidateGathered_w);
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700170 channel->SignalCandidatesRemoved.connect(
171 this, &TransportController::OnChannelCandidatesRemoved_w);
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700172 channel->SignalRoleConflict.connect(
173 this, &TransportController::OnChannelRoleConflict_w);
174 channel->SignalConnectionRemoved.connect(
175 this, &TransportController::OnChannelConnectionRemoved_w);
176 channels_.insert(channels_.end(), RefCountedChannel(channel))->AddRef();
177 // Adding a channel could cause aggregate state to change.
178 UpdateAggregateStates_w();
179 return channel;
deadbeefcbecd352015-09-23 11:50:27 -0700180}
181
182void TransportController::DestroyTransportChannel_w(
183 const std::string& transport_name,
184 int component) {
185 RTC_DCHECK(worker_thread_->IsCurrent());
186
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700187 auto it = FindChannel_w(transport_name, component);
188 if (it == channels_.end()) {
189 LOG(LS_WARNING) << "Attempting to delete " << transport_name
190 << " TransportChannel " << component
191 << ", which doesn't exist.";
deadbeefcbecd352015-09-23 11:50:27 -0700192 return;
193 }
deadbeefcbecd352015-09-23 11:50:27 -0700194
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700195 it->DecRef();
196 if (it->ref() > 0) {
197 return;
198 }
199
200 channels_.erase(it);
201 Transport* transport = GetTransport_w(transport_name);
202 transport->DestroyChannel(component);
deadbeefcbecd352015-09-23 11:50:27 -0700203 // Just as we create a Transport when its first channel is created,
204 // we delete it when its last channel is deleted.
205 if (!transport->HasChannels()) {
206 DestroyTransport_w(transport_name);
207 }
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700208 // Removing a channel could cause aggregate state to change.
209 UpdateAggregateStates_w();
deadbeefcbecd352015-09-23 11:50:27 -0700210}
211
212const rtc::scoped_refptr<rtc::RTCCertificate>&
213TransportController::certificate_for_testing() {
214 return certificate_;
215}
216
217Transport* TransportController::CreateTransport_w(
218 const std::string& transport_name) {
219 RTC_DCHECK(worker_thread_->IsCurrent());
220
221 Transport* transport = new DtlsTransport<P2PTransport>(
222 transport_name, port_allocator(), certificate_);
223 return transport;
224}
225
226Transport* TransportController::GetTransport_w(
227 const std::string& transport_name) {
228 RTC_DCHECK(worker_thread_->IsCurrent());
229
230 auto iter = transports_.find(transport_name);
231 return (iter != transports_.end()) ? iter->second : nullptr;
232}
233
234void TransportController::OnMessage(rtc::Message* pmsg) {
235 RTC_DCHECK(signaling_thread_->IsCurrent());
236
237 switch (pmsg->message_id) {
238 case MSG_ICECONNECTIONSTATE: {
239 rtc::TypedMessageData<IceConnectionState>* data =
240 static_cast<rtc::TypedMessageData<IceConnectionState>*>(pmsg->pdata);
241 SignalConnectionState(data->data());
242 delete data;
243 break;
244 }
245 case MSG_RECEIVING: {
246 rtc::TypedMessageData<bool>* data =
247 static_cast<rtc::TypedMessageData<bool>*>(pmsg->pdata);
248 SignalReceiving(data->data());
249 delete data;
250 break;
251 }
252 case MSG_ICEGATHERINGSTATE: {
253 rtc::TypedMessageData<IceGatheringState>* data =
254 static_cast<rtc::TypedMessageData<IceGatheringState>*>(pmsg->pdata);
255 SignalGatheringState(data->data());
256 delete data;
257 break;
258 }
259 case MSG_CANDIDATESGATHERED: {
260 CandidatesData* data = static_cast<CandidatesData*>(pmsg->pdata);
261 SignalCandidatesGathered(data->transport_name, data->candidates);
262 delete data;
263 break;
264 }
265 default:
266 ASSERT(false);
267 }
268}
269
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700270std::vector<TransportController::RefCountedChannel>::iterator
271TransportController::FindChannel_w(const std::string& transport_name,
272 int component) {
273 return std::find_if(
274 channels_.begin(), channels_.end(),
275 [transport_name, component](const RefCountedChannel& channel) {
276 return channel->transport_name() == transport_name &&
277 channel->component() == component;
278 });
279}
280
deadbeefcbecd352015-09-23 11:50:27 -0700281Transport* TransportController::GetOrCreateTransport_w(
282 const std::string& transport_name) {
283 RTC_DCHECK(worker_thread_->IsCurrent());
284
285 Transport* transport = GetTransport_w(transport_name);
286 if (transport) {
287 return transport;
288 }
289
290 transport = CreateTransport_w(transport_name);
291 // The stuff below happens outside of CreateTransport_w so that unit tests
292 // can override CreateTransport_w to return a different type of transport.
293 transport->SetSslMaxProtocolVersion(ssl_max_version_);
honghaiz1f429e32015-09-28 07:57:34 -0700294 transport->SetIceConfig(ice_config_);
deadbeefcbecd352015-09-23 11:50:27 -0700295 transport->SetIceRole(ice_role_);
296 transport->SetIceTiebreaker(ice_tiebreaker_);
297 if (certificate_) {
298 transport->SetLocalCertificate(certificate_);
299 }
deadbeefcbecd352015-09-23 11:50:27 -0700300 transports_[transport_name] = transport;
301
302 return transport;
303}
304
305void TransportController::DestroyTransport_w(
306 const std::string& transport_name) {
307 RTC_DCHECK(worker_thread_->IsCurrent());
308
309 auto iter = transports_.find(transport_name);
310 if (iter != transports_.end()) {
311 delete iter->second;
312 transports_.erase(transport_name);
313 }
deadbeefcbecd352015-09-23 11:50:27 -0700314}
315
316void TransportController::DestroyAllTransports_w() {
317 RTC_DCHECK(worker_thread_->IsCurrent());
318
319 for (const auto& kv : transports_) {
320 delete kv.second;
321 }
322 transports_.clear();
323}
324
325bool TransportController::SetSslMaxProtocolVersion_w(
326 rtc::SSLProtocolVersion version) {
327 RTC_DCHECK(worker_thread_->IsCurrent());
328
329 // Max SSL version can only be set before transports are created.
330 if (!transports_.empty()) {
331 return false;
332 }
333
334 ssl_max_version_ = version;
335 return true;
336}
337
honghaiz1f429e32015-09-28 07:57:34 -0700338void TransportController::SetIceConfig_w(const IceConfig& config) {
deadbeefcbecd352015-09-23 11:50:27 -0700339 RTC_DCHECK(worker_thread_->IsCurrent());
honghaiz1f429e32015-09-28 07:57:34 -0700340 ice_config_ = config;
deadbeefcbecd352015-09-23 11:50:27 -0700341 for (const auto& kv : transports_) {
honghaiz1f429e32015-09-28 07:57:34 -0700342 kv.second->SetIceConfig(ice_config_);
deadbeefcbecd352015-09-23 11:50:27 -0700343 }
344}
345
346void TransportController::SetIceRole_w(IceRole ice_role) {
347 RTC_DCHECK(worker_thread_->IsCurrent());
348 ice_role_ = ice_role;
349 for (const auto& kv : transports_) {
350 kv.second->SetIceRole(ice_role_);
351 }
352}
353
Taylor Brandstetterf475d362016-01-08 15:35:57 -0800354bool TransportController::GetSslRole_w(const std::string& transport_name,
355 rtc::SSLRole* role) {
deadbeefcbecd352015-09-23 11:50:27 -0700356 RTC_DCHECK(worker_thread()->IsCurrent());
357
Taylor Brandstetterf475d362016-01-08 15:35:57 -0800358 Transport* t = GetTransport_w(transport_name);
359 if (!t) {
deadbeefcbecd352015-09-23 11:50:27 -0700360 return false;
361 }
Taylor Brandstetterf475d362016-01-08 15:35:57 -0800362
363 return t->GetSslRole(role);
deadbeefcbecd352015-09-23 11:50:27 -0700364}
365
366bool TransportController::SetLocalCertificate_w(
367 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
368 RTC_DCHECK(worker_thread_->IsCurrent());
369
370 if (certificate_) {
371 return false;
372 }
373 if (!certificate) {
374 return false;
375 }
376 certificate_ = certificate;
377
378 for (const auto& kv : transports_) {
379 kv.second->SetLocalCertificate(certificate_);
380 }
381 return true;
382}
383
384bool TransportController::GetLocalCertificate_w(
385 const std::string& transport_name,
386 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
387 RTC_DCHECK(worker_thread_->IsCurrent());
388
389 Transport* t = GetTransport_w(transport_name);
390 if (!t) {
391 return false;
392 }
393
394 return t->GetLocalCertificate(certificate);
395}
396
kwibergb4d01c42016-04-06 05:15:06 -0700397rtc::scoped_ptr<rtc::SSLCertificate>
398TransportController::GetRemoteSSLCertificate_w(
399 const std::string& transport_name) {
deadbeefcbecd352015-09-23 11:50:27 -0700400 RTC_DCHECK(worker_thread_->IsCurrent());
401
402 Transport* t = GetTransport_w(transport_name);
403 if (!t) {
kwibergb4d01c42016-04-06 05:15:06 -0700404 return nullptr;
deadbeefcbecd352015-09-23 11:50:27 -0700405 }
406
kwibergb4d01c42016-04-06 05:15:06 -0700407 return t->GetRemoteSSLCertificate();
deadbeefcbecd352015-09-23 11:50:27 -0700408}
409
410bool TransportController::SetLocalTransportDescription_w(
411 const std::string& transport_name,
412 const TransportDescription& tdesc,
413 ContentAction action,
414 std::string* err) {
415 RTC_DCHECK(worker_thread()->IsCurrent());
416
417 Transport* transport = GetTransport_w(transport_name);
418 if (!transport) {
419 // If we didn't find a transport, that's not an error;
420 // it could have been deleted as a result of bundling.
421 // TODO(deadbeef): Make callers smarter so they won't attempt to set a
422 // description on a deleted transport.
423 return true;
424 }
425
426 return transport->SetLocalTransportDescription(tdesc, action, err);
427}
428
429bool TransportController::SetRemoteTransportDescription_w(
430 const std::string& transport_name,
431 const TransportDescription& tdesc,
432 ContentAction action,
433 std::string* err) {
434 RTC_DCHECK(worker_thread()->IsCurrent());
435
436 Transport* transport = GetTransport_w(transport_name);
437 if (!transport) {
438 // If we didn't find a transport, that's not an error;
439 // it could have been deleted as a result of bundling.
440 // TODO(deadbeef): Make callers smarter so they won't attempt to set a
441 // description on a deleted transport.
442 return true;
443 }
444
445 return transport->SetRemoteTransportDescription(tdesc, action, err);
446}
447
448void TransportController::MaybeStartGathering_w() {
449 for (const auto& kv : transports_) {
450 kv.second->MaybeStartGathering();
451 }
452}
453
454bool TransportController::AddRemoteCandidates_w(
455 const std::string& transport_name,
456 const Candidates& candidates,
457 std::string* err) {
458 RTC_DCHECK(worker_thread()->IsCurrent());
459
460 Transport* transport = GetTransport_w(transport_name);
461 if (!transport) {
462 // If we didn't find a transport, that's not an error;
463 // it could have been deleted as a result of bundling.
464 return true;
465 }
466
467 return transport->AddRemoteCandidates(candidates, err);
468}
469
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700470bool TransportController::RemoveRemoteCandidates_w(const Candidates& candidates,
471 std::string* err) {
472 RTC_DCHECK(worker_thread()->IsCurrent());
473 std::map<std::string, Candidates> candidates_by_transport_name;
474 for (const Candidate& cand : candidates) {
475 RTC_DCHECK(!cand.transport_name().empty());
476 candidates_by_transport_name[cand.transport_name()].push_back(cand);
477 }
478
479 bool result = true;
480 for (auto kv : candidates_by_transport_name) {
481 Transport* transport = GetTransport_w(kv.first);
482 if (!transport) {
483 // If we didn't find a transport, that's not an error;
484 // it could have been deleted as a result of bundling.
485 continue;
486 }
487 result &= transport->RemoveRemoteCandidates(kv.second, err);
488 }
489 return result;
490}
491
deadbeefcbecd352015-09-23 11:50:27 -0700492bool TransportController::ReadyForRemoteCandidates_w(
493 const std::string& transport_name) {
494 RTC_DCHECK(worker_thread()->IsCurrent());
495
496 Transport* transport = GetTransport_w(transport_name);
497 if (!transport) {
498 return false;
499 }
500 return transport->ready_for_remote_candidates();
501}
502
503bool TransportController::GetStats_w(const std::string& transport_name,
504 TransportStats* stats) {
505 RTC_DCHECK(worker_thread()->IsCurrent());
506
507 Transport* transport = GetTransport_w(transport_name);
508 if (!transport) {
509 return false;
510 }
511 return transport->GetStats(stats);
512}
513
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700514void TransportController::OnChannelWritableState_w(TransportChannel* channel) {
515 RTC_DCHECK(worker_thread_->IsCurrent());
516 LOG(LS_INFO) << channel->transport_name() << " TransportChannel "
517 << channel->component() << " writability changed to "
518 << channel->writable() << ".";
519 UpdateAggregateStates_w();
520}
521
522void TransportController::OnChannelReceivingState_w(TransportChannel* channel) {
deadbeefcbecd352015-09-23 11:50:27 -0700523 RTC_DCHECK(worker_thread_->IsCurrent());
524 UpdateAggregateStates_w();
525}
526
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700527void TransportController::OnChannelGatheringState_w(
528 TransportChannelImpl* channel) {
deadbeefcbecd352015-09-23 11:50:27 -0700529 RTC_DCHECK(worker_thread_->IsCurrent());
530 UpdateAggregateStates_w();
531}
532
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700533void TransportController::OnChannelCandidateGathered_w(
534 TransportChannelImpl* channel,
535 const Candidate& candidate) {
deadbeefcbecd352015-09-23 11:50:27 -0700536 RTC_DCHECK(worker_thread_->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -0700537
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700538 // We should never signal peer-reflexive candidates.
539 if (candidate.type() == PRFLX_PORT_TYPE) {
540 RTC_DCHECK(false);
541 return;
542 }
543 std::vector<Candidate> candidates;
544 candidates.push_back(candidate);
545 CandidatesData* data =
546 new CandidatesData(channel->transport_name(), candidates);
deadbeefcbecd352015-09-23 11:50:27 -0700547 signaling_thread_->Post(this, MSG_CANDIDATESGATHERED, data);
548}
549
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700550void TransportController::OnChannelCandidatesRemoved_w(
551 TransportChannelImpl* channel,
552 const Candidates& candidates) {
553 invoker_.AsyncInvoke<void>(
554 signaling_thread_,
555 rtc::Bind(&TransportController::OnChannelCandidatesRemoved, this,
556 candidates));
557}
558
559void TransportController::OnChannelCandidatesRemoved(
560 const Candidates& candidates) {
561 RTC_DCHECK(signaling_thread_->IsCurrent());
562 SignalCandidatesRemoved(candidates);
563}
564
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700565void TransportController::OnChannelRoleConflict_w(
566 TransportChannelImpl* channel) {
deadbeefcbecd352015-09-23 11:50:27 -0700567 RTC_DCHECK(worker_thread_->IsCurrent());
568
569 if (ice_role_switch_) {
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700570 LOG(LS_WARNING)
571 << "Repeat of role conflict signal from TransportChannelImpl.";
deadbeefcbecd352015-09-23 11:50:27 -0700572 return;
573 }
574
575 ice_role_switch_ = true;
576 IceRole reversed_role = (ice_role_ == ICEROLE_CONTROLLING)
577 ? ICEROLE_CONTROLLED
578 : ICEROLE_CONTROLLING;
579 for (const auto& kv : transports_) {
580 kv.second->SetIceRole(reversed_role);
581 }
582}
583
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700584void TransportController::OnChannelConnectionRemoved_w(
585 TransportChannelImpl* channel) {
586 RTC_DCHECK(worker_thread_->IsCurrent());
587 LOG(LS_INFO) << channel->transport_name() << " TransportChannel "
588 << channel->component()
589 << " connection removed. Check if state is complete.";
590 UpdateAggregateStates_w();
591}
592
deadbeefcbecd352015-09-23 11:50:27 -0700593void TransportController::UpdateAggregateStates_w() {
594 RTC_DCHECK(worker_thread_->IsCurrent());
595
596 IceConnectionState new_connection_state = kIceConnectionConnecting;
597 IceGatheringState new_gathering_state = kIceGatheringNew;
598 bool any_receiving = false;
599 bool any_failed = false;
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700600 bool all_connected = !channels_.empty();
601 bool all_completed = !channels_.empty();
deadbeefcbecd352015-09-23 11:50:27 -0700602 bool any_gathering = false;
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700603 bool all_done_gathering = !channels_.empty();
604 for (const auto& channel : channels_) {
605 any_receiving = any_receiving || channel->receiving();
606 any_failed = any_failed ||
607 channel->GetState() == TransportChannelState::STATE_FAILED;
608 all_connected = all_connected && channel->writable();
609 all_completed =
610 all_completed && channel->writable() &&
611 channel->GetState() == TransportChannelState::STATE_COMPLETED &&
612 channel->GetIceRole() == ICEROLE_CONTROLLING &&
613 channel->gathering_state() == kIceGatheringComplete;
deadbeefcbecd352015-09-23 11:50:27 -0700614 any_gathering =
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700615 any_gathering || channel->gathering_state() != kIceGatheringNew;
deadbeefcbecd352015-09-23 11:50:27 -0700616 all_done_gathering = all_done_gathering &&
Taylor Brandstetterc4d3a5d2015-09-30 10:32:59 -0700617 channel->gathering_state() == kIceGatheringComplete;
deadbeefcbecd352015-09-23 11:50:27 -0700618 }
619
620 if (any_failed) {
621 new_connection_state = kIceConnectionFailed;
622 } else if (all_completed) {
623 new_connection_state = kIceConnectionCompleted;
624 } else if (all_connected) {
625 new_connection_state = kIceConnectionConnected;
626 }
627 if (connection_state_ != new_connection_state) {
628 connection_state_ = new_connection_state;
629 signaling_thread_->Post(
630 this, MSG_ICECONNECTIONSTATE,
631 new rtc::TypedMessageData<IceConnectionState>(new_connection_state));
632 }
633
634 if (receiving_ != any_receiving) {
635 receiving_ = any_receiving;
636 signaling_thread_->Post(this, MSG_RECEIVING,
637 new rtc::TypedMessageData<bool>(any_receiving));
638 }
639
640 if (all_done_gathering) {
641 new_gathering_state = kIceGatheringComplete;
642 } else if (any_gathering) {
643 new_gathering_state = kIceGatheringGathering;
644 }
645 if (gathering_state_ != new_gathering_state) {
646 gathering_state_ = new_gathering_state;
647 signaling_thread_->Post(
648 this, MSG_ICEGATHERINGSTATE,
649 new rtc::TypedMessageData<IceGatheringState>(new_gathering_state));
650 }
651}
652
deadbeefcbecd352015-09-23 11:50:27 -0700653} // namespace cricket