1/*
2 * libjingle
3 * Copyright 2012, 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_BASE_TURNSERVER_H_
29#define TALK_P2P_BASE_TURNSERVER_H_
30
31#include <list>
32#include <map>
33#include <set>
34#include <string>
35
36#include "talk/p2p/base/portinterface.h"
37#include "webrtc/base/asyncpacketsocket.h"
38#include "webrtc/base/messagequeue.h"
39#include "webrtc/base/sigslot.h"
40#include "webrtc/base/socketaddress.h"
41
42namespace rtc {
43class ByteBuffer;
44class PacketSocketFactory;
45class Thread;
46}
47
48namespace cricket {
49
50class StunMessage;
51class TurnMessage;
52
53// The default server port for TURN, as specified in RFC5766.
54const int TURN_SERVER_PORT = 3478;
55
56// An interface through which the MD5 credential hash can be retrieved.
57class TurnAuthInterface {
58 public:
59  // Gets HA1 for the specified user and realm.
60  // HA1 = MD5(A1) = MD5(username:realm:password).
61  // Return true if the given username and realm are valid, or false if not.
62  virtual bool GetKey(const std::string& username, const std::string& realm,
63                      std::string* key) = 0;
64};
65
66// An interface enables Turn Server to control redirection behavior.
67class TurnRedirectInterface {
68 public:
69  virtual bool ShouldRedirect(const rtc::SocketAddress& address,
70                              rtc::SocketAddress* out) = 0;
71  virtual ~TurnRedirectInterface() {}
72};
73
74// The core TURN server class. Give it a socket to listen on via
75// AddInternalServerSocket, and a factory to create external sockets via
76// SetExternalSocketFactory, and it's ready to go.
77// Not yet wired up: TCP support.
78class TurnServer : public sigslot::has_slots<> {
79 public:
80  explicit TurnServer(rtc::Thread* thread);
81  ~TurnServer();
82
83  // Gets/sets the realm value to use for the server.
84  const std::string& realm() const { return realm_; }
85  void set_realm(const std::string& realm) { realm_ = realm; }
86
87  // Gets/sets the value for the SOFTWARE attribute for TURN messages.
88  const std::string& software() const { return software_; }
89  void set_software(const std::string& software) { software_ = software; }
90
91  // Sets the authentication callback; does not take ownership.
92  void set_auth_hook(TurnAuthInterface* auth_hook) { auth_hook_ = auth_hook; }
93
94  void set_redirect_hook(TurnRedirectInterface* redirect_hook) {
95    redirect_hook_ = redirect_hook;
96  }
97
98  void set_enable_otu_nonce(bool enable) { enable_otu_nonce_ = enable; }
99
100  // Starts listening for packets from internal clients.
101  void AddInternalSocket(rtc::AsyncPacketSocket* socket,
102                         ProtocolType proto);
103  // Starts listening for the connections on this socket. When someone tries
104  // to connect, the connection will be accepted and a new internal socket
105  // will be added.
106  void AddInternalServerSocket(rtc::AsyncSocket* socket,
107                               ProtocolType proto);
108  // Specifies the factory to use for creating external sockets.
109  void SetExternalSocketFactory(rtc::PacketSocketFactory* factory,
110                                const rtc::SocketAddress& address);
111
112 private:
113  // Encapsulates the client's connection to the server.
114  class Connection {
115   public:
116    Connection() : proto_(PROTO_UDP), socket_(NULL) {}
117    Connection(const rtc::SocketAddress& src,
118               ProtocolType proto,
119               rtc::AsyncPacketSocket* socket);
120    const rtc::SocketAddress& src() const { return src_; }
121    rtc::AsyncPacketSocket* socket() { return socket_; }
122    bool operator==(const Connection& t) const;
123    bool operator<(const Connection& t) const;
124    std::string ToString() const;
125
126   private:
127    rtc::SocketAddress src_;
128    rtc::SocketAddress dst_;
129    cricket::ProtocolType proto_;
130    rtc::AsyncPacketSocket* socket_;
131  };
132  class Allocation;
133  class Permission;
134  class Channel;
135  typedef std::map<Connection, Allocation*> AllocationMap;
136
137  void OnInternalPacket(rtc::AsyncPacketSocket* socket, const char* data,
138                        size_t size, const rtc::SocketAddress& address,
139                        const rtc::PacketTime& packet_time);
140
141  void OnNewInternalConnection(rtc::AsyncSocket* socket);
142
143  // Accept connections on this server socket.
144  void AcceptConnection(rtc::AsyncSocket* server_socket);
145  void OnInternalSocketClose(rtc::AsyncPacketSocket* socket, int err);
146
147  void HandleStunMessage(Connection* conn, const char* data, size_t size);
148  void HandleBindingRequest(Connection* conn, const StunMessage* msg);
149  void HandleAllocateRequest(Connection* conn, const TurnMessage* msg,
150                             const std::string& key);
151
152  bool GetKey(const StunMessage* msg, std::string* key);
153  bool CheckAuthorization(Connection* conn, const StunMessage* msg,
154                          const char* data, size_t size,
155                          const std::string& key);
156  std::string GenerateNonce() const;
157  bool ValidateNonce(const std::string& nonce) const;
158
159  Allocation* FindAllocation(Connection* conn);
160  Allocation* CreateAllocation(Connection* conn, int proto,
161                               const std::string& key);
162
163  void SendErrorResponse(Connection* conn, const StunMessage* req,
164                         int code, const std::string& reason);
165
166  void SendErrorResponseWithRealmAndNonce(Connection* conn,
167                                          const StunMessage* req,
168                                          int code,
169                                          const std::string& reason);
170
171  void SendErrorResponseWithAlternateServer(Connection* conn,
172                                            const StunMessage* req,
173                                            const rtc::SocketAddress& addr);
174
175  void SendStun(Connection* conn, StunMessage* msg);
176  void Send(Connection* conn, const rtc::ByteBuffer& buf);
177
178  void OnAllocationDestroyed(Allocation* allocation);
179  void DestroyInternalSocket(rtc::AsyncPacketSocket* socket);
180
181  typedef std::map<rtc::AsyncPacketSocket*,
182                   ProtocolType> InternalSocketMap;
183  typedef std::map<rtc::AsyncSocket*,
184                   ProtocolType> ServerSocketMap;
185
186  rtc::Thread* thread_;
187  std::string nonce_key_;
188  std::string realm_;
189  std::string software_;
190  TurnAuthInterface* auth_hook_;
191  TurnRedirectInterface* redirect_hook_;
192  // otu - one-time-use. Server will respond with 438 if it's
193  // sees the same nonce in next transaction.
194  bool enable_otu_nonce_;
195
196  InternalSocketMap server_sockets_;
197  ServerSocketMap server_listen_sockets_;
198  rtc::scoped_ptr<rtc::PacketSocketFactory>
199      external_socket_factory_;
200  rtc::SocketAddress external_addr_;
201
202  AllocationMap allocations_;
203};
204
205}  // namespace cricket
206
207#endif  // TALK_P2P_BASE_TURNSERVER_H_
208