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_TURNPORT_H_
29#define TALK_P2P_BASE_TURNPORT_H_
30
31#include <stdio.h>
32#include <list>
33#include <set>
34#include <string>
35
36#include "talk/p2p/base/port.h"
37#include "talk/p2p/client/basicportallocator.h"
38#include "webrtc/base/asyncpacketsocket.h"
39
40namespace rtc {
41class AsyncResolver;
42class SignalThread;
43}
44
45namespace cricket {
46
47extern const char TURN_PORT_TYPE[];
48class TurnAllocateRequest;
49class TurnEntry;
50
51class TurnPort : public Port {
52 public:
53  static TurnPort* Create(rtc::Thread* thread,
54                          rtc::PacketSocketFactory* factory,
55                          rtc::Network* network,
56                          rtc::AsyncPacketSocket* socket,
57                          const std::string& username,  // ice username.
58                          const std::string& password,  // ice password.
59                          const ProtocolAddress& server_address,
60                          const RelayCredentials& credentials,
61                          int server_priority) {
62    return new TurnPort(thread, factory, network, socket,
63                        username, password, server_address,
64                        credentials, server_priority);
65  }
66
67  static TurnPort* Create(rtc::Thread* thread,
68                          rtc::PacketSocketFactory* factory,
69                          rtc::Network* network,
70                          const rtc::IPAddress& ip,
71                          int min_port, int max_port,
72                          const std::string& username,  // ice username.
73                          const std::string& password,  // ice password.
74                          const ProtocolAddress& server_address,
75                          const RelayCredentials& credentials,
76                          int server_priority) {
77    return new TurnPort(thread, factory, network, ip, min_port, max_port,
78                        username, password, server_address, credentials,
79                        server_priority);
80  }
81
82  virtual ~TurnPort();
83
84  const ProtocolAddress& server_address() const { return server_address_; }
85
86  bool connected() const { return connected_; }
87  const RelayCredentials& credentials() const { return credentials_; }
88
89  virtual void PrepareAddress();
90  virtual Connection* CreateConnection(
91      const Candidate& c, PortInterface::CandidateOrigin origin);
92  virtual int SendTo(const void* data, size_t size,
93                     const rtc::SocketAddress& addr,
94                     const rtc::PacketOptions& options,
95                     bool payload);
96  virtual int SetOption(rtc::Socket::Option opt, int value);
97  virtual int GetOption(rtc::Socket::Option opt, int* value);
98  virtual int GetError();
99
100  virtual bool HandleIncomingPacket(
101      rtc::AsyncPacketSocket* socket, const char* data, size_t size,
102      const rtc::SocketAddress& remote_addr,
103      const rtc::PacketTime& packet_time) {
104    OnReadPacket(socket, data, size, remote_addr, packet_time);
105    return true;
106  }
107  virtual void OnReadPacket(rtc::AsyncPacketSocket* socket,
108                            const char* data, size_t size,
109                            const rtc::SocketAddress& remote_addr,
110                            const rtc::PacketTime& packet_time);
111
112  virtual void OnReadyToSend(rtc::AsyncPacketSocket* socket);
113
114  void OnSocketConnect(rtc::AsyncPacketSocket* socket);
115  void OnSocketClose(rtc::AsyncPacketSocket* socket, int error);
116
117
118  const std::string& hash() const { return hash_; }
119  const std::string& nonce() const { return nonce_; }
120
121  int error() const { return error_; }
122
123  void OnAllocateMismatch();
124
125  rtc::AsyncPacketSocket* socket() const {
126    return socket_;
127  }
128
129  // Signal with resolved server address.
130  // Parameters are port, server address and resolved server address.
131  // This signal will be sent only if server address is resolved successfully.
132  sigslot::signal3<TurnPort*,
133                   const rtc::SocketAddress&,
134                   const rtc::SocketAddress&> SignalResolvedServerAddress;
135
136  // This signal is only for testing purpose.
137  sigslot::signal3<TurnPort*, const rtc::SocketAddress&, int>
138      SignalCreatePermissionResult;
139
140 protected:
141  TurnPort(rtc::Thread* thread,
142           rtc::PacketSocketFactory* factory,
143           rtc::Network* network,
144           rtc::AsyncPacketSocket* socket,
145           const std::string& username,
146           const std::string& password,
147           const ProtocolAddress& server_address,
148           const RelayCredentials& credentials,
149           int server_priority);
150
151  TurnPort(rtc::Thread* thread,
152           rtc::PacketSocketFactory* factory,
153           rtc::Network* network,
154           const rtc::IPAddress& ip,
155           int min_port, int max_port,
156           const std::string& username,
157           const std::string& password,
158           const ProtocolAddress& server_address,
159           const RelayCredentials& credentials,
160           int server_priority);
161
162 private:
163  enum {
164    MSG_ERROR = MSG_FIRST_AVAILABLE,
165    MSG_ALLOCATE_MISMATCH
166  };
167
168  typedef std::list<TurnEntry*> EntryList;
169  typedef std::map<rtc::Socket::Option, int> SocketOptionsMap;
170  typedef std::set<rtc::SocketAddress> AttemptedServerSet;
171
172  virtual void OnMessage(rtc::Message* pmsg);
173
174  bool CreateTurnClientSocket();
175
176  void set_nonce(const std::string& nonce) { nonce_ = nonce; }
177  void set_realm(const std::string& realm) {
178    if (realm != realm_) {
179      realm_ = realm;
180      UpdateHash();
181    }
182  }
183
184  bool SetAlternateServer(const rtc::SocketAddress& address);
185  void ResolveTurnAddress(const rtc::SocketAddress& address);
186  void OnResolveResult(rtc::AsyncResolverInterface* resolver);
187
188  void AddRequestAuthInfo(StunMessage* msg);
189  void OnSendStunPacket(const void* data, size_t size, StunRequest* request);
190  // Stun address from allocate success response.
191  // Currently used only for testing.
192  void OnStunAddress(const rtc::SocketAddress& address);
193  void OnAllocateSuccess(const rtc::SocketAddress& address,
194                         const rtc::SocketAddress& stun_address);
195  void OnAllocateError();
196  void OnAllocateRequestTimeout();
197
198  void HandleDataIndication(const char* data, size_t size,
199                            const rtc::PacketTime& packet_time);
200  void HandleChannelData(int channel_id, const char* data, size_t size,
201                         const rtc::PacketTime& packet_time);
202  void DispatchPacket(const char* data, size_t size,
203      const rtc::SocketAddress& remote_addr,
204      ProtocolType proto, const rtc::PacketTime& packet_time);
205
206  bool ScheduleRefresh(int lifetime);
207  void SendRequest(StunRequest* request, int delay);
208  int Send(const void* data, size_t size,
209           const rtc::PacketOptions& options);
210  void UpdateHash();
211  bool UpdateNonce(StunMessage* response);
212
213  bool HasPermission(const rtc::IPAddress& ipaddr) const;
214  TurnEntry* FindEntry(const rtc::SocketAddress& address) const;
215  TurnEntry* FindEntry(int channel_id) const;
216  TurnEntry* CreateEntry(const rtc::SocketAddress& address);
217  void DestroyEntry(const rtc::SocketAddress& address);
218  void OnConnectionDestroyed(Connection* conn);
219
220  ProtocolAddress server_address_;
221  RelayCredentials credentials_;
222  AttemptedServerSet attempted_server_addresses_;
223
224  rtc::AsyncPacketSocket* socket_;
225  SocketOptionsMap socket_options_;
226  rtc::AsyncResolverInterface* resolver_;
227  int error_;
228
229  StunRequestManager request_manager_;
230  std::string realm_;       // From 401/438 response message.
231  std::string nonce_;       // From 401/438 response message.
232  std::string hash_;        // Digest of username:realm:password
233
234  int next_channel_number_;
235  EntryList entries_;
236
237  bool connected_;
238  // By default the value will be set to 0. This value will be used in
239  // calculating the candidate priority.
240  int server_priority_;
241
242  // The number of retries made due to allocate mismatch error.
243  size_t allocate_mismatch_retries_;
244
245  friend class TurnEntry;
246  friend class TurnAllocateRequest;
247  friend class TurnRefreshRequest;
248  friend class TurnCreatePermissionRequest;
249  friend class TurnChannelBindRequest;
250};
251
252}  // namespace cricket
253
254#endif  // TALK_P2P_BASE_TURNPORT_H_
255