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

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

Powered by Google App Engine
This is Rietveld 408576698