1 /* 2 * libjingle 3 * Copyright 2004, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/p2p/base/transport.h" 29 30 #include "talk/p2p/base/candidate.h" 31 #include "talk/p2p/base/constants.h" 32 #include "talk/p2p/base/parsing.h" 33 #include "talk/p2p/base/port.h" 34 #include "talk/p2p/base/sessionmanager.h" 35 #include "talk/p2p/base/transportchannelimpl.h" 36 #include "webrtc/libjingle/xmllite/xmlelement.h" 37 #include "talk/xmpp/constants.h" 38 #include "webrtc/base/bind.h" 39 #include "webrtc/base/common.h" 40 #include "webrtc/base/logging.h" 41 42 namespace cricket { 43 44 using rtc::Bind; 45 46 enum { 47 MSG_ONSIGNALINGREADY = 1, 48 MSG_ONREMOTECANDIDATE, 49 MSG_READSTATE, 50 MSG_WRITESTATE, 51 MSG_REQUESTSIGNALING, 52 MSG_CANDIDATEREADY, 53 MSG_ROUTECHANGE, 54 MSG_CONNECTING, 55 MSG_CANDIDATEALLOCATIONCOMPLETE, 56 MSG_ROLECONFLICT, 57 MSG_COMPLETED, 58 MSG_FAILED, 59 }; 60 61 struct ChannelParams : public rtc::MessageData { 62 ChannelParams() : channel(NULL), candidate(NULL) {} 63 explicit ChannelParams(int component) 64 : component(component), channel(NULL), candidate(NULL) {} 65 explicit ChannelParams(Candidate* candidate) 66 : channel(NULL), candidate(candidate) { 67 } 68 69 ~ChannelParams() { 70 delete candidate; 71 } 72 73 std::string name; 74 int component; 75 TransportChannelImpl* channel; 76 Candidate* candidate; 77 }; 78 79 static std::string IceProtoToString(TransportProtocol proto) { 80 std::string proto_str; 81 switch (proto) { 82 case ICEPROTO_GOOGLE: 83 proto_str = "gice"; 84 break; 85 case ICEPROTO_HYBRID: 86 proto_str = "hybrid"; 87 break; 88 case ICEPROTO_RFC5245: 89 proto_str = "ice"; 90 break; 91 default: 92 ASSERT(false); 93 break; 94 } 95 return proto_str; 96 } 97 98 static bool VerifyIceParams(const TransportDescription& desc) { 99 // For legacy protocols. 100 if (desc.ice_ufrag.empty() && desc.ice_pwd.empty()) 101 return true; 102 103 if (desc.ice_ufrag.length() < ICE_UFRAG_MIN_LENGTH || 104 desc.ice_ufrag.length() > ICE_UFRAG_MAX_LENGTH) { 105 return false; 106 } 107 if (desc.ice_pwd.length() < ICE_PWD_MIN_LENGTH || 108 desc.ice_pwd.length() > ICE_PWD_MAX_LENGTH) { 109 return false; 110 } 111 return true; 112 } 113 114 bool BadTransportDescription(const std::string& desc, std::string* err_desc) { 115 if (err_desc) { 116 *err_desc = desc; 117 } 118 LOG(LS_ERROR) << desc; 119 return false; 120 } 121 122 bool IceCredentialsChanged(const std::string& old_ufrag, 123 const std::string& old_pwd, 124 const std::string& new_ufrag, 125 const std::string& new_pwd) { 126 // TODO(jiayl): The standard (RFC 5245 Section 9.1.1.1) says that ICE should 127 // restart when both the ufrag and password are changed, but we do restart 128 // when either ufrag or passwrod is changed to keep compatible with GICE. We 129 // should clean this up when GICE is no longer used. 130 return (old_ufrag != new_ufrag) || (old_pwd != new_pwd); 131 } 132 133 static bool IceCredentialsChanged(const TransportDescription& old_desc, 134 const TransportDescription& new_desc) { 135 return IceCredentialsChanged(old_desc.ice_ufrag, old_desc.ice_pwd, 136 new_desc.ice_ufrag, new_desc.ice_pwd); 137 } 138 139 Transport::Transport(rtc::Thread* signaling_thread, 140 rtc::Thread* worker_thread, 141 const std::string& content_name, 142 const std::string& type, 143 PortAllocator* allocator) 144 : signaling_thread_(signaling_thread), 145 worker_thread_(worker_thread), 146 content_name_(content_name), 147 type_(type), 148 allocator_(allocator), 149 destroyed_(false), 150 readable_(TRANSPORT_STATE_NONE), 151 writable_(TRANSPORT_STATE_NONE), 152 was_writable_(false), 153 connect_requested_(false), 154 ice_role_(ICEROLE_UNKNOWN), 155 tiebreaker_(0), 156 protocol_(ICEPROTO_HYBRID), 157 remote_ice_mode_(ICEMODE_FULL) { 158 } 159 160 Transport::~Transport() { 161 ASSERT(signaling_thread_->IsCurrent()); 162 ASSERT(destroyed_); 163 } 164 165 void Transport::SetIceRole(IceRole role) { 166 worker_thread_->Invoke<void>(Bind(&Transport::SetIceRole_w, this, role)); 167 } 168 169 void Transport::SetIdentity(rtc::SSLIdentity* identity) { 170 worker_thread_->Invoke<void>(Bind(&Transport::SetIdentity_w, this, identity)); 171 } 172 173 bool Transport::GetIdentity(rtc::SSLIdentity** identity) { 174 // The identity is set on the worker thread, so for safety it must also be 175 // acquired on the worker thread. 176 return worker_thread_->Invoke<bool>( 177 Bind(&Transport::GetIdentity_w, this, identity)); 178 } 179 180 bool Transport::GetRemoteCertificate(rtc::SSLCertificate** cert) { 181 // Channels can be deleted on the worker thread, so for safety the remote 182 // certificate is acquired on the worker thread. 183 return worker_thread_->Invoke<bool>( 184 Bind(&Transport::GetRemoteCertificate_w, this, cert)); 185 } 186 187 bool Transport::GetRemoteCertificate_w(rtc::SSLCertificate** cert) { 188 ASSERT(worker_thread()->IsCurrent()); 189 if (channels_.empty()) 190 return false; 191 192 ChannelMap::iterator iter = channels_.begin(); 193 return iter->second->GetRemoteCertificate(cert); 194 } 195 196 bool Transport::SetLocalTransportDescription( 197 const TransportDescription& description, 198 ContentAction action, 199 std::string* error_desc) { 200 return worker_thread_->Invoke<bool>(Bind( 201 &Transport::SetLocalTransportDescription_w, this, 202 description, action, error_desc)); 203 } 204 205 bool Transport::SetRemoteTransportDescription( 206 const TransportDescription& description, 207 ContentAction action, 208 std::string* error_desc) { 209 return worker_thread_->Invoke<bool>(Bind( 210 &Transport::SetRemoteTransportDescription_w, this, 211 description, action, error_desc)); 212 } 213 214 TransportChannelImpl* Transport::CreateChannel(int component) { 215 return worker_thread_->Invoke<TransportChannelImpl*>(Bind( 216 &Transport::CreateChannel_w, this, component)); 217 } 218 219 TransportChannelImpl* Transport::CreateChannel_w(int component) { 220 ASSERT(worker_thread()->IsCurrent()); 221 TransportChannelImpl *impl; 222 rtc::CritScope cs(&crit_); 223 224 // Create the entry if it does not exist. 225 bool impl_exists = false; 226 if (channels_.find(component) == channels_.end()) { 227 impl = CreateTransportChannel(component); 228 channels_[component] = ChannelMapEntry(impl); 229 } else { 230 impl = channels_[component].get(); 231 impl_exists = true; 232 } 233 234 // Increase the ref count. 235 channels_[component].AddRef(); 236 destroyed_ = false; 237 238 if (impl_exists) { 239 // If this is an existing channel, we should just return it without 240 // connecting to all the signal again. 241 return impl; 242 } 243 244 // Push down our transport state to the new channel. 245 impl->SetIceRole(ice_role_); 246 impl->SetIceTiebreaker(tiebreaker_); 247 // TODO(ronghuawu): Change CreateChannel_w to be able to return error since 248 // below Apply**Description_w calls can fail. 249 if (local_description_) 250 ApplyLocalTransportDescription_w(impl, NULL); 251 if (remote_description_) 252 ApplyRemoteTransportDescription_w(impl, NULL); 253 if (local_description_ && remote_description_) 254 ApplyNegotiatedTransportDescription_w(impl, NULL); 255 256 impl->SignalReadableState.connect(this, &Transport::OnChannelReadableState); 257 impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState); 258 impl->SignalRequestSignaling.connect( 259 this, &Transport::OnChannelRequestSignaling); 260 impl->SignalCandidateReady.connect(this, &Transport::OnChannelCandidateReady); 261 impl->SignalRouteChange.connect(this, &Transport::OnChannelRouteChange); 262 impl->SignalCandidatesAllocationDone.connect( 263 this, &Transport::OnChannelCandidatesAllocationDone); 264 impl->SignalRoleConflict.connect(this, &Transport::OnRoleConflict); 265 impl->SignalConnectionRemoved.connect( 266 this, &Transport::OnChannelConnectionRemoved); 267 268 if (connect_requested_) { 269 impl->Connect(); 270 if (channels_.size() == 1) { 271 // If this is the first channel, then indicate that we have started 272 // connecting. 273 signaling_thread()->Post(this, MSG_CONNECTING, NULL); 274 } 275 } 276 return impl; 277 } 278 279 TransportChannelImpl* Transport::GetChannel(int component) { 280 rtc::CritScope cs(&crit_); 281 ChannelMap::iterator iter = channels_.find(component); 282 return (iter != channels_.end()) ? iter->second.get() : NULL; 283 } 284 285 bool Transport::HasChannels() { 286 rtc::CritScope cs(&crit_); 287 return !channels_.empty(); 288 } 289 290 void Transport::DestroyChannel(int component) { 291 worker_thread_->Invoke<void>(Bind( 292 &Transport::DestroyChannel_w, this, component)); 293 } 294 295 void Transport::DestroyChannel_w(int component) { 296 ASSERT(worker_thread()->IsCurrent()); 297 298 TransportChannelImpl* impl = NULL; 299 { 300 rtc::CritScope cs(&crit_); 301 ChannelMap::iterator iter = channels_.find(component); 302 if (iter == channels_.end()) 303 return; 304 305 iter->second.DecRef(); 306 if (!iter->second.ref()) { 307 impl = iter->second.get(); 308 channels_.erase(iter); 309 } 310 } 311 312 if (connect_requested_ && channels_.empty()) { 313 // We're no longer attempting to connect. 314 signaling_thread()->Post(this, MSG_CONNECTING, NULL); 315 } 316 317 if (impl) { 318 // Check in case the deleted channel was the only non-writable channel. 319 OnChannelWritableState(impl); 320 DestroyTransportChannel(impl); 321 } 322 } 323 324 void Transport::ConnectChannels() { 325 ASSERT(signaling_thread()->IsCurrent()); 326 worker_thread_->Invoke<void>(Bind(&Transport::ConnectChannels_w, this)); 327 } 328 329 void Transport::ConnectChannels_w() { 330 ASSERT(worker_thread()->IsCurrent()); 331 if (connect_requested_ || channels_.empty()) 332 return; 333 connect_requested_ = true; 334 signaling_thread()->Post( 335 this, MSG_CANDIDATEREADY, NULL); 336 337 if (!local_description_) { 338 // TOOD(mallinath) : TransportDescription(TD) shouldn't be generated here. 339 // As Transport must know TD is offer or answer and cricket::Transport 340 // doesn't have the capability to decide it. This should be set by the 341 // Session. 342 // Session must generate local TD before remote candidates pushed when 343 // initiate request initiated by the remote. 344 LOG(LS_INFO) << "Transport::ConnectChannels_w: No local description has " 345 << "been set. Will generate one."; 346 TransportDescription desc(NS_GINGLE_P2P, std::vector<std::string>(), 347 rtc::CreateRandomString(ICE_UFRAG_LENGTH), 348 rtc::CreateRandomString(ICE_PWD_LENGTH), 349 ICEMODE_FULL, CONNECTIONROLE_NONE, NULL, 350 Candidates()); 351 SetLocalTransportDescription_w(desc, CA_OFFER, NULL); 352 } 353 354 CallChannels_w(&TransportChannelImpl::Connect); 355 if (!channels_.empty()) { 356 signaling_thread()->Post(this, MSG_CONNECTING, NULL); 357 } 358 } 359 360 void Transport::OnConnecting_s() { 361 ASSERT(signaling_thread()->IsCurrent()); 362 SignalConnecting(this); 363 } 364 365 void Transport::DestroyAllChannels() { 366 ASSERT(signaling_thread()->IsCurrent()); 367 worker_thread_->Invoke<void>( 368 Bind(&Transport::DestroyAllChannels_w, this)); 369 worker_thread()->Clear(this); 370 signaling_thread()->Clear(this); 371 destroyed_ = true; 372 } 373 374 void Transport::DestroyAllChannels_w() { 375 ASSERT(worker_thread()->IsCurrent()); 376 std::vector<TransportChannelImpl*> impls; 377 { 378 rtc::CritScope cs(&crit_); 379 for (ChannelMap::iterator iter = channels_.begin(); 380 iter != channels_.end(); 381 ++iter) { 382 iter->second.DecRef(); 383 if (!iter->second.ref()) 384 impls.push_back(iter->second.get()); 385 } 386 } 387 channels_.clear(); 388 389 390 for (size_t i = 0; i < impls.size(); ++i) 391 DestroyTransportChannel(impls[i]); 392 } 393 394 void Transport::ResetChannels() { 395 ASSERT(signaling_thread()->IsCurrent()); 396 worker_thread_->Invoke<void>(Bind(&Transport::ResetChannels_w, this)); 397 } 398 399 void Transport::ResetChannels_w() { 400 ASSERT(worker_thread()->IsCurrent()); 401 402 // We are no longer attempting to connect 403 connect_requested_ = false; 404 405 // Clear out the old messages, they aren't relevant 406 rtc::CritScope cs(&crit_); 407 ready_candidates_.clear(); 408 409 // Reset all of the channels 410 CallChannels_w(&TransportChannelImpl::Reset); 411 } 412 413 void Transport::OnSignalingReady() { 414 ASSERT(signaling_thread()->IsCurrent()); 415 if (destroyed_) return; 416 417 worker_thread()->Post(this, MSG_ONSIGNALINGREADY, NULL); 418 419 // Notify the subclass. 420 OnTransportSignalingReady(); 421 } 422 423 void Transport::CallChannels_w(TransportChannelFunc func) { 424 ASSERT(worker_thread()->IsCurrent()); 425 rtc::CritScope cs(&crit_); 426 for (ChannelMap::iterator iter = channels_.begin(); 427 iter != channels_.end(); 428 ++iter) { 429 ((iter->second.get())->*func)(); 430 } 431 } 432 433 bool Transport::VerifyCandidate(const Candidate& cand, std::string* error) { 434 // No address zero. 435 if (cand.address().IsNil() || cand.address().IsAny()) { 436 *error = "candidate has address of zero"; 437 return false; 438 } 439 440 // Disallow all ports below 1024, except for 80 and 443 on public addresses. 441 int port = cand.address().port(); 442 if (cand.protocol() == TCP_PROTOCOL_NAME && 443 (cand.tcptype() == TCPTYPE_ACTIVE_STR || port == 0)) { 444 // Expected for active-only candidates per 445 // http://tools.ietf.org/html/rfc6544#section-4.5 so no error. 446 // Libjingle clients emit port 0, in "active" mode. 447 return true; 448 } 449 if (port < 1024) { 450 if ((port != 80) && (port != 443)) { 451 *error = "candidate has port below 1024, but not 80 or 443"; 452 return false; 453 } 454 455 if (cand.address().IsPrivateIP()) { 456 *error = "candidate has port of 80 or 443 with private IP address"; 457 return false; 458 } 459 } 460 461 return true; 462 } 463 464 465 bool Transport::GetStats(TransportStats* stats) { 466 ASSERT(signaling_thread()->IsCurrent()); 467 return worker_thread_->Invoke<bool>(Bind( 468 &Transport::GetStats_w, this, stats)); 469 } 470 471 bool Transport::GetStats_w(TransportStats* stats) { 472 ASSERT(worker_thread()->IsCurrent()); 473 stats->content_name = content_name(); 474 stats->channel_stats.clear(); 475 for (ChannelMap::iterator iter = channels_.begin(); 476 iter != channels_.end(); 477 ++iter) { 478 TransportChannelStats substats; 479 substats.component = iter->second->component(); 480 if (!iter->second->GetStats(&substats.connection_infos)) { 481 return false; 482 } 483 stats->channel_stats.push_back(substats); 484 } 485 return true; 486 } 487 488 bool Transport::GetSslRole(rtc::SSLRole* ssl_role) const { 489 return worker_thread_->Invoke<bool>(Bind( 490 &Transport::GetSslRole_w, this, ssl_role)); 491 } 492 493 void Transport::OnRemoteCandidates(const std::vector<Candidate>& candidates) { 494 for (std::vector<Candidate>::const_iterator iter = candidates.begin(); 495 iter != candidates.end(); 496 ++iter) { 497 OnRemoteCandidate(*iter); 498 } 499 } 500 501 void Transport::OnRemoteCandidate(const Candidate& candidate) { 502 ASSERT(signaling_thread()->IsCurrent()); 503 if (destroyed_) return; 504 505 if (!HasChannel(candidate.component())) { 506 LOG(LS_WARNING) << "Ignoring candidate for unknown component " 507 << candidate.component(); 508 return; 509 } 510 511 ChannelParams* params = new ChannelParams(new Candidate(candidate)); 512 worker_thread()->Post(this, MSG_ONREMOTECANDIDATE, params); 513 } 514 515 void Transport::OnRemoteCandidate_w(const Candidate& candidate) { 516 ASSERT(worker_thread()->IsCurrent()); 517 ChannelMap::iterator iter = channels_.find(candidate.component()); 518 // It's ok for a channel to go away while this message is in transit. 519 if (iter != channels_.end()) { 520 iter->second->OnCandidate(candidate); 521 } 522 } 523 524 void Transport::OnChannelReadableState(TransportChannel* channel) { 525 ASSERT(worker_thread()->IsCurrent()); 526 signaling_thread()->Post(this, MSG_READSTATE, NULL); 527 } 528 529 void Transport::OnChannelReadableState_s() { 530 ASSERT(signaling_thread()->IsCurrent()); 531 TransportState readable = GetTransportState_s(true); 532 if (readable_ != readable) { 533 readable_ = readable; 534 SignalReadableState(this); 535 } 536 } 537 538 void Transport::OnChannelWritableState(TransportChannel* channel) { 539 ASSERT(worker_thread()->IsCurrent()); 540 signaling_thread()->Post(this, MSG_WRITESTATE, NULL); 541 542 MaybeCompleted_w(); 543 } 544 545 void Transport::OnChannelWritableState_s() { 546 ASSERT(signaling_thread()->IsCurrent()); 547 TransportState writable = GetTransportState_s(false); 548 if (writable_ != writable) { 549 was_writable_ = (writable_ == TRANSPORT_STATE_ALL); 550 writable_ = writable; 551 SignalWritableState(this); 552 } 553 } 554 555 TransportState Transport::GetTransportState_s(bool read) { 556 ASSERT(signaling_thread()->IsCurrent()); 557 rtc::CritScope cs(&crit_); 558 bool any = false; 559 bool all = !channels_.empty(); 560 for (ChannelMap::iterator iter = channels_.begin(); 561 iter != channels_.end(); 562 ++iter) { 563 bool b = (read ? iter->second->readable() : 564 iter->second->writable()); 565 any = any || b; 566 all = all && b; 567 } 568 if (all) { 569 return TRANSPORT_STATE_ALL; 570 } else if (any) { 571 return TRANSPORT_STATE_SOME; 572 } else { 573 return TRANSPORT_STATE_NONE; 574 } 575 } 576 577 void Transport::OnChannelRequestSignaling(TransportChannelImpl* channel) { 578 ASSERT(worker_thread()->IsCurrent()); 579 ChannelParams* params = new ChannelParams(channel->component()); 580 signaling_thread()->Post(this, MSG_REQUESTSIGNALING, params); 581 } 582 583 void Transport::OnChannelRequestSignaling_s(int component) { 584 ASSERT(signaling_thread()->IsCurrent()); 585 LOG(LS_INFO) << "Transport: " << content_name_ << ", allocating candidates"; 586 // Resetting ICE state for the channel. 587 { 588 rtc::CritScope cs(&crit_); 589 ChannelMap::iterator iter = channels_.find(component); 590 if (iter != channels_.end()) 591 iter->second.set_candidates_allocated(false); 592 } 593 SignalRequestSignaling(this); 594 } 595 596 void Transport::OnChannelCandidateReady(TransportChannelImpl* channel, 597 const Candidate& candidate) { 598 ASSERT(worker_thread()->IsCurrent()); 599 rtc::CritScope cs(&crit_); 600 ready_candidates_.push_back(candidate); 601 602 // We hold any messages until the client lets us connect. 603 if (connect_requested_) { 604 signaling_thread()->Post( 605 this, MSG_CANDIDATEREADY, NULL); 606 } 607 } 608 609 void Transport::OnChannelCandidateReady_s() { 610 ASSERT(signaling_thread()->IsCurrent()); 611 ASSERT(connect_requested_); 612 613 std::vector<Candidate> candidates; 614 { 615 rtc::CritScope cs(&crit_); 616 candidates.swap(ready_candidates_); 617 } 618 619 // we do the deleting of Candidate* here to keep the new above and 620 // delete below close to each other 621 if (!candidates.empty()) { 622 SignalCandidatesReady(this, candidates); 623 } 624 } 625 626 void Transport::OnChannelRouteChange(TransportChannel* channel, 627 const Candidate& remote_candidate) { 628 ASSERT(worker_thread()->IsCurrent()); 629 ChannelParams* params = new ChannelParams(new Candidate(remote_candidate)); 630 params->channel = static_cast<cricket::TransportChannelImpl*>(channel); 631 signaling_thread()->Post(this, MSG_ROUTECHANGE, params); 632 } 633 634 void Transport::OnChannelRouteChange_s(const TransportChannel* channel, 635 const Candidate& remote_candidate) { 636 ASSERT(signaling_thread()->IsCurrent()); 637 SignalRouteChange(this, remote_candidate.component(), remote_candidate); 638 } 639 640 void Transport::OnChannelCandidatesAllocationDone( 641 TransportChannelImpl* channel) { 642 ASSERT(worker_thread()->IsCurrent()); 643 rtc::CritScope cs(&crit_); 644 ChannelMap::iterator iter = channels_.find(channel->component()); 645 ASSERT(iter != channels_.end()); 646 LOG(LS_INFO) << "Transport: " << content_name_ << ", component " 647 << channel->component() << " allocation complete"; 648 iter->second.set_candidates_allocated(true); 649 650 // If all channels belonging to this Transport got signal, then 651 // forward this signal to upper layer. 652 // Can this signal arrive before all transport channels are created? 653 for (iter = channels_.begin(); iter != channels_.end(); ++iter) { 654 if (!iter->second.candidates_allocated()) 655 return; 656 } 657 signaling_thread_->Post(this, MSG_CANDIDATEALLOCATIONCOMPLETE); 658 659 MaybeCompleted_w(); 660 } 661 662 void Transport::OnChannelCandidatesAllocationDone_s() { 663 ASSERT(signaling_thread()->IsCurrent()); 664 LOG(LS_INFO) << "Transport: " << content_name_ << " allocation complete"; 665 SignalCandidatesAllocationDone(this); 666 } 667 668 void Transport::OnRoleConflict(TransportChannelImpl* channel) { 669 signaling_thread_->Post(this, MSG_ROLECONFLICT); 670 } 671 672 void Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) { 673 ASSERT(worker_thread()->IsCurrent()); 674 MaybeCompleted_w(); 675 676 // Check if the state is now Failed. 677 // Failed is only available in the Controlling ICE role. 678 if (channel->GetIceRole() != ICEROLE_CONTROLLING) { 679 return; 680 } 681 682 ChannelMap::iterator iter = channels_.find(channel->component()); 683 ASSERT(iter != channels_.end()); 684 // Failed can only occur after candidate allocation has stopped. 685 if (!iter->second.candidates_allocated()) { 686 return; 687 } 688 689 size_t connections = channel->GetConnectionCount(); 690 if (connections == 0) { 691 // A Transport has failed if any of its channels have no remaining 692 // connections. 693 signaling_thread_->Post(this, MSG_FAILED); 694 } 695 } 696 697 void Transport::MaybeCompleted_w() { 698 ASSERT(worker_thread()->IsCurrent()); 699 700 // A Transport's ICE process is completed if all of its channels are writable, 701 // have finished allocating candidates, and have pruned all but one of their 702 // connections. 703 ChannelMap::const_iterator iter; 704 for (iter = channels_.begin(); iter != channels_.end(); ++iter) { 705 const TransportChannelImpl* channel = iter->second.get(); 706 if (!(channel->writable() && 707 channel->GetConnectionCount() == 1 && 708 channel->GetIceRole() == ICEROLE_CONTROLLING && 709 iter->second.candidates_allocated())) { 710 return; 711 } 712 } 713 714 signaling_thread_->Post(this, MSG_COMPLETED); 715 } 716 717 void Transport::SetIceRole_w(IceRole role) { 718 rtc::CritScope cs(&crit_); 719 ice_role_ = role; 720 for (ChannelMap::iterator iter = channels_.begin(); 721 iter != channels_.end(); ++iter) { 722 iter->second->SetIceRole(ice_role_); 723 } 724 } 725 726 void Transport::SetRemoteIceMode_w(IceMode mode) { 727 rtc::CritScope cs(&crit_); 728 remote_ice_mode_ = mode; 729 // Shouldn't channels be created after this method executed? 730 for (ChannelMap::iterator iter = channels_.begin(); 731 iter != channels_.end(); ++iter) { 732 iter->second->SetRemoteIceMode(remote_ice_mode_); 733 } 734 } 735 736 bool Transport::SetLocalTransportDescription_w( 737 const TransportDescription& desc, 738 ContentAction action, 739 std::string* error_desc) { 740 bool ret = true; 741 rtc::CritScope cs(&crit_); 742 743 if (!VerifyIceParams(desc)) { 744 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length", 745 error_desc); 746 } 747 748 if (local_description_ && IceCredentialsChanged(*local_description_, desc)) { 749 IceRole new_ice_role = (action == CA_OFFER) ? ICEROLE_CONTROLLING 750 : ICEROLE_CONTROLLED; 751 752 // It must be called before ApplyLocalTransportDescription_w, which may 753 // trigger an ICE restart and depends on the new ICE role. 754 SetIceRole_w(new_ice_role); 755 } 756 757 local_description_.reset(new TransportDescription(desc)); 758 759 for (ChannelMap::iterator iter = channels_.begin(); 760 iter != channels_.end(); ++iter) { 761 ret &= ApplyLocalTransportDescription_w(iter->second.get(), error_desc); 762 } 763 if (!ret) 764 return false; 765 766 // If PRANSWER/ANSWER is set, we should decide transport protocol type. 767 if (action == CA_PRANSWER || action == CA_ANSWER) { 768 ret &= NegotiateTransportDescription_w(action, error_desc); 769 } 770 return ret; 771 } 772 773 bool Transport::SetRemoteTransportDescription_w( 774 const TransportDescription& desc, 775 ContentAction action, 776 std::string* error_desc) { 777 bool ret = true; 778 rtc::CritScope cs(&crit_); 779 780 if (!VerifyIceParams(desc)) { 781 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length", 782 error_desc); 783 } 784 785 remote_description_.reset(new TransportDescription(desc)); 786 for (ChannelMap::iterator iter = channels_.begin(); 787 iter != channels_.end(); ++iter) { 788 ret &= ApplyRemoteTransportDescription_w(iter->second.get(), error_desc); 789 } 790 791 // If PRANSWER/ANSWER is set, we should decide transport protocol type. 792 if (action == CA_PRANSWER || action == CA_ANSWER) { 793 ret = NegotiateTransportDescription_w(CA_OFFER, error_desc); 794 } 795 return ret; 796 } 797 798 bool Transport::ApplyLocalTransportDescription_w(TransportChannelImpl* ch, 799 std::string* error_desc) { 800 // If existing protocol_type is HYBRID, we may have not chosen the final 801 // protocol type, so update the channel protocol type from the 802 // local description. Otherwise, skip updating the protocol type. 803 // We check for HYBRID to avoid accidental changes; in the case of a 804 // session renegotiation, the new offer will have the google-ice ICE option, 805 // so we need to make sure we don't switch back from ICE mode to HYBRID 806 // when this happens. 807 // There are some other ways we could have solved this, but this is the 808 // simplest. The ultimate solution will be to get rid of GICE altogether. 809 IceProtocolType protocol_type; 810 if (ch->GetIceProtocolType(&protocol_type) && 811 protocol_type == ICEPROTO_HYBRID) { 812 ch->SetIceProtocolType( 813 TransportProtocolFromDescription(local_description())); 814 } 815 ch->SetIceCredentials(local_description_->ice_ufrag, 816 local_description_->ice_pwd); 817 return true; 818 } 819 820 bool Transport::ApplyRemoteTransportDescription_w(TransportChannelImpl* ch, 821 std::string* error_desc) { 822 ch->SetRemoteIceCredentials(remote_description_->ice_ufrag, 823 remote_description_->ice_pwd); 824 return true; 825 } 826 827 bool Transport::ApplyNegotiatedTransportDescription_w( 828 TransportChannelImpl* channel, std::string* error_desc) { 829 channel->SetIceProtocolType(protocol_); 830 channel->SetRemoteIceMode(remote_ice_mode_); 831 return true; 832 } 833 834 bool Transport::NegotiateTransportDescription_w(ContentAction local_role, 835 std::string* error_desc) { 836 // TODO(ekr (at) rtfm.com): This is ICE-specific stuff. Refactor into 837 // P2PTransport. 838 const TransportDescription* offer; 839 const TransportDescription* answer; 840 841 if (local_role == CA_OFFER) { 842 offer = local_description_.get(); 843 answer = remote_description_.get(); 844 } else { 845 offer = remote_description_.get(); 846 answer = local_description_.get(); 847 } 848 849 TransportProtocol offer_proto = TransportProtocolFromDescription(offer); 850 TransportProtocol answer_proto = TransportProtocolFromDescription(answer); 851 852 // If offered protocol is gice/ice, then we expect to receive matching 853 // protocol in answer, anything else is treated as an error. 854 // HYBRID is not an option when offered specific protocol. 855 // If offered protocol is HYBRID and answered protocol is HYBRID then 856 // gice is preferred protocol. 857 // TODO(mallinath) - Answer from local or remote should't have both ice 858 // and gice support. It should always pick which protocol it wants to use. 859 // Once WebRTC stops supporting gice (for backward compatibility), HYBRID in 860 // answer must be treated as error. 861 if ((offer_proto == ICEPROTO_GOOGLE || offer_proto == ICEPROTO_RFC5245) && 862 (offer_proto != answer_proto)) { 863 std::ostringstream desc; 864 desc << "Offer and answer protocol mismatch: " 865 << IceProtoToString(offer_proto) 866 << " vs " 867 << IceProtoToString(answer_proto); 868 return BadTransportDescription(desc.str(), error_desc); 869 } 870 protocol_ = answer_proto == ICEPROTO_HYBRID ? ICEPROTO_GOOGLE : answer_proto; 871 872 // If transport is in ICEROLE_CONTROLLED and remote end point supports only 873 // ice_lite, this local end point should take CONTROLLING role. 874 if (ice_role_ == ICEROLE_CONTROLLED && 875 remote_description_->ice_mode == ICEMODE_LITE) { 876 SetIceRole_w(ICEROLE_CONTROLLING); 877 } 878 879 // Update remote ice_mode to all existing channels. 880 remote_ice_mode_ = remote_description_->ice_mode; 881 882 // Now that we have negotiated everything, push it downward. 883 // Note that we cache the result so that if we have race conditions 884 // between future SetRemote/SetLocal invocations and new channel 885 // creation, we have the negotiation state saved until a new 886 // negotiation happens. 887 for (ChannelMap::iterator iter = channels_.begin(); 888 iter != channels_.end(); 889 ++iter) { 890 if (!ApplyNegotiatedTransportDescription_w(iter->second.get(), error_desc)) 891 return false; 892 } 893 return true; 894 } 895 896 void Transport::OnMessage(rtc::Message* msg) { 897 switch (msg->message_id) { 898 case MSG_ONSIGNALINGREADY: 899 CallChannels_w(&TransportChannelImpl::OnSignalingReady); 900 break; 901 case MSG_ONREMOTECANDIDATE: { 902 ChannelParams* params = static_cast<ChannelParams*>(msg->pdata); 903 OnRemoteCandidate_w(*params->candidate); 904 delete params; 905 } 906 break; 907 case MSG_CONNECTING: 908 OnConnecting_s(); 909 break; 910 case MSG_READSTATE: 911 OnChannelReadableState_s(); 912 break; 913 case MSG_WRITESTATE: 914 OnChannelWritableState_s(); 915 break; 916 case MSG_REQUESTSIGNALING: { 917 ChannelParams* params = static_cast<ChannelParams*>(msg->pdata); 918 OnChannelRequestSignaling_s(params->component); 919 delete params; 920 } 921 break; 922 case MSG_CANDIDATEREADY: 923 OnChannelCandidateReady_s(); 924 break; 925 case MSG_ROUTECHANGE: { 926 ChannelParams* params = static_cast<ChannelParams*>(msg->pdata); 927 OnChannelRouteChange_s(params->channel, *params->candidate); 928 delete params; 929 } 930 break; 931 case MSG_CANDIDATEALLOCATIONCOMPLETE: 932 OnChannelCandidatesAllocationDone_s(); 933 break; 934 case MSG_ROLECONFLICT: 935 SignalRoleConflict(); 936 break; 937 case MSG_COMPLETED: 938 SignalCompleted(this); 939 break; 940 case MSG_FAILED: 941 SignalFailed(this); 942 break; 943 } 944 } 945 946 bool TransportParser::ParseAddress(const buzz::XmlElement* elem, 947 const buzz::QName& address_name, 948 const buzz::QName& port_name, 949 rtc::SocketAddress* address, 950 ParseError* error) { 951 if (!elem->HasAttr(address_name)) 952 return BadParse("address does not have " + address_name.LocalPart(), error); 953 if (!elem->HasAttr(port_name)) 954 return BadParse("address does not have " + port_name.LocalPart(), error); 955 956 address->SetIP(elem->Attr(address_name)); 957 std::istringstream ist(elem->Attr(port_name)); 958 int port = 0; 959 ist >> port; 960 address->SetPort(port); 961 962 return true; 963 } 964 965 // We're GICE if the namespace is NS_GOOGLE_P2P, or if NS_JINGLE_ICE_UDP is 966 // used and the GICE ice-option is set. 967 TransportProtocol TransportProtocolFromDescription( 968 const TransportDescription* desc) { 969 ASSERT(desc != NULL); 970 if (desc->transport_type == NS_JINGLE_ICE_UDP) { 971 return (desc->HasOption(ICE_OPTION_GICE)) ? 972 ICEPROTO_HYBRID : ICEPROTO_RFC5245; 973 } 974 return ICEPROTO_GOOGLE; 975 } 976 977 } // namespace cricket 978