OLD | NEW |
(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 } |
| 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 |
OLD | NEW |