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 <string>
33#include <list>
34
35#include "talk/p2p/base/port.h"
36#include "talk/p2p/client/basicportallocator.h"
37
38namespace talk_base {
39class AsyncPacketSocket;
40class AsyncResolver;
41class SignalThread;
42}
43
44namespace cricket {
45
46extern const char TURN_PORT_TYPE[];
47class TurnAllocateRequest;
48class TurnEntry;
49
50class TurnPort : public Port {
51 public:
52  static TurnPort* Create(talk_base::Thread* thread,
53                          talk_base::PacketSocketFactory* factory,
54                          talk_base::Network* network,
55                          const talk_base::IPAddress& ip,
56                          int min_port, int max_port,
57                          const std::string& username,  // ice username.
58                          const std::string& password,  // ice password.
59                          const ProtocolAddress& server_address,
60                          const RelayCredentials& credentials) {
61    return new TurnPort(thread, factory, network, ip, min_port, max_port,
62                        username, password, server_address, credentials);
63  }
64
65  virtual ~TurnPort();
66
67  const ProtocolAddress& server_address() const { return server_address_; }
68
69  bool connected() const { return connected_; }
70  const RelayCredentials& credentials() const { return credentials_; }
71
72  virtual void PrepareAddress();
73  virtual Connection* CreateConnection(
74      const Candidate& c, PortInterface::CandidateOrigin origin);
75  virtual int SendTo(const void* data, size_t size,
76                     const talk_base::SocketAddress& addr,
77                     bool payload);
78  virtual int SetOption(talk_base::Socket::Option opt, int value);
79  virtual int GetOption(talk_base::Socket::Option opt, int* value);
80  virtual int GetError();
81  virtual void OnReadPacket(talk_base::AsyncPacketSocket* socket,
82                            const char* data, size_t size,
83                            const talk_base::SocketAddress& remote_addr);
84  virtual void OnReadyToSend(talk_base::AsyncPacketSocket* socket);
85
86  void OnSocketConnect(talk_base::AsyncPacketSocket* socket);
87  void OnSocketClose(talk_base::AsyncPacketSocket* socket, int error);
88
89
90  const std::string& hash() const { return hash_; }
91  const std::string& nonce() const { return nonce_; }
92
93  // This signal is only for testing purpose.
94  sigslot::signal3<TurnPort*, const talk_base::SocketAddress&, int>
95      SignalCreatePermissionResult;
96
97 protected:
98  TurnPort(talk_base::Thread* thread,
99           talk_base::PacketSocketFactory* factory,
100           talk_base::Network* network,
101           const talk_base::IPAddress& ip,
102           int min_port, int max_port,
103           const std::string& username,
104           const std::string& password,
105           const ProtocolAddress& server_address,
106           const RelayCredentials& credentials);
107
108 private:
109  typedef std::list<TurnEntry*> EntryList;
110  typedef std::map<talk_base::Socket::Option, int> SocketOptionsMap;
111
112  virtual void OnMessage(talk_base::Message* pmsg);
113
114  void set_nonce(const std::string& nonce) { nonce_ = nonce; }
115  void set_realm(const std::string& realm) {
116    if (realm != realm_) {
117      realm_ = realm;
118      UpdateHash();
119    }
120  }
121
122  void ResolveTurnAddress(const talk_base::SocketAddress& address);
123  void OnResolveResult(talk_base::SignalThread* signal_thread);
124
125  void AddRequestAuthInfo(StunMessage* msg);
126  void OnSendStunPacket(const void* data, size_t size, StunRequest* request);
127  // Stun address from allocate success response.
128  // Currently used only for testing.
129  void OnStunAddress(const talk_base::SocketAddress& address);
130  void OnAllocateSuccess(const talk_base::SocketAddress& address);
131  void OnAllocateError();
132  void OnAllocateRequestTimeout();
133
134  void HandleDataIndication(const char* data, size_t size);
135  void HandleChannelData(int channel_id, const char* data, size_t size);
136  void DispatchPacket(const char* data, size_t size,
137      const talk_base::SocketAddress& remote_addr, ProtocolType proto);
138
139  bool ScheduleRefresh(int lifetime);
140  void SendRequest(StunRequest* request, int delay);
141  int Send(const void* data, size_t size);
142  void UpdateHash();
143  bool UpdateNonce(StunMessage* response);
144
145  bool HasPermission(const talk_base::IPAddress& ipaddr) const;
146  TurnEntry* FindEntry(const talk_base::SocketAddress& address) const;
147  TurnEntry* FindEntry(int channel_id) const;
148  TurnEntry* CreateEntry(const talk_base::SocketAddress& address);
149  void DestroyEntry(const talk_base::SocketAddress& address);
150  void OnConnectionDestroyed(Connection* conn);
151
152  ProtocolAddress server_address_;
153  RelayCredentials credentials_;
154
155  talk_base::scoped_ptr<talk_base::AsyncPacketSocket> socket_;
156  SocketOptionsMap socket_options_;
157  talk_base::AsyncResolver* resolver_;
158  int error_;
159
160  StunRequestManager request_manager_;
161  std::string realm_;       // From 401/438 response message.
162  std::string nonce_;       // From 401/438 response message.
163  std::string hash_;        // Digest of username:realm:password
164
165  int next_channel_number_;
166  EntryList entries_;
167
168  bool connected_;
169
170  friend class TurnEntry;
171  friend class TurnAllocateRequest;
172  friend class TurnRefreshRequest;
173  friend class TurnCreatePermissionRequest;
174  friend class TurnChannelBindRequest;
175};
176
177}  // namespace cricket
178
179#endif  // TALK_P2P_BASE_TURNPORT_H_
180