• Home
  • 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