1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/*
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc.
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met:
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  1. Redistributions of source code must retain the above copyright notice,
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer.
10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  2. Redistributions in binary form must reproduce the above copyright notice,
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer in the documentation
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     and/or other materials provided with the distribution.
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  3. The name of the author may not be used to endorse or promote products
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     derived from this software without specific prior written permission.
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/p2p/base/stun.h"
29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <cstring>
31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h"
33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h"
34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochusing talk_base::ByteBuffer;
36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace cricket {
38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string STUN_ERROR_REASON_BAD_REQUEST = "BAD REQUEST";
40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string STUN_ERROR_REASON_UNAUTHORIZED = "UNAUTHORIZED";
41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE = "UNKNOWN ATTRIBUTE";
42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string STUN_ERROR_REASON_STALE_CREDENTIALS = "STALE CREDENTIALS";
43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string STUN_ERROR_REASON_INTEGRITY_CHECK_FAILURE = "INTEGRITY CHECK FAILURE";
44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string STUN_ERROR_REASON_MISSING_USERNAME = "MISSING USERNAME";
45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string STUN_ERROR_REASON_USE_TLS = "USE TLS";
46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string STUN_ERROR_REASON_SERVER_ERROR = "SERVER ERROR";
47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string STUN_ERROR_REASON_GLOBAL_FAILURE = "GLOBAL FAILURE";
48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunMessage::StunMessage() : type_(0), length_(0),
50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    transaction_id_("0000000000000000") {
51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(transaction_id_.size() == 16);
52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attrs_ = new std::vector<StunAttribute*>();
53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunMessage::~StunMessage() {
56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (unsigned i = 0; i < attrs_->size(); i++)
57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    delete (*attrs_)[i];
58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete attrs_;
59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunMessage::SetTransactionID(const std::string& str) {
62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(str.size() == 16);
63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  transaction_id_ = str;
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunMessage::AddAttribute(StunAttribute* attr) {
67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attrs_->push_back(attr);
68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  length_ += attr->length() + 4;
69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst StunAddressAttribute*
72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunMessage::GetAddress(StunAttributeType type) const {
73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (type) {
74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_MAPPED_ADDRESS:
75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_RESPONSE_ADDRESS:
76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_SOURCE_ADDRESS:
77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_CHANGED_ADDRESS:
78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_REFLECTED_FROM:
79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_ALTERNATE_SERVER:
80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_DESTINATION_ADDRESS:
81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_SOURCE_ADDRESS2:
82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return reinterpret_cast<const StunAddressAttribute*>(GetAttribute(type));
83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT(0);
86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst StunUInt32Attribute*
91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunMessage::GetUInt32(StunAttributeType type) const {
92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (type) {
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_CHANGE_REQUEST:
94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_LIFETIME:
95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_BANDWIDTH:
96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_OPTIONS:
97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return reinterpret_cast<const StunUInt32Attribute*>(GetAttribute(type));
98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT(0);
101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst StunByteStringAttribute*
106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunMessage::GetByteString(StunAttributeType type) const {
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (type) {
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_USERNAME:
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_PASSWORD:
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_MESSAGE_INTEGRITY:
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_DATA:
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_MAGIC_COOKIE:
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return reinterpret_cast<const StunByteStringAttribute*>(GetAttribute(type));
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT(0);
117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return reinterpret_cast<const StunErrorCodeAttribute*>(
123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      GetAttribute(STUN_ATTR_ERROR_CODE));
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const {
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return reinterpret_cast<const StunUInt16ListAttribute*>(
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES));
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst StunTransportPrefsAttribute* StunMessage::GetTransportPrefs() const {
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return reinterpret_cast<const StunTransportPrefsAttribute*>(
133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      GetAttribute(STUN_ATTR_TRANSPORT_PREFERENCES));
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst StunAttribute* StunMessage::GetAttribute(StunAttributeType type) const {
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (unsigned i = 0; i < attrs_->size(); i++) {
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((*attrs_)[i]->type() == type)
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return (*attrs_)[i];
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return 0;
142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool StunMessage::Read(ByteBuffer* buf) {
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadUInt16(&type_))
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (type_ & 0x8000) {
149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // rtp and rtcp set MSB of first byte, since first two bits are version,
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // and version is always 2 (10).  If set, this is not a stun packet.
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadUInt16(&length_))
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string transaction_id;
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadString(&transaction_id, 16))
159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(transaction_id.size() == 16);
161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  transaction_id_ = transaction_id;
162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (length_ > buf->Length())
164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attrs_->resize(0);
167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  size_t rest = buf->Length() - length_;
169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (buf->Length() > rest) {
170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    uint16 attr_type, attr_length;
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!buf->ReadUInt16(&attr_type))
172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!buf->ReadUInt16(&attr_length))
174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    StunAttribute* attr = StunAttribute::Create(attr_type, attr_length);
177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!attr || !attr->Read(buf))
178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    attrs_->push_back(attr);
181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (buf->Length() != rest) {
184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // fixme: shouldn't be doing this
185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LERROR) << "wrong message length (" << rest << " != " << buf->Length()
186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                << ")";
187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunMessage::Write(ByteBuffer* buf) const {
194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteUInt16(type_);
195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteUInt16(length_);
196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteString(transaction_id_);
197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (unsigned i = 0; i < attrs_->size(); i++) {
199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    buf->WriteUInt16((*attrs_)[i]->type());
200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    buf->WriteUInt16((*attrs_)[i]->length());
201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    (*attrs_)[i]->Write(buf);
202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunAttribute::StunAttribute(uint16 type, uint16 length)
206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : type_(type), length_(length) {
207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunAttribute* StunAttribute::Create(uint16 type, uint16 length) {
210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (type) {
211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_MAPPED_ADDRESS:
212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_RESPONSE_ADDRESS:
213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_SOURCE_ADDRESS:
214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_CHANGED_ADDRESS:
215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_REFLECTED_FROM:
216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_ALTERNATE_SERVER:
217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_DESTINATION_ADDRESS:
218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_SOURCE_ADDRESS2:
219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (length != StunAddressAttribute::SIZE)
220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return new StunAddressAttribute(type);
222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_CHANGE_REQUEST:
224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_LIFETIME:
225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_BANDWIDTH:
226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_OPTIONS:
227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (length != StunUInt32Attribute::SIZE)
228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return new StunUInt32Attribute(type);
230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_USERNAME:
232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_PASSWORD:
233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_MAGIC_COOKIE:
234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return (length % 4 == 0) ? new StunByteStringAttribute(type, length) : 0;
235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_MESSAGE_INTEGRITY:
237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return (length == 20) ? new StunByteStringAttribute(type, length) : 0;
238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_DATA:
240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return new StunByteStringAttribute(type, length);
241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_ERROR_CODE:
243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (length < StunErrorCodeAttribute::MIN_SIZE)
244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return new StunErrorCodeAttribute(type, length);
246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_UNKNOWN_ATTRIBUTES:
248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return (length % 2 == 0) ? new StunUInt16ListAttribute(type, length) : 0;
249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_TRANSPORT_PREFERENCES:
251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((length != StunTransportPrefsAttribute::SIZE1) &&
252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        (length != StunTransportPrefsAttribute::SIZE2))
253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return new StunTransportPrefsAttribute(type, length);
255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunAddressAttribute* StunAttribute::CreateAddress(uint16 type) {
262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (type) {
263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_MAPPED_ADDRESS:
264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_RESPONSE_ADDRESS:
265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_SOURCE_ADDRESS:
266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_CHANGED_ADDRESS:
267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_REFLECTED_FROM:
268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_ALTERNATE_SERVER:
269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_DESTINATION_ADDRESS:
270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_SOURCE_ADDRESS2:
271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return new StunAddressAttribute(type);
272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT(false);
275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunUInt32Attribute* StunAttribute::CreateUInt32(uint16 type) {
280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (type) {
281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_CHANGE_REQUEST:
282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_LIFETIME:
283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_BANDWIDTH:
284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_OPTIONS:
285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return new StunUInt32Attribute(type);
286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT(false);
289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunByteStringAttribute* StunAttribute::CreateByteString(uint16 type) {
294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (type) {
295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_USERNAME:
296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_PASSWORD:
297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_MESSAGE_INTEGRITY:
298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_DATA:
299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ATTR_MAGIC_COOKIE:
300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return new StunByteStringAttribute(type, 0);
301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT(false);
304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunErrorCodeAttribute* StunAttribute::CreateErrorCode() {
309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return new StunErrorCodeAttribute(
310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() {
314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0);
315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunTransportPrefsAttribute* StunAttribute::CreateTransportPrefs() {
318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return new StunTransportPrefsAttribute(
319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      STUN_ATTR_TRANSPORT_PREFERENCES, StunTransportPrefsAttribute::SIZE1);
320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunAddressAttribute::StunAddressAttribute(uint16 type)
323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : StunAttribute(type, SIZE), family_(0), port_(0), ip_(0) {
324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool StunAddressAttribute::Read(ByteBuffer* buf) {
327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  uint8 dummy;
3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadUInt8(&dummy))
329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadUInt8(&family_))
331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadUInt16(&port_))
333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
3343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadUInt32(&ip_))
335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunAddressAttribute::Write(ByteBuffer* buf) const {
340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteUInt8(0);
341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteUInt8(family_);
342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteUInt16(port_);
343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteUInt32(ip_);
344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunUInt32Attribute::StunUInt32Attribute(uint16 type)
347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : StunAttribute(type, SIZE), bits_(0) {
348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool StunUInt32Attribute::GetBit(int index) const {
351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT((0 <= index) && (index < 32));
352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return static_cast<bool>((bits_ >> index) & 0x1);
353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunUInt32Attribute::SetBit(int index, bool value) {
356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT((0 <= index) && (index < 32));
357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bits_ &= ~(1 << index);
358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bits_ |= value ? (1 << index) : 0;
359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
361f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool StunUInt32Attribute::Read(ByteBuffer* buf) {
3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadUInt32(&bits_))
363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunUInt32Attribute::Write(ByteBuffer* buf) const {
368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteUInt32(bits_);
369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunByteStringAttribute::StunByteStringAttribute(uint16 type, uint16 length)
372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : StunAttribute(type, length), bytes_(0) {
373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunByteStringAttribute::~StunByteStringAttribute() {
376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete [] bytes_;
377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunByteStringAttribute::SetBytes(char* bytes, uint16 length) {
380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete [] bytes_;
381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bytes_ = bytes;
382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SetLength(length);
383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunByteStringAttribute::CopyBytes(const char* bytes) {
386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CopyBytes(bytes, static_cast<uint16>(strlen(bytes)));
387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunByteStringAttribute::CopyBytes(const void* bytes, uint16 length) {
390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  char* new_bytes = new char[length];
391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::memcpy(new_bytes, bytes, length);
392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SetBytes(new_bytes, length);
393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochuint8 StunByteStringAttribute::GetByte(int index) const {
396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(bytes_ != NULL);
397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT((0 <= index) && (index < length()));
398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return static_cast<uint8>(bytes_[index]);
399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunByteStringAttribute::SetByte(int index, uint8 value) {
402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(bytes_ != NULL);
403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT((0 <= index) && (index < length()));
404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bytes_[index] = value;
405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool StunByteStringAttribute::Read(ByteBuffer* buf) {
408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bytes_ = new char[length()];
409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!buf->ReadBytes(bytes_, length()))
410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunByteStringAttribute::Write(ByteBuffer* buf) const {
415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteBytes(bytes_, length());
416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, uint16 length)
419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : StunAttribute(type, length), class_(0), number_(0) {
420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunErrorCodeAttribute::~StunErrorCodeAttribute() {
423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunErrorCodeAttribute::SetErrorCode(uint32 code) {
426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  class_ = (uint8)((code >> 8) & 0x7);
427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  number_ = (uint8)(code & 0xff);
428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunErrorCodeAttribute::SetReason(const std::string& reason) {
431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SetLength(MIN_SIZE + static_cast<uint16>(reason.size()));
432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  reason_ = reason;
433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool StunErrorCodeAttribute::Read(ByteBuffer* buf) {
436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  uint32 val;
4373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadUInt32(&val))
438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if ((val >> 11) != 0)
441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LERROR) << "error-code bits not zero";
442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SetErrorCode(val);
444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
4453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadString(&reason_, length() - 4))
446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunErrorCodeAttribute::Write(ByteBuffer* buf) const {
452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteUInt32(error_code());
453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteString(reason_);
454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunUInt16ListAttribute::StunUInt16ListAttribute(uint16 type, uint16 length)
457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : StunAttribute(type, length) {
458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attr_types_ = new std::vector<uint16>();
459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunUInt16ListAttribute::~StunUInt16ListAttribute() {
462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete attr_types_;
463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochsize_t StunUInt16ListAttribute::Size() const {
466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return attr_types_->size();
467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochuint16 StunUInt16ListAttribute::GetType(int index) const {
470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return (*attr_types_)[index];
471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunUInt16ListAttribute::SetType(int index, uint16 value) {
474f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  (*attr_types_)[index] = value;
475f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunUInt16ListAttribute::AddType(uint16 value) {
478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attr_types_->push_back(value);
479f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SetLength(static_cast<uint16>(attr_types_->size() * 2));
480f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
482f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool StunUInt16ListAttribute::Read(ByteBuffer* buf) {
483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (int i = 0; i < length() / 2; i++) {
484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    uint16 attr;
4853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!buf->ReadUInt16(&attr))
486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
487f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    attr_types_->push_back(attr);
488f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
489f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
490f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
491f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
492f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunUInt16ListAttribute::Write(ByteBuffer* buf) const {
493f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (unsigned i = 0; i < attr_types_->size(); i++)
494f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    buf->WriteUInt16((*attr_types_)[i]);
495f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
496f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
497f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunTransportPrefsAttribute::StunTransportPrefsAttribute(
498f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    uint16 type, uint16 length)
499f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : StunAttribute(type, length), preallocate_(false), prefs_(0), addr_(0) {
500f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
501f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
502f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunTransportPrefsAttribute::~StunTransportPrefsAttribute() {
503f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete addr_;
504f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
505f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
506f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunTransportPrefsAttribute::SetPreallocateAddress(
507f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    StunAddressAttribute* addr) {
508f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!addr) {
509f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    preallocate_ = false;
510f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    addr_ = 0;
511f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SetLength(SIZE1);
512f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
513f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    preallocate_ = true;
514f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    addr_ = addr;
515f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SetLength(SIZE2);
516f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
517f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
518f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
519f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool StunTransportPrefsAttribute::Read(ByteBuffer* buf) {
520f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  uint32 val;
5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!buf->ReadUInt32(&val))
522f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
523f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
524f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if ((val >> 3) != 0)
525f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LERROR) << "transport-preferences bits not zero";
526f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
527f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  preallocate_ = static_cast<bool>((val >> 2) & 0x1);
528f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  prefs_ = (uint8)(val & 0x3);
529f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
530f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (preallocate_ && (prefs_ == 3))
531f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LERROR) << "transport-preferences imcompatible P and Typ";
532f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
533f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!preallocate_) {
534f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (length() != StunUInt32Attribute::SIZE)
535f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
536f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
537f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (length() != StunUInt32Attribute::SIZE + StunAddressAttribute::SIZE)
538f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
539f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
540f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    addr_ = new StunAddressAttribute(STUN_ATTR_SOURCE_ADDRESS);
541f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    addr_->Read(buf);
542f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
543f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
544f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
545f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
546f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
547f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StunTransportPrefsAttribute::Write(ByteBuffer* buf) const {
548f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buf->WriteUInt32((preallocate_ ? 4 : 0) | prefs_);
549f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
550f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (preallocate_)
551f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    addr_->Write(buf);
552f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
553f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
554f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunMessageType GetStunResponseType(StunMessageType request_type) {
555f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (request_type) {
556f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_SHARED_SECRET_REQUEST:
557f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STUN_SHARED_SECRET_RESPONSE;
558f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ALLOCATE_REQUEST:
559f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STUN_ALLOCATE_RESPONSE;
560f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_SEND_REQUEST:
561f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STUN_SEND_RESPONSE;
562f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
563f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STUN_BINDING_RESPONSE;
564f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
565f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
566f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
567f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStunMessageType GetStunErrorResponseType(StunMessageType request_type) {
568f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (request_type) {
569f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_SHARED_SECRET_REQUEST:
570f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STUN_SHARED_SECRET_ERROR_RESPONSE;
571f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_ALLOCATE_REQUEST:
572f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STUN_ALLOCATE_ERROR_RESPONSE;
573f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case STUN_SEND_REQUEST:
574f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STUN_SEND_ERROR_RESPONSE;
575f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
576f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STUN_BINDING_ERROR_RESPONSE;
577f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
578f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
579f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
580f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace cricket
581