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