Home | History | Annotate | Download | only in base
      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/messagequeue.h"
     37 #include "talk/base/sigslot.h"
     38 #include "talk/base/socketaddress.h"
     39 #include "talk/p2p/base/portinterface.h"
     40 
     41 namespace talk_base {
     42 class AsyncPacketSocket;
     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 
    128   void OnNewInternalConnection(talk_base::AsyncSocket* socket);
    129 
    130   // Accept connections on this server socket.
    131   void AcceptConnection(talk_base::AsyncSocket* server_socket);
    132   void OnInternalSocketClose(talk_base::AsyncPacketSocket* socket, int err);
    133 
    134   void HandleStunMessage(Connection* conn, const char* data, size_t size);
    135   void HandleBindingRequest(Connection* conn, const StunMessage* msg);
    136   void HandleAllocateRequest(Connection* conn, const TurnMessage* msg,
    137                              const std::string& key);
    138 
    139   bool GetKey(const StunMessage* msg, std::string* key);
    140   bool CheckAuthorization(Connection* conn, const StunMessage* msg,
    141                           const char* data, size_t size,
    142                           const std::string& key);
    143   std::string GenerateNonce() const;
    144   bool ValidateNonce(const std::string& nonce) const;
    145 
    146   Allocation* FindAllocation(Connection* conn);
    147   Allocation* CreateAllocation(Connection* conn, int proto,
    148                                const std::string& key);
    149 
    150   void SendErrorResponse(Connection* conn, const StunMessage* req,
    151                          int code, const std::string& reason);
    152 
    153   void SendErrorResponseWithRealmAndNonce(Connection* conn,
    154                                           const StunMessage* req,
    155                                           int code,
    156                                           const std::string& reason);
    157   void SendStun(Connection* conn, StunMessage* msg);
    158   void Send(Connection* conn, const talk_base::ByteBuffer& buf);
    159 
    160   void OnAllocationDestroyed(Allocation* allocation);
    161   void DestroyInternalSocket(talk_base::AsyncPacketSocket* socket);
    162 
    163   typedef std::map<talk_base::AsyncPacketSocket*,
    164                    ProtocolType> InternalSocketMap;
    165   typedef std::map<talk_base::AsyncSocket*,
    166                    ProtocolType> ServerSocketMap;
    167 
    168   talk_base::Thread* thread_;
    169   std::string nonce_key_;
    170   std::string realm_;
    171   std::string software_;
    172   TurnAuthInterface* auth_hook_;
    173   // otu - one-time-use. Server will respond with 438 if it's
    174   // sees the same nonce in next transaction.
    175   bool enable_otu_nonce_;
    176   InternalSocketMap server_sockets_;
    177   ServerSocketMap server_listen_sockets_;
    178   talk_base::scoped_ptr<talk_base::PacketSocketFactory>
    179       external_socket_factory_;
    180   talk_base::SocketAddress external_addr_;
    181   AllocationMap allocations_;
    182 };
    183 
    184 }  // namespace cricket
    185 
    186 #endif  // TALK_P2P_BASE_TURNSERVER_H_
    187