1269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org/* 2269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * 4269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * Use of this source code is governed by a BSD-style license 5269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 6269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 7269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * in the file PATENTS. All contributing project authors may 8269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org */ 10269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 11269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/stunport.h" 12269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 13269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/common.h" 14269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/portallocator.h" 15269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/stun.h" 169af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh#include "webrtc/base/checks.h" 17269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/common.h" 18269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/helpers.h" 19fe3bc9d5aeffed8bbfb34c330d8b991abd1a1abaGuo-wei Shieh#include "webrtc/base/ipaddress.h" 20269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/logging.h" 21269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/nethelpers.h" 22269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 23269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgnamespace cricket { 24269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 25269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// TODO: Move these to a common place (used in relayport too) 26269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgconst int KEEPALIVE_DELAY = 10 * 1000; // 10 seconds - sort timeouts 27269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgconst int RETRY_TIMEOUT = 50 * 1000; // ICE says 50 secs 2845b0efd378abef87676e6ec55516b10ce583ddachonghaiz// Stop sending STUN binding requests after this amount of time 2945b0efd378abef87676e6ec55516b10ce583ddachonghaiz// (in milliseconds) because the connection binding requests should keep 3045b0efd378abef87676e6ec55516b10ce583ddachonghaiz// the NAT binding alive. 3145b0efd378abef87676e6ec55516b10ce583ddachonghaizconst int KEEP_ALIVE_TIMEOUT = 2 * 60 * 1000; // 2 minutes 32269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 33269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Handles a binding request sent to the STUN server. 34269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass StunBindingRequest : public StunRequest { 35269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public: 3645b0efd378abef87676e6ec55516b10ce583ddachonghaiz StunBindingRequest(UDPPort* port, 3745b0efd378abef87676e6ec55516b10ce583ddachonghaiz const rtc::SocketAddress& addr, 3845b0efd378abef87676e6ec55516b10ce583ddachonghaiz uint32_t deadline) 3945b0efd378abef87676e6ec55516b10ce583ddachonghaiz : port_(port), server_addr_(addr), deadline_(deadline) { 40269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org start_time_ = rtc::Time(); 41269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 42269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 43269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org virtual ~StunBindingRequest() { 44269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 45269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 46269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& server_addr() const { return server_addr_; } 47269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 481cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher virtual void Prepare(StunMessage* request) override { 49269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request->SetType(STUN_BINDING_REQUEST); 50269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 51269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 521cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher virtual void OnResponse(StunMessage* response) override { 53269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunAddressAttribute* addr_attr = 54269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetAddress(STUN_ATTR_MAPPED_ADDRESS); 55269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!addr_attr) { 56269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_ERROR) << "Binding response missing mapped address."; 57269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else if (addr_attr->family() != STUN_ADDRESS_IPV4 && 58269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org addr_attr->family() != STUN_ADDRESS_IPV6) { 59269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_ERROR) << "Binding address has bad family"; 60269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 61269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress addr(addr_attr->ipaddr(), addr_attr->port()); 62269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->OnStunBindingRequestSucceeded(server_addr_, addr); 63269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 64269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 65269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // We will do a keep-alive regardless of whether this request succeeds. 6645b0efd378abef87676e6ec55516b10ce583ddachonghaiz // It will be stopped after |deadline_| mostly to conserve the battery life. 6745b0efd378abef87676e6ec55516b10ce583ddachonghaiz if (rtc::Time() <= deadline_) { 68269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->requests_.SendDelayed( 6945b0efd378abef87676e6ec55516b10ce583ddachonghaiz new StunBindingRequest(port_, server_addr_, deadline_), 70269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->stun_keepalive_delay()); 71269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 72269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 73269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 741cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher virtual void OnErrorResponse(StunMessage* response) override { 75269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunErrorCodeAttribute* attr = response->GetErrorCode(); 76269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!attr) { 77269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_ERROR) << "Bad allocate response error code"; 78269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 79269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_ERROR) << "Binding error response:" 80269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << " class=" << attr->eclass() 81269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << " number=" << attr->number() 82269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << " reason='" << attr->reason() << "'"; 83269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 84269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 85269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->OnStunBindingOrResolveRequestFailed(server_addr_); 86269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 8745b0efd378abef87676e6ec55516b10ce583ddachonghaiz uint32_t now = rtc::Time(); 8845b0efd378abef87676e6ec55516b10ce583ddachonghaiz if (now <= deadline_ && rtc::TimeDiff(now, start_time_) <= RETRY_TIMEOUT) { 89269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->requests_.SendDelayed( 9045b0efd378abef87676e6ec55516b10ce583ddachonghaiz new StunBindingRequest(port_, server_addr_, deadline_), 91269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->stun_keepalive_delay()); 92269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 93269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 94269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 951cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher virtual void OnTimeout() override { 96269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_ERROR) << "Binding request timed out from " 97269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << port_->GetLocalAddress().ToSensitiveString() 98269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << " (" << port_->Network()->name() << ")"; 99269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 100269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->OnStunBindingOrResolveRequestFailed(server_addr_); 101269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 102269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 103269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private: 104269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org UDPPort* port_; 105269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress server_addr_; 1060c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint32_t start_time_; 10745b0efd378abef87676e6ec55516b10ce583ddachonghaiz uint32_t deadline_; 108269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}; 109269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 110269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgUDPPort::AddressResolver::AddressResolver( 111269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::PacketSocketFactory* factory) 112269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org : socket_factory_(factory) {} 113269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 114269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgUDPPort::AddressResolver::~AddressResolver() { 115269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org for (ResolverMap::iterator it = resolvers_.begin(); 116269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org it != resolvers_.end(); ++it) { 1178a4f547dadecb1ec4e1647e0ca1ad74be3048801Guo-wei Shieh // TODO(guoweis): Change to asynchronous DNS resolution to prevent the hang 1188a4f547dadecb1ec4e1647e0ca1ad74be3048801Guo-wei Shieh // when passing true to the Destroy() which is a safer way to avoid the code 1198a4f547dadecb1ec4e1647e0ca1ad74be3048801Guo-wei Shieh // unloaded before the thread exits. Please see webrtc bug 5139. 1208a4f547dadecb1ec4e1647e0ca1ad74be3048801Guo-wei Shieh it->second->Destroy(false); 121269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 122269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::AddressResolver::Resolve( 125269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& address) { 126269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (resolvers_.find(address) != resolvers_.end()) 127269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 128269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 129269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::AsyncResolverInterface* resolver = 130269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_factory_->CreateAsyncResolver(); 131269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolvers_.insert( 132269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org std::pair<rtc::SocketAddress, rtc::AsyncResolverInterface*>( 133269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org address, resolver)); 134269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 135269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver->SignalDone.connect(this, 136269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org &UDPPort::AddressResolver::OnResolveResult); 137269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 138269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver->Start(address); 139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 140269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool UDPPort::AddressResolver::GetResolvedAddress( 142269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& input, 143269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int family, 144269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress* output) const { 145269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ResolverMap::const_iterator it = resolvers_.find(input); 146269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (it == resolvers_.end()) 147269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return false; 148269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 149269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return it->second->GetResolvedAddress(family, output); 150269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 151269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 152269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::AddressResolver::OnResolveResult( 153269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::AsyncResolverInterface* resolver) { 154269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org for (ResolverMap::iterator it = resolvers_.begin(); 155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org it != resolvers_.end(); ++it) { 156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (it->second == resolver) { 157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SignalDone(it->first, resolver->GetError()); 158269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 160269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 161269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 162269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 163269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgUDPPort::UDPPort(rtc::Thread* thread, 164269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::PacketSocketFactory* factory, 165269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::Network* network, 166269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::AsyncPacketSocket* socket, 167332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org const std::string& username, 1680ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org const std::string& password, 169fe3bc9d5aeffed8bbfb34c330d8b991abd1a1abaGuo-wei Shieh const std::string& origin, 1709af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh bool emit_local_for_anyaddress) 1719af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh : Port(thread, 1729af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh factory, 1739af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh network, 1749af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh socket->GetLocalAddress().ipaddr(), 1759af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh username, 1769af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh password), 177269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org requests_(thread), 178269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_(socket), 179269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org error_(0), 180269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ready_(false), 181fe3bc9d5aeffed8bbfb34c330d8b991abd1a1abaGuo-wei Shieh stun_keepalive_delay_(KEEPALIVE_DELAY), 1829af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh emit_local_for_anyaddress_(emit_local_for_anyaddress) { 1830ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org requests_.set_origin(origin); 184269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 185269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 186269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgUDPPort::UDPPort(rtc::Thread* thread, 187269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::PacketSocketFactory* factory, 188269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::Network* network, 189332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org const rtc::IPAddress& ip, 1900c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint16_t min_port, 1910c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint16_t max_port, 192332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org const std::string& username, 1930ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org const std::string& password, 194fe3bc9d5aeffed8bbfb34c330d8b991abd1a1abaGuo-wei Shieh const std::string& origin, 1959af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh bool emit_local_for_anyaddress) 1960c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström : Port(thread, 1970c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström LOCAL_PORT_TYPE, 1980c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström factory, 1990c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström network, 2000c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström ip, 2010c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström min_port, 2020c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström max_port, 2030c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström username, 2040c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström password), 205269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org requests_(thread), 206269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_(NULL), 207269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org error_(0), 208269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ready_(false), 209fe3bc9d5aeffed8bbfb34c330d8b991abd1a1abaGuo-wei Shieh stun_keepalive_delay_(KEEPALIVE_DELAY), 2109af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh emit_local_for_anyaddress_(emit_local_for_anyaddress) { 2110ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org requests_.set_origin(origin); 212269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 213269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 214269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool UDPPort::Init() { 215269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!SharedSocket()) { 216269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(socket_ == NULL); 217269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_ = socket_factory()->CreateUdpSocket( 218269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress(ip(), 0), min_port(), max_port()); 219269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!socket_) { 220269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "UDP socket creation failed"; 221269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return false; 222269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 223269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_->SignalReadPacket.connect(this, &UDPPort::OnReadPacket); 224269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 225c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan socket_->SignalSentPacket.connect(this, &UDPPort::OnSentPacket); 226269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_->SignalReadyToSend.connect(this, &UDPPort::OnReadyToSend); 227269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_->SignalAddressReady.connect(this, &UDPPort::OnLocalAddressReady); 228269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org requests_.SignalSendPacket.connect(this, &UDPPort::OnSendPacket); 229269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return true; 230269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 231269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 232269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgUDPPort::~UDPPort() { 233269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!SharedSocket()) 234269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org delete socket_; 235269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 236269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 237269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::PrepareAddress() { 238269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(requests_.empty()); 239269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (socket_->GetState() == rtc::AsyncPacketSocket::STATE_BOUND) { 240269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnLocalAddressReady(socket_, socket_->GetLocalAddress()); 241269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 242269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 243269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 244269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::MaybePrepareStunCandidate() { 245269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Sending binding request to the STUN server if address is available to 246269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // prepare STUN candidate. 247269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!server_addresses_.empty()) { 248269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SendStunBindingRequests(); 249269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 250269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Port is done allocating candidates. 251269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org MaybeSetPortCompleteOrError(); 252269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 253269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 254269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 255269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgConnection* UDPPort::CreateConnection(const Candidate& address, 256f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang CandidateOrigin origin) { 257f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang if (!SupportsProtocol(address.protocol())) { 258269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return NULL; 259f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang } 260269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 261269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!IsCompatibleAddress(address.address())) { 262269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return NULL; 263269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 264269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 265269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (SharedSocket() && Candidates()[0].type() != LOCAL_PORT_TYPE) { 266269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(false); 267269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return NULL; 268269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 269269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 270269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org Connection* conn = new ProxyConnection(this, 0, address); 271269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org AddConnection(conn); 272269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return conn; 273269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 274269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 275269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint UDPPort::SendTo(const void* data, size_t size, 276269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& addr, 277269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::PacketOptions& options, 278269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org bool payload) { 279269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int sent = socket_->SendTo(data, size, addr, options); 280269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (sent < 0) { 281269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org error_ = socket_->GetError(); 282269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_ERROR, this) << "UDP send of " << size 283269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << " bytes failed with error " << error_; 284269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 285269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return sent; 286269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 287269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 288269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint UDPPort::SetOption(rtc::Socket::Option opt, int value) { 289269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return socket_->SetOption(opt, value); 290269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 291269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 292269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint UDPPort::GetOption(rtc::Socket::Option opt, int* value) { 293269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return socket_->GetOption(opt, value); 294269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 295269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 296269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint UDPPort::GetError() { 297269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return error_; 298269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 299269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 300269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::OnLocalAddressReady(rtc::AsyncPacketSocket* socket, 301269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& address) { 302fe3bc9d5aeffed8bbfb34c330d8b991abd1a1abaGuo-wei Shieh // When adapter enumeration is disabled and binding to the any address, the 3039af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh // default local address will be issued as a candidate instead if 3049af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh // |emit_local_for_anyaddress| is true. This is to allow connectivity for 3059af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh // applications which absolutely requires a HOST candidate. 306fe3bc9d5aeffed8bbfb34c330d8b991abd1a1abaGuo-wei Shieh rtc::SocketAddress addr = address; 307e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh 308e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh // If MaybeSetDefaultLocalAddress fails, we keep the "any" IP so that at 309e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh // least the port is listening. 3109af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh MaybeSetDefaultLocalAddress(&addr); 311fe3bc9d5aeffed8bbfb34c330d8b991abd1a1abaGuo-wei Shieh 312fe3bc9d5aeffed8bbfb34c330d8b991abd1a1abaGuo-wei Shieh AddAddress(addr, addr, rtc::SocketAddress(), UDP_PROTOCOL_NAME, "", "", 3133d564c10157d7de1d2d4236f4e2a13ff1363d52bGuo-wei Shieh LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST, 0, false); 314269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org MaybePrepareStunCandidate(); 315269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 316269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 31720a34619080005c3b0e49d85b307113ea2b180c3tfarinavoid UDPPort::OnReadPacket(rtc::AsyncPacketSocket* socket, 31820a34619080005c3b0e49d85b307113ea2b180c3tfarina const char* data, 31920a34619080005c3b0e49d85b307113ea2b180c3tfarina size_t size, 32020a34619080005c3b0e49d85b307113ea2b180c3tfarina const rtc::SocketAddress& remote_addr, 32120a34619080005c3b0e49d85b307113ea2b180c3tfarina const rtc::PacketTime& packet_time) { 322269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(socket == socket_); 32320a34619080005c3b0e49d85b307113ea2b180c3tfarina ASSERT(!remote_addr.IsUnresolvedIP()); 324269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 325269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Look for a response from the STUN server. 326269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Even if the response doesn't match one of our outstanding requests, we 327269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // will eat it because it might be a response to a retransmitted packet, and 328269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // we already cleared the request when we got the first response. 329269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (server_addresses_.find(remote_addr) != server_addresses_.end()) { 330269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org requests_.CheckResponse(data, size); 331269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 332269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 333269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 334269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (Connection* conn = GetConnection(remote_addr)) { 335269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org conn->OnReadPacket(data, size, packet_time); 336269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 337269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org Port::OnReadPacket(data, size, remote_addr, PROTO_UDP); 338269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 339269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 340269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 341c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefanvoid UDPPort::OnSentPacket(rtc::AsyncPacketSocket* socket, 342c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan const rtc::SentPacket& sent_packet) { 34355674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer PortInterface::SignalSentPacket(sent_packet); 344c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan} 345c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan 346269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) { 347269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org Port::OnReadyToSend(); 348269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 349269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 350269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::SendStunBindingRequests() { 351269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // We will keep pinging the stun server to make sure our NAT pin-hole stays 35245b0efd378abef87676e6ec55516b10ce583ddachonghaiz // open until the deadline (specified in SendStunBindingRequest). 353269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(requests_.empty()); 354269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 355269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org for (ServerAddresses::const_iterator it = server_addresses_.begin(); 356269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org it != server_addresses_.end(); ++it) { 357269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SendStunBindingRequest(*it); 358269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 359269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 360269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 361269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::ResolveStunAddress(const rtc::SocketAddress& stun_addr) { 362269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!resolver_) { 363269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver_.reset(new AddressResolver(socket_factory())); 364269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver_->SignalDone.connect(this, &UDPPort::OnResolveResult); 365269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 366269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 3670f490a5b8609c1f10dba37d7a7b0b2fc055543ebHonghai Zhang LOG_J(LS_INFO, this) << "Starting STUN host lookup for " 3680f490a5b8609c1f10dba37d7a7b0b2fc055543ebHonghai Zhang << stun_addr.ToSensitiveString(); 369269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver_->Resolve(stun_addr); 370269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 371269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 372269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::OnResolveResult(const rtc::SocketAddress& input, 373269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int error) { 374269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(resolver_.get() != NULL); 375269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 376269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress resolved; 377269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (error != 0 || 378269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org !resolver_->GetResolvedAddress(input, ip().family(), &resolved)) { 379269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "StunPort: stun host lookup received error " 380269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << error; 381269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnStunBindingOrResolveRequestFailed(input); 382269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 383269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 384269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 385269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_addresses_.erase(input); 386269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 387269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (server_addresses_.find(resolved) == server_addresses_.end()) { 388269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_addresses_.insert(resolved); 389269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SendStunBindingRequest(resolved); 390269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 391269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 392269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 39320a34619080005c3b0e49d85b307113ea2b180c3tfarinavoid UDPPort::SendStunBindingRequest(const rtc::SocketAddress& stun_addr) { 39420a34619080005c3b0e49d85b307113ea2b180c3tfarina if (stun_addr.IsUnresolvedIP()) { 395269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ResolveStunAddress(stun_addr); 396269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 397269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else if (socket_->GetState() == rtc::AsyncPacketSocket::STATE_BOUND) { 398269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Check if |server_addr_| is compatible with the port's ip. 399269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (IsCompatibleAddress(stun_addr)) { 40045b0efd378abef87676e6ec55516b10ce583ddachonghaiz requests_.Send(new StunBindingRequest(this, stun_addr, 40145b0efd378abef87676e6ec55516b10ce583ddachonghaiz rtc::Time() + KEEP_ALIVE_TIMEOUT)); 402269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 403269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Since we can't send stun messages to the server, we should mark this 404269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // port ready. 405269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_WARNING) << "STUN server address is incompatible."; 406269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnStunBindingOrResolveRequestFailed(stun_addr); 407269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 408269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 409269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 410269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 411e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shiehbool UDPPort::MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const { 4129af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh if (!addr->IsAnyIP() || !emit_local_for_anyaddress_ || 4139af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh !Network()->default_local_address_provider()) { 414e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh return true; 4159af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh } 4169af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh rtc::IPAddress default_address; 4179af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh bool result = 4189af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh Network()->default_local_address_provider()->GetDefaultLocalAddress( 4199af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh addr->family(), &default_address); 420953eabc0273ba0566f2889904dd4ffb6ee50bfa9Guo-wei Shieh if (!result || default_address.IsNil()) { 421e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh return false; 422e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh } 423e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh 4249af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh addr->SetIP(default_address); 425e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh return true; 4269af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh} 4279af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh 428269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::OnStunBindingRequestSucceeded( 429269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& stun_server_addr, 430269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& stun_reflected_addr) { 431269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (bind_request_succeeded_servers_.find(stun_server_addr) != 432269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org bind_request_succeeded_servers_.end()) { 433269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 434269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 435269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org bind_request_succeeded_servers_.insert(stun_server_addr); 436269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 437269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If socket is shared and |stun_reflected_addr| is equal to local socket 438269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // address, or if the same address has been added by another STUN server, 439269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // then discarding the stun address. 440269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // For STUN, related address is the local socket address. 441269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if ((!SharedSocket() || stun_reflected_addr != socket_->GetLocalAddress()) && 442269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org !HasCandidateWithAddress(stun_reflected_addr)) { 443269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 444269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress related_address = socket_->GetLocalAddress(); 445e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh // If we can't stamp the related address correctly, empty it to avoid leak. 446e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh if (!MaybeSetDefaultLocalAddress(&related_address) || 447e03cab94c1bac43f4d6c4775023a957f98ee8132Guo-wei Shieh !(candidate_filter() & CF_HOST)) { 448269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If candidate filter doesn't have CF_HOST specified, empty raddr to 449269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // avoid local address leakage. 450269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org related_address = rtc::EmptySocketAddressWithFamily( 451269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org related_address.family()); 452269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 453269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 4543d564c10157d7de1d2d4236f4e2a13ff1363d52bGuo-wei Shieh AddAddress(stun_reflected_addr, socket_->GetLocalAddress(), related_address, 4553d564c10157d7de1d2d4236f4e2a13ff1363d52bGuo-wei Shieh UDP_PROTOCOL_NAME, "", "", STUN_PORT_TYPE, 4563d564c10157d7de1d2d4236f4e2a13ff1363d52bGuo-wei Shieh ICE_TYPE_PREFERENCE_SRFLX, 0, false); 457269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 458269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org MaybeSetPortCompleteOrError(); 459269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 460269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 461269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::OnStunBindingOrResolveRequestFailed( 462269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& stun_server_addr) { 463269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (bind_request_failed_servers_.find(stun_server_addr) != 464269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org bind_request_failed_servers_.end()) { 465269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 466269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 467269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org bind_request_failed_servers_.insert(stun_server_addr); 468269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org MaybeSetPortCompleteOrError(); 469269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 470269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 471269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::MaybeSetPortCompleteOrError() { 472269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (ready_) 473269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 474269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 475269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Do not set port ready if we are still waiting for bind responses. 476269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const size_t servers_done_bind_request = bind_request_failed_servers_.size() + 477269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org bind_request_succeeded_servers_.size(); 478269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (server_addresses_.size() != servers_done_bind_request) { 479269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 480269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 481269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 482269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Setting ready status. 483269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ready_ = true; 484269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 485269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // The port is "completed" if there is no stun server provided, or the bind 486269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // request succeeded for any stun server, or the socket is shared. 487269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (server_addresses_.empty() || 488269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org bind_request_succeeded_servers_.size() > 0 || 489269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SharedSocket()) { 490269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SignalPortComplete(this); 491269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 492269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SignalPortError(this); 493269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 494269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 495269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 496269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// TODO: merge this with SendTo above. 497269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid UDPPort::OnSendPacket(const void* data, size_t size, StunRequest* req) { 498269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org StunBindingRequest* sreq = static_cast<StunBindingRequest*>(req); 499269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::PacketOptions options(DefaultDscpValue()); 500269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (socket_->SendTo(data, size, sreq->server_addr(), options) < 0) 501269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org PLOG(LERROR, socket_->GetError()) << "sendto"; 502269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 503269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 504269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool UDPPort::HasCandidateWithAddress(const rtc::SocketAddress& addr) const { 505269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const std::vector<Candidate>& existing_candidates = Candidates(); 506269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org std::vector<Candidate>::const_iterator it = existing_candidates.begin(); 507269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org for (; it != existing_candidates.end(); ++it) { 508269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (it->address() == addr) 509269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return true; 510269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 511269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return false; 512269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 513269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 514269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} // namespace cricket 515