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