blob: b8660f0a3426dc7fd97efa6a8042e1c0b650c5dd [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
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102 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
112struct PortConfiguration;
113class AllocationSequence;
114
115class 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_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000207 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.
219struct 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.
buildbot@webrtc.orgf875f152014-04-14 16:06:21 +0000235 bool SupportsProtocol(const RelayServerConfig& relay,
236 ProtocolType type) const;
237 bool SupportsProtocol(const RelayType turn_type, ProtocolType type) const;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000238};
239
240} // namespace cricket
241
242#endif // TALK_P2P_CLIENT_BASICPORTALLOCATOR_H_