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/p2p/base/sessionmessages.h"
     37 #include "talk/p2p/base/sessionmanager.h"
     38 #include "talk/base/socketaddress.h"
     39 #include "talk/p2p/base/sessionclient.h"
     40 #include "talk/p2p/base/parsing.h"
     41 #include "talk/p2p/base/port.h"
     42 #include "talk/xmllite/xmlelement.h"
     43 #include "talk/xmpp/constants.h"
     44 
     45 namespace cricket {
     46 
     47 class P2PTransportChannel;
     48 class Transport;
     49 class TransportChannel;
     50 class TransportChannelProxy;
     51 class TransportChannelImpl;
     52 
     53 // Used for errors that will send back a specific error message to the
     54 // remote peer.  We add "type" to the errors because it's needed for
     55 // SignalErrorMessage.
     56 struct MessageError : ParseError {
     57   buzz::QName type;
     58 
     59   // if unset, assume type is a parse error
     60   MessageError() : ParseError(), type(buzz::QN_STANZA_BAD_REQUEST) {}
     61 
     62   void SetType(const buzz::QName type) {
     63     this->type = type;
     64   }
     65 };
     66 
     67 // Used for errors that may be returned by public session methods that
     68 // can fail.
     69 // TODO: Use this error in Session::Initiate and
     70 // Session::Accept.
     71 struct SessionError : WriteError {
     72 };
     73 
     74 // Bundles a Transport and ChannelMap together. ChannelMap is used to
     75 // create transport channels before receiving or sending a session
     76 // initiate, and for speculatively connecting channels.  Previously, a
     77 // session had one ChannelMap and transport.  Now, with multiple
     78 // transports per session, we need multiple ChannelMaps as well.
     79 class TransportProxy {
     80  public:
     81   TransportProxy(const std::string& content_name, Transport* transport)
     82       : content_name_(content_name),
     83         transport_(transport),
     84         state_(STATE_INIT),
     85         sent_candidates_(false) {}
     86   ~TransportProxy();
     87 
     88   std::string content_name() const { return content_name_; }
     89   Transport* impl() const { return transport_; }
     90   std::string type() const;
     91   bool negotiated() const { return state_ == STATE_NEGOTIATED; }
     92   const Candidates& sent_candidates() const { return sent_candidates_; }
     93 
     94   TransportChannel* GetChannel(const std::string& name);
     95   TransportChannel* CreateChannel(const std::string& name,
     96                                   const std::string& content_type);
     97   void DestroyChannel(const std::string& name);
     98   void AddSentCandidates(const Candidates& candidates);
     99   void ClearSentCandidates() { sent_candidates_.clear(); }
    100   void SpeculativelyConnectChannels();
    101   void CompleteNegotiation();
    102 
    103  private:
    104   enum TransportState {
    105     STATE_INIT,
    106     STATE_CONNECTING,
    107     STATE_NEGOTIATED
    108   };
    109 
    110   typedef std::map<std::string, TransportChannelProxy*> ChannelMap;
    111 
    112   TransportChannelProxy* GetProxy(const std::string& name);
    113   TransportChannelImpl* GetOrCreateImpl(const std::string& name,
    114                                         const std::string& content_type);
    115   void SetProxyImpl(const std::string& name, TransportChannelProxy* proxy);
    116 
    117   std::string content_name_;
    118   Transport* transport_;
    119   TransportState state_;
    120   ChannelMap channels_;
    121   Candidates sent_candidates_;
    122 };
    123 
    124 typedef std::map<std::string, TransportProxy*> TransportMap;
    125 
    126 // TODO: Consider simplifying the dependency from Voice/VideoChannel
    127 // on Session. Right now the Channel class requires a BaseSession, but it only
    128 // uses CreateChannel/DestroyChannel. Perhaps something like a
    129 // TransportChannelFactory could be hoisted up out of BaseSession, or maybe
    130 // the transports could be passed in directly.
    131 
    132 // A BaseSession manages general session state. This includes negotiation
    133 // of both the application-level and network-level protocols:  the former
    134 // defines what will be sent and the latter defines how it will be sent.  Each
    135 // network-level protocol is represented by a Transport object.  Each Transport
    136 // participates in the network-level negotiation.  The individual streams of
    137 // packets are represented by TransportChannels.  The application-level protocol
    138 // is represented by SessionDecription objects.
    139 class BaseSession : public sigslot::has_slots<>,
    140                     public talk_base::MessageHandler {
    141  public:
    142   enum State {
    143     STATE_INIT = 0,
    144     STATE_SENTINITIATE,       // sent initiate, waiting for Accept or Reject
    145     STATE_RECEIVEDINITIATE,   // received an initiate. Call Accept or Reject
    146     STATE_SENTACCEPT,         // sent accept. begin connecting transport
    147     STATE_RECEIVEDACCEPT,     // received accept. begin connecting transport
    148     STATE_SENTMODIFY,         // sent modify, waiting for Accept or Reject
    149     STATE_RECEIVEDMODIFY,     // received modify, call Accept or Reject
    150     STATE_SENTREJECT,         // sent reject after receiving initiate
    151     STATE_RECEIVEDREJECT,     // received reject after sending initiate
    152     STATE_SENTREDIRECT,       // sent direct after receiving initiate
    153     STATE_SENTTERMINATE,      // sent terminate (any time / either side)
    154     STATE_RECEIVEDTERMINATE,  // received terminate (any time / either side)
    155     STATE_INPROGRESS,         // session accepted and in progress
    156     STATE_DEINIT,             // session is being destroyed
    157   };
    158 
    159   enum Error {
    160     ERROR_NONE = 0,      // no error
    161     ERROR_TIME = 1,      // no response to signaling
    162     ERROR_RESPONSE = 2,  // error during signaling
    163     ERROR_NETWORK = 3,   // network error, could not allocate network resources
    164     ERROR_CONTENT = 4,   // channel errors in SetLocalContent/SetRemoteContent
    165   };
    166 
    167   explicit BaseSession(talk_base::Thread *signaling_thread);
    168   virtual ~BaseSession();
    169 
    170   // Updates the state, signaling if necessary.
    171   void SetState(State state);
    172 
    173   // Updates the error state, signaling if necessary.
    174   virtual void SetError(Error error);
    175 
    176   // Handles messages posted to us.
    177   virtual void OnMessage(talk_base::Message *pmsg);
    178 
    179   // Returns the current state of the session.  See the enum above for details.
    180   // Each time the state changes, we will fire this signal.
    181   State state() const { return state_; }
    182   sigslot::signal2<BaseSession *, State> SignalState;
    183 
    184   // Returns the last error in the session.  See the enum above for details.
    185   // Each time the an error occurs, we will fire this signal.
    186   Error error() const { return error_; }
    187   sigslot::signal2<BaseSession *, Error> SignalError;
    188 
    189   // Creates a new channel with the given names.  This method may be called
    190   // immediately after creating the session.  However, the actual
    191   // implementation may not be fixed until transport negotiation completes.
    192   // This will usually be called from the worker thread, but that
    193   // shouldn't be an issue since the main thread will be blocked in
    194   // Send when doing so.
    195   virtual TransportChannel* CreateChannel(const std::string& content_name,
    196                                           const std::string& channel_name) = 0;
    197 
    198   // Returns the channel with the given names.
    199   virtual TransportChannel* GetChannel(const std::string& content_name,
    200                                        const std::string& channel_name) = 0;
    201 
    202   // Destroys the channel with the given names.
    203   // This will usually be called from the worker thread, but that
    204   // shouldn't be an issue since the main thread will be blocked in
    205   // Send when doing so.
    206   virtual void DestroyChannel(const std::string& content_name,
    207                               const std::string& channel_name) = 0;
    208 
    209   // Invoked when we notice that there is no matching channel on our peer.
    210   sigslot::signal2<Session*, const std::string&> SignalChannelGone;
    211 
    212   // Returns the application-level description given by our client.
    213   // If we are the recipient, this will be NULL until we send an accept.
    214   const SessionDescription* local_description() const {
    215     return local_description_;
    216   }
    217   // Takes ownership of SessionDescription*
    218   bool set_local_description(const SessionDescription* sdesc) {
    219     if (sdesc != local_description_) {
    220       delete local_description_;
    221       local_description_ = sdesc;
    222     }
    223     return true;
    224   }
    225 
    226   // Returns the application-level description given by the other client.
    227   // If we are the initiator, this will be NULL until we receive an accept.
    228   const SessionDescription* remote_description() const {
    229     return remote_description_;
    230   }
    231   // Takes ownership of SessionDescription*
    232   bool set_remote_description(const SessionDescription* sdesc) {
    233     if (sdesc != remote_description_) {
    234       delete remote_description_;
    235       remote_description_ = sdesc;
    236     }
    237     return true;
    238   }
    239 
    240   // When we receive an initiate, we create a session in the
    241   // RECEIVEDINITIATE state and respond by accepting or rejecting.
    242   // Takes ownership of session description.
    243   virtual bool Accept(const SessionDescription* sdesc) = 0;
    244   virtual bool Reject(const std::string& reason) = 0;
    245   bool Terminate() {
    246     return TerminateWithReason(STR_TERMINATE_SUCCESS);
    247   }
    248   virtual bool TerminateWithReason(const std::string& reason) = 0;
    249 
    250   // The worker thread used by the session manager
    251   virtual talk_base::Thread *worker_thread() = 0;
    252 
    253   talk_base::Thread *signaling_thread() {
    254     return signaling_thread_;
    255   }
    256 
    257   // Returns the JID of this client.
    258   const std::string& local_name() const { return local_name_; }
    259 
    260   // Returns the JID of the other peer in this session.
    261   const std::string& remote_name() const { return remote_name_; }
    262 
    263   // Set the JID of the other peer in this session.
    264   // Typically the remote_name_ is set when the session is initiated.
    265   // However, sometimes (e.g when a proxy is used) the peer name is
    266   // known after the BaseSession has been initiated and it must be updated
    267   // explicitly.
    268   void set_remote_name(const std::string& name) { remote_name_ = name; }
    269 
    270   const std::string& id() const { return sid_; }
    271 
    272  protected:
    273   State state_;
    274   Error error_;
    275   const SessionDescription* local_description_;
    276   const SessionDescription* remote_description_;
    277   std::string sid_;
    278   // We don't use buzz::Jid because changing to buzz:Jid here has a
    279   // cascading effect that requires an enormous number places to
    280   // change to buzz::Jid as well.
    281   std::string local_name_;
    282   std::string remote_name_;
    283   talk_base::Thread *signaling_thread_;
    284 };
    285 
    286 // A specific Session created by the SessionManager, using XMPP for protocol.
    287 class Session : public BaseSession {
    288  public:
    289   // Returns the manager that created and owns this session.
    290   SessionManager* session_manager() const { return session_manager_; }
    291 
    292   // the worker thread used by the session manager
    293   talk_base::Thread *worker_thread() {
    294     return session_manager_->worker_thread();
    295   }
    296 
    297   // Returns the XML namespace identifying the type of this session.
    298   const std::string& content_type() const { return content_type_; }
    299 
    300   // Returns the client that is handling the application data of this session.
    301   SessionClient* client() const { return client_; }
    302 
    303   SignalingProtocol current_protocol() const { return current_protocol_; }
    304 
    305   void set_current_protocol(SignalingProtocol protocol) {
    306     current_protocol_ = protocol;
    307   }
    308 
    309   // Indicates whether we initiated this session.
    310   bool initiator() const { return initiator_; }
    311 
    312   const SessionDescription* initiator_description() const {
    313     if (initiator_) {
    314       return local_description_;
    315     } else {
    316       return remote_description_;
    317     }
    318   }
    319 
    320   // Fired whenever we receive a terminate message along with a reason
    321   sigslot::signal2<Session*, const std::string&> SignalReceivedTerminateReason;
    322 
    323   void set_allow_local_ips(bool allow);
    324 
    325   // Returns the transport that has been negotiated or NULL if
    326   // negotiation is still in progress.
    327   Transport* GetTransport(const std::string& content_name);
    328 
    329   // Takes ownership of session description.
    330   // TODO: Add an error argument to pass back to the caller.
    331   bool Initiate(const std::string& to,
    332                 const SessionDescription* sdesc);
    333 
    334   // When we receive an initiate, we create a session in the
    335   // RECEIVEDINITIATE state and respond by accepting or rejecting.
    336   // Takes ownership of session description.
    337   // TODO: Add an error argument to pass back to the caller.
    338   virtual bool Accept(const SessionDescription* sdesc);
    339   virtual bool Reject(const std::string& reason);
    340   virtual bool TerminateWithReason(const std::string& reason);
    341 
    342   // The two clients in the session may also send one another arbitrary XML
    343   // messages, which are called "info" messages.  Both of these functions take
    344   // ownership of the XmlElements and delete them when done.
    345   bool SendInfoMessage(const XmlElements& elems);
    346   sigslot::signal2<Session*, const XmlElements&> SignalInfoMessage;
    347 
    348   // Maps passed to serialization functions.
    349   TransportParserMap GetTransportParsers();
    350   ContentParserMap GetContentParsers();
    351 
    352   // Creates a new channel with the given names.  This method may be called
    353   // immediately after creating the session.  However, the actual
    354   // implementation may not be fixed until transport negotiation completes.
    355   virtual TransportChannel* CreateChannel(const std::string& content_name,
    356                                           const std::string& channel_name);
    357 
    358   // Returns the channel with the given names.
    359   virtual TransportChannel* GetChannel(const std::string& content_name,
    360                                        const std::string& channel_name);
    361 
    362   // Destroys the channel with the given names.
    363   virtual void DestroyChannel(const std::string& content_name,
    364                               const std::string& channel_name);
    365 
    366   // Updates the error state, signaling if necessary.
    367   virtual void SetError(Error error);
    368 
    369   // Handles messages posted to us.
    370   virtual void OnMessage(talk_base::Message *pmsg);
    371 
    372   // Fired when notification of media sources is received from the server.
    373   // Passes a map whose keys are strings containing nick names for users
    374   // in the session and whose values contain the SSRCs for each user.
    375   sigslot::signal1<const StringToMediaSourcesMap&> SignalMediaSources;
    376 
    377   // Sets the video streams to receive from the server.
    378   bool SetVideoView(const VideoViewRequestVector& view_requests);
    379 
    380  private:
    381   // Creates or destroys a session.  (These are called only SessionManager.)
    382   Session(SessionManager *session_manager,
    383           const std::string& local_name, const std::string& initiator_name,
    384           const std::string& sid, const std::string& content_type,
    385           SessionClient* client);
    386   ~Session();
    387 
    388   // Get a TransportProxy by content_name or transport. NULL if not found.
    389   TransportProxy* GetTransportProxy(const std::string& content_name);
    390   TransportProxy* GetTransportProxy(const Transport* transport);
    391   TransportProxy* GetFirstTransportProxy();
    392   // TransportProxy is owned by session.  Return proxy just for convenience.
    393   TransportProxy* GetOrCreateTransportProxy(const std::string& content_name);
    394   // For each transport info, create a transport proxy.  Can fail for
    395   // incompatible transport types.
    396   bool CreateTransportProxies(const TransportInfos& tinfos,
    397                               SessionError* error);
    398   void SpeculativelyConnectAllTransportChannels();
    399   bool OnRemoteCandidates(const TransportInfos& tinfos,
    400                           ParseError* error);
    401   // Returns a TransportInfo without candidates for each content name.
    402   // Uses the transport_type_ of the session.
    403   TransportInfos GetEmptyTransportInfos(const ContentInfos& contents) const;
    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   void OnTransportConnecting(Transport* transport);
    409 
    410   // Called when a transport changes its writable state.  We track this to make
    411   // sure that the transport becomes writable within a reasonable amount of
    412   // time.  If this does not occur, we signal an error.
    413   void OnTransportWritable(Transport* transport);
    414 
    415   // Called when a transport requests signaling.
    416   void OnTransportRequestSignaling(Transport* transport);
    417 
    418   // Called when a transport signals that it has a message to send.   Note that
    419   // these messages are just the transport part of the stanza; they need to be
    420   // wrapped in the appropriate session tags.
    421   void OnTransportCandidatesReady(Transport* transport,
    422                                   const Candidates& candidates);
    423 
    424   // Called when a transport signals that it found an error in an incoming
    425   // message.
    426   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   // Called when we notice that one of our local channels has no peer, so it
    434   // should be destroyed.
    435   void OnTransportChannelGone(Transport* transport, const std::string& name);
    436 
    437   // When the session needs to send signaling messages, it beings by requesting
    438   // signaling.  The client should handle this by calling OnSignalingReady once
    439   // it is ready to send the messages.
    440   // (These are called only by SessionManager.)
    441   sigslot::signal1<Session*> SignalRequestSignaling;
    442   void OnSignalingReady();
    443 
    444   // Send various kinds of session messages.
    445   bool SendInitiateMessage(const SessionDescription* sdesc,
    446                            SessionError* error);
    447   bool SendAcceptMessage(const SessionDescription* sdesc, SessionError* error);
    448   bool SendRejectMessage(const std::string& reason, SessionError* error);
    449   bool SendTerminateMessage(const std::string& reason, SessionError* error);
    450   bool SendTransportInfoMessage(const TransportInfo& tinfo,
    451                                 SessionError* error);
    452   bool SendViewMessage(const SessionView& view, SessionError* error);
    453   bool ResendAllTransportInfoMessages(SessionError* error);
    454 
    455   // Both versions of SendMessage send a message of the given type to
    456   // the other client.  Can pass either a set of elements or an
    457   // "action", which must have a WriteSessionAction method to go along
    458   // with it.  Sending with an action supports sending a "hybrid"
    459   // message.  Sending with elements must be sent as Jingle or Gingle.
    460 
    461   // When passing elems, must be either Jingle or Gingle protocol.
    462   // Takes ownership of action_elems.
    463   bool SendMessage(ActionType type, const XmlElements& action_elems,
    464                    SessionError* error);
    465   // When passing an action, may be Hybrid protocol.
    466   template <typename Action>
    467   bool SendMessage(ActionType type, const Action& action,
    468                    SessionError* error);
    469 
    470   // Helper methods to write the session message stanza.
    471   template <typename Action>
    472   bool WriteActionMessage(ActionType type, const Action& action,
    473                           buzz::XmlElement* stanza, WriteError* error);
    474   template <typename Action>
    475   bool WriteActionMessage(SignalingProtocol protocol,
    476                           ActionType type, const Action& action,
    477                           buzz::XmlElement* stanza, WriteError* error);
    478 
    479   // Sending messages in hybrid form requires being able to write them
    480   // on a per-protocol basis with a common method signature, which all
    481   // of these have.
    482   bool WriteSessionAction(SignalingProtocol protocol,
    483                           const SessionInitiate& init,
    484                           XmlElements* elems, WriteError* error);
    485   bool WriteSessionAction(SignalingProtocol protocol,
    486                           const TransportInfo& tinfo,
    487                           XmlElements* elems, WriteError* error);
    488   bool WriteSessionAction(SignalingProtocol protocol,
    489                           const SessionTerminate& term,
    490                           XmlElements* elems, WriteError* error);
    491 
    492   // Sends a message back to the other client indicating that we have received
    493   // and accepted their message.
    494   void SendAcknowledgementMessage(const buzz::XmlElement* stanza);
    495 
    496   // Once signaling is ready, the session will use this signal to request the
    497   // sending of each message.  When messages are received by the other client,
    498   // they should be handed to OnIncomingMessage.
    499   // (These are called only by SessionManager.)
    500   sigslot::signal2<Session *, const buzz::XmlElement*> SignalOutgoingMessage;
    501   void OnIncomingMessage(const SessionMessage& msg);
    502 
    503   void OnFailedSend(const buzz::XmlElement* orig_stanza,
    504                     const buzz::XmlElement* error_stanza);
    505 
    506   // Invoked when an error is found in an incoming message.  This is translated
    507   // into the appropriate XMPP response by SessionManager.
    508   sigslot::signal6<BaseSession*,
    509                    const buzz::XmlElement*,
    510                    const buzz::QName&,
    511                    const std::string&,
    512                    const std::string&,
    513                    const buzz::XmlElement*> SignalErrorMessage;
    514 
    515   // Handlers for the various types of messages.  These functions may take
    516   // pointers to the whole stanza or to just the session element.
    517   bool OnInitiateMessage(const SessionMessage& msg, MessageError* error);
    518   bool OnAcceptMessage(const SessionMessage& msg, MessageError* error);
    519   bool OnRejectMessage(const SessionMessage& msg, MessageError* error);
    520   bool OnInfoMessage(const SessionMessage& msg);
    521   bool OnTerminateMessage(const SessionMessage& msg, MessageError* error);
    522   bool OnTransportInfoMessage(const SessionMessage& msg, MessageError* error);
    523   bool OnTransportAcceptMessage(const SessionMessage& msg, MessageError* error);
    524   bool OnNotifyMessage(const SessionMessage& msg, MessageError* error);
    525   bool OnUpdateMessage(const SessionMessage& msg, MessageError* error);
    526   bool OnRedirectError(const SessionRedirect& redirect, SessionError* error);
    527 
    528   // Verifies that we are in the appropriate state to receive this message.
    529   bool CheckState(State state, MessageError* error);
    530 
    531   SessionManager *session_manager_;
    532   bool initiator_;
    533   std::string initiator_name_;
    534   std::string content_type_;
    535   SessionClient* client_;
    536   std::string transport_type_;
    537   TransportParser* transport_parser_;
    538   // This is transport-specific but required so much by unit tests
    539   // that it's much easier to put it here.
    540   bool allow_local_ips_;
    541   TransportMap transports_;
    542   // Keeps track of what protocol we are speaking.
    543   SignalingProtocol current_protocol_;
    544 
    545   friend class SessionManager;  // For access to constructor, destructor,
    546                                 // and signaling related methods.
    547 };
    548 
    549 }  // namespace cricket
    550 
    551 #endif  // TALK_P2P_BASE_SESSION_H_
    552