blob: 44a8b3827899904b514e8f23742361466a36713e [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_TURNSERVER_H_
12#define WEBRTC_P2P_BASE_TURNSERVER_H_
13
14#include <list>
15#include <map>
16#include <set>
17#include <string>
18
19#include "webrtc/p2p/base/portinterface.h"
20#include "webrtc/base/asyncpacketsocket.h"
21#include "webrtc/base/messagequeue.h"
22#include "webrtc/base/sigslot.h"
23#include "webrtc/base/socketaddress.h"
24
25namespace rtc {
26class ByteBuffer;
27class PacketSocketFactory;
28class Thread;
29}
30
31namespace cricket {
32
33class StunMessage;
34class TurnMessage;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000035class TurnServer;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000036
37// The default server port for TURN, as specified in RFC5766.
38const int TURN_SERVER_PORT = 3478;
39
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000040// Encapsulates the client's connection to the server.
41class TurnServerConnection {
42 public:
43 TurnServerConnection() : proto_(PROTO_UDP), socket_(NULL) {}
44 TurnServerConnection(const rtc::SocketAddress& src,
45 ProtocolType proto,
46 rtc::AsyncPacketSocket* socket);
47 const rtc::SocketAddress& src() const { return src_; }
48 rtc::AsyncPacketSocket* socket() { return socket_; }
49 bool operator==(const TurnServerConnection& t) const;
50 bool operator<(const TurnServerConnection& t) const;
51 std::string ToString() const;
52
53 private:
54 rtc::SocketAddress src_;
55 rtc::SocketAddress dst_;
56 cricket::ProtocolType proto_;
57 rtc::AsyncPacketSocket* socket_;
58};
59
60// Encapsulates a TURN allocation.
61// The object is created when an allocation request is received, and then
62// handles TURN messages (via HandleTurnMessage) and channel data messages
63// (via HandleChannelData) for this allocation when received by the server.
64// The object self-deletes and informs the server if its lifetime timer expires.
65class TurnServerAllocation : public rtc::MessageHandler,
66 public sigslot::has_slots<> {
67 public:
68 TurnServerAllocation(TurnServer* server_,
69 rtc::Thread* thread,
70 const TurnServerConnection& conn,
71 rtc::AsyncPacketSocket* server_socket,
72 const std::string& key);
73 virtual ~TurnServerAllocation();
74
75 TurnServerConnection* conn() { return &conn_; }
76 const std::string& key() const { return key_; }
77 const std::string& transaction_id() const { return transaction_id_; }
78 const std::string& username() const { return username_; }
79 const std::string& origin() const { return origin_; }
80 const std::string& last_nonce() const { return last_nonce_; }
81 void set_last_nonce(const std::string& nonce) { last_nonce_ = nonce; }
82
83 std::string ToString() const;
84
85 void HandleTurnMessage(const TurnMessage* msg);
86 void HandleChannelData(const char* data, size_t size);
87
88 sigslot::signal1<TurnServerAllocation*> SignalDestroyed;
89
90 private:
91 class Channel;
92 class Permission;
93 typedef std::list<Permission*> PermissionList;
94 typedef std::list<Channel*> ChannelList;
95
96 void HandleAllocateRequest(const TurnMessage* msg);
97 void HandleRefreshRequest(const TurnMessage* msg);
98 void HandleSendIndication(const TurnMessage* msg);
99 void HandleCreatePermissionRequest(const TurnMessage* msg);
100 void HandleChannelBindRequest(const TurnMessage* msg);
101
102 void OnExternalPacket(rtc::AsyncPacketSocket* socket,
103 const char* data, size_t size,
104 const rtc::SocketAddress& addr,
105 const rtc::PacketTime& packet_time);
106
107 static int ComputeLifetime(const TurnMessage* msg);
108 bool HasPermission(const rtc::IPAddress& addr);
109 void AddPermission(const rtc::IPAddress& addr);
110 Permission* FindPermission(const rtc::IPAddress& addr) const;
111 Channel* FindChannel(int channel_id) const;
112 Channel* FindChannel(const rtc::SocketAddress& addr) const;
113
114 void SendResponse(TurnMessage* msg);
115 void SendBadRequestResponse(const TurnMessage* req);
116 void SendErrorResponse(const TurnMessage* req, int code,
117 const std::string& reason);
118 void SendExternal(const void* data, size_t size,
119 const rtc::SocketAddress& peer);
120
121 void OnPermissionDestroyed(Permission* perm);
122 void OnChannelDestroyed(Channel* channel);
123 virtual void OnMessage(rtc::Message* msg);
124
125 TurnServer* server_;
126 rtc::Thread* thread_;
127 TurnServerConnection conn_;
128 rtc::scoped_ptr<rtc::AsyncPacketSocket> external_socket_;
129 std::string key_;
130 std::string transaction_id_;
131 std::string username_;
132 std::string origin_;
133 std::string last_nonce_;
134 PermissionList perms_;
135 ChannelList channels_;
136};
137
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000138// An interface through which the MD5 credential hash can be retrieved.
139class TurnAuthInterface {
140 public:
141 // Gets HA1 for the specified user and realm.
142 // HA1 = MD5(A1) = MD5(username:realm:password).
143 // Return true if the given username and realm are valid, or false if not.
144 virtual bool GetKey(const std::string& username, const std::string& realm,
145 std::string* key) = 0;
146};
147
148// An interface enables Turn Server to control redirection behavior.
149class TurnRedirectInterface {
150 public:
151 virtual bool ShouldRedirect(const rtc::SocketAddress& address,
152 rtc::SocketAddress* out) = 0;
153 virtual ~TurnRedirectInterface() {}
154};
155
156// The core TURN server class. Give it a socket to listen on via
157// AddInternalServerSocket, and a factory to create external sockets via
158// SetExternalSocketFactory, and it's ready to go.
159// Not yet wired up: TCP support.
160class TurnServer : public sigslot::has_slots<> {
161 public:
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000162 typedef std::map<TurnServerConnection, TurnServerAllocation*> AllocationMap;
163
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000164 explicit TurnServer(rtc::Thread* thread);
165 ~TurnServer();
166
167 // Gets/sets the realm value to use for the server.
168 const std::string& realm() const { return realm_; }
169 void set_realm(const std::string& realm) { realm_ = realm; }
170
171 // Gets/sets the value for the SOFTWARE attribute for TURN messages.
172 const std::string& software() const { return software_; }
173 void set_software(const std::string& software) { software_ = software; }
174
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000175 const AllocationMap& allocations() const { return allocations_; }
176
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000177 // Sets the authentication callback; does not take ownership.
178 void set_auth_hook(TurnAuthInterface* auth_hook) { auth_hook_ = auth_hook; }
179
180 void set_redirect_hook(TurnRedirectInterface* redirect_hook) {
181 redirect_hook_ = redirect_hook;
182 }
183
184 void set_enable_otu_nonce(bool enable) { enable_otu_nonce_ = enable; }
185
deadbeef376e1232015-11-25 09:00:08 -0800186 // If set to true, reject CreatePermission requests to RFC1918 addresses.
187 void set_reject_private_addresses(bool filter) {
188 reject_private_addresses_ = filter;
189 }
190
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000191 // Starts listening for packets from internal clients.
192 void AddInternalSocket(rtc::AsyncPacketSocket* socket,
193 ProtocolType proto);
194 // Starts listening for the connections on this socket. When someone tries
195 // to connect, the connection will be accepted and a new internal socket
196 // will be added.
197 void AddInternalServerSocket(rtc::AsyncSocket* socket,
198 ProtocolType proto);
199 // Specifies the factory to use for creating external sockets.
200 void SetExternalSocketFactory(rtc::PacketSocketFactory* factory,
201 const rtc::SocketAddress& address);
honghaizc463e202016-02-01 15:19:08 -0800202 // For testing only.
203 std::string SetTimestampForNextNonce(uint32_t timestamp) {
204 ts_for_next_nonce_ = timestamp;
205 return GenerateNonce(timestamp);
206 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000207
208 private:
honghaizc463e202016-02-01 15:19:08 -0800209 std::string GenerateNonce(uint32_t now) const;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000210 void OnInternalPacket(rtc::AsyncPacketSocket* socket, const char* data,
211 size_t size, const rtc::SocketAddress& address,
212 const rtc::PacketTime& packet_time);
213
214 void OnNewInternalConnection(rtc::AsyncSocket* socket);
215
216 // Accept connections on this server socket.
217 void AcceptConnection(rtc::AsyncSocket* server_socket);
218 void OnInternalSocketClose(rtc::AsyncPacketSocket* socket, int err);
219
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000220 void HandleStunMessage(
221 TurnServerConnection* conn, const char* data, size_t size);
222 void HandleBindingRequest(TurnServerConnection* conn, const StunMessage* msg);
223 void HandleAllocateRequest(TurnServerConnection* conn, const TurnMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000224 const std::string& key);
225
226 bool GetKey(const StunMessage* msg, std::string* key);
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000227 bool CheckAuthorization(TurnServerConnection* conn, const StunMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000228 const char* data, size_t size,
229 const std::string& key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000230 bool ValidateNonce(const std::string& nonce) const;
231
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000232 TurnServerAllocation* FindAllocation(TurnServerConnection* conn);
233 TurnServerAllocation* CreateAllocation(
234 TurnServerConnection* conn, int proto, const std::string& key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000235
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000236 void SendErrorResponse(TurnServerConnection* conn, const StunMessage* req,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000237 int code, const std::string& reason);
238
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000239 void SendErrorResponseWithRealmAndNonce(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000240 const StunMessage* req,
241 int code,
242 const std::string& reason);
243
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000244 void SendErrorResponseWithAlternateServer(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000245 const StunMessage* req,
246 const rtc::SocketAddress& addr);
247
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000248 void SendStun(TurnServerConnection* conn, StunMessage* msg);
249 void Send(TurnServerConnection* conn, const rtc::ByteBuffer& buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000250
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000251 void OnAllocationDestroyed(TurnServerAllocation* allocation);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000252 void DestroyInternalSocket(rtc::AsyncPacketSocket* socket);
253
254 typedef std::map<rtc::AsyncPacketSocket*,
255 ProtocolType> InternalSocketMap;
256 typedef std::map<rtc::AsyncSocket*,
257 ProtocolType> ServerSocketMap;
258
259 rtc::Thread* thread_;
260 std::string nonce_key_;
261 std::string realm_;
262 std::string software_;
263 TurnAuthInterface* auth_hook_;
264 TurnRedirectInterface* redirect_hook_;
265 // otu - one-time-use. Server will respond with 438 if it's
266 // sees the same nonce in next transaction.
267 bool enable_otu_nonce_;
deadbeef376e1232015-11-25 09:00:08 -0800268 bool reject_private_addresses_ = false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000269
270 InternalSocketMap server_sockets_;
271 ServerSocketMap server_listen_sockets_;
272 rtc::scoped_ptr<rtc::PacketSocketFactory>
273 external_socket_factory_;
274 rtc::SocketAddress external_addr_;
275
276 AllocationMap allocations_;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000277
honghaizc463e202016-02-01 15:19:08 -0800278 // For testing only. If this is non-zero, the next NONCE will be generated
279 // from this value, and it will be reset to 0 after generating the NONCE.
280 uint32_t ts_for_next_nonce_ = 0;
281
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000282 friend class TurnServerAllocation;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000283};
284
285} // namespace cricket
286
287#endif // WEBRTC_P2P_BASE_TURNSERVER_H_