📄 stun.cxx
字号:
/* * libjingle * Copyright 2004--2005, Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "stun.h"#include <cassert>#if defined(_MSC_VER) && _MSC_VER < 1300namespace std { using ::memcpy;}#endifnamespace cricket {const std::string STUN_ERROR_REASON_BAD_REQUEST = "BAD REQUEST";const std::string STUN_ERROR_REASON_UNAUTHORIZED = "UNAUTHORIZED";const std::string STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE = "UNKNOWN ATTRIBUTE";const std::string STUN_ERROR_REASON_STALE_CREDENTIALS = "STALE CREDENTIALS";const std::string STUN_ERROR_REASON_INTEGRITY_CHECK_FAILURE = "INTEGRITY CHECK FAILURE";const std::string STUN_ERROR_REASON_MISSING_USERNAME = "MISSING USERNAME";const std::string STUN_ERROR_REASON_USE_TLS = "USE TLS";const std::string STUN_ERROR_REASON_SERVER_ERROR = "SERVER ERROR";const std::string STUN_ERROR_REASON_GLOBAL_FAILURE = "GLOBAL FAILURE";StunMessage::StunMessage() : type_(0), length_(0), transaction_id_("0000000000000000") { assert(transaction_id_.size() == 16); attrs_ = new std::vector<StunAttribute*>();}StunMessage::~StunMessage() { for (unsigned i = 0; i < attrs_->size(); i++) delete (*attrs_)[i]; delete attrs_;}void StunMessage::SetTransactionID(const std::string& str) { assert(str.size() == 16); transaction_id_ = str;}void StunMessage::AddAttribute(StunAttribute* attr) { attrs_->push_back(attr); length_ += attr->length() + 4;}const StunAddressAttribute*StunMessage::GetAddress(StunAttributeType type) const { switch (type) { case STUN_ATTR_MAPPED_ADDRESS: case STUN_ATTR_RESPONSE_ADDRESS: case STUN_ATTR_SOURCE_ADDRESS: case STUN_ATTR_CHANGED_ADDRESS: case STUN_ATTR_REFLECTED_FROM: case STUN_ATTR_ALTERNATE_SERVER: case STUN_ATTR_DESTINATION_ADDRESS: case STUN_ATTR_SOURCE_ADDRESS2: return reinterpret_cast<const StunAddressAttribute*>(GetAttribute(type)); default: assert(0); return 0; }}const StunUInt32Attribute*StunMessage::GetUInt32(StunAttributeType type) const { switch (type) { case STUN_ATTR_CHANGE_REQUEST: case STUN_ATTR_LIFETIME: case STUN_ATTR_BANDWIDTH: case STUN_ATTR_OPTIONS: return reinterpret_cast<const StunUInt32Attribute*>(GetAttribute(type)); default: assert(0); return 0; }}const StunByteStringAttribute*StunMessage::GetByteString(StunAttributeType type) const { switch (type) { case STUN_ATTR_USERNAME: case STUN_ATTR_PASSWORD: case STUN_ATTR_MESSAGE_INTEGRITY: case STUN_ATTR_DATA: case STUN_ATTR_MAGIC_COOKIE: return reinterpret_cast<const StunByteStringAttribute*>(GetAttribute(type)); default: assert(0); return 0; }}const StunErrorCodeAttribute* StunMessage::GetErrorCode() const { return reinterpret_cast<const StunErrorCodeAttribute*>( GetAttribute(STUN_ATTR_ERROR_CODE));}const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const { return reinterpret_cast<const StunUInt16ListAttribute*>( GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES));}const StunTransportPrefsAttribute* StunMessage::GetTransportPrefs() const { return reinterpret_cast<const StunTransportPrefsAttribute*>( GetAttribute(STUN_ATTR_TRANSPORT_PREFERENCES));}const StunAttribute* StunMessage::GetAttribute(StunAttributeType type) const { for (unsigned i = 0; i < attrs_->size(); i++) { if ((*attrs_)[i]->type() == type) return (*attrs_)[i]; } return 0;}bool StunMessage::Read(ByteBuffer* buf) { if (!buf->ReadUInt16(type_)) return false; if (!buf->ReadUInt16(length_)) return false; std::string transaction_id; if (!buf->ReadString(transaction_id, 16)) return false; assert(transaction_id.size() == 16); transaction_id_ = transaction_id; if (length_ > buf->Length()) return false; attrs_->resize(0); size_t rest = buf->Length() - length_; while (buf->Length() > rest) { uint16 attr_type, attr_length; if (!buf->ReadUInt16(attr_type)) return false; if (!buf->ReadUInt16(attr_length)) return false; StunAttribute* attr = StunAttribute::Create(attr_type, attr_length); if (!attr || !attr->Read(buf)) return false; attrs_->push_back(attr); } if (buf->Length() != rest) { // fixme: shouldn't be doing this return false; } return true;}void StunMessage::Write(ByteBuffer* buf) const { buf->WriteUInt16(type_); buf->WriteUInt16(length_); buf->WriteString(transaction_id_); for (unsigned i = 0; i < attrs_->size(); i++) { buf->WriteUInt16((*attrs_)[i]->type()); buf->WriteUInt16((*attrs_)[i]->length()); (*attrs_)[i]->Write(buf); }}StunAttribute::StunAttribute(uint16 type, uint16 length) : type_(type), length_(length) {}StunAttribute* StunAttribute::Create(uint16 type, uint16 length) { switch (type) { case STUN_ATTR_MAPPED_ADDRESS: case STUN_ATTR_RESPONSE_ADDRESS: case STUN_ATTR_SOURCE_ADDRESS: case STUN_ATTR_CHANGED_ADDRESS: case STUN_ATTR_REFLECTED_FROM: case STUN_ATTR_ALTERNATE_SERVER: case STUN_ATTR_DESTINATION_ADDRESS: case STUN_ATTR_SOURCE_ADDRESS2: if (length != StunAddressAttribute::SIZE) return 0; return new StunAddressAttribute(type); case STUN_ATTR_CHANGE_REQUEST: case STUN_ATTR_LIFETIME: case STUN_ATTR_BANDWIDTH: case STUN_ATTR_OPTIONS: if (length != StunUInt32Attribute::SIZE) return 0; return new StunUInt32Attribute(type); case STUN_ATTR_USERNAME: case STUN_ATTR_PASSWORD: case STUN_ATTR_MAGIC_COOKIE: return (length % 4 == 0) ? new StunByteStringAttribute(type, length) : 0; case STUN_ATTR_MESSAGE_INTEGRITY: return (length == 20) ? new StunByteStringAttribute(type, length) : 0; case STUN_ATTR_DATA: return new StunByteStringAttribute(type, length); case STUN_ATTR_ERROR_CODE: if (length < StunErrorCodeAttribute::MIN_SIZE) return 0; return new StunErrorCodeAttribute(type, length); case STUN_ATTR_UNKNOWN_ATTRIBUTES: return (length % 2 == 0) ? new StunUInt16ListAttribute(type, length) : 0; case STUN_ATTR_TRANSPORT_PREFERENCES: if ((length != StunTransportPrefsAttribute::SIZE1) && (length != StunTransportPrefsAttribute::SIZE2)) return 0; return new StunTransportPrefsAttribute(type, length); default: return 0; }}StunAddressAttribute* StunAttribute::CreateAddress(uint16 type) { switch (type) { case STUN_ATTR_MAPPED_ADDRESS: case STUN_ATTR_RESPONSE_ADDRESS: case STUN_ATTR_SOURCE_ADDRESS: case STUN_ATTR_CHANGED_ADDRESS: case STUN_ATTR_REFLECTED_FROM: case STUN_ATTR_ALTERNATE_SERVER: case STUN_ATTR_DESTINATION_ADDRESS: case STUN_ATTR_SOURCE_ADDRESS2: return new StunAddressAttribute(type); default: assert(false); return 0; }}StunUInt32Attribute* StunAttribute::CreateUInt32(uint16 type) { switch (type) { case STUN_ATTR_CHANGE_REQUEST: case STUN_ATTR_LIFETIME: case STUN_ATTR_BANDWIDTH: case STUN_ATTR_OPTIONS: return new StunUInt32Attribute(type); default: assert(false); return 0; }}StunByteStringAttribute* StunAttribute::CreateByteString(uint16 type) { switch (type) { case STUN_ATTR_USERNAME:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -