Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / p2p / base / stunserver.cc
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