1 /* 2 * libjingle 3 * Copyright 2004--2005, 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/session.h" 29 #include "talk/base/common.h" 30 #include "talk/base/logging.h" 31 #include "talk/base/helpers.h" 32 #include "talk/base/scoped_ptr.h" 33 #include "talk/xmpp/constants.h" 34 #include "talk/xmpp/jid.h" 35 #include "talk/p2p/base/sessionclient.h" 36 #include "talk/p2p/base/transport.h" 37 #include "talk/p2p/base/transportchannelproxy.h" 38 #include "talk/p2p/base/p2ptransport.h" 39 #include "talk/p2p/base/p2ptransportchannel.h" 40 41 #include "talk/p2p/base/constants.h" 42 43 namespace { 44 45 const uint32 MSG_TIMEOUT = 1; 46 const uint32 MSG_ERROR = 2; 47 const uint32 MSG_STATE = 3; 48 49 } // namespace 50 51 namespace cricket { 52 53 bool BadMessage(const buzz::QName type, 54 const std::string& text, 55 MessageError* err) { 56 err->SetType(type); 57 err->SetText(text); 58 return false; 59 } 60 61 TransportProxy::~TransportProxy() { 62 for (ChannelMap::iterator iter = channels_.begin(); 63 iter != channels_.end(); ++iter) { 64 iter->second->SignalDestroyed(iter->second); 65 delete iter->second; 66 } 67 delete transport_; 68 } 69 70 std::string TransportProxy::type() const { 71 return transport_->type(); 72 } 73 74 TransportChannel* TransportProxy::GetChannel(const std::string& name) { 75 return GetProxy(name); 76 } 77 78 TransportChannel* TransportProxy::CreateChannel( 79 const std::string& name, const std::string& content_type) { 80 ASSERT(GetChannel(name) == NULL); 81 ASSERT(!transport_->HasChannel(name)); 82 83 // We always create a proxy in case we need to change out the transport later. 84 TransportChannelProxy* channel = 85 new TransportChannelProxy(name, content_type); 86 channels_[name] = channel; 87 88 if (state_ == STATE_NEGOTIATED) { 89 SetProxyImpl(name, channel); 90 } else if (state_ == STATE_CONNECTING) { 91 GetOrCreateImpl(name, content_type); 92 } 93 return channel; 94 } 95 96 void TransportProxy::DestroyChannel(const std::string& name) { 97 TransportChannel* channel = GetChannel(name); 98 if (channel) { 99 channels_.erase(name); 100 channel->SignalDestroyed(channel); 101 delete channel; 102 } 103 } 104 105 void TransportProxy::SpeculativelyConnectChannels() { 106 ASSERT(state_ == STATE_INIT || state_ == STATE_CONNECTING); 107 state_ = STATE_CONNECTING; 108 for (ChannelMap::iterator iter = channels_.begin(); 109 iter != channels_.end(); ++iter) { 110 GetOrCreateImpl(iter->first, iter->second->content_type()); 111 } 112 transport_->ConnectChannels(); 113 } 114 115 void TransportProxy::CompleteNegotiation() { 116 if (state_ != STATE_NEGOTIATED) { 117 state_ = STATE_NEGOTIATED; 118 for (ChannelMap::iterator iter = channels_.begin(); 119 iter != channels_.end(); ++iter) { 120 SetProxyImpl(iter->first, iter->second); 121 } 122 transport_->ConnectChannels(); 123 } 124 } 125 126 void TransportProxy::AddSentCandidates(const Candidates& candidates) { 127 for (Candidates::const_iterator cand = candidates.begin(); 128 cand != candidates.end(); ++cand) { 129 sent_candidates_.push_back(*cand); 130 } 131 } 132 133 134 TransportChannelProxy* TransportProxy::GetProxy(const std::string& name) { 135 ChannelMap::iterator iter = channels_.find(name); 136 return (iter != channels_.end()) ? iter->second : NULL; 137 } 138 139 TransportChannelImpl* TransportProxy::GetOrCreateImpl( 140 const std::string& name, const std::string& content_type) { 141 TransportChannelImpl* impl = transport_->GetChannel(name); 142 if (impl == NULL) { 143 impl = transport_->CreateChannel(name, content_type); 144 } 145 return impl; 146 } 147 148 void TransportProxy::SetProxyImpl( 149 const std::string& name, TransportChannelProxy* proxy) { 150 TransportChannelImpl* impl = GetOrCreateImpl(name, proxy->content_type()); 151 ASSERT(impl != NULL); 152 proxy->SetImplementation(impl); 153 } 154 155 156 157 158 BaseSession::BaseSession(talk_base::Thread *signaling_thread) 159 : state_(STATE_INIT), error_(ERROR_NONE), 160 local_description_(NULL), remote_description_(NULL), 161 signaling_thread_(signaling_thread) { 162 } 163 164 BaseSession::~BaseSession() { 165 delete remote_description_; 166 delete local_description_; 167 } 168 169 void BaseSession::SetState(State state) { 170 ASSERT(signaling_thread_->IsCurrent()); 171 if (state != state_) { 172 state_ = state; 173 SignalState(this, state_); 174 signaling_thread_->Post(this, MSG_STATE); 175 } 176 } 177 178 void BaseSession::SetError(Error error) { 179 ASSERT(signaling_thread_->IsCurrent()); 180 if (error != error_) { 181 error_ = error; 182 SignalError(this, error); 183 } 184 } 185 186 void BaseSession::OnMessage(talk_base::Message *pmsg) { 187 switch (pmsg->message_id) { 188 case MSG_TIMEOUT: 189 // Session timeout has occured. 190 SetError(ERROR_TIME); 191 break; 192 193 case MSG_ERROR: 194 TerminateWithReason(STR_TERMINATE_ERROR); 195 break; 196 197 case MSG_STATE: 198 switch (state_) { 199 case STATE_SENTACCEPT: 200 case STATE_RECEIVEDACCEPT: 201 SetState(STATE_INPROGRESS); 202 break; 203 204 case STATE_SENTREJECT: 205 case STATE_RECEIVEDREJECT: 206 // Assume clean termination. 207 Terminate(); 208 break; 209 210 default: 211 // Explicitly ignoring some states here. 212 break; 213 } 214 break; 215 } 216 } 217 218 219 Session::Session(SessionManager *session_manager, 220 const std::string& local_name, 221 const std::string& initiator_name, 222 const std::string& sid, const std::string& content_type, 223 SessionClient* client) : 224 BaseSession(session_manager->signaling_thread()) { 225 ASSERT(session_manager->signaling_thread()->IsCurrent()); 226 ASSERT(client != NULL); 227 session_manager_ = session_manager; 228 local_name_ = local_name; 229 sid_ = sid; 230 initiator_name_ = initiator_name; 231 content_type_ = content_type; 232 // TODO: Once we support different transport types, 233 // don't hard code this here. 234 transport_type_ = NS_GINGLE_P2P; 235 transport_parser_ = new P2PTransportParser(); 236 client_ = client; 237 error_ = ERROR_NONE; 238 state_ = STATE_INIT; 239 initiator_ = false; 240 current_protocol_ = PROTOCOL_HYBRID; 241 } 242 243 Session::~Session() { 244 ASSERT(signaling_thread_->IsCurrent()); 245 246 ASSERT(state_ != STATE_DEINIT); 247 state_ = STATE_DEINIT; 248 SignalState(this, state_); 249 250 for (TransportMap::iterator iter = transports_.begin(); 251 iter != transports_.end(); ++iter) { 252 delete iter->second; 253 } 254 255 delete transport_parser_; 256 } 257 258 Transport* Session::GetTransport(const std::string& content_name) { 259 TransportProxy* transproxy = GetTransportProxy(content_name); 260 if (transproxy == NULL) 261 return NULL; 262 return transproxy->impl(); 263 } 264 265 void Session::set_allow_local_ips(bool allow) { 266 allow_local_ips_ = allow; 267 for (TransportMap::iterator iter = transports_.begin(); 268 iter != transports_.end(); ++iter) { 269 iter->second->impl()->set_allow_local_ips(allow); 270 } 271 } 272 273 bool Session::Initiate(const std::string &to, 274 const SessionDescription* sdesc) { 275 ASSERT(signaling_thread_->IsCurrent()); 276 SessionError error; 277 278 // Only from STATE_INIT 279 if (state_ != STATE_INIT) 280 return false; 281 282 // Setup for signaling. 283 remote_name_ = to; 284 initiator_ = true; 285 set_local_description(sdesc); 286 if (!CreateTransportProxies(GetEmptyTransportInfos(sdesc->contents()), 287 &error)) { 288 LOG(LS_ERROR) << "Could not create transports: " << error.text; 289 return false; 290 } 291 292 if (!SendInitiateMessage(sdesc, &error)) { 293 LOG(LS_ERROR) << "Could not send initiate message: " << error.text; 294 return false; 295 } 296 297 SetState(Session::STATE_SENTINITIATE); 298 299 SpeculativelyConnectAllTransportChannels(); 300 return true; 301 } 302 303 bool Session::Accept(const SessionDescription* sdesc) { 304 ASSERT(signaling_thread_->IsCurrent()); 305 306 // Only if just received initiate 307 if (state_ != STATE_RECEIVEDINITIATE) 308 return false; 309 310 // Setup for signaling. 311 initiator_ = false; 312 set_local_description(sdesc); 313 314 SessionError error; 315 if (!SendAcceptMessage(sdesc, &error)) { 316 LOG(LS_ERROR) << "Could not send accept message: " << error.text; 317 return false; 318 } 319 320 SetState(Session::STATE_SENTACCEPT); 321 return true; 322 } 323 324 bool Session::Reject(const std::string& reason) { 325 ASSERT(signaling_thread_->IsCurrent()); 326 327 // Reject is sent in response to an initiate or modify, to reject the 328 // request 329 if (state_ != STATE_RECEIVEDINITIATE && state_ != STATE_RECEIVEDMODIFY) 330 return false; 331 332 // Setup for signaling. 333 initiator_ = false; 334 335 SessionError error; 336 if (!SendRejectMessage(reason, &error)) { 337 LOG(LS_ERROR) << "Could not send reject message: " << error.text; 338 return false; 339 } 340 341 SetState(STATE_SENTREJECT); 342 return true; 343 } 344 345 bool Session::TerminateWithReason(const std::string& reason) { 346 ASSERT(signaling_thread_->IsCurrent()); 347 348 // Either side can terminate, at any time. 349 switch (state_) { 350 case STATE_SENTTERMINATE: 351 case STATE_RECEIVEDTERMINATE: 352 return false; 353 354 case STATE_SENTREJECT: 355 case STATE_RECEIVEDREJECT: 356 // We don't need to send terminate if we sent or received a reject... 357 // it's implicit. 358 break; 359 360 default: 361 SessionError error; 362 if (!SendTerminateMessage(reason, &error)) { 363 LOG(LS_ERROR) << "Could not send terminate message: " << error.text; 364 return false; 365 } 366 break; 367 } 368 369 SetState(STATE_SENTTERMINATE); 370 return true; 371 } 372 373 bool Session::SendInfoMessage(const XmlElements& elems) { 374 ASSERT(signaling_thread_->IsCurrent()); 375 SessionError error; 376 if (!SendMessage(ACTION_SESSION_INFO, elems, &error)) { 377 LOG(LS_ERROR) << "Could not send info message " << error.text; 378 return false; 379 } 380 return true; 381 } 382 383 384 TransportProxy* Session::GetTransportProxy(const Transport* transport) { 385 for (TransportMap::iterator iter = transports_.begin(); 386 iter != transports_.end(); ++iter) { 387 TransportProxy* transproxy = iter->second; 388 if (transproxy->impl() == transport) { 389 return transproxy; 390 } 391 } 392 return NULL; 393 } 394 395 TransportProxy* Session::GetTransportProxy(const std::string& content_name) { 396 TransportMap::iterator iter = transports_.find(content_name); 397 return (iter != transports_.end()) ? iter->second : NULL; 398 } 399 400 TransportProxy* Session::GetFirstTransportProxy() { 401 if (transports_.empty()) 402 return NULL; 403 return transports_.begin()->second; 404 } 405 406 TransportInfos Session::GetEmptyTransportInfos( 407 const ContentInfos& contents) const { 408 TransportInfos tinfos; 409 for (ContentInfos::const_iterator content = contents.begin(); 410 content != contents.end(); ++content) { 411 tinfos.push_back( 412 TransportInfo(content->name, transport_type_, Candidates())); 413 } 414 return tinfos; 415 } 416 417 418 bool Session::OnRemoteCandidates( 419 const TransportInfos& tinfos, ParseError* error) { 420 for (TransportInfos::const_iterator tinfo = tinfos.begin(); 421 tinfo != tinfos.end(); ++tinfo) { 422 TransportProxy* transproxy = GetTransportProxy(tinfo->content_name); 423 if (transproxy == NULL) { 424 return BadParse("Unknown content name: " + tinfo->content_name, error); 425 } 426 427 // Must complete negotiation before sending remote candidates, or 428 // there won't be any channel impls. 429 transproxy->CompleteNegotiation(); 430 for (Candidates::const_iterator cand = tinfo->candidates.begin(); 431 cand != tinfo->candidates.end(); ++cand) { 432 if (!transproxy->impl()->VerifyCandidate(*cand, error)) 433 return false; 434 435 if (!transproxy->impl()->HasChannel(cand->name())) { 436 buzz::XmlElement* extra_info = 437 new buzz::XmlElement(QN_GINGLE_P2P_UNKNOWN_CHANNEL_NAME); 438 extra_info->AddAttr(buzz::QN_NAME, cand->name()); 439 error->extra = extra_info; 440 441 return BadParse("channel named in candidate does not exist: " + 442 cand->name() + " for content: "+ tinfo->content_name, 443 error); 444 } 445 } 446 transproxy->impl()->OnRemoteCandidates(tinfo->candidates); 447 } 448 449 return true; 450 } 451 452 453 TransportProxy* Session::GetOrCreateTransportProxy( 454 const std::string& content_name) { 455 TransportProxy* transproxy = GetTransportProxy(content_name); 456 if (transproxy) 457 return transproxy; 458 459 Transport* transport = 460 new P2PTransport(signaling_thread_, 461 session_manager_->worker_thread(), 462 session_manager_->port_allocator()); 463 transport->set_allow_local_ips(allow_local_ips_); 464 transport->SignalConnecting.connect( 465 this, &Session::OnTransportConnecting); 466 transport->SignalWritableState.connect( 467 this, &Session::OnTransportWritable); 468 transport->SignalRequestSignaling.connect( 469 this, &Session::OnTransportRequestSignaling); 470 transport->SignalCandidatesReady.connect( 471 this, &Session::OnTransportCandidatesReady); 472 transport->SignalTransportError.connect( 473 this, &Session::OnTransportSendError); 474 transport->SignalChannelGone.connect( 475 this, &Session::OnTransportChannelGone); 476 477 transproxy = new TransportProxy(content_name, transport); 478 transports_[content_name] = transproxy; 479 480 return transproxy; 481 } 482 483 bool Session::CreateTransportProxies(const TransportInfos& tinfos, 484 SessionError* error) { 485 for (TransportInfos::const_iterator tinfo = tinfos.begin(); 486 tinfo != tinfos.end(); ++tinfo) { 487 if (tinfo->transport_type != transport_type_) { 488 error->SetText("No supported transport in offer."); 489 return false; 490 } 491 492 GetOrCreateTransportProxy(tinfo->content_name); 493 } 494 return true; 495 } 496 497 void Session::SpeculativelyConnectAllTransportChannels() { 498 for (TransportMap::iterator iter = transports_.begin(); 499 iter != transports_.end(); ++iter) { 500 iter->second->SpeculativelyConnectChannels(); 501 } 502 } 503 504 TransportParserMap Session::GetTransportParsers() { 505 TransportParserMap parsers; 506 parsers[transport_type_] = transport_parser_; 507 return parsers; 508 } 509 510 ContentParserMap Session::GetContentParsers() { 511 ContentParserMap parsers; 512 parsers[content_type_] = client_; 513 return parsers; 514 } 515 516 TransportChannel* Session::CreateChannel(const std::string& content_name, 517 const std::string& channel_name) { 518 // We create the proxy "on demand" here because we need to support 519 // creating channels at any time, even before we send or receive 520 // initiate messages, which is before we create the transports. 521 TransportProxy* transproxy = GetOrCreateTransportProxy(content_name); 522 return transproxy->CreateChannel(channel_name, content_type_); 523 } 524 525 TransportChannel* Session::GetChannel(const std::string& content_name, 526 const std::string& channel_name) { 527 TransportProxy* transproxy = GetTransportProxy(content_name); 528 if (transproxy == NULL) 529 return NULL; 530 else 531 return transproxy->GetChannel(channel_name); 532 } 533 534 void Session::DestroyChannel(const std::string& content_name, 535 const std::string& channel_name) { 536 TransportProxy* transproxy = GetTransportProxy(content_name); 537 ASSERT(transproxy != NULL); 538 transproxy->DestroyChannel(channel_name); 539 } 540 541 void Session::OnSignalingReady() { 542 ASSERT(signaling_thread_->IsCurrent()); 543 for (TransportMap::iterator iter = transports_.begin(); 544 iter != transports_.end(); ++iter) { 545 iter->second->impl()->OnSignalingReady(); 546 } 547 } 548 549 void Session::OnTransportConnecting(Transport* transport) { 550 // This is an indication that we should begin watching the writability 551 // state of the transport. 552 OnTransportWritable(transport); 553 } 554 555 void Session::OnTransportWritable(Transport* transport) { 556 ASSERT(signaling_thread_->IsCurrent()); 557 558 // If the transport is not writable, start a timer to make sure that it 559 // becomes writable within a reasonable amount of time. If it does not, we 560 // terminate since we can't actually send data. If the transport is writable, 561 // cancel the timer. Note that writability transitions may occur repeatedly 562 // during the lifetime of the session. 563 signaling_thread_->Clear(this, MSG_TIMEOUT); 564 if (transport->HasChannels() && !transport->writable()) { 565 signaling_thread_->PostDelayed( 566 session_manager_->session_timeout() * 1000, this, MSG_TIMEOUT); 567 } 568 } 569 570 void Session::OnTransportRequestSignaling(Transport* transport) { 571 ASSERT(signaling_thread_->IsCurrent()); 572 SignalRequestSignaling(this); 573 } 574 575 void Session::OnTransportCandidatesReady(Transport* transport, 576 const Candidates& candidates) { 577 ASSERT(signaling_thread_->IsCurrent()); 578 TransportProxy* transproxy = GetTransportProxy(transport); 579 if (transproxy != NULL) { 580 if (!transproxy->negotiated()) { 581 transproxy->AddSentCandidates(candidates); 582 } 583 SessionError error; 584 if (!SendTransportInfoMessage( 585 TransportInfo(transproxy->content_name(), transproxy->type(), 586 candidates), 587 &error)) { 588 LOG(LS_ERROR) << "Could not send transport info message: " 589 << error.text; 590 return; 591 } 592 } 593 } 594 595 void Session::OnTransportSendError(Transport* transport, 596 const buzz::XmlElement* stanza, 597 const buzz::QName& name, 598 const std::string& type, 599 const std::string& text, 600 const buzz::XmlElement* extra_info) { 601 ASSERT(signaling_thread_->IsCurrent()); 602 SignalErrorMessage(this, stanza, name, type, text, extra_info); 603 } 604 605 void Session::OnTransportChannelGone(Transport* transport, 606 const std::string& name) { 607 ASSERT(signaling_thread_->IsCurrent()); 608 SignalChannelGone(this, name); 609 } 610 611 void Session::OnIncomingMessage(const SessionMessage& msg) { 612 ASSERT(signaling_thread_->IsCurrent()); 613 ASSERT(state_ == STATE_INIT || msg.from == remote_name_); 614 615 if (current_protocol_== PROTOCOL_HYBRID) { 616 if (msg.protocol == PROTOCOL_GINGLE) { 617 current_protocol_ = PROTOCOL_GINGLE; 618 } else { 619 current_protocol_ = PROTOCOL_JINGLE; 620 } 621 } 622 623 bool valid = false; 624 MessageError error; 625 switch (msg.type) { 626 case ACTION_SESSION_INITIATE: 627 valid = OnInitiateMessage(msg, &error); 628 break; 629 case ACTION_SESSION_INFO: 630 valid = OnInfoMessage(msg); 631 break; 632 case ACTION_SESSION_ACCEPT: 633 valid = OnAcceptMessage(msg, &error); 634 break; 635 case ACTION_SESSION_REJECT: 636 valid = OnRejectMessage(msg, &error); 637 break; 638 case ACTION_SESSION_TERMINATE: 639 valid = OnTerminateMessage(msg, &error); 640 break; 641 case ACTION_TRANSPORT_INFO: 642 valid = OnTransportInfoMessage(msg, &error); 643 break; 644 case ACTION_TRANSPORT_ACCEPT: 645 valid = OnTransportAcceptMessage(msg, &error); 646 break; 647 case ACTION_NOTIFY: 648 valid = OnNotifyMessage(msg, &error); 649 break; 650 case ACTION_UPDATE: 651 valid = OnUpdateMessage(msg, &error); 652 break; 653 default: 654 valid = BadMessage(buzz::QN_STANZA_BAD_REQUEST, 655 "unknown session message type", 656 &error); 657 } 658 659 if (valid) { 660 SendAcknowledgementMessage(msg.stanza); 661 } else { 662 SignalErrorMessage(this, msg.stanza, error.type, 663 "modify", error.text, NULL); 664 } 665 } 666 667 void Session::OnFailedSend(const buzz::XmlElement* orig_stanza, 668 const buzz::XmlElement* error_stanza) { 669 ASSERT(signaling_thread_->IsCurrent()); 670 671 SessionMessage msg; 672 ParseError parse_error; 673 if (!ParseSessionMessage(orig_stanza, &msg, &parse_error)) { 674 LOG(LS_ERROR) << "Error parsing failed send: " << parse_error.text 675 << ":" << orig_stanza; 676 return; 677 } 678 679 // If the error is a session redirect, call OnRedirectError, which will 680 // continue the session with a new remote JID. 681 SessionRedirect redirect; 682 if (FindSessionRedirect(error_stanza, &redirect)) { 683 SessionError error; 684 if (!OnRedirectError(redirect, &error)) { 685 // TODO: Should we send a message back? The standard 686 // says nothing about it. 687 LOG(LS_ERROR) << "Failed to redirect: " << error.text; 688 SetError(ERROR_RESPONSE); 689 } 690 return; 691 } 692 693 std::string error_type = "cancel"; 694 695 const buzz::XmlElement* error = error_stanza->FirstNamed(buzz::QN_ERROR); 696 if (error) { 697 ASSERT(error->HasAttr(buzz::QN_TYPE)); 698 error_type = error->Attr(buzz::QN_TYPE); 699 700 LOG(LS_ERROR) << "Session error:\n" << error->Str() << "\n" 701 << "in response to:\n" << orig_stanza->Str(); 702 } else { 703 // don't crash if <error> is missing 704 LOG(LS_ERROR) << "Session error without <error/> element, ignoring"; 705 return; 706 } 707 708 if (msg.type == ACTION_TRANSPORT_INFO) { 709 // Transport messages frequently generate errors because they are sent right 710 // when we detect a network failure. For that reason, we ignore such 711 // errors, because if we do not establish writability again, we will 712 // terminate anyway. The exceptions are transport-specific error tags, 713 // which we pass on to the respective transport. 714 715 // TODO: This is only used for unknown channel name. 716 // For Jingle, find a stanard-compliant way of doing this. For 717 // Gingle, guess the content name based on the channel name. 718 for (const buzz::XmlElement* elem = error->FirstElement(); 719 NULL != elem; elem = elem->NextElement()) { 720 TransportProxy* transproxy = GetFirstTransportProxy(); 721 if (transproxy && transproxy->type() == error->Name().Namespace()) { 722 transproxy->impl()->OnTransportError(elem); 723 } 724 } 725 } else if ((error_type != "continue") && (error_type != "wait")) { 726 // We do not set an error if the other side said it is okay to continue 727 // (possibly after waiting). These errors can be ignored. 728 SetError(ERROR_RESPONSE); 729 } 730 } 731 732 bool Session::OnInitiateMessage(const SessionMessage& msg, 733 MessageError* error) { 734 if (!CheckState(STATE_INIT, error)) 735 return false; 736 737 SessionInitiate init; 738 if (!ParseSessionInitiate(msg.protocol, msg.action_elem, 739 GetContentParsers(), GetTransportParsers(), 740 &init, error)) 741 return false; 742 743 SessionError session_error; 744 if (!CreateTransportProxies(init.transports, &session_error)) { 745 return BadMessage(buzz::QN_STANZA_NOT_ACCEPTABLE, 746 session_error.text, error); 747 } 748 749 initiator_ = false; 750 remote_name_ = msg.from; 751 set_remote_description(new SessionDescription(init.ClearContents())); 752 SetState(STATE_RECEIVEDINITIATE); 753 754 // Users of Session may listen to state change and call Reject(). 755 if (state_ != STATE_SENTREJECT) { 756 if (!OnRemoteCandidates(init.transports, error)) 757 return false; 758 } 759 return true; 760 } 761 762 bool Session::OnAcceptMessage(const SessionMessage& msg, MessageError* error) { 763 if (!CheckState(STATE_SENTINITIATE, error)) 764 return false; 765 766 SessionAccept accept; 767 if (!ParseSessionAccept(msg.protocol, msg.action_elem, 768 GetContentParsers(), GetTransportParsers(), 769 &accept, error)) 770 return false; 771 772 set_remote_description(new SessionDescription(accept.ClearContents())); 773 SetState(STATE_RECEIVEDACCEPT); 774 775 // Users of Session may listen to state change and call Reject(). 776 if (state_ != STATE_SENTREJECT) { 777 if (!OnRemoteCandidates(accept.transports, error)) 778 return false; 779 } 780 781 return true; 782 } 783 784 bool Session::OnRejectMessage(const SessionMessage& msg, MessageError* error) { 785 if (!CheckState(STATE_SENTINITIATE, error)) 786 return false; 787 788 SetState(STATE_RECEIVEDREJECT); 789 return true; 790 } 791 792 // Only used by app/win32/fileshare.cc. 793 bool Session::OnInfoMessage(const SessionMessage& msg) { 794 SignalInfoMessage(this, CopyOfXmlChildren(msg.action_elem)); 795 return true; 796 } 797 798 bool Session::OnTerminateMessage(const SessionMessage& msg, 799 MessageError* error) { 800 SessionTerminate term; 801 if (!ParseSessionTerminate(msg.protocol, msg.action_elem, &term, error)) 802 return false; 803 804 SignalReceivedTerminateReason(this, term.reason); 805 if (term.debug_reason != buzz::STR_EMPTY) { 806 LOG(LS_VERBOSE) << "Received error on call: " << term.debug_reason; 807 } 808 809 SetState(STATE_RECEIVEDTERMINATE); 810 return true; 811 } 812 813 bool Session::OnTransportInfoMessage(const SessionMessage& msg, 814 MessageError* error) { 815 TransportInfos tinfos; 816 if (!ParseTransportInfos(msg.protocol, msg.action_elem, 817 initiator_description()->contents(), 818 GetTransportParsers(), &tinfos, error)) 819 return false; 820 821 if (!OnRemoteCandidates(tinfos, error)) 822 return false; 823 824 return true; 825 } 826 827 bool Session::OnTransportAcceptMessage(const SessionMessage& msg, 828 MessageError* error) { 829 // TODO: Currently here only for compatibility with 830 // Gingle 1.1 clients (notably, Google Voice). 831 return true; 832 } 833 834 bool Session::OnNotifyMessage(const SessionMessage& msg, 835 MessageError* error) { 836 SessionNotify notify; 837 if (!ParseSessionNotify(msg.action_elem, ¬ify, error)) { 838 return false; 839 } 840 841 SignalMediaSources(notify.nickname_to_sources); 842 843 return true; 844 } 845 846 bool Session::OnUpdateMessage(const SessionMessage& msg, 847 MessageError* error) { 848 SessionUpdate update; 849 if (!ParseSessionUpdate(msg.action_elem, &update, error)) { 850 return false; 851 } 852 853 // TODO: Process this message appropriately. 854 855 return true; 856 } 857 858 bool BareJidsEqual(const std::string& name1, 859 const std::string& name2) { 860 buzz::Jid jid1(name1); 861 buzz::Jid jid2(name2); 862 863 return jid1.IsValid() && jid2.IsValid() && jid1.BareEquals(jid2); 864 } 865 866 bool Session::OnRedirectError(const SessionRedirect& redirect, 867 SessionError* error) { 868 MessageError message_error; 869 if (!CheckState(STATE_SENTINITIATE, &message_error)) { 870 return BadWrite(message_error.text, error); 871 } 872 873 if (!BareJidsEqual(remote_name_, redirect.target)) 874 return BadWrite("Redirection not allowed: must be the same bare jid.", 875 error); 876 877 // When we receive a redirect, we point the session at the new JID 878 // and resend the candidates. 879 remote_name_ = redirect.target; 880 return (SendInitiateMessage(local_description(), error) && 881 ResendAllTransportInfoMessages(error)); 882 } 883 884 bool Session::CheckState(State state, MessageError* error) { 885 ASSERT(state_ == state); 886 if (state_ != state) { 887 return BadMessage(buzz::QN_STANZA_NOT_ALLOWED, 888 "message not allowed in current state", 889 error); 890 } 891 return true; 892 } 893 894 void Session::SetError(Error error) { 895 BaseSession::SetError(error); 896 if (error_ != ERROR_NONE) 897 signaling_thread_->Post(this, MSG_ERROR); 898 } 899 900 void Session::OnMessage(talk_base::Message *pmsg) { 901 // preserve this because BaseSession::OnMessage may modify it 902 BaseSession::State orig_state = state_; 903 904 BaseSession::OnMessage(pmsg); 905 906 switch (pmsg->message_id) { 907 case MSG_STATE: 908 switch (orig_state) { 909 case STATE_SENTTERMINATE: 910 case STATE_RECEIVEDTERMINATE: 911 session_manager_->DestroySession(this); 912 break; 913 914 default: 915 // Explicitly ignoring some states here. 916 break; 917 } 918 break; 919 } 920 } 921 922 bool Session::SendInitiateMessage(const SessionDescription* sdesc, 923 SessionError* error) { 924 SessionInitiate init; 925 init.contents = sdesc->contents(); 926 init.transports = GetEmptyTransportInfos(init.contents); 927 return SendMessage(ACTION_SESSION_INITIATE, init, error); 928 } 929 930 bool Session::WriteSessionAction( 931 SignalingProtocol protocol, const SessionInitiate& init, 932 XmlElements* elems, WriteError* error) { 933 ContentParserMap content_parsers = GetContentParsers(); 934 TransportParserMap trans_parsers = GetTransportParsers(); 935 936 return WriteSessionInitiate(protocol, init.contents, init.transports, 937 content_parsers, trans_parsers, 938 elems, error); 939 } 940 941 bool Session::SetVideoView( 942 const std::vector<VideoViewRequest>& view_requests) { 943 SessionView view; 944 SessionError error; 945 946 view.view_requests = view_requests; 947 948 return !SendViewMessage(view, &error); 949 } 950 951 bool Session::SendAcceptMessage(const SessionDescription* sdesc, 952 SessionError* error) { 953 XmlElements elems; 954 if (!WriteSessionAccept(current_protocol_, 955 sdesc->contents(), 956 GetEmptyTransportInfos(sdesc->contents()), 957 GetContentParsers(), GetTransportParsers(), 958 &elems, error)) { 959 return false; 960 } 961 return SendMessage(ACTION_SESSION_ACCEPT, elems, error); 962 } 963 964 bool Session::SendRejectMessage(const std::string& reason, 965 SessionError* error) { 966 XmlElements elems; 967 return SendMessage(ACTION_SESSION_REJECT, elems, error); 968 } 969 970 971 bool Session::SendTerminateMessage(const std::string& reason, 972 SessionError* error) { 973 SessionTerminate term(reason); 974 return SendMessage(ACTION_SESSION_TERMINATE, term, error); 975 } 976 977 bool Session::WriteSessionAction(SignalingProtocol protocol, 978 const SessionTerminate& term, 979 XmlElements* elems, WriteError* error) { 980 WriteSessionTerminate(protocol, term, elems); 981 return true; 982 } 983 984 bool Session::SendTransportInfoMessage(const TransportInfo& tinfo, 985 SessionError* error) { 986 return SendMessage(ACTION_TRANSPORT_INFO, tinfo, error); 987 } 988 989 bool Session::WriteSessionAction(SignalingProtocol protocol, 990 const TransportInfo& tinfo, 991 XmlElements* elems, WriteError* error) { 992 TransportInfos tinfos; 993 tinfos.push_back(tinfo); 994 TransportParserMap parsers = GetTransportParsers(); 995 996 return WriteTransportInfos(protocol, tinfos, parsers, 997 elems, error); 998 } 999 1000 bool Session::SendViewMessage(const SessionView& view, SessionError* error) { 1001 XmlElements elems; 1002 WriteSessionView(view, &elems); 1003 return SendMessage(ACTION_VIEW, elems, error); 1004 } 1005 1006 bool Session::ResendAllTransportInfoMessages(SessionError* error) { 1007 for (TransportMap::iterator iter = transports_.begin(); 1008 iter != transports_.end(); ++iter) { 1009 TransportProxy* transproxy = iter->second; 1010 if (transproxy->sent_candidates().size() > 0) { 1011 if (!SendTransportInfoMessage( 1012 TransportInfo( 1013 transproxy->content_name(), 1014 transproxy->type(), 1015 transproxy->sent_candidates()), 1016 error)) { 1017 return false; 1018 } 1019 transproxy->ClearSentCandidates(); 1020 } 1021 } 1022 return true; 1023 } 1024 1025 bool Session::SendMessage(ActionType type, const XmlElements& action_elems, 1026 SessionError* error) { 1027 talk_base::scoped_ptr<buzz::XmlElement> stanza( 1028 new buzz::XmlElement(buzz::QN_IQ)); 1029 1030 SessionMessage msg(current_protocol_, type, sid_, initiator_name_); 1031 msg.to = remote_name_; 1032 WriteSessionMessage(msg, action_elems, stanza.get()); 1033 1034 SignalOutgoingMessage(this, stanza.get()); 1035 return true; 1036 } 1037 1038 template <typename Action> 1039 bool Session::SendMessage(ActionType type, const Action& action, 1040 SessionError* error) { 1041 talk_base::scoped_ptr<buzz::XmlElement> stanza( 1042 new buzz::XmlElement(buzz::QN_IQ)); 1043 if (!WriteActionMessage(type, action, stanza.get(), error)) 1044 return false; 1045 1046 SignalOutgoingMessage(this, stanza.get()); 1047 return true; 1048 } 1049 1050 template <typename Action> 1051 bool Session::WriteActionMessage(ActionType type, const Action& action, 1052 buzz::XmlElement* stanza, 1053 WriteError* error) { 1054 if (current_protocol_ == PROTOCOL_HYBRID) { 1055 if (!WriteActionMessage(PROTOCOL_JINGLE, type, action, stanza, error)) 1056 return false; 1057 if (!WriteActionMessage(PROTOCOL_GINGLE, type, action, stanza, error)) 1058 return false; 1059 } else { 1060 if (!WriteActionMessage(current_protocol_, type, action, stanza, error)) 1061 return false; 1062 } 1063 return true; 1064 } 1065 1066 template <typename Action> 1067 bool Session::WriteActionMessage(SignalingProtocol protocol, 1068 ActionType type, const Action& action, 1069 buzz::XmlElement* stanza, WriteError* error) { 1070 XmlElements action_elems; 1071 if (!WriteSessionAction(protocol, action, &action_elems, error)) 1072 return false; 1073 1074 SessionMessage msg(protocol, type, sid_, initiator_name_); 1075 msg.to = remote_name_; 1076 1077 WriteSessionMessage(msg, action_elems, stanza); 1078 return true; 1079 } 1080 1081 void Session::SendAcknowledgementMessage(const buzz::XmlElement* stanza) { 1082 talk_base::scoped_ptr<buzz::XmlElement> ack( 1083 new buzz::XmlElement(buzz::QN_IQ)); 1084 ack->SetAttr(buzz::QN_TO, remote_name_); 1085 ack->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID)); 1086 ack->SetAttr(buzz::QN_TYPE, "result"); 1087 1088 SignalOutgoingMessage(this, ack.get()); 1089 } 1090 1091 } // namespace cricket 1092