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