/* Copyright(C) 2007-2016 VoIP objects (voipobjects.com) * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ICEPlatform.h" #include "ICEStunAttributes.h" #include "ICENetworkHelper.h" #include using namespace ice; // --- MappedAddress --- MappedAddress::MappedAddress() { } MappedAddress::~MappedAddress() { } int MappedAddress::type() const { return StunAttribute::MappedAddress; } NetworkAddress& MappedAddress::address() { return mAddress; } void MappedAddress::buildPacket(BufferWriter& writer) { writer.writeUChar(0); writer.writeUChar(mAddress.stunType()); writer.writeUShort(mAddress.port()); switch (mAddress.stunType()) { case IPv4: writer.writeBuffer(&mAddress.sockaddr4()->sin_addr, 4); break; case IPv6: writer.writeBuffer(&mAddress.sockaddr6()->sin6_addr, 16); break; default: assert(0); } } bool MappedAddress::parsePacket(BufferReader& reader) { // Dequeue zero byte and ignore it /*uint8_t zeroByte = */reader.readUChar(); // Dequeue family mAddress.setStunType(reader.readUChar()); // Dequeue port mAddress.setPort(reader.readUShort()); // Deqeueue IP mAddress.setIp(reader.readIp(mAddress.stunType() == IPv4 ? AF_INET : AF_INET6)); return true; } void MappedAddress::dump(std::ostream& output) { output << "MappedAddress " << mAddress.toStdString(); } //----------- XorMappedAddress --------------- XorMappedAddress::XorMappedAddress() {} XorMappedAddress::~XorMappedAddress() {} int XorMappedAddress::type() const { return StunAttribute::XorMappedAddress; } void XorMappedAddress::buildPacket(BufferWriter& writer) { // Queue zero byte writer.writeUChar(0); // Queue family writer.writeUChar(mAddress.stunType()); // Xor&queue port uint16_t port = mAddress.port() ^ 0x2112; writer.writeUShort(port); // Xor&queue ip unsigned int ip4 = 0; uint32_t ip6[4]; switch (mAddress.stunType()) { case IPv4: ip4 = mAddress.sockaddr4()->sin_addr.s_addr; //this gets ip in network byte order ip4 = ntohl(ip4); // get host byte order ip4 ^= 0x2112A442; writer.writeUInt(ip4); // It will convert again to network byte order break; case IPv6: // Get copy of address in network byte order memcpy(&ip6, &mAddress.sockaddr6()->sin6_addr, 16); for (int i=0; i<3; i++) ip6[i] ^= htonl(0x2112A442); writer.writeBuffer(ip6, 16); break; } } bool XorMappedAddress::parsePacket(BufferReader& reader) { // Dequeue zero byte and ignore it reader.readUChar(); // Dequeue family mAddress.setStunType(reader.readUChar()); // Dequeue port mAddress.setPort(reader.readUShort() ^ 0x2112); // Deqeueue IP unsigned int ip4; union { uint32_t ip6[4]; in6_addr addr6; } v6; switch (mAddress.stunType()) { case IPv4: ip4 = htonl(reader.readUInt() ^ 0x2112A442); mAddress.setIp(ip4); break; case IPv6: reader.readBuffer(v6.ip6, 16); // XOR buffer for (int i=0; i<3; i++) v6.ip6[i] ^= htonl(0x2112A442); mAddress.setIp(v6.addr6); break; default: assert(0); } return true; } void XorMappedAddress::dump(std::ostream &output) { output << "XorMappedAddress " << mAddress.toStdString(); } //------------ StringAttr ----------------------- StringAttr::StringAttr() { } StringAttr::~StringAttr() { } int StringAttr::type() const { return StunAttribute::UnknownAttributes; } std::string StringAttr::value() const { return mValue; } void StringAttr::setValue(const std::string& value) { mValue = value; } void StringAttr::buildPacket(BufferWriter& writer) { if (!mValue.empty()) writer.writeBuffer(mValue.c_str(), mValue.length()); } bool StringAttr::parsePacket(BufferReader& reader) { char temp[1024]; memset(temp, 0, sizeof temp); reader.readBuffer(temp, sizeof temp); mValue = temp; return true; } void StringAttr::dump(std::ostream& output) { output << "StringAttr " << mValue; } //----------- Username --------------------------------- Username::Username() {} Username::~Username() {} int Username::type() const { return StunAttribute::Username; } void Username::dump(std::ostream &output) { output << "Username " << value(); } //----------- MessageIntegrity ------------------------- MessageIntegrity::MessageIntegrity() { memset(mValue, 0, sizeof(mValue)); } MessageIntegrity::~MessageIntegrity() { } int MessageIntegrity::type() const { return StunAttribute::MessageIntegrity; } void MessageIntegrity::setValue(const void* data) { if (data) memcpy(mValue, data, 20); } const void* MessageIntegrity::value() const { return mValue; } void MessageIntegrity::buildPacket(BufferWriter& stream) { stream.writeBuffer(mValue, 20); } bool MessageIntegrity::parsePacket(BufferReader& stream) { try { stream.readBuffer(mValue, 20); } catch(...) { return false; } return true; } void MessageIntegrity::dump(std::ostream &output) { ByteBuffer buffer(mValue, 20); output << "MessageIntegrity " << buffer.hexstring(); } //--------------- Fingerprint ---------------- Fingerprint::Fingerprint() { mCRC32 = 0; } Fingerprint::~Fingerprint() { } int Fingerprint::type() const { return StunAttribute::Fingerprint; } void Fingerprint::setCrc32(unsigned int crc) { mCRC32 = crc; } unsigned int Fingerprint::crc32() const { return mCRC32; } void Fingerprint::buildPacket(BufferWriter& stream) { stream.writeUInt(mCRC32); } bool Fingerprint::parsePacket(BufferReader& stream) { try { mCRC32 = stream.readUInt(); } catch(...) { return false; } return true; } void Fingerprint::dump(std::ostream &output) { output << "Fingerprint " << mCRC32; } //---------------- ErrorCode --------------- ErrorCode::ErrorCode() { mErrorCode = 0; } ErrorCode::~ErrorCode() { } int ErrorCode::type() const { return StunAttribute::ErrorCode; } void ErrorCode::setErrorCode(int errorCode) { mErrorCode = errorCode; } int ErrorCode::errorCode() const { return mErrorCode; } void ErrorCode::setErrorPhrase(const std::string& phrase) { mErrorPhrase = phrase; } std::string ErrorCode::errorPhrase() const { return mErrorPhrase; } void ErrorCode::buildPacket(BufferWriter& stream) { stream.writeUShort(0); uint8_t b = 0; // Get hundreds digit int digit = mErrorCode / 100; b = (digit & 4 ? 1 : 0) << 2; b |= (digit & 2 ? 1 : 0) << 1; b |= (digit & 1 ? 1 : 0); stream.writeUChar(b); stream.writeUChar(mErrorCode % 100); if (!mErrorPhrase.empty()) stream.writeBuffer(mErrorPhrase.c_str(), mErrorPhrase.length()); } bool ErrorCode::parsePacket(BufferReader& stream) { try { stream.readUShort(); unsigned char _class = stream.readUChar(); unsigned char _number = stream.readUChar(); mErrorCode = _class * 100 + _number; char temp[1024]; memset(temp, 0, sizeof temp); stream.readBuffer(temp, sizeof temp); mErrorPhrase = std::string(temp); } catch(...) { return false; } return true; } void ErrorCode::dump(std::ostream &output) { output << "ErrorCode " << mErrorCode << " " << mErrorPhrase; } //----------------- Realm ------------------------ Realm::Realm() {} Realm::~Realm() {} int Realm::type() const { return StunAttribute::Realm; } void Realm::dump(std::ostream &output) { output << "Realm " << value(); } //----------------- Nonce ------------------------ Nonce::Nonce() {} Nonce::~Nonce() {} int Nonce::type() const { return StunAttribute::Nonce; } void Nonce::dump(std::ostream &output) { output << "Nonce " << value(); } //----------------- Server ----------------------- Server::Server() {} Server::~Server() {} int Server::type() const { return StunAttribute::Server; } void Server::dump(std::ostream &output) { output << "Server " << value(); } //----------------- AlternateServer -------------- AlternateServer::AlternateServer() {} AlternateServer::~AlternateServer() {} int AlternateServer::type() const { return StunAttribute::AlternateServer; } void AlternateServer::dump(std::ostream &output) { output << "AlternateServer " << address().toStdString(); } //----------------- UnknownAttributes ------------ UnknownAttributes::UnknownAttributes() { } UnknownAttributes::~UnknownAttributes() { } int UnknownAttributes::type() const { return StunAttribute::UnknownAttributes; } void UnknownAttributes::buildPacket(BufferWriter& stream) { char zeroBytes[8]; memset(zeroBytes, 0, sizeof(zeroBytes)); stream.writeBuffer(zeroBytes, sizeof(zeroBytes)); } bool UnknownAttributes::parsePacket(BufferReader& stream) { try { char zeroBytes[8]; memset(zeroBytes, 0, sizeof(zeroBytes)); stream.readBuffer(zeroBytes, sizeof(zeroBytes)); } catch(...) { return false; } return true; } void UnknownAttributes::dump(std::ostream &output) { output << "UnknownAttributes"; } //---------------- ChannelNumber ---------------- ChannelNumber::ChannelNumber() :mChannelNumber(0) { } ChannelNumber::~ChannelNumber() { } int ChannelNumber::type() const { return StunAttribute::ChannelNumber; } void ChannelNumber::setChannelNumber(unsigned short value) { mChannelNumber = value; } unsigned short ChannelNumber::channelNumber() const { return mChannelNumber; } void ChannelNumber::buildPacket(BufferWriter& stream) { stream.writeUShort(mChannelNumber); stream.writeUChar(0); stream.writeUChar(0); } bool ChannelNumber::parsePacket(BufferReader& stream) { try { mChannelNumber = stream.readUShort(); stream.readUChar(); stream.readUChar(); } catch(...) { return false; } return true; } void ChannelNumber::dump(std::ostream &output) { output << "ChannelNumber " << mChannelNumber; } //--------------------------------- Lifetime ----------------------- Lifetime::Lifetime() :mLifetime(0) { } Lifetime::~Lifetime() { } int Lifetime::type() const { return StunAttribute::Lifetime; } void Lifetime::setLifetime(unsigned int value) { mLifetime = value; } unsigned int Lifetime::lifetime() const { return mLifetime; } void Lifetime::buildPacket(BufferWriter& stream) { stream.writeUInt(mLifetime); } bool Lifetime::parsePacket(BufferReader& stream) { try { mLifetime = stream.readUInt(); } catch(...) { return false; } return true; } void Lifetime::dump(std::ostream &output) { output << "Lifetime " << mLifetime; } //----------------------- DataAttribute ---------------------- DataAttribute::DataAttribute() { } DataAttribute::~DataAttribute() { } int DataAttribute::type() const { return StunAttribute::Data; } void DataAttribute::setData(ByteBuffer& buffer) { mData = buffer; } ByteBuffer DataAttribute::data() const { return mData; } void DataAttribute::buildPacket(BufferWriter& stream) { stream.writeBuffer(mData.data(), mData.size()); } bool DataAttribute::parsePacket(BufferReader& stream) { mData.resize(1024); mData.resize(stream.readBuffer(mData.mutableData(), mData.size())); return true; } void DataAttribute::dump(std::ostream &output) { output << "DataAttribute " << mData.hexstring(); } //---------------------- XorRelayedTransport ------------------------- XorRelayedAddress::XorRelayedAddress() {} XorRelayedAddress::~XorRelayedAddress() {} int XorRelayedAddress::type() const { return StunAttribute::XorRelayedAddress; } void XorRelayedAddress::dump(std::ostream &output) { output << "XorRelayedAddress " << address().toStdString(); } //---------------------- RequestedTransport --------------------------- RequestedTransport::RequestedTransport() :mRequestedTransport(UDP) { } RequestedTransport::~RequestedTransport() { } int RequestedTransport::type() const { return StunAttribute::RequestedTransport; } void RequestedTransport::setRequestedTransport(RequestedTransport::TransportType value) { mRequestedTransport = value; } unsigned char RequestedTransport::requestedTransport() const { return mRequestedTransport; } void RequestedTransport::buildPacket(BufferWriter& stream) { stream.writeUChar(mRequestedTransport); stream.writeUChar(0); stream.writeUChar(0); stream.writeUChar(0); } bool RequestedTransport::parsePacket(BufferReader& stream) { try { mRequestedTransport = stream.readUChar(); stream.readUChar(); stream.readUChar(); stream.readUChar(); } catch(...) { return false; } return true; } void RequestedTransport::dump(std::ostream &output) { output << "RequestedTransport " << mRequestedTransport; } //--------------------------------- Controlled ----------------------- ControlledAttr::ControlledAttr() { } ControlledAttr::~ControlledAttr() { } int ControlledAttr::type() const { return StunAttribute::ControlledAttr; } std::string ControlledAttr::tieBreaker() const { return std::string((const char*)mTieBreaker, 8); } void ControlledAttr::setTieBreaker(const std::string& tieBreaker) { assert(tieBreaker.length() == 8); memcpy(mTieBreaker, tieBreaker.c_str(), 8); } void ControlledAttr::buildPacket(BufferWriter& stream) { stream.writeBuffer(mTieBreaker, 8); } bool ControlledAttr::parsePacket(BufferReader& stream) { try { stream.readBuffer(mTieBreaker, 8); } catch(...) { return false; } return true; } void ControlledAttr::dump(std::ostream &output) { ByteBuffer b(mTieBreaker, 8); output << "ControlledAttr " << b.hexstring(); } //------------------- ControllingAttr -------------- ControllingAttr::ControllingAttr() { memset(mTieBreaker, 0, sizeof(mTieBreaker)); } ControllingAttr::~ControllingAttr() { } int ControllingAttr::type() const { return StunAttribute::ControllingAttr; } std::string ControllingAttr::tieBreaker() const { return std::string((const char*)mTieBreaker, 8); } void ControllingAttr::setTieBreaker(const std::string& tieBreaker) { memcpy(mTieBreaker, tieBreaker.c_str(), 8); } void ControllingAttr::buildPacket(BufferWriter& stream) { stream.writeBuffer(mTieBreaker, 8); } bool ControllingAttr::parsePacket(BufferReader& stream) { try { stream.readBuffer(mTieBreaker, 8); } catch(...) { return false; } return true; } void ControllingAttr::dump(std::ostream &output) { ByteBuffer b(mTieBreaker, 8); output << "ControllingAttr " << b.hexstring(); } //----------- ICEPriority --------------- ICEPriority::ICEPriority() { mPriority = 0; } ICEPriority::~ICEPriority() { } int ICEPriority::type() const { return StunAttribute::ICEPriority; } unsigned int ICEPriority::priority() const { return mPriority; } void ICEPriority::setPriority(unsigned int priority) { mPriority = priority; } void ICEPriority::buildPacket(BufferWriter& stream) { stream.writeUInt(mPriority); } bool ICEPriority::parsePacket(BufferReader& stream) { try { mPriority = stream.readUInt(); } catch(...) { return false; } return true; } void ICEPriority::dump(std::ostream &output) { output << "ICEPriority " << mPriority; } //------------------ USE-CANDIDATE ----------------------- ICEUseCandidate::ICEUseCandidate() { } ICEUseCandidate::~ICEUseCandidate() { } int ICEUseCandidate::type() const { return StunAttribute::ICEUseCandidate; } void ICEUseCandidate::buildPacket(BufferWriter& /*buffer*/) { } bool ICEUseCandidate::parsePacket(BufferReader& /*buffer*/) { return true; } void ICEUseCandidate::dump(std::ostream &output) { output << "ICEUseCandidate"; } // ------------- REQUESTED-ADDRESS-FAMILY ------------- RequestedAddressFamily::RequestedAddressFamily() :mAddressFamily(IPv4) {} RequestedAddressFamily::RequestedAddressFamily(AddressFamily family) :mAddressFamily(family) {} RequestedAddressFamily::~RequestedAddressFamily() {} int RequestedAddressFamily::type() const { return StunAttribute::RequestedAddressFamily; } AddressFamily RequestedAddressFamily::family() const { return mAddressFamily; } void RequestedAddressFamily::buildPacket(BufferWriter& stream) { stream.writeUChar(mAddressFamily); stream.writeUChar(0); stream.writeUChar(0); stream.writeUChar(0); } bool RequestedAddressFamily::parsePacket(BufferReader& stream) { try { mAddressFamily = (AddressFamily)stream.readUChar(); } catch(...) { return false; } return true; } void RequestedAddressFamily::dump(std::ostream &output) { output << "RequestedAddressFamily " << (mAddressFamily == IPv4 ? "IPv4" : "IPv6"); }