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