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

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: Set media engine on voice channel 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_GATHERINGSTATE,
24 MSG_CANDIDATESREADY,
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 ice_receiving_timeout_ms_(-1),
43 ice_role_(ICEROLE_CONTROLLING),
44 ssl_max_version_(rtc::SSL_PROTOCOL_DTLS_10),
45 ice_role_switch_(false),
46 ice_tiebreaker_(rtc::CreateRandomId64()),
47 connection_state_(kConnectionConnecting),
48 receiving_(false),
49 gathering_state_(kGatheringNew) {
50 ASSERT(signaling_thread_->IsCurrent());
pthatcher2 2015/08/19 18:32:15 Is this necessary? I don't think it is.
Taylor Brandstetter 2015/08/25 01:04:05 Done.
51 }
52
53 TransportController::~TransportController() {
54 ASSERT(signaling_thread_->IsCurrent());
pthatcher2 2015/08/19 18:32:15 I don't think this is necessary either.
Taylor Brandstetter 2015/08/25 01:04:06 Done.
55 worker_thread_->Invoke<void>(
56 rtc::Bind(&TransportController::DestroyAllTransports_w, this));
57 signaling_thread_->Clear(this);
58 }
59
60 void TransportController::SetIceConnectionReceivingTimeout(int timeout_ms) {
61 ASSERT(signaling_thread_->IsCurrent());
pthatcher2 2015/08/19 18:32:15 In fact, I don't think any of these checks to be o
Taylor Brandstetter 2015/08/25 01:04:05 Done.
62 worker_thread_->Invoke<void>(
63 rtc::Bind(&TransportController::SetIceConnectionReceivingTimeout_w, this,
64 timeout_ms));
65 }
66
67 void TransportController::SetIceRole(IceRole ice_role) {
68 ASSERT(signaling_thread_->IsCurrent());
69 worker_thread_->Invoke<void>(
70 rtc::Bind(&TransportController::SetIceRole_w, this, ice_role));
71 }
72
73 bool TransportController::SetIdentity(rtc::SSLIdentity* identity) {
74 ASSERT(signaling_thread_->IsCurrent());
75 return worker_thread_->Invoke<bool>(
76 rtc::Bind(&TransportController::SetIdentity_w, this, identity));
77 }
78
79 bool TransportController::GetIdentity(const std::string& transport_name,
80 rtc::SSLIdentity** identity) {
81 ASSERT(signaling_thread_->IsCurrent());
82 return worker_thread_->Invoke<bool>(rtc::Bind(
83 &TransportController::GetIdentity_w, this, transport_name, identity));
84 }
85
86 bool TransportController::GetRemoteCertificate(
87 const std::string& transport_name,
88 rtc::SSLCertificate** cert) {
89 ASSERT(signaling_thread_->IsCurrent());
90 return worker_thread_->Invoke<bool>(
91 rtc::Bind(&TransportController::GetRemoteCertificate_w, this,
92 transport_name, cert));
93 }
94
95 bool TransportController::SetSslMaxProtocolVersion(
96 rtc::SSLProtocolVersion version) {
97 ASSERT(signaling_thread_->IsCurrent());
98 return worker_thread_->Invoke<bool>(rtc::Bind(
99 &TransportController::SetSslMaxProtocolVersion_w, this, version));
100 }
101
102 bool TransportController::SetLocalTransportDescription(
pthatcher2 2015/08/19 18:32:15 We could probably call this SetLocalDescription an
Taylor Brandstetter 2015/08/25 01:04:05 We discussed this and decided we'll just leave it
103 const std::string& transport_name,
104 const TransportDescription& tdesc,
105 ContentAction action,
106 std::string* err) {
107 ASSERT(signaling_thread_->IsCurrent());
108 return worker_thread_->Invoke<bool>(
109 rtc::Bind(&TransportController::SetLocalTransportDescription_w, this,
110 transport_name, tdesc, action, err));
111 }
112
113 bool TransportController::SetRemoteTransportDescription(
114 const std::string& transport_name,
115 const TransportDescription& tdesc,
116 ContentAction action,
117 std::string* err) {
118 ASSERT(signaling_thread_->IsCurrent());
119 return worker_thread_->Invoke<bool>(
120 rtc::Bind(&TransportController::SetRemoteTransportDescription_w, this,
121 transport_name, tdesc, action, err));
122 }
123
124 bool TransportController::AddRemoteCandidates(const std::string& transport_name,
125 const Candidates& candidates,
126 std::string* err) {
127 ASSERT(signaling_thread_->IsCurrent());
128 return worker_thread_->Invoke<bool>(
129 rtc::Bind(&TransportController::AddRemoteCandidates_w, this,
130 transport_name, candidates, err));
131 }
132
133 bool TransportController::ReadyForRemoteCandidates(
134 const std::string& transport_name) {
135 ASSERT(signaling_thread_->IsCurrent());
136 return worker_thread_->Invoke<bool>(rtc::Bind(
137 &TransportController::ReadyForRemoteCandidates_w, this, transport_name));
138 }
139
140 bool TransportController::GetSslRole(rtc::SSLRole* role) {
141 ASSERT(signaling_thread_->IsCurrent());
142 return worker_thread_->Invoke<bool>(
143 rtc::Bind(&TransportController::GetSslRole_w, this, role));
144 }
145
146 bool TransportController::GetStats(const std::string& transport_name,
147 TransportStats* stats) {
148 ASSERT(signaling_thread_->IsCurrent());
149 return worker_thread_->Invoke<bool>(
150 rtc::Bind(&TransportController::GetStats_w, this, transport_name, stats));
151 }
152
153 TransportChannel* TransportController::CreateTransportChannel_w(
154 const std::string& transport_name,
155 int component) {
156 ASSERT(worker_thread_->IsCurrent());
pthatcher2 2015/08/19 18:32:15 These for the worker_thread_ *are* needed. Only t
Taylor Brandstetter 2015/08/25 01:04:06 Acknowledged.
157
158 Transport* transport = GetOrCreateTransport_w(transport_name);
159 return transport->CreateChannel(component);
160 }
161
162 void TransportController::DestroyTransportChannel_w(
163 const std::string& transport_name,
164 int component) {
165 ASSERT(worker_thread_->IsCurrent());
166
167 Transport* transport = GetTransport_w(transport_name);
168 ASSERT(transport != nullptr);
pthatcher2 2015/08/19 18:32:15 This will only protect debug builds. For release
Taylor Brandstetter 2015/08/25 01:04:05 Done.
169 transport->DestroyChannel(component);
170
171 // Just as we create a Transport when its first channel is created,
172 // we delete it when its last channel is deleted.
173 if (!transport->HasChannels()) {
174 DestroyTransport_w(transport_name);
175 UpdateState_w();
176 UpdateGatheringState_w();
pthatcher2 2015/08/19 18:32:15 I think it would be more clear to put UpdateState_
Taylor Brandstetter 2015/08/25 01:04:06 Done.
177 }
178 }
179
180 void TransportController::OnMessage(rtc::Message* pmsg) {
181 ASSERT(signaling_thread_->IsCurrent());
182
183 switch (pmsg->message_id) {
184 case MSG_CONNECTIONSTATE: {
185 rtc::TypedMessageData<ConnectionState>* data =
186 static_cast<rtc::TypedMessageData<ConnectionState>*>(pmsg->pdata);
187 SignalConnectionState(data->data());
188 delete data;
189 break;
190 }
191 case MSG_RECEIVING: {
192 rtc::TypedMessageData<bool>* data =
193 static_cast<rtc::TypedMessageData<bool>*>(pmsg->pdata);
194 SignalReceiving(data->data());
195 delete data;
196 break;
197 }
198 case MSG_GATHERINGSTATE: {
199 rtc::TypedMessageData<GatheringState>* data =
200 static_cast<rtc::TypedMessageData<GatheringState>*>(pmsg->pdata);
201 SignalGatheringState(data->data());
202 delete data;
203 break;
204 }
205 case MSG_CANDIDATESREADY: {
pthatcher2 2015/08/19 18:32:15 MSG_CANDIDATESGATHERED
Taylor Brandstetter 2015/08/25 01:04:06 Done.
206 CandidatesData* data = static_cast<CandidatesData*>(pmsg->pdata);
207 SignalCandidatesGathered(data->transport_name, data->candidates);
208 delete data;
209 break;
210 }
211 default:
212 ASSERT(false);
213 }
214 }
215
216 Transport* TransportController::CreateTransport_w(
217 const std::string& transport_name) {
218 ASSERT(worker_thread_->IsCurrent());
219
220 Transport* transport = new DtlsTransport<P2PTransport>(
221 transport_name, port_allocator(), identity_.get());
222 return transport;
223 }
224
225 Transport* TransportController::GetOrCreateTransport_w(
226 const std::string& transport_name) {
227 ASSERT(worker_thread_->IsCurrent());
228
229 Transport* transport = GetTransport_w(transport_name);
230 if (transport)
231 return transport;
pthatcher2 2015/08/19 18:32:15 {}s please
Taylor Brandstetter 2015/08/25 01:04:05 Done.
232
233 transport = CreateTransport_w(transport_name);
234 transport->SetChannelReceivingTimeout(ice_receiving_timeout_ms_);
235 transport->SetIceRole(ice_role_);
236 transport->SetIceTiebreaker(ice_tiebreaker_);
237 transport->SetSslMaxProtocolVersion(ssl_max_version_);
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->SignalGatheringState.connect(
245 this, &TransportController::OnTransportGatheringState_w);
246 transport->SignalRouteChange.connect(
247 this, &TransportController::OnTransportRouteChange_w);
248 transport->SignalRoleConflict.connect(
249 this, &TransportController::OnTransportRoleConflict_w);
250 transport->SignalCompleted.connect(
251 this, &TransportController::OnTransportCompleted_w);
252 transport->SignalFailed.connect(this,
253 &TransportController::OnTransportFailed_w);
pthatcher2 2015/08/19 18:32:15 Can you make this one consistent with the other wi
Taylor Brandstetter 2015/08/25 01:04:05 This is just what "git cl format" does, since "Sig
pthatcher1 2015/08/25 18:40:38 Just go with "git cl format".
254 transport->SignalCandidatesGathered.connect(
255 this, &TransportController::OnTransportCandidatesGathered_w);
256 if (identity_)
257 transport->SetIdentity(identity_.get());
pthatcher2 2015/08/19 18:32:15 {}s please. Can can you move it up to before th
Taylor Brandstetter 2015/08/25 01:04:05 Done.
258 transports_[transport_name] = transport;
pthatcher2 2015/08/19 18:32:15 It seems like all of this stuff that happens after
Taylor Brandstetter 2015/08/25 01:04:05 Done.
259
260 return transport;
261 }
262
263 Transport* TransportController::GetTransport_w(
264 const std::string& transport_name) {
265 ASSERT(worker_thread_->IsCurrent());
266
267 auto iter = transports_.find(transport_name);
268 return (iter != transports_.end()) ? iter->second : nullptr;
269 }
270
271 void TransportController::DestroyTransport_w(
272 const std::string& transport_name) {
273 ASSERT(worker_thread_->IsCurrent());
274
275 auto iter = transports_.find(transport_name);
276 if (iter != transports_.end()) {
277 delete iter->second;
278 transports_.erase(transport_name);
279 }
280 }
281
282 void TransportController::DestroyAllTransports_w() {
283 ASSERT(worker_thread_->IsCurrent());
284
285 for (const auto& kv : transports_) {
286 delete kv.second;
287 }
288 transports_.clear();
289 }
290
291 void TransportController::SetIceConnectionReceivingTimeout_w(int timeout_ms) {
292 ASSERT(worker_thread_->IsCurrent());
293 ice_receiving_timeout_ms_ = timeout_ms;
294 for (const auto& kv : transports_) {
295 kv.second->SetChannelReceivingTimeout(timeout_ms);
296 }
297 }
298
299 void TransportController::SetIceRole_w(IceRole ice_role) {
300 ASSERT(worker_thread_->IsCurrent());
301 ice_role_ = ice_role;
302 for (const auto& kv : transports_) {
303 kv.second->SetIceRole(ice_role_);
304 }
305 }
306
307 bool TransportController::SetIdentity_w(rtc::SSLIdentity* identity) {
308 ASSERT(worker_thread_->IsCurrent());
309
310 if (identity_)
311 return false;
pthatcher2 2015/08/19 18:32:15 {} please Also, we should leave a comment in the
Taylor Brandstetter 2015/08/25 01:04:05 Done.
312 identity_.reset(identity);
313
314 for (const auto& kv : transports_) {
315 kv.second->SetIdentity(identity_.get());
316 }
317 return true;
318 }
319
320 bool TransportController::GetIdentity_w(const std::string& transport_name,
321 rtc::SSLIdentity** identity) {
322 ASSERT(worker_thread_->IsCurrent());
323
324 Transport* t = GetTransport_w(transport_name);
325 if (!t) {
326 return false;
327 }
328
329 return t->GetIdentity(identity);
330 }
331
332 bool TransportController::GetRemoteCertificate_w(
333 const std::string& transport_name,
334 rtc::SSLCertificate** cert) {
335 ASSERT(worker_thread_->IsCurrent());
336
337 Transport* t = GetTransport_w(transport_name);
338 if (!t) {
339 return false;
340 }
341
342 return t->GetRemoteCertificate(cert);
343 }
344
345 bool TransportController::SetSslMaxProtocolVersion_w(
346 rtc::SSLProtocolVersion version) {
347 ASSERT(worker_thread_->IsCurrent());
348
349 // Max SSL version can only be set before transports are created
350 if (!transports_.empty()) {
351 return false;
352 }
353
354 ssl_max_version_ = version;
355 return true;
356 }
357
358 bool TransportController::SetLocalTransportDescription_w(
359 const std::string& transport_name,
360 const TransportDescription& tdesc,
361 ContentAction action,
362 std::string* err) {
363 ASSERT(worker_thread()->IsCurrent());
364
365 Transport* transport = GetTransport_w(transport_name);
366 if (!transport) {
367 // If we didn't find a transport, that's not an error;
368 // it could have been deleted as a result of bundling.
369 return true;
pthatcher2 2015/08/19 18:32:14 That's weird. Can you put a TODO to fix the calle
Taylor Brandstetter 2015/08/25 01:04:05 Done.
370 }
371
372 if (!transport->SetLocalTransportDescription(tdesc, action, err)) {
373 return false;
374 }
375 transport->ConnectChannels();
pthatcher2 2015/08/19 18:32:15 If we always ConnectChannels after SetLocalDescrip
Taylor Brandstetter 2015/08/25 01:04:05 Except ConnectChannels is still used for unit test
376 return true;
377 }
378
379 bool TransportController::SetRemoteTransportDescription_w(
380 const std::string& transport_name,
381 const TransportDescription& tdesc,
382 ContentAction action,
383 std::string* err) {
384 ASSERT(worker_thread()->IsCurrent());
385
386 Transport* transport = GetTransport_w(transport_name);
387 if (!transport) {
388 // If we didn't find a transport, that's not an error;
389 // it could have been deleted as a result of bundling.
390 return true;
391 }
392
393 return transport->SetRemoteTransportDescription(tdesc, action, err);
394 }
395
396 bool TransportController::AddRemoteCandidates_w(
397 const std::string& transport_name,
398 const Candidates& candidates,
399 std::string* err) {
400 ASSERT(worker_thread()->IsCurrent());
401
402 Transport* transport = GetTransport_w(transport_name);
403 if (!transport) {
404 // If we didn't find a transport, that's not an error;
405 // it could have been deleted as a result of bundling.
406 return true;
407 }
408
409 return transport->AddRemoteCandidates(candidates, err);
410 }
411
412 bool TransportController::ReadyForRemoteCandidates_w(
413 const std::string& transport_name) {
414 ASSERT(worker_thread()->IsCurrent());
415
416 Transport* transport = GetTransport_w(transport_name);
417 if (!transport) {
418 return false;
419 }
420 return transport->local_description_set() &&
421 transport->remote_description_set();
pthatcher2 2015/08/19 18:32:15 Can we move this logic into Transport (have a Tran
Taylor Brandstetter 2015/08/25 01:04:06 Done.
422 }
423
424 bool TransportController::GetSslRole_w(rtc::SSLRole* role) {
425 ASSERT(worker_thread()->IsCurrent());
426
427 // TODO(mallinath) - Return role of each transport, as role may differ from
428 // one another.
429 // In current implementaion we just return the role of first transport in the
430 // transport map.
431 for (const auto& kv : transports_) {
432 return kv.second->GetSslRole(role);
433 }
pthatcher2 2015/08/19 18:32:15 We should probably just follow the same pattern we
Taylor Brandstetter 2015/08/25 01:04:06 I think we already do support different roles for
434 return false;
435 }
436
437 bool TransportController::GetStats_w(const std::string& transport_name,
438 TransportStats* stats) {
439 ASSERT(worker_thread()->IsCurrent());
440
441 Transport* transport = GetTransport_w(transport_name);
442 if (!transport) {
443 return false;
444 }
445 return transport->GetStats(stats);
446 }
447
448 void TransportController::OnTransportConnecting_w(Transport* transport) {
449 ASSERT(worker_thread_->IsCurrent());
450 UpdateState_w();
451 }
452
453 void TransportController::OnTransportWritableState_w(Transport* transport) {
454 ASSERT(worker_thread_->IsCurrent());
455 UpdateState_w();
456 }
457
458 void TransportController::OnTransportReceivingState_w(Transport* transport) {
459 ASSERT(worker_thread_->IsCurrent());
460 UpdateState_w();
461 }
462
463 void TransportController::OnTransportGatheringState_w(Transport* transport) {
464 ASSERT(worker_thread_->IsCurrent());
465 UpdateGatheringState_w();
pthatcher2 2015/08/19 18:32:15 It might be less efficient, but would it be more r
Taylor Brandstetter 2015/08/25 01:04:05 I generally prefer code readability/maintainabilit
466 }
467
468 void TransportController::OnTransportRouteChange_w(Transport* transport,
469 int component,
470 const Candidate& candidate) {
471 ASSERT(worker_thread_->IsCurrent());
472 // This signal is not currently used for anything
pthatcher2 2015/08/19 18:32:16 Then let's not listen to it.
Taylor Brandstetter 2015/08/25 01:04:05 Done.
473 }
474
475 void TransportController::OnTransportRoleConflict_w() {
476 ASSERT(worker_thread_->IsCurrent());
477
478 if (ice_role_switch_) {
479 LOG(LS_WARNING) << "Repeat of role conflic signal from Transport.";
pthatcher2 2015/08/19 18:32:15 conflic => conflict
Taylor Brandstetter 2015/08/25 01:04:06 Done.
480 return;
481 }
482
483 ice_role_switch_ = true;
484 IceRole reversed_role = (ice_role_ == ICEROLE_CONTROLLING)
485 ? ICEROLE_CONTROLLED
486 : ICEROLE_CONTROLLING;
487 for (const auto& kv : transports_) {
488 kv.second->SetIceRole(reversed_role);
489 }
490 }
491
492 void TransportController::OnTransportCompleted_w(Transport* transport) {
493 ASSERT(worker_thread_->IsCurrent());
494 UpdateState_w();
495 }
496
497 void TransportController::OnTransportFailed_w(Transport* transport) {
498 ASSERT(worker_thread_->IsCurrent());
499 UpdateState_w();
500 }
pthatcher2 2015/08/19 18:32:15 Can you put these up next to others? (before OnT
Taylor Brandstetter 2015/08/25 01:04:05 Done. Also moved a couple other handlers so they'r
501
502 void TransportController::OnTransportCandidatesGathered_w(
503 Transport* transport,
504 const std::vector<Candidate>& candidates) {
505 ASSERT(worker_thread_->IsCurrent());
506 CandidatesData* data =
507 new CandidatesData(transport->content_name(), candidates);
508 signaling_thread_->Post(this, MSG_CANDIDATESREADY, data);
509 }
510
511 void TransportController::UpdateState_w() {
512 ASSERT(worker_thread_->IsCurrent());
513
514 ConnectionState new_state = kConnectionConnecting;
515 bool receiving = false;
516 // If we don't have ANY Transports, we shouldn't signal that we're completed
517 if (!transports_.empty()) {
518 bool failed = false;
519 bool connected = true;
520 bool completed = true;
pthatcher2 2015/08/19 18:32:15 Can you call these the following? any_failed all_
Taylor Brandstetter 2015/08/25 01:04:06 Done.
521 for (const auto& kv : transports_) {
522 if (!kv.second->Completed()) {
523 completed = false;
524 }
525 if (!kv.second->all_channels_writable()) {
526 connected = false;
527 }
528 if (kv.second->any_channel_receiving()) {
529 // The connection is considered receiving if at least one transport is
530 // receiving on any channel.
531 receiving = true;
532 }
pthatcher2 2015/08/19 18:32:16 Could be more readable as: bool all_completed = !
Taylor Brandstetter 2015/08/25 01:04:05 I actually prefer the former since there's less bo
533 }
534
535 if (failed) {
pthatcher2 2015/08/19 18:32:16 Actually, wait.... failed can never happen. So wh
Taylor Brandstetter 2015/08/25 01:04:05 That was unintentional... I wonder how the unit te
536 new_state = kConnectionFailed;
537 } else if (completed) {
538 new_state = kConnectionCompleted;
539 } else if (connected) {
540 new_state = kConnectionConnected;
541 }
542 }
543
544 if (connection_state_ != new_state) {
545 connection_state_ = new_state;
546 signaling_thread_->Post(
547 this, MSG_CONNECTIONSTATE,
pthatcher2 2015/08/19 18:32:15 Since "connection" is a word we use for "candidate
Taylor Brandstetter 2015/08/25 01:04:05 But weren't we going to call the enum "IceConnecti
548 new rtc::TypedMessageData<ConnectionState>(new_state));
549 }
550
551 if (receiving_ != receiving) {
552 receiving_ = receiving;
553 signaling_thread_->Post(this, MSG_RECEIVING,
554 new rtc::TypedMessageData<bool>(receiving));
555 }
556 }
557
558 void TransportController::UpdateGatheringState_w() {
559 ASSERT(worker_thread_->IsCurrent());
560
561 GatheringState new_state = kGatheringNew;
562 if (!transports_.empty()) {
563 bool gathering = false;
564 bool complete = true;
565 for (const auto& kv : transports_) {
566 // Complete if ALL transports complete
567 if (kv.second->gathering_state() != kGatheringComplete) {
568 complete = false;
569 }
570 // Gathering if ANY transport started gathering
571 if (kv.second->gathering_state() != kGatheringNew) {
pthatcher2 2015/08/19 18:32:15 Did you mean kGatheringGathering here?
Taylor Brandstetter 2015/08/25 01:04:05 No; consider a case where one transport is done ga
572 gathering = true;
573 }
574 }
575 if (complete) {
576 new_state = kGatheringComplete;
577 } else if (gathering) {
578 new_state = kGatheringGathering;
579 }
580 }
pthatcher2 2015/08/19 18:32:15 This could be more readable as: bool any_gatherin
Taylor Brandstetter 2015/08/25 01:04:05 See earlier comment about UpdateState_w
581
582 if (gathering_state_ != new_state) {
583 gathering_state_ = new_state;
584 signaling_thread_->Post(
585 this, MSG_GATHERINGSTATE,
586 new rtc::TypedMessageData<GatheringState>(new_state));
587 }
588 }
589
590 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698