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 // A Transport manages a set of named channels of the same type.
     29 //
     30 // Subclasses choose the appropriate class to instantiate for each channel;
     31 // however, this base class keeps track of the channels by name, watches their
     32 // state changes (in order to update the manager's state), and forwards
     33 // requests to begin connecting or to reset to each of the channels.
     34 //
     35 // On Threading:  Transport performs work on both the signaling and worker
     36 // threads.  For subclasses, the rule is that all signaling related calls will
     37 // be made on the signaling thread and all channel related calls (including
     38 // signaling for a channel) will be made on the worker thread.  When
     39 // information needs to be sent between the two threads, this class should do
     40 // the work (e.g., OnRemoteCandidate).
     41 //
     42 // Note: Subclasses must call DestroyChannels() in their own constructors.
     43 // It is not possible to do so here because the subclass constructor will
     44 // already have run.
     45 
     46 #ifndef TALK_P2P_BASE_TRANSPORT_H_
     47 #define TALK_P2P_BASE_TRANSPORT_H_
     48 
     49 #include <string>
     50 #include <map>
     51 #include <vector>
     52 #include "talk/base/criticalsection.h"
     53 #include "talk/base/messagequeue.h"
     54 #include "talk/base/sigslot.h"
     55 #include "talk/p2p/base/candidate.h"
     56 #include "talk/p2p/base/constants.h"
     57 
     58 namespace talk_base {
     59 class Thread;
     60 }
     61 
     62 namespace buzz {
     63 class QName;
     64 class XmlElement;
     65 }
     66 
     67 namespace cricket {
     68 
     69 struct ParseError;
     70 struct WriteError;
     71 class PortAllocator;
     72 class SessionManager;
     73 class Session;
     74 class TransportChannel;
     75 class TransportChannelImpl;
     76 
     77 typedef std::vector<buzz::XmlElement*> XmlElements;
     78 typedef std::vector<Candidate> Candidates;
     79 
     80 // Used to parse and serialize (write) transport candidates.  For
     81 // convenience of old code, Transports will implement TransportParser.
     82 // Parse/Write seems better than Serialize/Deserialize or
     83 // Create/Translate.
     84 class TransportParser {
     85  public:
     86   virtual bool ParseCandidates(SignalingProtocol protocol,
     87                                const buzz::XmlElement* elem,
     88                                Candidates* candidates,
     89                                ParseError* error) = 0;
     90   virtual bool WriteCandidates(SignalingProtocol protocol,
     91                                const Candidates& candidates,
     92                                XmlElements* candidate_elems,
     93                                WriteError* error) = 0;
     94 
     95   // Helper function to parse an element describing an address.  This
     96   // retrieves the IP and port from the given element and verifies
     97   // that they look like plausible values.
     98   bool ParseAddress(const buzz::XmlElement* elem,
     99                     const buzz::QName& address_name,
    100                     const buzz::QName& port_name,
    101                     talk_base::SocketAddress* address,
    102                     ParseError* error);
    103 
    104   virtual ~TransportParser() {}
    105 };
    106 
    107 class Transport : public talk_base::MessageHandler,
    108                   public sigslot::has_slots<> {
    109  public:
    110   Transport(talk_base::Thread* signaling_thread,
    111             talk_base::Thread* worker_thread,
    112             const std::string& type,
    113             PortAllocator* allocator);
    114   virtual ~Transport();
    115 
    116   // Returns the signaling thread. The app talks to Transport on this thread.
    117   talk_base::Thread* signaling_thread() { return signaling_thread_; }
    118   // Returns the worker thread. The actual networking is done on this thread.
    119   talk_base::Thread* worker_thread() { return worker_thread_; }
    120 
    121   // Returns the type of this transport.
    122   const std::string& type() const { return type_; }
    123 
    124   // Returns the port allocator object for this transport.
    125   PortAllocator* port_allocator() { return allocator_; }
    126 
    127   // Returns the readable and states of this manager.  These bits are the ORs
    128   // of the corresponding bits on the managed channels.  Each time one of these
    129   // states changes, a signal is raised.
    130   bool readable() const { return readable_; }
    131   bool writable() const { return writable_; }
    132   sigslot::signal1<Transport*> SignalReadableState;
    133   sigslot::signal1<Transport*> SignalWritableState;
    134 
    135   // Returns whether the client has requested the channels to connect.
    136   bool connect_requested() const { return connect_requested_; }
    137 
    138   // Create, destroy, and lookup the channels of this type by their names.
    139   TransportChannelImpl* CreateChannel(const std::string& name,
    140                                       const std::string& content_type);
    141   // Note: GetChannel may lead to race conditions, since the mutex is not held
    142   // after the pointer is returned.
    143   TransportChannelImpl* GetChannel(const std::string& name);
    144   // Note: HasChannel does not lead to race conditions, unlike GetChannel.
    145   bool HasChannel(const std::string& name) {
    146     return (NULL != GetChannel(name));
    147   }
    148   bool HasChannels();
    149   void DestroyChannel(const std::string& name);
    150 
    151   // Tells all current and future channels to start connecting.  When the first
    152   // channel begins connecting, the following signal is raised.
    153   void ConnectChannels();
    154   sigslot::signal1<Transport*> SignalConnecting;
    155 
    156   // Resets all of the channels back to their initial state.  They are no
    157   // longer connecting.
    158   void ResetChannels();
    159 
    160   // Destroys every channel created so far.
    161   void DestroyAllChannels();
    162 
    163   // Before any stanza is sent, the manager will request signaling.  Once
    164   // signaling is available, the client should call OnSignalingReady.  Once
    165   // this occurs, the transport (or its channels) can send any waiting stanzas.
    166   // OnSignalingReady invokes OnTransportSignalingReady and then forwards this
    167   // signal to each channel.
    168   sigslot::signal1<Transport*> SignalRequestSignaling;
    169   void OnSignalingReady();
    170 
    171   // Handles sending of ready candidates and receiving of remote candidates.
    172   sigslot::signal2<Transport*,
    173                    const std::vector<Candidate>&> SignalCandidatesReady;
    174   void OnRemoteCandidates(const std::vector<Candidate>& candidates);
    175 
    176   // If candidate is not acceptable, returns false and sets error.
    177   // Call this before calling OnRemoteCandidates.
    178   virtual bool VerifyCandidate(const Candidate& candidate,
    179                                ParseError* error);
    180 
    181   // A transport message has generated an transport-specific error.  The
    182   // stanza that caused the error is available in session_msg.  If false is
    183   // returned, the error is considered unrecoverable, and the session is
    184   // terminated.
    185   // TODO: Make OnTransportError take an abstract data type
    186   // rather than an XmlElement.  It isn't needed yet, but it might be
    187   // later for Jingle compliance.
    188   virtual void OnTransportError(const buzz::XmlElement* error) {}
    189   sigslot::signal6<Transport*, const buzz::XmlElement*, const buzz::QName&,
    190                    const std::string&, const std::string&,
    191                    const buzz::XmlElement*>
    192       SignalTransportError;
    193 
    194   sigslot::signal2<Transport*, const std::string&> SignalChannelGone;
    195 
    196   // (For testing purposes only.)  This indicates whether we will allow local
    197   // IPs (e.g. 127.*) to be used as addresses for P2P.
    198   bool allow_local_ips() const { return allow_local_ips_; }
    199   void set_allow_local_ips(bool value) { allow_local_ips_ = value; }
    200 
    201  protected:
    202   // These are called by Create/DestroyChannel above in order to create or
    203   // destroy the appropriate type of channel.
    204   virtual TransportChannelImpl* CreateTransportChannel(
    205       const std::string& name, const std::string &content_type) = 0;
    206   virtual void DestroyTransportChannel(TransportChannelImpl* channel) = 0;
    207 
    208   // Informs the subclass that we received the signaling ready message.
    209   virtual void OnTransportSignalingReady() {}
    210 
    211  private:
    212   typedef std::map<std::string, TransportChannelImpl*> ChannelMap;
    213 
    214   // Called when the state of a channel changes.
    215   void OnChannelReadableState(TransportChannel* channel);
    216   void OnChannelWritableState(TransportChannel* channel);
    217 
    218   // Called when a channel requests signaling.
    219   void OnChannelRequestSignaling();
    220 
    221   // Called when a candidate is ready from remote peer.
    222   void OnRemoteCandidate(const Candidate& candidate);
    223   // Called when a candidate is ready from channel.
    224   void OnChannelCandidateReady(TransportChannelImpl* channel,
    225                                const Candidate& candidate);
    226 
    227   // Dispatches messages to the appropriate handler (below).
    228   void OnMessage(talk_base::Message* msg);
    229 
    230   // These are versions of the above methods that are called only on a
    231   // particular thread (s = signaling, w = worker).  The above methods post or
    232   // send a message to invoke this version.
    233   TransportChannelImpl* CreateChannel_w(const std::string& name,
    234                                         const std::string& content_type);
    235   void DestroyChannel_w(const std::string& name);
    236   void ConnectChannels_w();
    237   void ResetChannels_w();
    238   void DestroyAllChannels_w();
    239   void OnRemoteCandidate_w(const Candidate& candidate);
    240   void OnChannelReadableState_s();
    241   void OnChannelWritableState_s();
    242   void OnChannelRequestSignaling_s();
    243   void OnConnecting_s();
    244 
    245   // Helper function that invokes the given function on every channel.
    246   typedef void (TransportChannelImpl::* TransportChannelFunc)();
    247   void CallChannels_w(TransportChannelFunc func);
    248 
    249   // Computes the OR of the channel's read or write state (argument picks).
    250   bool GetTransportState_s(bool read);
    251 
    252   void OnChannelCandidateReady_s();
    253 
    254   talk_base::Thread* signaling_thread_;
    255   talk_base::Thread* worker_thread_;
    256   std::string type_;
    257   PortAllocator* allocator_;
    258   bool destroyed_;
    259   bool readable_;
    260   bool writable_;
    261   bool connect_requested_;
    262   ChannelMap channels_;
    263   // Buffers the ready_candidates so that SignalCanidatesReady can
    264   // provide them in multiples.
    265   std::vector<Candidate> ready_candidates_;
    266   // Protects changes to channels and messages
    267   talk_base::CriticalSection crit_;
    268   bool allow_local_ips_;
    269 
    270   DISALLOW_EVIL_CONSTRUCTORS(Transport);
    271 };
    272 
    273 }  // namespace cricket
    274 
    275 #endif  // TALK_P2P_BASE_TRANSPORT_H_
    276