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_STUNPORT_H_ 29#define TALK_P2P_BASE_STUNPORT_H_ 30 31#include <string> 32 33#include "talk/p2p/base/port.h" 34#include "talk/p2p/base/stunrequest.h" 35#include "webrtc/base/asyncpacketsocket.h" 36 37// TODO(mallinath) - Rename stunport.cc|h to udpport.cc|h. 38namespace rtc { 39class AsyncResolver; 40class SignalThread; 41} 42 43namespace cricket { 44 45// Communicates using the address on the outside of a NAT. 46class UDPPort : public Port { 47 public: 48 static UDPPort* Create(rtc::Thread* thread, 49 rtc::PacketSocketFactory* factory, 50 rtc::Network* network, 51 rtc::AsyncPacketSocket* socket, 52 const std::string& username, 53 const std::string& password) { 54 UDPPort* port = new UDPPort(thread, factory, network, socket, 55 username, password); 56 if (!port->Init()) { 57 delete port; 58 port = NULL; 59 } 60 return port; 61 } 62 63 static UDPPort* Create(rtc::Thread* thread, 64 rtc::PacketSocketFactory* factory, 65 rtc::Network* network, 66 const rtc::IPAddress& ip, 67 int min_port, int max_port, 68 const std::string& username, 69 const std::string& password) { 70 UDPPort* port = new UDPPort(thread, factory, network, 71 ip, min_port, max_port, 72 username, password); 73 if (!port->Init()) { 74 delete port; 75 port = NULL; 76 } 77 return port; 78 } 79 virtual ~UDPPort(); 80 81 rtc::SocketAddress GetLocalAddress() const { 82 return socket_->GetLocalAddress(); 83 } 84 85 const ServerAddresses& server_addresses() const { 86 return server_addresses_; 87 } 88 void 89 set_server_addresses(const ServerAddresses& addresses) { 90 server_addresses_ = addresses; 91 } 92 93 virtual void PrepareAddress(); 94 95 virtual Connection* CreateConnection(const Candidate& address, 96 CandidateOrigin origin); 97 virtual int SetOption(rtc::Socket::Option opt, int value); 98 virtual int GetOption(rtc::Socket::Option opt, int* value); 99 virtual int GetError(); 100 101 virtual bool HandleIncomingPacket( 102 rtc::AsyncPacketSocket* socket, const char* data, size_t size, 103 const rtc::SocketAddress& remote_addr, 104 const rtc::PacketTime& packet_time) { 105 // All packets given to UDP port will be consumed. 106 OnReadPacket(socket, data, size, remote_addr, packet_time); 107 return true; 108 } 109 110 void set_stun_keepalive_delay(int delay) { 111 stun_keepalive_delay_ = delay; 112 } 113 int stun_keepalive_delay() const { 114 return stun_keepalive_delay_; 115 } 116 117 protected: 118 UDPPort(rtc::Thread* thread, rtc::PacketSocketFactory* factory, 119 rtc::Network* network, const rtc::IPAddress& ip, 120 int min_port, int max_port, 121 const std::string& username, const std::string& password); 122 123 UDPPort(rtc::Thread* thread, rtc::PacketSocketFactory* factory, 124 rtc::Network* network, rtc::AsyncPacketSocket* socket, 125 const std::string& username, const std::string& password); 126 127 bool Init(); 128 129 virtual int SendTo(const void* data, size_t size, 130 const rtc::SocketAddress& addr, 131 const rtc::PacketOptions& options, 132 bool payload); 133 134 void OnLocalAddressReady(rtc::AsyncPacketSocket* socket, 135 const rtc::SocketAddress& address); 136 void OnReadPacket(rtc::AsyncPacketSocket* socket, 137 const char* data, size_t size, 138 const rtc::SocketAddress& remote_addr, 139 const rtc::PacketTime& packet_time); 140 141 void OnReadyToSend(rtc::AsyncPacketSocket* socket); 142 143 // This method will send STUN binding request if STUN server address is set. 144 void MaybePrepareStunCandidate(); 145 146 void SendStunBindingRequests(); 147 148 private: 149 // A helper class which can be called repeatedly to resolve multiple 150 // addresses, as opposed to rtc::AsyncResolverInterface, which can only 151 // resolve one address per instance. 152 class AddressResolver : public sigslot::has_slots<> { 153 public: 154 explicit AddressResolver(rtc::PacketSocketFactory* factory); 155 ~AddressResolver(); 156 157 void Resolve(const rtc::SocketAddress& address); 158 bool GetResolvedAddress(const rtc::SocketAddress& input, 159 int family, 160 rtc::SocketAddress* output) const; 161 162 // The signal is sent when resolving the specified address is finished. The 163 // first argument is the input address, the second argument is the error 164 // or 0 if it succeeded. 165 sigslot::signal2<const rtc::SocketAddress&, int> SignalDone; 166 167 private: 168 typedef std::map<rtc::SocketAddress, 169 rtc::AsyncResolverInterface*> ResolverMap; 170 171 void OnResolveResult(rtc::AsyncResolverInterface* resolver); 172 173 rtc::PacketSocketFactory* socket_factory_; 174 ResolverMap resolvers_; 175 }; 176 177 // DNS resolution of the STUN server. 178 void ResolveStunAddress(const rtc::SocketAddress& stun_addr); 179 void OnResolveResult(const rtc::SocketAddress& input, int error); 180 181 void SendStunBindingRequest(const rtc::SocketAddress& stun_addr); 182 183 // Below methods handles binding request responses. 184 void OnStunBindingRequestSucceeded( 185 const rtc::SocketAddress& stun_server_addr, 186 const rtc::SocketAddress& stun_reflected_addr); 187 void OnStunBindingOrResolveRequestFailed( 188 const rtc::SocketAddress& stun_server_addr); 189 190 // Sends STUN requests to the server. 191 void OnSendPacket(const void* data, size_t size, StunRequest* req); 192 193 // TODO(mallinaht) - Move this up to cricket::Port when SignalAddressReady is 194 // changed to SignalPortReady. 195 void MaybeSetPortCompleteOrError(); 196 197 ServerAddresses server_addresses_; 198 ServerAddresses bind_request_succeeded_servers_; 199 ServerAddresses bind_request_failed_servers_; 200 StunRequestManager requests_; 201 rtc::AsyncPacketSocket* socket_; 202 int error_; 203 rtc::scoped_ptr<AddressResolver> resolver_; 204 bool ready_; 205 int stun_keepalive_delay_; 206 207 friend class StunBindingRequest; 208}; 209 210class StunPort : public UDPPort { 211 public: 212 static StunPort* Create( 213 rtc::Thread* thread, 214 rtc::PacketSocketFactory* factory, 215 rtc::Network* network, 216 const rtc::IPAddress& ip, 217 int min_port, int max_port, 218 const std::string& username, 219 const std::string& password, 220 const ServerAddresses& servers) { 221 StunPort* port = new StunPort(thread, factory, network, 222 ip, min_port, max_port, 223 username, password, servers); 224 if (!port->Init()) { 225 delete port; 226 port = NULL; 227 } 228 return port; 229 } 230 231 virtual ~StunPort() {} 232 233 virtual void PrepareAddress() { 234 SendStunBindingRequests(); 235 } 236 237 protected: 238 StunPort(rtc::Thread* thread, rtc::PacketSocketFactory* factory, 239 rtc::Network* network, const rtc::IPAddress& ip, 240 int min_port, int max_port, 241 const std::string& username, const std::string& password, 242 const ServerAddresses& servers) 243 : UDPPort(thread, factory, network, ip, min_port, max_port, username, 244 password) { 245 // UDPPort will set these to local udp, updating these to STUN. 246 set_type(STUN_PORT_TYPE); 247 set_server_addresses(servers); 248 } 249}; 250 251} // namespace cricket 252 253#endif // TALK_P2P_BASE_STUNPORT_H_ 254