Home | History | Annotate | Download | only in client
      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_CLIENT_BASICPORTALLOCATOR_H_
     29 #define TALK_P2P_CLIENT_BASICPORTALLOCATOR_H_
     30 
     31 #include <string>
     32 #include <vector>
     33 
     34 #include "talk/base/messagequeue.h"
     35 #include "talk/base/network.h"
     36 #include "talk/base/scoped_ptr.h"
     37 #include "talk/base/thread.h"
     38 #include "talk/p2p/base/port.h"
     39 #include "talk/p2p/base/portallocator.h"
     40 
     41 namespace cricket {
     42 
     43 struct RelayCredentials {
     44   RelayCredentials() {}
     45   RelayCredentials(const std::string& username,
     46                    const std::string& password)
     47       : username(username),
     48         password(password) {
     49   }
     50 
     51   std::string username;
     52   std::string password;
     53 };
     54 
     55 typedef std::vector<ProtocolAddress> PortList;
     56 struct RelayServerConfig {
     57   RelayServerConfig(RelayType type) : type(type) {}
     58 
     59   RelayType type;
     60   PortList ports;
     61   RelayCredentials credentials;
     62 };
     63 
     64 class BasicPortAllocator : public PortAllocator {
     65  public:
     66   BasicPortAllocator(talk_base::NetworkManager* network_manager,
     67                      talk_base::PacketSocketFactory* socket_factory);
     68   explicit BasicPortAllocator(talk_base::NetworkManager* network_manager);
     69   BasicPortAllocator(talk_base::NetworkManager* network_manager,
     70                      talk_base::PacketSocketFactory* socket_factory,
     71                      const talk_base::SocketAddress& stun_server);
     72   BasicPortAllocator(talk_base::NetworkManager* network_manager,
     73                      const talk_base::SocketAddress& stun_server,
     74                      const talk_base::SocketAddress& relay_server_udp,
     75                      const talk_base::SocketAddress& relay_server_tcp,
     76                      const talk_base::SocketAddress& relay_server_ssl);
     77   virtual ~BasicPortAllocator();
     78 
     79   talk_base::NetworkManager* network_manager() { return network_manager_; }
     80 
     81   // If socket_factory() is set to NULL each PortAllocatorSession
     82   // creates its own socket factory.
     83   talk_base::PacketSocketFactory* socket_factory() { return socket_factory_; }
     84 
     85   const talk_base::SocketAddress& stun_address() const {
     86     return stun_address_;
     87   }
     88 
     89   const std::vector<RelayServerConfig>& relays() const {
     90     return relays_;
     91   }
     92   virtual void AddRelay(const RelayServerConfig& relay) {
     93     relays_.push_back(relay);
     94   }
     95 
     96   virtual PortAllocatorSession* CreateSessionInternal(
     97       const std::string& content_name,
     98       int component,
     99       const std::string& ice_ufrag,
    100       const std::string& ice_pwd);
    101 
    102  private:
    103   void Construct();
    104 
    105   talk_base::NetworkManager* network_manager_;
    106   talk_base::PacketSocketFactory* socket_factory_;
    107   const talk_base::SocketAddress stun_address_;
    108   std::vector<RelayServerConfig> relays_;
    109   bool allow_tcp_listen_;
    110 };
    111 
    112 struct PortConfiguration;
    113 class AllocationSequence;
    114 
    115 class BasicPortAllocatorSession : public PortAllocatorSession,
    116                                   public talk_base::MessageHandler {
    117  public:
    118   BasicPortAllocatorSession(BasicPortAllocator* allocator,
    119                             const std::string& content_name,
    120                             int component,
    121                             const std::string& ice_ufrag,
    122                             const std::string& ice_pwd);
    123   ~BasicPortAllocatorSession();
    124 
    125   virtual BasicPortAllocator* allocator() { return allocator_; }
    126   talk_base::Thread* network_thread() { return network_thread_; }
    127   talk_base::PacketSocketFactory* socket_factory() { return socket_factory_; }
    128 
    129   virtual void StartGettingPorts();
    130   virtual void StopGettingPorts();
    131   virtual bool IsGettingPorts() { return running_; }
    132 
    133  protected:
    134   // Starts the process of getting the port configurations.
    135   virtual void GetPortConfigurations();
    136 
    137   // Adds a port configuration that is now ready.  Once we have one for each
    138   // network (or a timeout occurs), we will start allocating ports.
    139   virtual void ConfigReady(PortConfiguration* config);
    140 
    141   // MessageHandler.  Can be overriden if message IDs do not conflict.
    142   virtual void OnMessage(talk_base::Message *message);
    143 
    144  private:
    145   class PortData {
    146    public:
    147     PortData() : port_(NULL), sequence_(NULL), state_(STATE_INIT) {}
    148     PortData(Port* port, AllocationSequence* seq)
    149     : port_(port), sequence_(seq), state_(STATE_INIT) {
    150     }
    151 
    152     Port* port() { return port_; }
    153     AllocationSequence* sequence() { return sequence_; }
    154     bool ready() const { return state_ == STATE_READY; }
    155     bool complete() const {
    156       // Returns true if candidate allocation has completed one way or another.
    157       return ((state_ == STATE_COMPLETE) || (state_ == STATE_ERROR));
    158     }
    159 
    160     void set_ready() { ASSERT(state_ == STATE_INIT); state_ = STATE_READY; }
    161     void set_complete() {
    162       ASSERT(state_ == STATE_READY);
    163       state_ = STATE_COMPLETE;
    164     }
    165     void set_error() {
    166       ASSERT(state_ == STATE_INIT || state_ == STATE_READY);
    167       state_ = STATE_ERROR;
    168     }
    169 
    170    private:
    171     enum State {
    172       STATE_INIT,      // No candidates allocated yet.
    173       STATE_READY,     // At least one candidate is ready for process.
    174       STATE_COMPLETE,  // All candidates allocated and ready for process.
    175       STATE_ERROR      // Error in gathering candidates.
    176     };
    177     Port* port_;
    178     AllocationSequence* sequence_;
    179     State state_;
    180   };
    181 
    182   void OnConfigReady(PortConfiguration* config);
    183   void OnConfigStop();
    184   void AllocatePorts();
    185   void OnAllocate();
    186   void DoAllocate();
    187   void OnNetworksChanged();
    188   void OnAllocationSequenceObjectsCreated();
    189   void DisableEquivalentPhases(talk_base::Network* network,
    190                                PortConfiguration* config, uint32* flags);
    191   void AddAllocatedPort(Port* port, AllocationSequence* seq,
    192                         bool prepare_address);
    193   void OnCandidateReady(Port* port, const Candidate& c);
    194   void OnPortComplete(Port* port);
    195   void OnPortError(Port* port);
    196   void OnProtocolEnabled(AllocationSequence* seq, ProtocolType proto);
    197   void OnPortDestroyed(PortInterface* port);
    198   void OnShake();
    199   void MaybeSignalCandidatesAllocationDone();
    200   void OnPortAllocationComplete(AllocationSequence* seq);
    201   PortData* FindPort(Port* port);
    202 
    203   BasicPortAllocator* allocator_;
    204   talk_base::Thread* network_thread_;
    205   talk_base::scoped_ptr<talk_base::PacketSocketFactory> owned_socket_factory_;
    206   talk_base::PacketSocketFactory* socket_factory_;
    207   bool allocation_started_;
    208   bool network_manager_started_;
    209   bool running_;  // set when StartGetAllPorts is called
    210   bool allocation_sequences_created_;
    211   std::vector<PortConfiguration*> configs_;
    212   std::vector<AllocationSequence*> sequences_;
    213   std::vector<PortData> ports_;
    214 
    215   friend class AllocationSequence;
    216 };
    217 
    218 // Records configuration information useful in creating ports.
    219 struct PortConfiguration : public talk_base::MessageData {
    220   talk_base::SocketAddress stun_address;
    221   std::string username;
    222   std::string password;
    223 
    224   typedef std::vector<RelayServerConfig> RelayList;
    225   RelayList relays;
    226 
    227   PortConfiguration(const talk_base::SocketAddress& stun_address,
    228                     const std::string& username,
    229                     const std::string& password);
    230 
    231   // Adds another relay server, with the given ports and modifier, to the list.
    232   void AddRelay(const RelayServerConfig& config);
    233 
    234   // Determines whether the given relay server supports the given protocol.
    235   bool SupportsProtocol(const RelayServerConfig& relay,
    236                         ProtocolType type) const;
    237   bool SupportsProtocol(RelayType turn_type, ProtocolType type) const;
    238   // Helper method returns the first server address for the matching
    239   // RelayType and Protocol type.
    240   talk_base::SocketAddress GetFirstRelayServerAddress(
    241       RelayType turn_type, ProtocolType type) const;
    242 };
    243 
    244 }  // namespace cricket
    245 
    246 #endif  // TALK_P2P_CLIENT_BASICPORTALLOCATOR_H_
    247