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