• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3   *
4   *  Use of this source code is governed by a BSD-style license
5   *  that can be found in the LICENSE file in the root of the source
6   *  tree. An additional intellectual property rights grant can be found
7   *  in the file PATENTS.  All contributing project authors may
8   *  be found in the AUTHORS file in the root of the source tree.
9   */
10  
11  #include "webrtc/p2p/base/stunport.h"
12  
13  #include "webrtc/p2p/base/common.h"
14  #include "webrtc/p2p/base/portallocator.h"
15  #include "webrtc/p2p/base/stun.h"
16  #include "webrtc/base/checks.h"
17  #include "webrtc/base/common.h"
18  #include "webrtc/base/helpers.h"
19  #include "webrtc/base/ipaddress.h"
20  #include "webrtc/base/logging.h"
21  #include "webrtc/base/nethelpers.h"
22  
23  namespace cricket {
24  
25  // TODO: Move these to a common place (used in relayport too)
26  const int KEEPALIVE_DELAY = 10 * 1000;  // 10 seconds - sort timeouts
27  const int RETRY_TIMEOUT = 50 * 1000;    // ICE says 50 secs
28  // Stop sending STUN binding requests after this amount of time
29  // (in milliseconds) because the connection binding requests should keep
30  // the NAT binding alive.
31  const int KEEP_ALIVE_TIMEOUT = 2 * 60 * 1000;  // 2 minutes
32  
33  // Handles a binding request sent to the STUN server.
34  class StunBindingRequest : public StunRequest {
35   public:
StunBindingRequest(UDPPort * port,const rtc::SocketAddress & addr,uint32_t deadline)36    StunBindingRequest(UDPPort* port,
37                       const rtc::SocketAddress& addr,
38                       uint32_t deadline)
39        : port_(port), server_addr_(addr), deadline_(deadline) {
40      start_time_ = rtc::Time();
41    }
42  
~StunBindingRequest()43    virtual ~StunBindingRequest() {
44    }
45  
server_addr() const46    const rtc::SocketAddress& server_addr() const { return server_addr_; }
47  
Prepare(StunMessage * request)48    virtual void Prepare(StunMessage* request) override {
49      request->SetType(STUN_BINDING_REQUEST);
50    }
51  
OnResponse(StunMessage * response)52    virtual void OnResponse(StunMessage* response) override {
53      const StunAddressAttribute* addr_attr =
54          response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
55      if (!addr_attr) {
56        LOG(LS_ERROR) << "Binding response missing mapped address.";
57      } else if (addr_attr->family() != STUN_ADDRESS_IPV4 &&
58                 addr_attr->family() != STUN_ADDRESS_IPV6) {
59        LOG(LS_ERROR) << "Binding address has bad family";
60      } else {
61        rtc::SocketAddress addr(addr_attr->ipaddr(), addr_attr->port());
62        port_->OnStunBindingRequestSucceeded(server_addr_, addr);
63      }
64  
65      // We will do a keep-alive regardless of whether this request succeeds.
66      // It will be stopped after |deadline_| mostly to conserve the battery life.
67      if (rtc::Time() <= deadline_) {
68        port_->requests_.SendDelayed(
69            new StunBindingRequest(port_, server_addr_, deadline_),
70            port_->stun_keepalive_delay());
71      }
72    }
73  
OnErrorResponse(StunMessage * response)74    virtual void OnErrorResponse(StunMessage* response) override {
75      const StunErrorCodeAttribute* attr = response->GetErrorCode();
76      if (!attr) {
77        LOG(LS_ERROR) << "Bad allocate response error code";
78      } else {
79        LOG(LS_ERROR) << "Binding error response:"
80                   << " class=" << attr->eclass()
81                   << " number=" << attr->number()
82                   << " reason='" << attr->reason() << "'";
83      }
84  
85      port_->OnStunBindingOrResolveRequestFailed(server_addr_);
86  
87      uint32_t now = rtc::Time();
88      if (now <= deadline_ && rtc::TimeDiff(now, start_time_) <= RETRY_TIMEOUT) {
89        port_->requests_.SendDelayed(
90            new StunBindingRequest(port_, server_addr_, deadline_),
91            port_->stun_keepalive_delay());
92      }
93    }
94  
OnTimeout()95    virtual void OnTimeout() override {
96      LOG(LS_ERROR) << "Binding request timed out from "
97        << port_->GetLocalAddress().ToSensitiveString()
98        << " (" << port_->Network()->name() << ")";
99  
100      port_->OnStunBindingOrResolveRequestFailed(server_addr_);
101    }
102  
103   private:
104    UDPPort* port_;
105    const rtc::SocketAddress server_addr_;
106    uint32_t start_time_;
107    uint32_t deadline_;
108  };
109  
AddressResolver(rtc::PacketSocketFactory * factory)110  UDPPort::AddressResolver::AddressResolver(
111      rtc::PacketSocketFactory* factory)
112      : socket_factory_(factory) {}
113  
~AddressResolver()114  UDPPort::AddressResolver::~AddressResolver() {
115    for (ResolverMap::iterator it = resolvers_.begin();
116         it != resolvers_.end(); ++it) {
117      // TODO(guoweis): Change to asynchronous DNS resolution to prevent the hang
118      // when passing true to the Destroy() which is a safer way to avoid the code
119      // unloaded before the thread exits. Please see webrtc bug 5139.
120      it->second->Destroy(false);
121    }
122  }
123  
Resolve(const rtc::SocketAddress & address)124  void UDPPort::AddressResolver::Resolve(
125      const rtc::SocketAddress& address) {
126    if (resolvers_.find(address) != resolvers_.end())
127      return;
128  
129    rtc::AsyncResolverInterface* resolver =
130        socket_factory_->CreateAsyncResolver();
131    resolvers_.insert(
132        std::pair<rtc::SocketAddress, rtc::AsyncResolverInterface*>(
133            address, resolver));
134  
135    resolver->SignalDone.connect(this,
136                                 &UDPPort::AddressResolver::OnResolveResult);
137  
138    resolver->Start(address);
139  }
140  
GetResolvedAddress(const rtc::SocketAddress & input,int family,rtc::SocketAddress * output) const141  bool UDPPort::AddressResolver::GetResolvedAddress(
142      const rtc::SocketAddress& input,
143      int family,
144      rtc::SocketAddress* output) const {
145    ResolverMap::const_iterator it = resolvers_.find(input);
146    if (it == resolvers_.end())
147      return false;
148  
149    return it->second->GetResolvedAddress(family, output);
150  }
151  
OnResolveResult(rtc::AsyncResolverInterface * resolver)152  void UDPPort::AddressResolver::OnResolveResult(
153      rtc::AsyncResolverInterface* resolver) {
154    for (ResolverMap::iterator it = resolvers_.begin();
155         it != resolvers_.end(); ++it) {
156      if (it->second == resolver) {
157        SignalDone(it->first, resolver->GetError());
158        return;
159      }
160    }
161  }
162  
UDPPort(rtc::Thread * thread,rtc::PacketSocketFactory * factory,rtc::Network * network,rtc::AsyncPacketSocket * socket,const std::string & username,const std::string & password,const std::string & origin,bool emit_local_for_anyaddress)163  UDPPort::UDPPort(rtc::Thread* thread,
164                   rtc::PacketSocketFactory* factory,
165                   rtc::Network* network,
166                   rtc::AsyncPacketSocket* socket,
167                   const std::string& username,
168                   const std::string& password,
169                   const std::string& origin,
170                   bool emit_local_for_anyaddress)
171      : Port(thread,
172             factory,
173             network,
174             socket->GetLocalAddress().ipaddr(),
175             username,
176             password),
177        requests_(thread),
178        socket_(socket),
179        error_(0),
180        ready_(false),
181        stun_keepalive_delay_(KEEPALIVE_DELAY),
182        emit_local_for_anyaddress_(emit_local_for_anyaddress) {
183    requests_.set_origin(origin);
184  }
185  
UDPPort(rtc::Thread * thread,rtc::PacketSocketFactory * factory,rtc::Network * network,const rtc::IPAddress & ip,uint16_t min_port,uint16_t max_port,const std::string & username,const std::string & password,const std::string & origin,bool emit_local_for_anyaddress)186  UDPPort::UDPPort(rtc::Thread* thread,
187                   rtc::PacketSocketFactory* factory,
188                   rtc::Network* network,
189                   const rtc::IPAddress& ip,
190                   uint16_t min_port,
191                   uint16_t max_port,
192                   const std::string& username,
193                   const std::string& password,
194                   const std::string& origin,
195                   bool emit_local_for_anyaddress)
196      : Port(thread,
197             LOCAL_PORT_TYPE,
198             factory,
199             network,
200             ip,
201             min_port,
202             max_port,
203             username,
204             password),
205        requests_(thread),
206        socket_(NULL),
207        error_(0),
208        ready_(false),
209        stun_keepalive_delay_(KEEPALIVE_DELAY),
210        emit_local_for_anyaddress_(emit_local_for_anyaddress) {
211    requests_.set_origin(origin);
212  }
213  
Init()214  bool UDPPort::Init() {
215    if (!SharedSocket()) {
216      ASSERT(socket_ == NULL);
217      socket_ = socket_factory()->CreateUdpSocket(
218          rtc::SocketAddress(ip(), 0), min_port(), max_port());
219      if (!socket_) {
220        LOG_J(LS_WARNING, this) << "UDP socket creation failed";
221        return false;
222      }
223      socket_->SignalReadPacket.connect(this, &UDPPort::OnReadPacket);
224    }
225    socket_->SignalSentPacket.connect(this, &UDPPort::OnSentPacket);
226    socket_->SignalReadyToSend.connect(this, &UDPPort::OnReadyToSend);
227    socket_->SignalAddressReady.connect(this, &UDPPort::OnLocalAddressReady);
228    requests_.SignalSendPacket.connect(this, &UDPPort::OnSendPacket);
229    return true;
230  }
231  
~UDPPort()232  UDPPort::~UDPPort() {
233    if (!SharedSocket())
234      delete socket_;
235  }
236  
PrepareAddress()237  void UDPPort::PrepareAddress() {
238    ASSERT(requests_.empty());
239    if (socket_->GetState() == rtc::AsyncPacketSocket::STATE_BOUND) {
240      OnLocalAddressReady(socket_, socket_->GetLocalAddress());
241    }
242  }
243  
MaybePrepareStunCandidate()244  void UDPPort::MaybePrepareStunCandidate() {
245    // Sending binding request to the STUN server if address is available to
246    // prepare STUN candidate.
247    if (!server_addresses_.empty()) {
248      SendStunBindingRequests();
249    } else {
250      // Port is done allocating candidates.
251      MaybeSetPortCompleteOrError();
252    }
253  }
254  
CreateConnection(const Candidate & address,CandidateOrigin origin)255  Connection* UDPPort::CreateConnection(const Candidate& address,
256                                        CandidateOrigin origin) {
257    if (!SupportsProtocol(address.protocol())) {
258      return NULL;
259    }
260  
261    if (!IsCompatibleAddress(address.address())) {
262      return NULL;
263    }
264  
265    if (SharedSocket() && Candidates()[0].type() != LOCAL_PORT_TYPE) {
266      ASSERT(false);
267      return NULL;
268    }
269  
270    Connection* conn = new ProxyConnection(this, 0, address);
271    AddConnection(conn);
272    return conn;
273  }
274  
SendTo(const void * data,size_t size,const rtc::SocketAddress & addr,const rtc::PacketOptions & options,bool payload)275  int UDPPort::SendTo(const void* data, size_t size,
276                      const rtc::SocketAddress& addr,
277                      const rtc::PacketOptions& options,
278                      bool payload) {
279    int sent = socket_->SendTo(data, size, addr, options);
280    if (sent < 0) {
281      error_ = socket_->GetError();
282      LOG_J(LS_ERROR, this) << "UDP send of " << size
283                            << " bytes failed with error " << error_;
284    }
285    return sent;
286  }
287  
SetOption(rtc::Socket::Option opt,int value)288  int UDPPort::SetOption(rtc::Socket::Option opt, int value) {
289    return socket_->SetOption(opt, value);
290  }
291  
GetOption(rtc::Socket::Option opt,int * value)292  int UDPPort::GetOption(rtc::Socket::Option opt, int* value) {
293    return socket_->GetOption(opt, value);
294  }
295  
GetError()296  int UDPPort::GetError() {
297    return error_;
298  }
299  
OnLocalAddressReady(rtc::AsyncPacketSocket * socket,const rtc::SocketAddress & address)300  void UDPPort::OnLocalAddressReady(rtc::AsyncPacketSocket* socket,
301                                    const rtc::SocketAddress& address) {
302    // When adapter enumeration is disabled and binding to the any address, the
303    // default local address will be issued as a candidate instead if
304    // |emit_local_for_anyaddress| is true. This is to allow connectivity for
305    // applications which absolutely requires a HOST candidate.
306    rtc::SocketAddress addr = address;
307  
308    // If MaybeSetDefaultLocalAddress fails, we keep the "any" IP so that at
309    // least the port is listening.
310    MaybeSetDefaultLocalAddress(&addr);
311  
312    AddAddress(addr, addr, rtc::SocketAddress(), UDP_PROTOCOL_NAME, "", "",
313               LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST, 0, false);
314    MaybePrepareStunCandidate();
315  }
316  
OnReadPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & remote_addr,const rtc::PacketTime & packet_time)317  void UDPPort::OnReadPacket(rtc::AsyncPacketSocket* socket,
318                             const char* data,
319                             size_t size,
320                             const rtc::SocketAddress& remote_addr,
321                             const rtc::PacketTime& packet_time) {
322    ASSERT(socket == socket_);
323    ASSERT(!remote_addr.IsUnresolvedIP());
324  
325    // Look for a response from the STUN server.
326    // Even if the response doesn't match one of our outstanding requests, we
327    // will eat it because it might be a response to a retransmitted packet, and
328    // we already cleared the request when we got the first response.
329    if (server_addresses_.find(remote_addr) != server_addresses_.end()) {
330      requests_.CheckResponse(data, size);
331      return;
332    }
333  
334    if (Connection* conn = GetConnection(remote_addr)) {
335      conn->OnReadPacket(data, size, packet_time);
336    } else {
337      Port::OnReadPacket(data, size, remote_addr, PROTO_UDP);
338    }
339  }
340  
OnSentPacket(rtc::AsyncPacketSocket * socket,const rtc::SentPacket & sent_packet)341  void UDPPort::OnSentPacket(rtc::AsyncPacketSocket* socket,
342                             const rtc::SentPacket& sent_packet) {
343    PortInterface::SignalSentPacket(sent_packet);
344  }
345  
OnReadyToSend(rtc::AsyncPacketSocket * socket)346  void UDPPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
347    Port::OnReadyToSend();
348  }
349  
SendStunBindingRequests()350  void UDPPort::SendStunBindingRequests() {
351    // We will keep pinging the stun server to make sure our NAT pin-hole stays
352    // open until the deadline (specified in SendStunBindingRequest).
353    ASSERT(requests_.empty());
354  
355    for (ServerAddresses::const_iterator it = server_addresses_.begin();
356         it != server_addresses_.end(); ++it) {
357      SendStunBindingRequest(*it);
358    }
359  }
360  
ResolveStunAddress(const rtc::SocketAddress & stun_addr)361  void UDPPort::ResolveStunAddress(const rtc::SocketAddress& stun_addr) {
362    if (!resolver_) {
363      resolver_.reset(new AddressResolver(socket_factory()));
364      resolver_->SignalDone.connect(this, &UDPPort::OnResolveResult);
365    }
366  
367    LOG_J(LS_INFO, this) << "Starting STUN host lookup for "
368                         << stun_addr.ToSensitiveString();
369    resolver_->Resolve(stun_addr);
370  }
371  
OnResolveResult(const rtc::SocketAddress & input,int error)372  void UDPPort::OnResolveResult(const rtc::SocketAddress& input,
373                                int error) {
374    ASSERT(resolver_.get() != NULL);
375  
376    rtc::SocketAddress resolved;
377    if (error != 0 ||
378        !resolver_->GetResolvedAddress(input, ip().family(), &resolved))  {
379      LOG_J(LS_WARNING, this) << "StunPort: stun host lookup received error "
380                              << error;
381      OnStunBindingOrResolveRequestFailed(input);
382      return;
383    }
384  
385    server_addresses_.erase(input);
386  
387    if (server_addresses_.find(resolved) == server_addresses_.end()) {
388      server_addresses_.insert(resolved);
389      SendStunBindingRequest(resolved);
390    }
391  }
392  
SendStunBindingRequest(const rtc::SocketAddress & stun_addr)393  void UDPPort::SendStunBindingRequest(const rtc::SocketAddress& stun_addr) {
394    if (stun_addr.IsUnresolvedIP()) {
395      ResolveStunAddress(stun_addr);
396  
397    } else if (socket_->GetState() == rtc::AsyncPacketSocket::STATE_BOUND) {
398      // Check if |server_addr_| is compatible with the port's ip.
399      if (IsCompatibleAddress(stun_addr)) {
400        requests_.Send(new StunBindingRequest(this, stun_addr,
401                                              rtc::Time() + KEEP_ALIVE_TIMEOUT));
402      } else {
403        // Since we can't send stun messages to the server, we should mark this
404        // port ready.
405        LOG(LS_WARNING) << "STUN server address is incompatible.";
406        OnStunBindingOrResolveRequestFailed(stun_addr);
407      }
408    }
409  }
410  
MaybeSetDefaultLocalAddress(rtc::SocketAddress * addr) const411  bool UDPPort::MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const {
412    if (!addr->IsAnyIP() || !emit_local_for_anyaddress_ ||
413        !Network()->default_local_address_provider()) {
414      return true;
415    }
416    rtc::IPAddress default_address;
417    bool result =
418        Network()->default_local_address_provider()->GetDefaultLocalAddress(
419            addr->family(), &default_address);
420    if (!result || default_address.IsNil()) {
421      return false;
422    }
423  
424    addr->SetIP(default_address);
425    return true;
426  }
427  
OnStunBindingRequestSucceeded(const rtc::SocketAddress & stun_server_addr,const rtc::SocketAddress & stun_reflected_addr)428  void UDPPort::OnStunBindingRequestSucceeded(
429      const rtc::SocketAddress& stun_server_addr,
430      const rtc::SocketAddress& stun_reflected_addr) {
431    if (bind_request_succeeded_servers_.find(stun_server_addr) !=
432            bind_request_succeeded_servers_.end()) {
433      return;
434    }
435    bind_request_succeeded_servers_.insert(stun_server_addr);
436  
437    // If socket is shared and |stun_reflected_addr| is equal to local socket
438    // address, or if the same address has been added by another STUN server,
439    // then discarding the stun address.
440    // For STUN, related address is the local socket address.
441    if ((!SharedSocket() || stun_reflected_addr != socket_->GetLocalAddress()) &&
442        !HasCandidateWithAddress(stun_reflected_addr)) {
443  
444      rtc::SocketAddress related_address = socket_->GetLocalAddress();
445      // If we can't stamp the related address correctly, empty it to avoid leak.
446      if (!MaybeSetDefaultLocalAddress(&related_address) ||
447          !(candidate_filter() & CF_HOST)) {
448        // If candidate filter doesn't have CF_HOST specified, empty raddr to
449        // avoid local address leakage.
450        related_address = rtc::EmptySocketAddressWithFamily(
451            related_address.family());
452      }
453  
454      AddAddress(stun_reflected_addr, socket_->GetLocalAddress(), related_address,
455                 UDP_PROTOCOL_NAME, "", "", STUN_PORT_TYPE,
456                 ICE_TYPE_PREFERENCE_SRFLX, 0, false);
457    }
458    MaybeSetPortCompleteOrError();
459  }
460  
OnStunBindingOrResolveRequestFailed(const rtc::SocketAddress & stun_server_addr)461  void UDPPort::OnStunBindingOrResolveRequestFailed(
462      const rtc::SocketAddress& stun_server_addr) {
463    if (bind_request_failed_servers_.find(stun_server_addr) !=
464            bind_request_failed_servers_.end()) {
465      return;
466    }
467    bind_request_failed_servers_.insert(stun_server_addr);
468    MaybeSetPortCompleteOrError();
469  }
470  
MaybeSetPortCompleteOrError()471  void UDPPort::MaybeSetPortCompleteOrError() {
472    if (ready_)
473      return;
474  
475    // Do not set port ready if we are still waiting for bind responses.
476    const size_t servers_done_bind_request = bind_request_failed_servers_.size() +
477        bind_request_succeeded_servers_.size();
478    if (server_addresses_.size() != servers_done_bind_request) {
479      return;
480    }
481  
482    // Setting ready status.
483    ready_ = true;
484  
485    // The port is "completed" if there is no stun server provided, or the bind
486    // request succeeded for any stun server, or the socket is shared.
487    if (server_addresses_.empty() ||
488        bind_request_succeeded_servers_.size() > 0 ||
489        SharedSocket()) {
490      SignalPortComplete(this);
491    } else {
492      SignalPortError(this);
493    }
494  }
495  
496  // TODO: merge this with SendTo above.
OnSendPacket(const void * data,size_t size,StunRequest * req)497  void UDPPort::OnSendPacket(const void* data, size_t size, StunRequest* req) {
498    StunBindingRequest* sreq = static_cast<StunBindingRequest*>(req);
499    rtc::PacketOptions options(DefaultDscpValue());
500    if (socket_->SendTo(data, size, sreq->server_addr(), options) < 0)
501      PLOG(LERROR, socket_->GetError()) << "sendto";
502  }
503  
HasCandidateWithAddress(const rtc::SocketAddress & addr) const504  bool UDPPort::HasCandidateWithAddress(const rtc::SocketAddress& addr) const {
505    const std::vector<Candidate>& existing_candidates = Candidates();
506    std::vector<Candidate>::const_iterator it = existing_candidates.begin();
507    for (; it != existing_candidates.end(); ++it) {
508      if (it->address() == addr)
509        return true;
510    }
511    return false;
512  }
513  
514  }  // namespace cricket
515