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#ifndef TALK_P2P_BASE_SESSION_H_ 29#define TALK_P2P_BASE_SESSION_H_ 30 31#include <list> 32#include <map> 33#include <string> 34#include <vector> 35 36#include "talk/base/refcount.h" 37#include "talk/base/scoped_ptr.h" 38#include "talk/base/scoped_ref_ptr.h" 39#include "talk/base/socketaddress.h" 40#include "talk/p2p/base/parsing.h" 41#include "talk/p2p/base/port.h" 42#include "talk/p2p/base/sessionclient.h" 43#include "talk/p2p/base/sessionmanager.h" 44#include "talk/p2p/base/sessionmessages.h" 45#include "talk/p2p/base/transport.h" 46#include "talk/xmllite/xmlelement.h" 47#include "talk/xmpp/constants.h" 48 49namespace cricket { 50 51class BaseSession; 52class P2PTransportChannel; 53class Transport; 54class TransportChannel; 55class TransportChannelProxy; 56class TransportChannelImpl; 57 58typedef talk_base::RefCountedObject<talk_base::scoped_ptr<Transport> > 59TransportWrapper; 60 61// Used for errors that will send back a specific error message to the 62// remote peer. We add "type" to the errors because it's needed for 63// SignalErrorMessage. 64struct MessageError : ParseError { 65 buzz::QName type; 66 67 // if unset, assume type is a parse error 68 MessageError() : ParseError(), type(buzz::QN_STANZA_BAD_REQUEST) {} 69 70 void SetType(const buzz::QName type) { 71 this->type = type; 72 } 73}; 74 75// Used for errors that may be returned by public session methods that 76// can fail. 77// TODO: Use this error in Session::Initiate and 78// Session::Accept. 79struct SessionError : WriteError { 80}; 81 82// Bundles a Transport and ChannelMap together. ChannelMap is used to 83// create transport channels before receiving or sending a session 84// initiate, and for speculatively connecting channels. Previously, a 85// session had one ChannelMap and transport. Now, with multiple 86// transports per session, we need multiple ChannelMaps as well. 87 88typedef std::map<int, TransportChannelProxy*> ChannelMap; 89 90class TransportProxy : public sigslot::has_slots<>, 91 public CandidateTranslator { 92 public: 93 TransportProxy( 94 const std::string& sid, 95 const std::string& content_name, 96 TransportWrapper* transport) 97 : sid_(sid), 98 content_name_(content_name), 99 transport_(transport), 100 connecting_(false), 101 negotiated_(false), 102 sent_candidates_(false), 103 candidates_allocated_(false) { 104 transport_->get()->SignalCandidatesReady.connect( 105 this, &TransportProxy::OnTransportCandidatesReady); 106 } 107 ~TransportProxy(); 108 109 std::string content_name() const { return content_name_; } 110 // TODO(juberti): It's not good form to expose the object you're wrapping, 111 // since callers can mutate it. Can we make this return a const Transport*? 112 Transport* impl() const { return transport_->get(); } 113 114 std::string type() const; 115 bool negotiated() const { return negotiated_; } 116 const Candidates& sent_candidates() const { return sent_candidates_; } 117 const Candidates& unsent_candidates() const { return unsent_candidates_; } 118 bool candidates_allocated() const { return candidates_allocated_; } 119 void set_candidates_allocated(bool allocated) { 120 candidates_allocated_ = allocated; 121 } 122 123 TransportChannel* GetChannel(int component); 124 TransportChannel* CreateChannel(const std::string& channel_name, 125 int component); 126 bool HasChannel(int component); 127 void DestroyChannel(int component); 128 129 void AddSentCandidates(const Candidates& candidates); 130 void AddUnsentCandidates(const Candidates& candidates); 131 void ClearSentCandidates() { sent_candidates_.clear(); } 132 void ClearUnsentCandidates() { unsent_candidates_.clear(); } 133 134 // Start the connection process for any channels, creating impls if needed. 135 void ConnectChannels(); 136 // Hook up impls to the proxy channels. Doesn't change connect state. 137 void CompleteNegotiation(); 138 139 // Mux this proxy onto the specified proxy's transport. 140 bool SetupMux(TransportProxy* proxy); 141 142 // Simple functions that thunk down to the same functions on Transport. 143 void SetIceRole(IceRole role); 144 void SetIdentity(talk_base::SSLIdentity* identity); 145 bool SetLocalTransportDescription(const TransportDescription& description, 146 ContentAction action); 147 bool SetRemoteTransportDescription(const TransportDescription& description, 148 ContentAction action); 149 void OnSignalingReady(); 150 bool OnRemoteCandidates(const Candidates& candidates, std::string* error); 151 152 // CandidateTranslator methods. 153 virtual bool GetChannelNameFromComponent( 154 int component, std::string* channel_name) const; 155 virtual bool GetComponentFromChannelName( 156 const std::string& channel_name, int* component) const; 157 158 // Called when a transport signals that it has new candidates. 159 void OnTransportCandidatesReady(cricket::Transport* transport, 160 const Candidates& candidates) { 161 SignalCandidatesReady(this, candidates); 162 } 163 164 // Handles sending of ready candidates and receiving of remote candidates. 165 sigslot::signal2<TransportProxy*, 166 const std::vector<Candidate>&> SignalCandidatesReady; 167 168 private: 169 TransportChannelProxy* GetChannelProxy(int component) const; 170 TransportChannelProxy* GetChannelProxyByName(const std::string& name) const; 171 void ReplaceChannelProxyImpl(TransportChannelProxy* channel_proxy, 172 size_t index); 173 TransportChannelImpl* GetOrCreateChannelProxyImpl(int component); 174 void SetChannelProxyImpl(int component, 175 TransportChannelProxy* proxy); 176 177 std::string sid_; 178 std::string content_name_; 179 talk_base::scoped_refptr<TransportWrapper> transport_; 180 bool connecting_; 181 bool negotiated_; 182 ChannelMap channels_; 183 Candidates sent_candidates_; 184 Candidates unsent_candidates_; 185 bool candidates_allocated_; 186}; 187 188typedef std::map<std::string, TransportProxy*> TransportMap; 189 190// Statistics for all the transports of this session. 191typedef std::map<std::string, TransportStats> TransportStatsMap; 192typedef std::map<std::string, std::string> ProxyTransportMap; 193 194struct SessionStats { 195 ProxyTransportMap proxy_to_transport; 196 TransportStatsMap transport_stats; 197}; 198 199// A BaseSession manages general session state. This includes negotiation 200// of both the application-level and network-level protocols: the former 201// defines what will be sent and the latter defines how it will be sent. Each 202// network-level protocol is represented by a Transport object. Each Transport 203// participates in the network-level negotiation. The individual streams of 204// packets are represented by TransportChannels. The application-level protocol 205// is represented by SessionDecription objects. 206class BaseSession : public sigslot::has_slots<>, 207 public talk_base::MessageHandler { 208 public: 209 enum { 210 MSG_TIMEOUT = 0, 211 MSG_ERROR, 212 MSG_STATE, 213 }; 214 215 enum State { 216 STATE_INIT = 0, 217 STATE_SENTINITIATE, // sent initiate, waiting for Accept or Reject 218 STATE_RECEIVEDINITIATE, // received an initiate. Call Accept or Reject 219 STATE_SENTPRACCEPT, // sent provisional Accept 220 STATE_SENTACCEPT, // sent accept. begin connecting transport 221 STATE_RECEIVEDPRACCEPT, // received provisional Accept, waiting for Accept 222 STATE_RECEIVEDACCEPT, // received accept. begin connecting transport 223 STATE_SENTMODIFY, // sent modify, waiting for Accept or Reject 224 STATE_RECEIVEDMODIFY, // received modify, call Accept or Reject 225 STATE_SENTREJECT, // sent reject after receiving initiate 226 STATE_RECEIVEDREJECT, // received reject after sending initiate 227 STATE_SENTREDIRECT, // sent direct after receiving initiate 228 STATE_SENTTERMINATE, // sent terminate (any time / either side) 229 STATE_RECEIVEDTERMINATE, // received terminate (any time / either side) 230 STATE_INPROGRESS, // session accepted and in progress 231 STATE_DEINIT, // session is being destroyed 232 }; 233 234 enum Error { 235 ERROR_NONE = 0, // no error 236 ERROR_TIME = 1, // no response to signaling 237 ERROR_RESPONSE = 2, // error during signaling 238 ERROR_NETWORK = 3, // network error, could not allocate network resources 239 ERROR_CONTENT = 4, // channel errors in SetLocalContent/SetRemoteContent 240 ERROR_TRANSPORT = 5, // transport error of some kind 241 }; 242 243 // Convert State to a readable string. 244 static std::string StateToString(State state); 245 246 BaseSession(talk_base::Thread* signaling_thread, 247 talk_base::Thread* worker_thread, 248 PortAllocator* port_allocator, 249 const std::string& sid, 250 const std::string& content_type, 251 bool initiator); 252 virtual ~BaseSession(); 253 254 talk_base::Thread* signaling_thread() { return signaling_thread_; } 255 talk_base::Thread* worker_thread() { return worker_thread_; } 256 PortAllocator* port_allocator() { return port_allocator_; } 257 258 // The ID of this session. 259 const std::string& id() const { return sid_; } 260 261 // TODO(juberti): This data is largely redundant, as it can now be obtained 262 // from local/remote_description(). Remove these functions and members. 263 // Returns the XML namespace identifying the type of this session. 264 const std::string& content_type() const { return content_type_; } 265 // Returns the XML namespace identifying the transport used for this session. 266 const std::string& transport_type() const { return transport_type_; } 267 268 // Indicates whether we initiated this session. 269 bool initiator() const { return initiator_; } 270 271 // Returns the application-level description given by our client. 272 // If we are the recipient, this will be NULL until we send an accept. 273 const SessionDescription* local_description() const { 274 return local_description_; 275 } 276 // Returns the application-level description given by the other client. 277 // If we are the initiator, this will be NULL until we receive an accept. 278 const SessionDescription* remote_description() const { 279 return remote_description_; 280 } 281 SessionDescription* remote_description() { 282 return remote_description_; 283 } 284 285 // Takes ownership of SessionDescription* 286 bool set_local_description(const SessionDescription* sdesc) { 287 if (sdesc != local_description_) { 288 delete local_description_; 289 local_description_ = sdesc; 290 } 291 return true; 292 } 293 294 // Takes ownership of SessionDescription* 295 bool set_remote_description(SessionDescription* sdesc) { 296 if (sdesc != remote_description_) { 297 delete remote_description_; 298 remote_description_ = sdesc; 299 } 300 return true; 301 } 302 303 const SessionDescription* initiator_description() const { 304 if (initiator_) { 305 return local_description_; 306 } else { 307 return remote_description_; 308 } 309 } 310 311 // Returns the current state of the session. See the enum above for details. 312 // Each time the state changes, we will fire this signal. 313 State state() const { return state_; } 314 sigslot::signal2<BaseSession* , State> SignalState; 315 316 // Returns the last error in the session. See the enum above for details. 317 // Each time the an error occurs, we will fire this signal. 318 Error error() const { return error_; } 319 sigslot::signal2<BaseSession* , Error> SignalError; 320 321 // Updates the state, signaling if necessary. 322 virtual void SetState(State state); 323 324 // Updates the error state, signaling if necessary. 325 virtual void SetError(Error error); 326 327 // Fired when the remote description is updated, with the updated 328 // contents. 329 sigslot::signal2<BaseSession* , const ContentInfos&> 330 SignalRemoteDescriptionUpdate; 331 332 // Fired when SetState is called (regardless if there's a state change), which 333 // indicates the session description might have be updated. 334 sigslot::signal2<BaseSession*, ContentAction> SignalNewLocalDescription; 335 336 // Fired when SetState is called (regardless if there's a state change), which 337 // indicates the session description might have be updated. 338 sigslot::signal2<BaseSession*, ContentAction> SignalNewRemoteDescription; 339 340 // Returns the transport that has been negotiated or NULL if 341 // negotiation is still in progress. 342 Transport* GetTransport(const std::string& content_name); 343 344 // Creates a new channel with the given names. This method may be called 345 // immediately after creating the session. However, the actual 346 // implementation may not be fixed until transport negotiation completes. 347 // This will usually be called from the worker thread, but that 348 // shouldn't be an issue since the main thread will be blocked in 349 // Send when doing so. 350 virtual TransportChannel* CreateChannel(const std::string& content_name, 351 const std::string& channel_name, 352 int component); 353 354 // Returns the channel with the given names. 355 virtual TransportChannel* GetChannel(const std::string& content_name, 356 int component); 357 358 // Destroys the channel with the given names. 359 // This will usually be called from the worker thread, but that 360 // shouldn't be an issue since the main thread will be blocked in 361 // Send when doing so. 362 virtual void DestroyChannel(const std::string& content_name, 363 int component); 364 365 // Returns stats for all channels of all transports. 366 // This avoids exposing the internal structures used to track them. 367 virtual bool GetStats(SessionStats* stats); 368 369 talk_base::SSLIdentity* identity() { return identity_; } 370 371 protected: 372 // Specifies the identity to use in this session. 373 bool SetIdentity(talk_base::SSLIdentity* identity); 374 375 bool PushdownTransportDescription(ContentSource source, 376 ContentAction action); 377 void set_initiator(bool initiator) { initiator_ = initiator; } 378 379 const TransportMap& transport_proxies() const { return transports_; } 380 // Get a TransportProxy by content_name or transport. NULL if not found. 381 TransportProxy* GetTransportProxy(const std::string& content_name); 382 TransportProxy* GetTransportProxy(const Transport* transport); 383 TransportProxy* GetFirstTransportProxy(); 384 void DestroyTransportProxy(const std::string& content_name); 385 // TransportProxy is owned by session. Return proxy just for convenience. 386 TransportProxy* GetOrCreateTransportProxy(const std::string& content_name); 387 // Creates the actual transport object. Overridable for testing. 388 virtual Transport* CreateTransport(const std::string& content_name); 389 390 void OnSignalingReady(); 391 void SpeculativelyConnectAllTransportChannels(); 392 // Helper method to provide remote candidates to the transport. 393 bool OnRemoteCandidates(const std::string& content_name, 394 const Candidates& candidates, 395 std::string* error); 396 397 // This method will mux transport channels by content_name. 398 // First content is used for muxing. 399 bool MaybeEnableMuxingSupport(); 400 401 // Called when a transport requests signaling. 402 virtual void OnTransportRequestSignaling(Transport* transport) { 403 } 404 405 // Called when the first channel of a transport begins connecting. We use 406 // this to start a timer, to make sure that the connection completes in a 407 // reasonable amount of time. 408 virtual void OnTransportConnecting(Transport* transport) { 409 } 410 411 // Called when a transport changes its writable state. We track this to make 412 // sure that the transport becomes writable within a reasonable amount of 413 // time. If this does not occur, we signal an error. 414 virtual void OnTransportWritable(Transport* transport) { 415 } 416 virtual void OnTransportReadable(Transport* transport) { 417 } 418 419 // Called when a transport signals that it has new candidates. 420 virtual void OnTransportProxyCandidatesReady(TransportProxy* proxy, 421 const Candidates& candidates) { 422 } 423 424 // Called when a transport signals that it found an error in an incoming 425 // message. 426 virtual void OnTransportSendError(Transport* transport, 427 const buzz::XmlElement* stanza, 428 const buzz::QName& name, 429 const std::string& type, 430 const std::string& text, 431 const buzz::XmlElement* extra_info) { 432 } 433 434 virtual void OnTransportRouteChange( 435 Transport* transport, 436 int component, 437 const cricket::Candidate& remote_candidate) { 438 } 439 440 virtual void OnTransportCandidatesAllocationDone(Transport* transport); 441 442 // Called when all transport channels allocated required candidates. 443 // This method should be used as an indication of candidates gathering process 444 // is completed and application can now send local candidates list to remote. 445 virtual void OnCandidatesAllocationDone() { 446 } 447 448 // Handles the ice role change callback from Transport. This must be 449 // propagated to all the transports. 450 virtual void OnRoleConflict(); 451 452 // Handles messages posted to us. 453 virtual void OnMessage(talk_base::Message *pmsg); 454 455 protected: 456 State state_; 457 Error error_; 458 459 private: 460 // Helper methods to push local and remote transport descriptions. 461 bool PushdownLocalTransportDescription( 462 const SessionDescription* sdesc, ContentAction action); 463 bool PushdownRemoteTransportDescription( 464 const SessionDescription* sdesc, ContentAction action); 465 466 bool IsCandidateAllocationDone() const; 467 void MaybeCandidateAllocationDone(); 468 469 // This method will delete the Transport and TransportChannelImpls and 470 // replace those with the selected Transport objects. Selection is done 471 // based on the content_name and in this case first MediaContent information 472 // is used for mux. 473 bool SetSelectedProxy(const std::string& content_name, 474 const ContentGroup* muxed_group); 475 // Log session state. 476 void LogState(State old_state, State new_state); 477 478 // Returns true and the TransportInfo of the given |content_name| 479 // from |description|. Returns false if it's not available. 480 bool GetTransportDescription(const SessionDescription* description, 481 const std::string& content_name, 482 TransportDescription* info); 483 484 // Fires the new description signal according to the current state. 485 void SignalNewDescription(); 486 487 // Gets the ContentAction and ContentSource according to the session state. 488 bool GetContentAction(ContentAction* action, ContentSource* source); 489 490 talk_base::Thread* signaling_thread_; 491 talk_base::Thread* worker_thread_; 492 PortAllocator* port_allocator_; 493 std::string sid_; 494 std::string content_type_; 495 std::string transport_type_; 496 bool initiator_; 497 talk_base::SSLIdentity* identity_; 498 const SessionDescription* local_description_; 499 SessionDescription* remote_description_; 500 uint64 ice_tiebreaker_; 501 // This flag will be set to true after the first role switch. This flag 502 // will enable us to stop any role switch during the call. 503 bool role_switch_; 504 TransportMap transports_; 505}; 506 507// A specific Session created by the SessionManager, using XMPP for protocol. 508class Session : public BaseSession { 509 public: 510 // Returns the manager that created and owns this session. 511 SessionManager* session_manager() const { return session_manager_; } 512 513 // Returns the client that is handling the application data of this session. 514 SessionClient* client() const { return client_; } 515 516 // Returns the JID of this client. 517 const std::string& local_name() const { return local_name_; } 518 519 // Returns the JID of the other peer in this session. 520 const std::string& remote_name() const { return remote_name_; } 521 522 // Set the JID of the other peer in this session. 523 // Typically the remote_name_ is set when the session is initiated. 524 // However, sometimes (e.g when a proxy is used) the peer name is 525 // known after the BaseSession has been initiated and it must be updated 526 // explicitly. 527 void set_remote_name(const std::string& name) { remote_name_ = name; } 528 529 // Set the JID of the initiator of this session. Allows for the overriding 530 // of the initiator to be a third-party, eg. the MUC JID when creating p2p 531 // sessions. 532 void set_initiator_name(const std::string& name) { initiator_name_ = name; } 533 534 // Indicates the JID of the entity who initiated this session. 535 // In special cases, may be different than both local_name and remote_name. 536 const std::string& initiator_name() const { return initiator_name_; } 537 538 SignalingProtocol current_protocol() const { return current_protocol_; } 539 540 void set_current_protocol(SignalingProtocol protocol) { 541 current_protocol_ = protocol; 542 } 543 544 // Updates the error state, signaling if necessary. 545 virtual void SetError(Error error); 546 547 // When the session needs to send signaling messages, it beings by requesting 548 // signaling. The client should handle this by calling OnSignalingReady once 549 // it is ready to send the messages. 550 // (These are called only by SessionManager.) 551 sigslot::signal1<Session*> SignalRequestSignaling; 552 void OnSignalingReady() { BaseSession::OnSignalingReady(); } 553 554 // Takes ownership of session description. 555 // TODO: Add an error argument to pass back to the caller. 556 bool Initiate(const std::string& to, 557 const SessionDescription* sdesc); 558 559 // When we receive an initiate, we create a session in the 560 // RECEIVEDINITIATE state and respond by accepting or rejecting. 561 // Takes ownership of session description. 562 // TODO: Add an error argument to pass back to the caller. 563 bool Accept(const SessionDescription* sdesc); 564 bool Reject(const std::string& reason); 565 bool Terminate() { 566 return TerminateWithReason(STR_TERMINATE_SUCCESS); 567 } 568 bool TerminateWithReason(const std::string& reason); 569 // Fired whenever we receive a terminate message along with a reason 570 sigslot::signal2<Session*, const std::string&> SignalReceivedTerminateReason; 571 572 // The two clients in the session may also send one another 573 // arbitrary XML messages, which are called "info" messages. Sending 574 // takes ownership of the given elements. The signal does not; the 575 // parent element will be deleted after the signal. 576 bool SendInfoMessage(const XmlElements& elems); 577 bool SendDescriptionInfoMessage(const ContentInfos& contents); 578 sigslot::signal2<Session*, const buzz::XmlElement*> SignalInfoMessage; 579 580 private: 581 // Creates or destroys a session. (These are called only SessionManager.) 582 Session(SessionManager *session_manager, 583 const std::string& local_name, const std::string& initiator_name, 584 const std::string& sid, const std::string& content_type, 585 SessionClient* client); 586 ~Session(); 587 // For each transport info, create a transport proxy. Can fail for 588 // incompatible transport types. 589 bool CreateTransportProxies(const TransportInfos& tinfos, 590 SessionError* error); 591 bool OnRemoteCandidates(const TransportInfos& tinfos, 592 ParseError* error); 593 // Returns a TransportInfo without candidates for each content name. 594 // Uses the transport_type_ of the session. 595 TransportInfos GetEmptyTransportInfos(const ContentInfos& contents) const; 596 597 // Maps passed to serialization functions. 598 TransportParserMap GetTransportParsers(); 599 ContentParserMap GetContentParsers(); 600 CandidateTranslatorMap GetCandidateTranslators(); 601 602 virtual void OnTransportRequestSignaling(Transport* transport); 603 virtual void OnTransportConnecting(Transport* transport); 604 virtual void OnTransportWritable(Transport* transport); 605 virtual void OnTransportProxyCandidatesReady(TransportProxy* proxy, 606 const Candidates& candidates); 607 virtual void OnTransportSendError(Transport* transport, 608 const buzz::XmlElement* stanza, 609 const buzz::QName& name, 610 const std::string& type, 611 const std::string& text, 612 const buzz::XmlElement* extra_info); 613 virtual void OnMessage(talk_base::Message *pmsg); 614 615 // Send various kinds of session messages. 616 bool SendInitiateMessage(const SessionDescription* sdesc, 617 SessionError* error); 618 bool SendAcceptMessage(const SessionDescription* sdesc, SessionError* error); 619 bool SendRejectMessage(const std::string& reason, SessionError* error); 620 bool SendTerminateMessage(const std::string& reason, SessionError* error); 621 bool SendTransportInfoMessage(const TransportInfo& tinfo, 622 SessionError* error); 623 bool SendTransportInfoMessage(const TransportProxy* transproxy, 624 const Candidates& candidates, 625 SessionError* error); 626 627 bool ResendAllTransportInfoMessages(SessionError* error); 628 bool SendAllUnsentTransportInfoMessages(SessionError* error); 629 630 // Both versions of SendMessage send a message of the given type to 631 // the other client. Can pass either a set of elements or an 632 // "action", which must have a WriteSessionAction method to go along 633 // with it. Sending with an action supports sending a "hybrid" 634 // message. Sending with elements must be sent as Jingle or Gingle. 635 636 // When passing elems, must be either Jingle or Gingle protocol. 637 // Takes ownership of action_elems. 638 bool SendMessage(ActionType type, const XmlElements& action_elems, 639 SessionError* error); 640 // When passing an action, may be Hybrid protocol. 641 template <typename Action> 642 bool SendMessage(ActionType type, const Action& action, 643 SessionError* error); 644 645 // Helper methods to write the session message stanza. 646 template <typename Action> 647 bool WriteActionMessage(ActionType type, const Action& action, 648 buzz::XmlElement* stanza, WriteError* error); 649 template <typename Action> 650 bool WriteActionMessage(SignalingProtocol protocol, 651 ActionType type, const Action& action, 652 buzz::XmlElement* stanza, WriteError* error); 653 654 // Sending messages in hybrid form requires being able to write them 655 // on a per-protocol basis with a common method signature, which all 656 // of these have. 657 bool WriteSessionAction(SignalingProtocol protocol, 658 const SessionInitiate& init, 659 XmlElements* elems, WriteError* error); 660 bool WriteSessionAction(SignalingProtocol protocol, 661 const TransportInfo& tinfo, 662 XmlElements* elems, WriteError* error); 663 bool WriteSessionAction(SignalingProtocol protocol, 664 const SessionTerminate& term, 665 XmlElements* elems, WriteError* error); 666 667 // Sends a message back to the other client indicating that we have received 668 // and accepted their message. 669 void SendAcknowledgementMessage(const buzz::XmlElement* stanza); 670 671 // Once signaling is ready, the session will use this signal to request the 672 // sending of each message. When messages are received by the other client, 673 // they should be handed to OnIncomingMessage. 674 // (These are called only by SessionManager.) 675 sigslot::signal2<Session* , const buzz::XmlElement*> SignalOutgoingMessage; 676 void OnIncomingMessage(const SessionMessage& msg); 677 678 void OnIncomingResponse(const buzz::XmlElement* orig_stanza, 679 const buzz::XmlElement* response_stanza, 680 const SessionMessage& msg); 681 void OnInitiateAcked(); 682 void OnFailedSend(const buzz::XmlElement* orig_stanza, 683 const buzz::XmlElement* error_stanza); 684 685 // Invoked when an error is found in an incoming message. This is translated 686 // into the appropriate XMPP response by SessionManager. 687 sigslot::signal6<BaseSession*, 688 const buzz::XmlElement*, 689 const buzz::QName&, 690 const std::string&, 691 const std::string&, 692 const buzz::XmlElement*> SignalErrorMessage; 693 694 // Handlers for the various types of messages. These functions may take 695 // pointers to the whole stanza or to just the session element. 696 bool OnInitiateMessage(const SessionMessage& msg, MessageError* error); 697 bool OnAcceptMessage(const SessionMessage& msg, MessageError* error); 698 bool OnRejectMessage(const SessionMessage& msg, MessageError* error); 699 bool OnInfoMessage(const SessionMessage& msg); 700 bool OnTerminateMessage(const SessionMessage& msg, MessageError* error); 701 bool OnTransportInfoMessage(const SessionMessage& msg, MessageError* error); 702 bool OnTransportAcceptMessage(const SessionMessage& msg, MessageError* error); 703 bool OnDescriptionInfoMessage(const SessionMessage& msg, MessageError* error); 704 bool OnRedirectError(const SessionRedirect& redirect, SessionError* error); 705 706 // Verifies that we are in the appropriate state to receive this message. 707 bool CheckState(State state, MessageError* error); 708 709 SessionManager* session_manager_; 710 bool initiate_acked_; 711 std::string local_name_; 712 std::string initiator_name_; 713 std::string remote_name_; 714 SessionClient* client_; 715 TransportParser* transport_parser_; 716 // Keeps track of what protocol we are speaking. 717 SignalingProtocol current_protocol_; 718 719 friend class SessionManager; // For access to constructor, destructor, 720 // and signaling related methods. 721}; 722 723} // namespace cricket 724 725#endif // TALK_P2P_BASE_SESSION_H_ 726