blob: ed281b46f003c002cba978f30eb121811bb88a53 [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>
kwiberg3ec46792016-04-27 07:22:53 -070016#include <memory>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000017#include <set>
18#include <string>
19
20#include "webrtc/p2p/base/portinterface.h"
21#include "webrtc/base/asyncpacketsocket.h"
22#include "webrtc/base/messagequeue.h"
23#include "webrtc/base/sigslot.h"
24#include "webrtc/base/socketaddress.h"
25
26namespace rtc {
jbauchf1f87202016-03-30 06:43:37 -070027class ByteBufferWriter;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000028class PacketSocketFactory;
29class Thread;
30}
31
32namespace cricket {
33
34class StunMessage;
35class TurnMessage;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000036class TurnServer;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000037
38// The default server port for TURN, as specified in RFC5766.
39const int TURN_SERVER_PORT = 3478;
40
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000041// Encapsulates the client's connection to the server.
42class TurnServerConnection {
43 public:
44 TurnServerConnection() : proto_(PROTO_UDP), socket_(NULL) {}
45 TurnServerConnection(const rtc::SocketAddress& src,
46 ProtocolType proto,
47 rtc::AsyncPacketSocket* socket);
48 const rtc::SocketAddress& src() const { return src_; }
49 rtc::AsyncPacketSocket* socket() { return socket_; }
50 bool operator==(const TurnServerConnection& t) const;
51 bool operator<(const TurnServerConnection& t) const;
52 std::string ToString() const;
53
54 private:
55 rtc::SocketAddress src_;
56 rtc::SocketAddress dst_;
57 cricket::ProtocolType proto_;
58 rtc::AsyncPacketSocket* socket_;
59};
60
61// Encapsulates a TURN allocation.
62// The object is created when an allocation request is received, and then
63// handles TURN messages (via HandleTurnMessage) and channel data messages
64// (via HandleChannelData) for this allocation when received by the server.
65// The object self-deletes and informs the server if its lifetime timer expires.
66class TurnServerAllocation : public rtc::MessageHandler,
67 public sigslot::has_slots<> {
68 public:
69 TurnServerAllocation(TurnServer* server_,
70 rtc::Thread* thread,
71 const TurnServerConnection& conn,
72 rtc::AsyncPacketSocket* server_socket,
73 const std::string& key);
74 virtual ~TurnServerAllocation();
75
76 TurnServerConnection* conn() { return &conn_; }
77 const std::string& key() const { return key_; }
78 const std::string& transaction_id() const { return transaction_id_; }
79 const std::string& username() const { return username_; }
80 const std::string& origin() const { return origin_; }
81 const std::string& last_nonce() const { return last_nonce_; }
82 void set_last_nonce(const std::string& nonce) { last_nonce_ = nonce; }
83
84 std::string ToString() const;
85
86 void HandleTurnMessage(const TurnMessage* msg);
87 void HandleChannelData(const char* data, size_t size);
88
89 sigslot::signal1<TurnServerAllocation*> SignalDestroyed;
90
91 private:
92 class Channel;
93 class Permission;
94 typedef std::list<Permission*> PermissionList;
95 typedef std::list<Channel*> ChannelList;
96
97 void HandleAllocateRequest(const TurnMessage* msg);
98 void HandleRefreshRequest(const TurnMessage* msg);
99 void HandleSendIndication(const TurnMessage* msg);
100 void HandleCreatePermissionRequest(const TurnMessage* msg);
101 void HandleChannelBindRequest(const TurnMessage* msg);
102
103 void OnExternalPacket(rtc::AsyncPacketSocket* socket,
104 const char* data, size_t size,
105 const rtc::SocketAddress& addr,
106 const rtc::PacketTime& packet_time);
107
108 static int ComputeLifetime(const TurnMessage* msg);
109 bool HasPermission(const rtc::IPAddress& addr);
110 void AddPermission(const rtc::IPAddress& addr);
111 Permission* FindPermission(const rtc::IPAddress& addr) const;
112 Channel* FindChannel(int channel_id) const;
113 Channel* FindChannel(const rtc::SocketAddress& addr) const;
114
115 void SendResponse(TurnMessage* msg);
116 void SendBadRequestResponse(const TurnMessage* req);
117 void SendErrorResponse(const TurnMessage* req, int code,
118 const std::string& reason);
119 void SendExternal(const void* data, size_t size,
120 const rtc::SocketAddress& peer);
121
122 void OnPermissionDestroyed(Permission* perm);
123 void OnChannelDestroyed(Channel* channel);
124 virtual void OnMessage(rtc::Message* msg);
125
126 TurnServer* server_;
127 rtc::Thread* thread_;
128 TurnServerConnection conn_;
kwiberg3ec46792016-04-27 07:22:53 -0700129 std::unique_ptr<rtc::AsyncPacketSocket> external_socket_;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000130 std::string key_;
131 std::string transaction_id_;
132 std::string username_;
133 std::string origin_;
134 std::string last_nonce_;
135 PermissionList perms_;
136 ChannelList channels_;
137};
138
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000139// An interface through which the MD5 credential hash can be retrieved.
140class TurnAuthInterface {
141 public:
142 // Gets HA1 for the specified user and realm.
143 // HA1 = MD5(A1) = MD5(username:realm:password).
144 // Return true if the given username and realm are valid, or false if not.
145 virtual bool GetKey(const std::string& username, const std::string& realm,
146 std::string* key) = 0;
Henrik Kjellander3fe372d2016-05-12 08:10:52 +0200147 virtual ~TurnAuthInterface() = default;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000148};
149
150// An interface enables Turn Server to control redirection behavior.
151class TurnRedirectInterface {
152 public:
153 virtual bool ShouldRedirect(const rtc::SocketAddress& address,
154 rtc::SocketAddress* out) = 0;
155 virtual ~TurnRedirectInterface() {}
156};
157
158// The core TURN server class. Give it a socket to listen on via
159// AddInternalServerSocket, and a factory to create external sockets via
160// SetExternalSocketFactory, and it's ready to go.
161// Not yet wired up: TCP support.
162class TurnServer : public sigslot::has_slots<> {
163 public:
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000164 typedef std::map<TurnServerConnection, TurnServerAllocation*> AllocationMap;
165
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000166 explicit TurnServer(rtc::Thread* thread);
167 ~TurnServer();
168
169 // Gets/sets the realm value to use for the server.
170 const std::string& realm() const { return realm_; }
171 void set_realm(const std::string& realm) { realm_ = realm; }
172
173 // Gets/sets the value for the SOFTWARE attribute for TURN messages.
174 const std::string& software() const { return software_; }
175 void set_software(const std::string& software) { software_ = software; }
176
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000177 const AllocationMap& allocations() const { return allocations_; }
178
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000179 // Sets the authentication callback; does not take ownership.
180 void set_auth_hook(TurnAuthInterface* auth_hook) { auth_hook_ = auth_hook; }
181
182 void set_redirect_hook(TurnRedirectInterface* redirect_hook) {
183 redirect_hook_ = redirect_hook;
184 }
185
186 void set_enable_otu_nonce(bool enable) { enable_otu_nonce_ = enable; }
187
deadbeef376e1232015-11-25 09:00:08 -0800188 // If set to true, reject CreatePermission requests to RFC1918 addresses.
189 void set_reject_private_addresses(bool filter) {
190 reject_private_addresses_ = filter;
191 }
192
Taylor Brandstetteref184702016-06-23 17:35:47 -0700193 void set_enable_permission_checks(bool enable) {
194 enable_permission_checks_ = enable;
195 }
196
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000197 // Starts listening for packets from internal clients.
198 void AddInternalSocket(rtc::AsyncPacketSocket* socket,
199 ProtocolType proto);
200 // Starts listening for the connections on this socket. When someone tries
201 // to connect, the connection will be accepted and a new internal socket
202 // will be added.
203 void AddInternalServerSocket(rtc::AsyncSocket* socket,
204 ProtocolType proto);
205 // Specifies the factory to use for creating external sockets.
206 void SetExternalSocketFactory(rtc::PacketSocketFactory* factory,
207 const rtc::SocketAddress& address);
honghaizc463e202016-02-01 15:19:08 -0800208 // For testing only.
honghaiz34b11eb2016-03-16 08:55:44 -0700209 std::string SetTimestampForNextNonce(int64_t timestamp) {
honghaizc463e202016-02-01 15:19:08 -0800210 ts_for_next_nonce_ = timestamp;
211 return GenerateNonce(timestamp);
212 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000213
214 private:
honghaiz34b11eb2016-03-16 08:55:44 -0700215 std::string GenerateNonce(int64_t now) const;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000216 void OnInternalPacket(rtc::AsyncPacketSocket* socket, const char* data,
217 size_t size, const rtc::SocketAddress& address,
218 const rtc::PacketTime& packet_time);
219
220 void OnNewInternalConnection(rtc::AsyncSocket* socket);
221
222 // Accept connections on this server socket.
223 void AcceptConnection(rtc::AsyncSocket* server_socket);
224 void OnInternalSocketClose(rtc::AsyncPacketSocket* socket, int err);
225
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000226 void HandleStunMessage(
227 TurnServerConnection* conn, const char* data, size_t size);
228 void HandleBindingRequest(TurnServerConnection* conn, const StunMessage* msg);
229 void HandleAllocateRequest(TurnServerConnection* conn, const TurnMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000230 const std::string& key);
231
232 bool GetKey(const StunMessage* msg, std::string* key);
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000233 bool CheckAuthorization(TurnServerConnection* conn, const StunMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000234 const char* data, size_t size,
235 const std::string& key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000236 bool ValidateNonce(const std::string& nonce) const;
237
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000238 TurnServerAllocation* FindAllocation(TurnServerConnection* conn);
239 TurnServerAllocation* CreateAllocation(
240 TurnServerConnection* conn, int proto, const std::string& key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000241
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000242 void SendErrorResponse(TurnServerConnection* conn, const StunMessage* req,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000243 int code, const std::string& reason);
244
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000245 void SendErrorResponseWithRealmAndNonce(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000246 const StunMessage* req,
247 int code,
248 const std::string& reason);
249
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000250 void SendErrorResponseWithAlternateServer(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000251 const StunMessage* req,
252 const rtc::SocketAddress& addr);
253
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000254 void SendStun(TurnServerConnection* conn, StunMessage* msg);
jbauchf1f87202016-03-30 06:43:37 -0700255 void Send(TurnServerConnection* conn, const rtc::ByteBufferWriter& buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000256
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000257 void OnAllocationDestroyed(TurnServerAllocation* allocation);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000258 void DestroyInternalSocket(rtc::AsyncPacketSocket* socket);
259
260 typedef std::map<rtc::AsyncPacketSocket*,
261 ProtocolType> InternalSocketMap;
262 typedef std::map<rtc::AsyncSocket*,
263 ProtocolType> ServerSocketMap;
264
265 rtc::Thread* thread_;
266 std::string nonce_key_;
267 std::string realm_;
268 std::string software_;
269 TurnAuthInterface* auth_hook_;
270 TurnRedirectInterface* redirect_hook_;
271 // otu - one-time-use. Server will respond with 438 if it's
272 // sees the same nonce in next transaction.
273 bool enable_otu_nonce_;
deadbeef376e1232015-11-25 09:00:08 -0800274 bool reject_private_addresses_ = false;
Taylor Brandstetteref184702016-06-23 17:35:47 -0700275 // Check for permission when receiving an external packet.
276 bool enable_permission_checks_ = true;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000277
278 InternalSocketMap server_sockets_;
279 ServerSocketMap server_listen_sockets_;
kwiberg3ec46792016-04-27 07:22:53 -0700280 std::unique_ptr<rtc::PacketSocketFactory> external_socket_factory_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000281 rtc::SocketAddress external_addr_;
282
283 AllocationMap allocations_;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000284
honghaizc463e202016-02-01 15:19:08 -0800285 // For testing only. If this is non-zero, the next NONCE will be generated
286 // from this value, and it will be reset to 0 after generating the NONCE.
honghaiz34b11eb2016-03-16 08:55:44 -0700287 int64_t ts_for_next_nonce_ = 0;
honghaizc463e202016-02-01 15:19:08 -0800288
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000289 friend class TurnServerAllocation;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000290};
291
292} // namespace cricket
293
294#endif // WEBRTC_P2P_BASE_TURNSERVER_H_