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