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