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