• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
25 namespace rtc {
26 class ByteBuffer;
27 class PacketSocketFactory;
28 class Thread;
29 }
30 
31 namespace cricket {
32 
33 class StunMessage;
34 class TurnMessage;
35 class TurnServer;
36 
37 // The default server port for TURN, as specified in RFC5766.
38 const int TURN_SERVER_PORT = 3478;
39 
40 // Encapsulates the client's connection to the server.
41 class TurnServerConnection {
42  public:
TurnServerConnection()43   TurnServerConnection() : proto_(PROTO_UDP), socket_(NULL) {}
44   TurnServerConnection(const rtc::SocketAddress& src,
45                        ProtocolType proto,
46                        rtc::AsyncPacketSocket* socket);
src()47   const rtc::SocketAddress& src() const { return src_; }
socket()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.
65 class 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 
conn()75   TurnServerConnection* conn() { return &conn_; }
key()76   const std::string& key() const { return key_; }
transaction_id()77   const std::string& transaction_id() const { return transaction_id_; }
username()78   const std::string& username() const { return username_; }
origin()79   const std::string& origin() const { return origin_; }
last_nonce()80   const std::string& last_nonce() const { return last_nonce_; }
set_last_nonce(const std::string & 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 
138 // An interface through which the MD5 credential hash can be retrieved.
139 class 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.
149 class TurnRedirectInterface {
150  public:
151   virtual bool ShouldRedirect(const rtc::SocketAddress& address,
152                               rtc::SocketAddress* out) = 0;
~TurnRedirectInterface()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.
160 class TurnServer : public sigslot::has_slots<> {
161  public:
162   typedef std::map<TurnServerConnection, TurnServerAllocation*> AllocationMap;
163 
164   explicit TurnServer(rtc::Thread* thread);
165   ~TurnServer();
166 
167   // Gets/sets the realm value to use for the server.
realm()168   const std::string& realm() const { return realm_; }
set_realm(const std::string & realm)169   void set_realm(const std::string& realm) { realm_ = realm; }
170 
171   // Gets/sets the value for the SOFTWARE attribute for TURN messages.
software()172   const std::string& software() const { return software_; }
set_software(const std::string & software)173   void set_software(const std::string& software) { software_ = software; }
174 
allocations()175   const AllocationMap& allocations() const { return allocations_; }
176 
177   // Sets the authentication callback; does not take ownership.
set_auth_hook(TurnAuthInterface * auth_hook)178   void set_auth_hook(TurnAuthInterface* auth_hook) { auth_hook_ = auth_hook; }
179 
set_redirect_hook(TurnRedirectInterface * redirect_hook)180   void set_redirect_hook(TurnRedirectInterface* redirect_hook) {
181     redirect_hook_ = redirect_hook;
182   }
183 
set_enable_otu_nonce(bool enable)184   void set_enable_otu_nonce(bool enable) { enable_otu_nonce_ = enable; }
185 
186   // If set to true, reject CreatePermission requests to RFC1918 addresses.
set_reject_private_addresses(bool filter)187   void set_reject_private_addresses(bool filter) {
188     reject_private_addresses_ = filter;
189   }
190 
191   // 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);
202 
203  private:
204   void OnInternalPacket(rtc::AsyncPacketSocket* socket, const char* data,
205                         size_t size, const rtc::SocketAddress& address,
206                         const rtc::PacketTime& packet_time);
207 
208   void OnNewInternalConnection(rtc::AsyncSocket* socket);
209 
210   // Accept connections on this server socket.
211   void AcceptConnection(rtc::AsyncSocket* server_socket);
212   void OnInternalSocketClose(rtc::AsyncPacketSocket* socket, int err);
213 
214   void HandleStunMessage(
215       TurnServerConnection* conn, const char* data, size_t size);
216   void HandleBindingRequest(TurnServerConnection* conn, const StunMessage* msg);
217   void HandleAllocateRequest(TurnServerConnection* conn, const TurnMessage* msg,
218                              const std::string& key);
219 
220   bool GetKey(const StunMessage* msg, std::string* key);
221   bool CheckAuthorization(TurnServerConnection* conn, const StunMessage* msg,
222                           const char* data, size_t size,
223                           const std::string& key);
224   std::string GenerateNonce() const;
225   bool ValidateNonce(const std::string& nonce) const;
226 
227   TurnServerAllocation* FindAllocation(TurnServerConnection* conn);
228   TurnServerAllocation* CreateAllocation(
229       TurnServerConnection* conn, int proto, const std::string& key);
230 
231   void SendErrorResponse(TurnServerConnection* conn, const StunMessage* req,
232                          int code, const std::string& reason);
233 
234   void SendErrorResponseWithRealmAndNonce(TurnServerConnection* conn,
235                                           const StunMessage* req,
236                                           int code,
237                                           const std::string& reason);
238 
239   void SendErrorResponseWithAlternateServer(TurnServerConnection* conn,
240                                             const StunMessage* req,
241                                             const rtc::SocketAddress& addr);
242 
243   void SendStun(TurnServerConnection* conn, StunMessage* msg);
244   void Send(TurnServerConnection* conn, const rtc::ByteBuffer& buf);
245 
246   void OnAllocationDestroyed(TurnServerAllocation* allocation);
247   void DestroyInternalSocket(rtc::AsyncPacketSocket* socket);
248 
249   typedef std::map<rtc::AsyncPacketSocket*,
250                    ProtocolType> InternalSocketMap;
251   typedef std::map<rtc::AsyncSocket*,
252                    ProtocolType> ServerSocketMap;
253 
254   rtc::Thread* thread_;
255   std::string nonce_key_;
256   std::string realm_;
257   std::string software_;
258   TurnAuthInterface* auth_hook_;
259   TurnRedirectInterface* redirect_hook_;
260   // otu - one-time-use. Server will respond with 438 if it's
261   // sees the same nonce in next transaction.
262   bool enable_otu_nonce_;
263   bool reject_private_addresses_ = false;
264 
265   InternalSocketMap server_sockets_;
266   ServerSocketMap server_listen_sockets_;
267   rtc::scoped_ptr<rtc::PacketSocketFactory>
268       external_socket_factory_;
269   rtc::SocketAddress external_addr_;
270 
271   AllocationMap allocations_;
272 
273   friend class TurnServerAllocation;
274 };
275 
276 }  // namespace cricket
277 
278 #endif  // WEBRTC_P2P_BASE_TURNSERVER_H_
279