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/p2p/base/port.h" 35 #include "talk/p2p/base/portallocator.h" 36 #include "webrtc/base/messagequeue.h" 37 #include "webrtc/base/network.h" 38 #include "webrtc/base/scoped_ptr.h" 39 #include "webrtc/base/thread.h" 40 41 namespace cricket { 42 43 struct RelayCredentials { RelayCredentialsRelayCredentials44 RelayCredentials() {} RelayCredentialsRelayCredentials45 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 { RelayServerConfigRelayServerConfig57 RelayServerConfig(RelayType type) : type(type), priority(0) {} 58 59 RelayType type; 60 PortList ports; 61 RelayCredentials credentials; 62 int priority; 63 }; 64 65 class BasicPortAllocator : public PortAllocator { 66 public: 67 BasicPortAllocator(rtc::NetworkManager* network_manager, 68 rtc::PacketSocketFactory* socket_factory); 69 explicit BasicPortAllocator(rtc::NetworkManager* network_manager); 70 BasicPortAllocator(rtc::NetworkManager* network_manager, 71 rtc::PacketSocketFactory* socket_factory, 72 const ServerAddresses& stun_servers); 73 BasicPortAllocator(rtc::NetworkManager* network_manager, 74 const ServerAddresses& stun_servers, 75 const rtc::SocketAddress& relay_server_udp, 76 const rtc::SocketAddress& relay_server_tcp, 77 const rtc::SocketAddress& relay_server_ssl); 78 virtual ~BasicPortAllocator(); 79 network_manager()80 rtc::NetworkManager* network_manager() { return network_manager_; } 81 82 // If socket_factory() is set to NULL each PortAllocatorSession 83 // creates its own socket factory. socket_factory()84 rtc::PacketSocketFactory* socket_factory() { return socket_factory_; } 85 stun_servers()86 const ServerAddresses& stun_servers() const { 87 return stun_servers_; 88 } 89 relays()90 const std::vector<RelayServerConfig>& relays() const { 91 return relays_; 92 } AddRelay(const RelayServerConfig & relay)93 virtual void AddRelay(const RelayServerConfig& relay) { 94 relays_.push_back(relay); 95 } 96 97 virtual PortAllocatorSession* CreateSessionInternal( 98 const std::string& content_name, 99 int component, 100 const std::string& ice_ufrag, 101 const std::string& ice_pwd); 102 103 private: 104 void Construct(); 105 106 rtc::NetworkManager* network_manager_; 107 rtc::PacketSocketFactory* socket_factory_; 108 const ServerAddresses stun_servers_; 109 std::vector<RelayServerConfig> relays_; 110 bool allow_tcp_listen_; 111 }; 112 113 struct PortConfiguration; 114 class AllocationSequence; 115 116 class BasicPortAllocatorSession : public PortAllocatorSession, 117 public rtc::MessageHandler { 118 public: 119 BasicPortAllocatorSession(BasicPortAllocator* allocator, 120 const std::string& content_name, 121 int component, 122 const std::string& ice_ufrag, 123 const std::string& ice_pwd); 124 ~BasicPortAllocatorSession(); 125 allocator()126 virtual BasicPortAllocator* allocator() { return allocator_; } network_thread()127 rtc::Thread* network_thread() { return network_thread_; } socket_factory()128 rtc::PacketSocketFactory* socket_factory() { return socket_factory_; } 129 130 virtual void StartGettingPorts(); 131 virtual void StopGettingPorts(); IsGettingPorts()132 virtual bool IsGettingPorts() { return running_; } 133 134 protected: 135 // Starts the process of getting the port configurations. 136 virtual void GetPortConfigurations(); 137 138 // Adds a port configuration that is now ready. Once we have one for each 139 // network (or a timeout occurs), we will start allocating ports. 140 virtual void ConfigReady(PortConfiguration* config); 141 142 // MessageHandler. Can be overriden if message IDs do not conflict. 143 virtual void OnMessage(rtc::Message *message); 144 145 private: 146 class PortData { 147 public: PortData()148 PortData() : port_(NULL), sequence_(NULL), state_(STATE_INIT) {} PortData(Port * port,AllocationSequence * seq)149 PortData(Port* port, AllocationSequence* seq) 150 : port_(port), sequence_(seq), state_(STATE_INIT) { 151 } 152 port()153 Port* port() { return port_; } sequence()154 AllocationSequence* sequence() { return sequence_; } ready()155 bool ready() const { return state_ == STATE_READY; } complete()156 bool complete() const { 157 // Returns true if candidate allocation has completed one way or another. 158 return ((state_ == STATE_COMPLETE) || (state_ == STATE_ERROR)); 159 } 160 set_ready()161 void set_ready() { ASSERT(state_ == STATE_INIT); state_ = STATE_READY; } set_complete()162 void set_complete() { 163 state_ = STATE_COMPLETE; 164 } set_error()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(rtc::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 bool CheckCandidateFilter(const Candidate& c); 204 205 BasicPortAllocator* allocator_; 206 rtc::Thread* network_thread_; 207 rtc::scoped_ptr<rtc::PacketSocketFactory> owned_socket_factory_; 208 rtc::PacketSocketFactory* socket_factory_; 209 bool allocation_started_; 210 bool network_manager_started_; 211 bool running_; // set when StartGetAllPorts is called 212 bool allocation_sequences_created_; 213 std::vector<PortConfiguration*> configs_; 214 std::vector<AllocationSequence*> sequences_; 215 std::vector<PortData> ports_; 216 217 friend class AllocationSequence; 218 }; 219 220 // Records configuration information useful in creating ports. 221 struct PortConfiguration : public rtc::MessageData { 222 // TODO(jiayl): remove |stun_address| when Chrome is updated. 223 rtc::SocketAddress stun_address; 224 ServerAddresses stun_servers; 225 std::string username; 226 std::string password; 227 228 typedef std::vector<RelayServerConfig> RelayList; 229 RelayList relays; 230 231 // TODO(jiayl): remove this ctor when Chrome is updated. 232 PortConfiguration(const rtc::SocketAddress& stun_address, 233 const std::string& username, 234 const std::string& password); 235 236 PortConfiguration(const ServerAddresses& stun_servers, 237 const std::string& username, 238 const std::string& password); 239 240 // TODO(jiayl): remove when |stun_address| is removed. 241 ServerAddresses StunServers(); 242 243 // Adds another relay server, with the given ports and modifier, to the list. 244 void AddRelay(const RelayServerConfig& config); 245 246 // Determines whether the given relay server supports the given protocol. 247 bool SupportsProtocol(const RelayServerConfig& relay, 248 ProtocolType type) const; 249 bool SupportsProtocol(RelayType turn_type, ProtocolType type) const; 250 // Helper method returns the server addresses for the matching RelayType and 251 // Protocol type. 252 ServerAddresses GetRelayServerAddresses( 253 RelayType turn_type, ProtocolType type) const; 254 }; 255 256 } // namespace cricket 257 258 #endif // TALK_P2P_CLIENT_BASICPORTALLOCATOR_H_ 259