blob: 797fa3f94f167f7e7db637050c0ba93553f6ed3a [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef WEBRTC_P2P_BASE_TURNPORT_H_
12#define WEBRTC_P2P_BASE_TURNPORT_H_
13
14#include <stdio.h>
15#include <list>
16#include <set>
17#include <string>
18
honghaiz32f39962015-11-17 11:36:31 -080019#include "webrtc/base/asyncinvoker.h"
20#include "webrtc/base/asyncpacketsocket.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000021#include "webrtc/p2p/base/port.h"
22#include "webrtc/p2p/client/basicportallocator.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000023
24namespace rtc {
25class AsyncResolver;
26class SignalThread;
27}
28
29namespace cricket {
30
31extern const char TURN_PORT_TYPE[];
32class TurnAllocateRequest;
33class TurnEntry;
34
35class TurnPort : public Port {
36 public:
honghaizb19eba32015-08-03 10:23:31 -070037 enum PortState {
38 STATE_CONNECTING, // Initial state, cannot send any packets.
39 STATE_CONNECTED, // Socket connected, ready to send stun requests.
40 STATE_READY, // Received allocate success, can send any packets.
41 STATE_DISCONNECTED, // TCP connection died, cannot send any packets.
42 };
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000043 static TurnPort* Create(rtc::Thread* thread,
44 rtc::PacketSocketFactory* factory,
45 rtc::Network* network,
46 rtc::AsyncPacketSocket* socket,
47 const std::string& username, // ice username.
48 const std::string& password, // ice password.
49 const ProtocolAddress& server_address,
50 const RelayCredentials& credentials,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000051 int server_priority,
52 const std::string& origin) {
pkasting@chromium.org332331f2014-11-06 20:19:22 +000053 return new TurnPort(thread, factory, network, socket, username, password,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000054 server_address, credentials, server_priority, origin);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000055 }
56
57 static TurnPort* Create(rtc::Thread* thread,
58 rtc::PacketSocketFactory* factory,
59 rtc::Network* network,
60 const rtc::IPAddress& ip,
Peter Boström0c4e06b2015-10-07 12:23:21 +020061 uint16_t min_port,
62 uint16_t max_port,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000063 const std::string& username, // ice username.
64 const std::string& password, // ice password.
65 const ProtocolAddress& server_address,
66 const RelayCredentials& credentials,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000067 int server_priority,
68 const std::string& origin) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000069 return new TurnPort(thread, factory, network, ip, min_port, max_port,
70 username, password, server_address, credentials,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000071 server_priority, origin);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000072 }
73
74 virtual ~TurnPort();
75
76 const ProtocolAddress& server_address() const { return server_address_; }
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000077 // Returns an empty address if the local address has not been assigned.
78 rtc::SocketAddress GetLocalAddress() const;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000079
honghaizb19eba32015-08-03 10:23:31 -070080 bool ready() const { return state_ == STATE_READY; }
81 bool connected() const {
82 return state_ == STATE_READY || state_ == STATE_CONNECTED;
83 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000084 const RelayCredentials& credentials() const { return credentials_; }
85
86 virtual void PrepareAddress();
87 virtual Connection* CreateConnection(
88 const Candidate& c, PortInterface::CandidateOrigin origin);
89 virtual int SendTo(const void* data, size_t size,
90 const rtc::SocketAddress& addr,
91 const rtc::PacketOptions& options,
92 bool payload);
93 virtual int SetOption(rtc::Socket::Option opt, int value);
94 virtual int GetOption(rtc::Socket::Option opt, int* value);
95 virtual int GetError();
96
97 virtual bool HandleIncomingPacket(
98 rtc::AsyncPacketSocket* socket, const char* data, size_t size,
99 const rtc::SocketAddress& remote_addr,
100 const rtc::PacketTime& packet_time) {
101 OnReadPacket(socket, data, size, remote_addr, packet_time);
102 return true;
103 }
104 virtual void OnReadPacket(rtc::AsyncPacketSocket* socket,
105 const char* data, size_t size,
106 const rtc::SocketAddress& remote_addr,
107 const rtc::PacketTime& packet_time);
108
Stefan Holmer55674ff2016-01-14 15:49:16 +0100109 virtual void OnSentPacket(rtc::AsyncPacketSocket* socket,
110 const rtc::SentPacket& sent_packet);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000111 virtual void OnReadyToSend(rtc::AsyncPacketSocket* socket);
Honghai Zhangf9945b22015-12-15 12:20:13 -0800112 virtual bool SupportsProtocol(const std::string& protocol) const {
113 // Turn port only connects to UDP candidates.
114 return protocol == UDP_PROTOCOL_NAME;
115 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000116
117 void OnSocketConnect(rtc::AsyncPacketSocket* socket);
118 void OnSocketClose(rtc::AsyncPacketSocket* socket, int error);
119
120
121 const std::string& hash() const { return hash_; }
122 const std::string& nonce() const { return nonce_; }
123
124 int error() const { return error_; }
125
126 void OnAllocateMismatch();
127
128 rtc::AsyncPacketSocket* socket() const {
129 return socket_;
130 }
131
honghaiz32f39962015-11-17 11:36:31 -0800132 // For testing only.
133 rtc::AsyncInvoker* invoker() { return &invoker_; }
134
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000135 // Signal with resolved server address.
136 // Parameters are port, server address and resolved server address.
137 // This signal will be sent only if server address is resolved successfully.
138 sigslot::signal3<TurnPort*,
139 const rtc::SocketAddress&,
140 const rtc::SocketAddress&> SignalResolvedServerAddress;
141
Honghai Zhangf67c5482015-12-11 15:16:54 -0800142 // All public methods/signals below are for testing only.
143 sigslot::signal2<TurnPort*, int> SignalTurnRefreshResult;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000144 sigslot::signal3<TurnPort*, const rtc::SocketAddress&, int>
145 SignalCreatePermissionResult;
honghaiz6b9ab922016-01-05 09:06:12 -0800146 void FlushRequests(int msg_type) { request_manager_.Flush(msg_type); }
147 bool HasRequests() { return !request_manager_.empty(); }
Honghai Zhangf67c5482015-12-11 15:16:54 -0800148 void set_credentials(RelayCredentials& credentials) {
149 credentials_ = credentials;
150 }
151 // Finds the turn entry with |address| and sets its channel id.
152 // Returns true if the entry is found.
153 bool SetEntryChannelId(const rtc::SocketAddress& address, int channel_id);
honghaiz9dfed792016-01-29 13:22:31 -0800154 // Visible for testing.
155 // Shuts down the turn port, usually because of some fatal errors.
156 void Close();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000157
158 protected:
159 TurnPort(rtc::Thread* thread,
160 rtc::PacketSocketFactory* factory,
161 rtc::Network* network,
162 rtc::AsyncPacketSocket* socket,
163 const std::string& username,
164 const std::string& password,
165 const ProtocolAddress& server_address,
166 const RelayCredentials& credentials,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000167 int server_priority,
168 const std::string& origin);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000169
170 TurnPort(rtc::Thread* thread,
171 rtc::PacketSocketFactory* factory,
172 rtc::Network* network,
173 const rtc::IPAddress& ip,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200174 uint16_t min_port,
175 uint16_t max_port,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000176 const std::string& username,
177 const std::string& password,
178 const ProtocolAddress& server_address,
179 const RelayCredentials& credentials,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000180 int server_priority,
181 const std::string& origin);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000182
183 private:
184 enum {
Honghai Zhangf67c5482015-12-11 15:16:54 -0800185 MSG_ALLOCATE_ERROR = MSG_FIRST_AVAILABLE,
guoweis@webrtc.org19e4e8d2015-01-10 02:41:32 +0000186 MSG_ALLOCATE_MISMATCH,
honghaiz6b9ab922016-01-05 09:06:12 -0800187 MSG_TRY_ALTERNATE_SERVER,
188 MSG_REFRESH_ERROR
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000189 };
190
191 typedef std::list<TurnEntry*> EntryList;
192 typedef std::map<rtc::Socket::Option, int> SocketOptionsMap;
193 typedef std::set<rtc::SocketAddress> AttemptedServerSet;
194
195 virtual void OnMessage(rtc::Message* pmsg);
196
197 bool CreateTurnClientSocket();
198
199 void set_nonce(const std::string& nonce) { nonce_ = nonce; }
200 void set_realm(const std::string& realm) {
201 if (realm != realm_) {
202 realm_ = realm;
203 UpdateHash();
204 }
205 }
206
honghaiz6b9ab922016-01-05 09:06:12 -0800207 void OnTurnRefreshError();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000208 bool SetAlternateServer(const rtc::SocketAddress& address);
209 void ResolveTurnAddress(const rtc::SocketAddress& address);
210 void OnResolveResult(rtc::AsyncResolverInterface* resolver);
211
212 void AddRequestAuthInfo(StunMessage* msg);
213 void OnSendStunPacket(const void* data, size_t size, StunRequest* request);
214 // Stun address from allocate success response.
215 // Currently used only for testing.
216 void OnStunAddress(const rtc::SocketAddress& address);
217 void OnAllocateSuccess(const rtc::SocketAddress& address,
218 const rtc::SocketAddress& stun_address);
219 void OnAllocateError();
220 void OnAllocateRequestTimeout();
221
222 void HandleDataIndication(const char* data, size_t size,
223 const rtc::PacketTime& packet_time);
224 void HandleChannelData(int channel_id, const char* data, size_t size,
225 const rtc::PacketTime& packet_time);
226 void DispatchPacket(const char* data, size_t size,
227 const rtc::SocketAddress& remote_addr,
228 ProtocolType proto, const rtc::PacketTime& packet_time);
229
230 bool ScheduleRefresh(int lifetime);
231 void SendRequest(StunRequest* request, int delay);
232 int Send(const void* data, size_t size,
233 const rtc::PacketOptions& options);
234 void UpdateHash();
235 bool UpdateNonce(StunMessage* response);
honghaizc463e202016-02-01 15:19:08 -0800236 void ResetNonce();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000237
238 bool HasPermission(const rtc::IPAddress& ipaddr) const;
239 TurnEntry* FindEntry(const rtc::SocketAddress& address) const;
240 TurnEntry* FindEntry(int channel_id) const;
honghaizc3e0fe72015-12-02 16:43:25 -0800241 bool EntryExists(TurnEntry* e);
honghaiz32f39962015-11-17 11:36:31 -0800242 void CreateOrRefreshEntry(const rtc::SocketAddress& address);
243 void DestroyEntry(TurnEntry* entry);
244 // Destroys the entry only if |timestamp| matches the destruction timestamp
245 // in |entry|.
honghaiz34b11eb2016-03-16 08:55:44 -0700246 void DestroyEntryIfNotCancelled(TurnEntry* entry, int64_t timestamp);
honghaiz32f39962015-11-17 11:36:31 -0800247 void ScheduleEntryDestruction(TurnEntry* entry);
248 void CancelEntryDestruction(TurnEntry* entry);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000249 void OnConnectionDestroyed(Connection* conn);
250
Honghai Zhangf67c5482015-12-11 15:16:54 -0800251 // Destroys the connection with remote address |address|. Returns true if
252 // a connection is found and destroyed.
253 bool DestroyConnection(const rtc::SocketAddress& address);
254
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000255 ProtocolAddress server_address_;
256 RelayCredentials credentials_;
257 AttemptedServerSet attempted_server_addresses_;
258
259 rtc::AsyncPacketSocket* socket_;
260 SocketOptionsMap socket_options_;
261 rtc::AsyncResolverInterface* resolver_;
262 int error_;
263
264 StunRequestManager request_manager_;
265 std::string realm_; // From 401/438 response message.
266 std::string nonce_; // From 401/438 response message.
267 std::string hash_; // Digest of username:realm:password
268
269 int next_channel_number_;
270 EntryList entries_;
271
honghaizb19eba32015-08-03 10:23:31 -0700272 PortState state_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000273 // By default the value will be set to 0. This value will be used in
274 // calculating the candidate priority.
275 int server_priority_;
276
277 // The number of retries made due to allocate mismatch error.
278 size_t allocate_mismatch_retries_;
279
honghaiz32f39962015-11-17 11:36:31 -0800280 rtc::AsyncInvoker invoker_;
281
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000282 friend class TurnEntry;
283 friend class TurnAllocateRequest;
284 friend class TurnRefreshRequest;
285 friend class TurnCreatePermissionRequest;
286 friend class TurnChannelBindRequest;
287};
288
289} // namespace cricket
290
291#endif // WEBRTC_P2P_BASE_TURNPORT_H_