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