blob: 0d5f64285587be96b744d91f338207a9136bd990 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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
41namespace cricket {
42
43struct 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
55typedef std::vector<ProtocolAddress> PortList;
56struct RelayServerConfig {
57 RelayServerConfig(RelayType type) : type(type) {}
58
59 RelayType type;
60 PortList ports;
61 RelayCredentials credentials;
62};
63
64class 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 bool allow_tcp_listen() const {
103 return allow_tcp_listen_;
104 }
105 void set_allow_tcp_listen(bool allow_tcp_listen) {
106 allow_tcp_listen_ = allow_tcp_listen;
107 }
108
109 private:
110 void Construct();
111
112 talk_base::NetworkManager* network_manager_;
113 talk_base::PacketSocketFactory* socket_factory_;
114 const talk_base::SocketAddress stun_address_;
115 std::vector<RelayServerConfig> relays_;
116 bool allow_tcp_listen_;
117};
118
119struct PortConfiguration;
120class AllocationSequence;
121
122class BasicPortAllocatorSession : public PortAllocatorSession,
123 public talk_base::MessageHandler {
124 public:
125 BasicPortAllocatorSession(BasicPortAllocator* allocator,
126 const std::string& content_name,
127 int component,
128 const std::string& ice_ufrag,
129 const std::string& ice_pwd);
130 ~BasicPortAllocatorSession();
131
132 virtual BasicPortAllocator* allocator() { return allocator_; }
133 talk_base::Thread* network_thread() { return network_thread_; }
134 talk_base::PacketSocketFactory* socket_factory() { return socket_factory_; }
135
136 virtual void StartGettingPorts();
137 virtual void StopGettingPorts();
138 virtual bool IsGettingPorts() { return running_; }
139
140 protected:
141 // Starts the process of getting the port configurations.
142 virtual void GetPortConfigurations();
143
144 // Adds a port configuration that is now ready. Once we have one for each
145 // network (or a timeout occurs), we will start allocating ports.
146 virtual void ConfigReady(PortConfiguration* config);
147
148 // MessageHandler. Can be overriden if message IDs do not conflict.
149 virtual void OnMessage(talk_base::Message *message);
150
151 private:
152 class PortData {
153 public:
154 PortData() : port_(NULL), sequence_(NULL), state_(STATE_INIT) {}
155 PortData(Port* port, AllocationSequence* seq)
156 : port_(port), sequence_(seq), state_(STATE_INIT) {
157 }
158
159 Port* port() { return port_; }
160 AllocationSequence* sequence() { return sequence_; }
161 bool ready() const { return state_ == STATE_READY; }
162 bool complete() const {
163 // Returns true if candidate allocation has completed one way or another.
164 return ((state_ == STATE_COMPLETE) || (state_ == STATE_ERROR));
165 }
166
167 void set_ready() { ASSERT(state_ == STATE_INIT); state_ = STATE_READY; }
168 void set_complete() {
169 ASSERT(state_ == STATE_READY);
170 state_ = STATE_COMPLETE;
171 }
172 void set_error() {
173 ASSERT(state_ == STATE_INIT || state_ == STATE_READY);
174 state_ = STATE_ERROR;
175 }
176
177 private:
178 enum State {
179 STATE_INIT, // No candidates allocated yet.
180 STATE_READY, // At least one candidate is ready for process.
181 STATE_COMPLETE, // All candidates allocated and ready for process.
182 STATE_ERROR // Error in gathering candidates.
183 };
184 Port* port_;
185 AllocationSequence* sequence_;
186 State state_;
187 };
188
189 void OnConfigReady(PortConfiguration* config);
190 void OnConfigStop();
191 void AllocatePorts();
192 void OnAllocate();
193 void DoAllocate();
194 void OnNetworksChanged();
195 void OnAllocationSequenceObjectsCreated();
196 void DisableEquivalentPhases(talk_base::Network* network,
197 PortConfiguration* config, uint32* flags);
198 void AddAllocatedPort(Port* port, AllocationSequence* seq,
199 bool prepare_address);
200 void OnCandidateReady(Port* port, const Candidate& c);
201 void OnPortComplete(Port* port);
202 void OnPortError(Port* port);
203 void OnProtocolEnabled(AllocationSequence* seq, ProtocolType proto);
204 void OnPortDestroyed(PortInterface* port);
205 void OnShake();
206 void MaybeSignalCandidatesAllocationDone();
207 void OnPortAllocationComplete(AllocationSequence* seq);
208 PortData* FindPort(Port* port);
209
210 BasicPortAllocator* allocator_;
211 talk_base::Thread* network_thread_;
212 talk_base::scoped_ptr<talk_base::PacketSocketFactory> owned_socket_factory_;
213 talk_base::PacketSocketFactory* socket_factory_;
214 bool configuration_done_;
215 bool allocation_started_;
216 bool network_manager_started_;
217 bool running_; // set when StartGetAllPorts is called
218 bool allocation_sequences_created_;
219 std::vector<PortConfiguration*> configs_;
220 std::vector<AllocationSequence*> sequences_;
221 std::vector<PortData> ports_;
222
223 friend class AllocationSequence;
224};
225
226// Records configuration information useful in creating ports.
227struct PortConfiguration : public talk_base::MessageData {
228 talk_base::SocketAddress stun_address;
229 std::string username;
230 std::string password;
231
232 typedef std::vector<RelayServerConfig> RelayList;
233 RelayList relays;
234
235 PortConfiguration(const talk_base::SocketAddress& stun_address,
236 const std::string& username,
237 const std::string& password);
238
239 // Adds another relay server, with the given ports and modifier, to the list.
240 void AddRelay(const RelayServerConfig& config);
241
242 // Determines whether the given relay server supports the given protocol.
243 static bool SupportsProtocol(const RelayServerConfig& relay,
244 ProtocolType type);
245};
246
247} // namespace cricket
248
249#endif // TALK_P2P_CLIENT_BASICPORTALLOCATOR_H_