1 /* 2 * libjingle 3 * Copyright 2004--2005, 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_RELAYSERVER_H_ 29 #define TALK_P2P_BASE_RELAYSERVER_H_ 30 31 #include <string> 32 #include <vector> 33 #include <map> 34 35 #include "talk/base/asyncudpsocket.h" 36 #include "talk/base/socketaddresspair.h" 37 #include "talk/base/thread.h" 38 #include "talk/base/time.h" 39 #include "talk/p2p/base/port.h" 40 #include "talk/p2p/base/stun.h" 41 42 namespace cricket { 43 44 class RelayServerBinding; 45 class RelayServerConnection; 46 47 // Relays traffic between connections to the server that are "bound" together. 48 // All connections created with the same username/password are bound together. 49 class RelayServer : public talk_base::MessageHandler, 50 public sigslot::has_slots<> { 51 public: 52 // Creates a server, which will use this thread to post messages to itself. 53 explicit RelayServer(talk_base::Thread* thread); 54 ~RelayServer(); 55 56 talk_base::Thread* thread() { return thread_; } 57 58 // Indicates whether we will print updates of the number of bindings. 59 bool log_bindings() const { return log_bindings_; } 60 void set_log_bindings(bool log_bindings) { log_bindings_ = log_bindings; } 61 62 // Updates the set of sockets that the server uses to talk to "internal" 63 // clients. These are clients that do the "port allocations". 64 void AddInternalSocket(talk_base::AsyncPacketSocket* socket); 65 void RemoveInternalSocket(talk_base::AsyncPacketSocket* socket); 66 67 // Updates the set of sockets that the server uses to talk to "external" 68 // clients. These are the clients that do not do allocations. They do not 69 // know that these addresses represent a relay server. 70 void AddExternalSocket(talk_base::AsyncPacketSocket* socket); 71 void RemoveExternalSocket(talk_base::AsyncPacketSocket* socket); 72 73 // Starts listening for connections on this sockets. When someone 74 // tries to connect, the connection will be accepted and a new 75 // internal socket will be added. 76 void AddInternalServerSocket(talk_base::AsyncSocket* socket, 77 cricket::ProtocolType proto); 78 79 // Removes this server socket from the list. 80 void RemoveInternalServerSocket(talk_base::AsyncSocket* socket); 81 82 // Methods for testing and debuging. 83 int GetConnectionCount() const; 84 talk_base::SocketAddressPair GetConnection(int connection) const; 85 bool HasConnection(const talk_base::SocketAddress& address) const; 86 87 private: 88 typedef std::vector<talk_base::AsyncPacketSocket*> SocketList; 89 typedef std::map<talk_base::AsyncSocket*, 90 cricket::ProtocolType> ServerSocketMap; 91 typedef std::map<std::string, RelayServerBinding*> BindingMap; 92 typedef std::map<talk_base::SocketAddressPair, 93 RelayServerConnection*> ConnectionMap; 94 95 talk_base::Thread* thread_; 96 bool log_bindings_; 97 SocketList internal_sockets_; 98 SocketList external_sockets_; 99 ServerSocketMap server_sockets_; 100 BindingMap bindings_; 101 ConnectionMap connections_; 102 103 // Called when a packet is received by the server on one of its sockets. 104 void OnInternalPacket(talk_base::AsyncPacketSocket* socket, 105 const char* bytes, size_t size, 106 const talk_base::SocketAddress& remote_addr); 107 void OnExternalPacket(talk_base::AsyncPacketSocket* socket, 108 const char* bytes, size_t size, 109 const talk_base::SocketAddress& remote_addr); 110 111 void OnReadEvent(talk_base::AsyncSocket* socket); 112 113 // Processes the relevant STUN request types from the client. 114 bool HandleStun(const char* bytes, size_t size, 115 const talk_base::SocketAddress& remote_addr, 116 talk_base::AsyncPacketSocket* socket, 117 std::string* username, StunMessage* msg); 118 void HandleStunAllocate(const char* bytes, size_t size, 119 const talk_base::SocketAddressPair& ap, 120 talk_base::AsyncPacketSocket* socket); 121 void HandleStun(RelayServerConnection* int_conn, const char* bytes, 122 size_t size); 123 void HandleStunAllocate(RelayServerConnection* int_conn, 124 const StunMessage& msg); 125 void HandleStunSend(RelayServerConnection* int_conn, const StunMessage& msg); 126 127 // Adds/Removes the a connection or binding. 128 void AddConnection(RelayServerConnection* conn); 129 void RemoveConnection(RelayServerConnection* conn); 130 void RemoveBinding(RelayServerBinding* binding); 131 132 // Handle messages in our worker thread. 133 void OnMessage(talk_base::Message *pmsg); 134 135 // Called when the timer for checking lifetime times out. 136 void OnTimeout(RelayServerBinding* binding); 137 138 // Accept connections on this server socket. 139 void AcceptConnection(talk_base::AsyncSocket* server_socket); 140 141 friend class RelayServerConnection; 142 friend class RelayServerBinding; 143 }; 144 145 // Maintains information about a connection to the server. Each connection is 146 // part of one and only one binding. 147 class RelayServerConnection { 148 public: 149 RelayServerConnection(RelayServerBinding* binding, 150 const talk_base::SocketAddressPair& addrs, 151 talk_base::AsyncPacketSocket* socket); 152 ~RelayServerConnection(); 153 154 RelayServerBinding* binding() { return binding_; } 155 talk_base::AsyncPacketSocket* socket() { return socket_; } 156 157 // Returns a pair where the source is the remote address and the destination 158 // is the local address. 159 const talk_base::SocketAddressPair& addr_pair() { return addr_pair_; } 160 161 // Sends a packet to the connected client. If an address is provided, then 162 // we make sure the internal client receives it, wrapping if necessary. 163 void Send(const char* data, size_t size); 164 void Send(const char* data, size_t size, 165 const talk_base::SocketAddress& ext_addr); 166 167 // Sends a STUN message to the connected client with no wrapping. 168 void SendStun(const StunMessage& msg); 169 void SendStunError(const StunMessage& request, int code, const char* desc); 170 171 // A locked connection is one for which we know the intended destination of 172 // any raw packet received. 173 bool locked() const { return locked_; } 174 void Lock(); 175 void Unlock(); 176 177 // Records the address that raw packets should be forwarded to (for internal 178 // packets only; for external, we already know where they go). 179 const talk_base::SocketAddress& default_destination() const { 180 return default_dest_; 181 } 182 void set_default_destination(const talk_base::SocketAddress& addr) { 183 default_dest_ = addr; 184 } 185 186 private: 187 RelayServerBinding* binding_; 188 talk_base::SocketAddressPair addr_pair_; 189 talk_base::AsyncPacketSocket* socket_; 190 bool locked_; 191 talk_base::SocketAddress default_dest_; 192 }; 193 194 // Records a set of internal and external connections that we relay between, 195 // or in other words, that are "bound" together. 196 class RelayServerBinding : public talk_base::MessageHandler { 197 public: 198 RelayServerBinding( 199 RelayServer* server, const std::string& username, 200 const std::string& password, uint32 lifetime); 201 virtual ~RelayServerBinding(); 202 203 RelayServer* server() { return server_; } 204 uint32 lifetime() { return lifetime_; } 205 const std::string& username() { return username_; } 206 const std::string& password() { return password_; } 207 const std::string& magic_cookie() { return magic_cookie_; } 208 209 // Adds/Removes a connection into the binding. 210 void AddInternalConnection(RelayServerConnection* conn); 211 void AddExternalConnection(RelayServerConnection* conn); 212 213 // We keep track of the use of each binding. If we detect that it was not 214 // used for longer than the lifetime, then we send a signal. 215 void NoteUsed(); 216 sigslot::signal1<RelayServerBinding*> SignalTimeout; 217 218 // Determines whether the given packet has the magic cookie present (in the 219 // right place). 220 bool HasMagicCookie(const char* bytes, size_t size) const; 221 222 // Determines the connection to use to send packets to or from the given 223 // external address. 224 RelayServerConnection* GetInternalConnection( 225 const talk_base::SocketAddress& ext_addr); 226 RelayServerConnection* GetExternalConnection( 227 const talk_base::SocketAddress& ext_addr); 228 229 // MessageHandler: 230 void OnMessage(talk_base::Message *pmsg); 231 232 private: 233 RelayServer* server_; 234 235 std::string username_; 236 std::string password_; 237 std::string magic_cookie_; 238 239 std::vector<RelayServerConnection*> internal_connections_; 240 std::vector<RelayServerConnection*> external_connections_; 241 242 uint32 lifetime_; 243 uint32 last_used_; 244 // TODO: bandwidth 245 }; 246 247 } // namespace cricket 248 249 #endif // TALK_P2P_BASE_RELAYSERVER_H_ 250