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/thread.h"
     37 #include "talk/p2p/base/portallocator.h"
     38 
     39 namespace cricket {
     40 
     41 class BasicPortAllocator : public PortAllocator {
     42  public:
     43   BasicPortAllocator(talk_base::NetworkManager* network_manager,
     44                      talk_base::PacketSocketFactory* socket_factory);
     45   BasicPortAllocator(talk_base::NetworkManager* network_manager,
     46                      talk_base::PacketSocketFactory* socket_factory,
     47                      const talk_base::SocketAddress& stun_server,
     48                      const talk_base::SocketAddress& relay_server_udp,
     49                      const talk_base::SocketAddress& relay_server_tcp,
     50                      const talk_base::SocketAddress& relay_server_ssl);
     51   virtual ~BasicPortAllocator();
     52 
     53   talk_base::NetworkManager* network_manager() { return network_manager_; }
     54 
     55   talk_base::PacketSocketFactory* socket_factory() { return socket_factory_; }
     56 
     57   const talk_base::SocketAddress& stun_address() const {
     58     return stun_address_;
     59   }
     60   const talk_base::SocketAddress& relay_address_udp() const {
     61     return relay_address_udp_;
     62   }
     63   const talk_base::SocketAddress& relay_address_tcp() const {
     64     return relay_address_tcp_;
     65   }
     66   const talk_base::SocketAddress& relay_address_ssl() const {
     67     return relay_address_ssl_;
     68   }
     69 
     70   // Returns the best (highest preference) phase that has produced a port that
     71   // produced a writable connection.  If no writable connections have been
     72   // produced, this returns -1.
     73   int best_writable_phase() const;
     74 
     75   virtual PortAllocatorSession* CreateSession(const std::string& name,
     76                                               const std::string& session_type);
     77 
     78   // Called whenever a connection becomes writable with the argument being the
     79   // phase that the corresponding port was created in.
     80   void AddWritablePhase(int phase);
     81 
     82   bool allow_tcp_listen() const {
     83     return allow_tcp_listen_;
     84   }
     85   void set_allow_tcp_listen(bool allow_tcp_listen) {
     86     allow_tcp_listen_ = allow_tcp_listen;
     87   }
     88 
     89  private:
     90   talk_base::NetworkManager* network_manager_;
     91   talk_base::PacketSocketFactory* socket_factory_;
     92   const talk_base::SocketAddress stun_address_;
     93   const talk_base::SocketAddress relay_address_udp_;
     94   const talk_base::SocketAddress relay_address_tcp_;
     95   const talk_base::SocketAddress relay_address_ssl_;
     96   int best_writable_phase_;
     97   bool allow_tcp_listen_;
     98 };
     99 
    100 struct PortConfiguration;
    101 class AllocationSequence;
    102 
    103 class BasicPortAllocatorSession : public PortAllocatorSession,
    104     public talk_base::MessageHandler {
    105  public:
    106   BasicPortAllocatorSession(BasicPortAllocator* allocator,
    107                             const std::string& name,
    108                             const std::string& session_type);
    109   ~BasicPortAllocatorSession();
    110 
    111   virtual BasicPortAllocator* allocator() { return allocator_; }
    112   const std::string& name() const { return name_; }
    113   const std::string& session_type() const { return session_type_; }
    114   talk_base::Thread* network_thread() { return network_thread_; }
    115 
    116   virtual void GetInitialPorts();
    117   virtual void StartGetAllPorts();
    118   virtual void StopGetAllPorts();
    119   virtual bool IsGettingAllPorts() { return running_; }
    120 
    121  protected:
    122   // Starts the process of getting the port configurations.
    123   virtual void GetPortConfigurations();
    124 
    125   // Adds a port configuration that is now ready.  Once we have one for each
    126   // network (or a timeout occurs), we will start allocating ports.
    127   void ConfigReady(PortConfiguration* config);
    128 
    129   // MessageHandler.  Can be overriden if message IDs do not conflict.
    130   virtual void OnMessage(talk_base::Message *message);
    131 
    132  private:
    133   void OnConfigReady(PortConfiguration* config);
    134   void OnConfigTimeout();
    135   void AllocatePorts();
    136   void OnAllocate();
    137   void DisableEquivalentPhases(talk_base::Network* network,
    138       PortConfiguration* config, uint32* flags);
    139   void AddAllocatedPort(Port* port, AllocationSequence* seq, float pref,
    140       bool prepare_address = true);
    141   void OnAddressReady(Port* port);
    142   void OnProtocolEnabled(AllocationSequence* seq, ProtocolType proto);
    143   void OnPortDestroyed(Port* port);
    144   void OnConnectionCreated(Port* port, Connection* conn);
    145   void OnConnectionStateChange(Connection* conn);
    146   void OnShake();
    147 
    148   BasicPortAllocator* allocator_;
    149   std::string name_;
    150   std::string session_type_;
    151   talk_base::Thread* network_thread_;
    152   bool configuration_done_;
    153   bool allocation_started_;
    154   bool running_;  // set when StartGetAllPorts is called
    155   std::vector<PortConfiguration*> configs_;
    156   std::vector<AllocationSequence*> sequences_;
    157 
    158   struct PortData {
    159     Port* port;
    160     AllocationSequence* sequence;
    161     bool ready;
    162 
    163     bool operator==(Port* rhs) const { return (port == rhs); }
    164   };
    165   std::vector<PortData> ports_;
    166 
    167   friend class AllocationSequence;
    168 };
    169 
    170 // Records configuration information useful in creating ports.
    171 struct PortConfiguration : public talk_base::MessageData {
    172   talk_base::SocketAddress stun_address;
    173   std::string username;
    174   std::string password;
    175   std::string magic_cookie;
    176 
    177   typedef std::vector<ProtocolAddress> PortList;
    178   struct RelayServer {
    179     PortList ports;
    180     float pref_modifier;  // added to the protocol modifier to get the
    181                           // preference for this particular server
    182   };
    183 
    184   typedef std::vector<RelayServer> RelayList;
    185   RelayList relays;
    186 
    187   PortConfiguration(const talk_base::SocketAddress& stun_address,
    188                     const std::string& username,
    189                     const std::string& password,
    190                     const std::string& magic_cookie);
    191 
    192   // Adds another relay server, with the given ports and modifier, to the list.
    193   void AddRelay(const PortList& ports, float pref_modifier);
    194 
    195   bool ResolveStunAddress();
    196 
    197   // Determines whether the given relay server supports the given protocol.
    198   static bool SupportsProtocol(const PortConfiguration::RelayServer& relay,
    199                                ProtocolType type);
    200 };
    201 
    202 }  // namespace cricket
    203 
    204 #endif  // TALK_P2P_CLIENT_BASICPORTALLOCATOR_H_
    205