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