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