• 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 "p2p/base/stun_server.h"
12 
13 #include <utility>
14 
15 #include "rtc_base/byte_buffer.h"
16 #include "rtc_base/logging.h"
17 
18 namespace cricket {
19 
StunServer(rtc::AsyncUDPSocket * socket)20 StunServer::StunServer(rtc::AsyncUDPSocket* socket) : socket_(socket) {
21   socket_->SignalReadPacket.connect(this, &StunServer::OnPacket);
22 }
23 
~StunServer()24 StunServer::~StunServer() {
25   socket_->SignalReadPacket.disconnect(this);
26 }
27 
OnPacket(rtc::AsyncPacketSocket * socket,const char * buf,size_t size,const rtc::SocketAddress & remote_addr,const int64_t &)28 void StunServer::OnPacket(rtc::AsyncPacketSocket* socket,
29                           const char* buf,
30                           size_t size,
31                           const rtc::SocketAddress& remote_addr,
32                           const int64_t& /* packet_time_us */) {
33   // Parse the STUN message; eat any messages that fail to parse.
34   rtc::ByteBufferReader bbuf(buf, size);
35   StunMessage msg;
36   if (!msg.Read(&bbuf)) {
37     return;
38   }
39 
40   // TODO(?): If unknown non-optional (<= 0x7fff) attributes are found, send a
41   //          420 "Unknown Attribute" response.
42 
43   // Send the message to the appropriate handler function.
44   switch (msg.type()) {
45     case STUN_BINDING_REQUEST:
46       OnBindingRequest(&msg, remote_addr);
47       break;
48 
49     default:
50       SendErrorResponse(msg, remote_addr, 600, "Operation Not Supported");
51   }
52 }
53 
OnBindingRequest(StunMessage * msg,const rtc::SocketAddress & remote_addr)54 void StunServer::OnBindingRequest(StunMessage* msg,
55                                   const rtc::SocketAddress& remote_addr) {
56   StunMessage response;
57   GetStunBindResponse(msg, remote_addr, &response);
58   SendResponse(response, remote_addr);
59 }
60 
SendErrorResponse(const StunMessage & msg,const rtc::SocketAddress & addr,int error_code,const char * error_desc)61 void StunServer::SendErrorResponse(const StunMessage& msg,
62                                    const rtc::SocketAddress& addr,
63                                    int error_code,
64                                    const char* error_desc) {
65   StunMessage err_msg;
66   err_msg.SetType(GetStunErrorResponseType(msg.type()));
67   err_msg.SetTransactionID(msg.transaction_id());
68 
69   auto err_code = StunAttribute::CreateErrorCode();
70   err_code->SetCode(error_code);
71   err_code->SetReason(error_desc);
72   err_msg.AddAttribute(std::move(err_code));
73 
74   SendResponse(err_msg, addr);
75 }
76 
SendResponse(const StunMessage & msg,const rtc::SocketAddress & addr)77 void StunServer::SendResponse(const StunMessage& msg,
78                               const rtc::SocketAddress& addr) {
79   rtc::ByteBufferWriter buf;
80   msg.Write(&buf);
81   rtc::PacketOptions options;
82   if (socket_->SendTo(buf.Data(), buf.Length(), addr, options) < 0)
83     RTC_LOG_ERR(LS_ERROR) << "sendto";
84 }
85 
GetStunBindResponse(StunMessage * request,const rtc::SocketAddress & remote_addr,StunMessage * response) const86 void StunServer::GetStunBindResponse(StunMessage* request,
87                                      const rtc::SocketAddress& remote_addr,
88                                      StunMessage* response) const {
89   response->SetType(STUN_BINDING_RESPONSE);
90   response->SetTransactionID(request->transaction_id());
91 
92   // Tell the user the address that we received their request from.
93   std::unique_ptr<StunAddressAttribute> mapped_addr;
94   if (request->IsLegacy()) {
95     mapped_addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
96   } else {
97     mapped_addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
98   }
99   mapped_addr->SetAddress(remote_addr);
100   response->AddAttribute(std::move(mapped_addr));
101 }
102 
103 }  // namespace cricket
104