//// Packet.cpp// libraries/networking/src//// Created by Clement on 7/2/15.// Copyright 2015 High Fidelity, Inc.// Copyright 2021 Vircadia contributors.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #include "Packet.h" #include <array> #include <LogHandler.h> #include "Socket.h" #include "../NetworkLogging.h" using namespace udt; int packetMetaTypeId = qRegisterMetaType<Packet*>("Packet*"); using Key = uint64_t;static const std::array<Key, 4> KEYS {{ 0x0, 0x6362726973736574, 0x7362697261726461, 0x72687566666d616e,}}; void xorHelper(char* start, int size, Key key) { auto current = start; auto xorValue = reinterpret_cast<const char*>(&key); for (int i = 0; i < size; ++i) { *(current++) ^= *(xorValue + (i % sizeof(Key))); }} int Packet::localHeaderSize(bool isPartOfMessage) { return sizeof(Packet::SequenceNumberAndBitField) + (isPartOfMessage ? sizeof(Packet::MessageNumberAndBitField) + sizeof(MessagePartNumber) : 0);} int Packet::totalHeaderSize(bool isPartOfMessage) { return BasePacket::totalHeaderSize() + Packet::localHeaderSize(isPartOfMessage);} int Packet::maxPayloadSize(bool isPartOfMessage) { return BasePacket::maxPayloadSize() - Packet::localHeaderSize(isPartOfMessage);} std::unique_ptr<Packet> Packet::create(qint64 size, bool isReliable, bool isPartOfMessage) { auto packet = std::unique_ptr<Packet>(new Packet(size, isReliable, isPartOfMessage)); packet->open(QIODevice::ReadWrite); return packet;} std::unique_ptr<Packet> Packet::fromReceivedPacket(std::unique_ptr<char[]> data, qint64 size, const SockAddr& senderSockAddr) { // Fail with invalid size Q_ASSERT(size >= 0); // allocate memory auto packet = std::unique_ptr<Packet>(new Packet(std::move(data), size, senderSockAddr)); packet->open(QIODevice::ReadOnly); return packet;} std::unique_ptr<Packet> Packet::createCopy(const Packet& other) { return std::unique_ptr<Packet>(new Packet(other));} Packet::Packet(qint64 size, bool isReliable, bool isPartOfMessage) : BasePacket((size == -1) ? -1 : (Packet::localHeaderSize() + size)), _isReliable(isReliable), _isPartOfMessage(isPartOfMessage){ adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage)); // set the UDT header to default values writeHeader();} Packet::Packet(std::unique_ptr<char[]> data, qint64 size, const SockAddr& senderSockAddr) : BasePacket(std::move(data), size, senderSockAddr){ readHeader(); adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); if (getObfuscationLevel() != Packet::NoObfuscation) {#ifdef UDT_CONNECTION_DEBUG QString debugString = "Unobfuscating packet %1 with level %2"; debugString = debugString.arg(QString::number((uint32_t)getSequenceNumber()), QString::number(getObfuscationLevel())); if (isPartOfMessage()) { debugString += "\n"; debugString += " Message Number: %1, Part Number: %2."; debugString = debugString.arg(QString::number(getMessageNumber()), QString::number(getMessagePartNumber())); } HIFI_FCDEBUG(networking(), debugString);#endif obfuscate(NoObfuscation); // Undo obfuscation }} Packet::Packet(const Packet& other) : BasePacket(other) { copyMembers(other);} Packet& Packet::operator=(const Packet& other) { BasePacket::operator=(other); copyMembers(other); return *this;} Packet::Packet(Packet&& other) : BasePacket(std::move(other)) { copyMembers(other);} Packet& Packet::operator=(Packet&& other) { BasePacket::operator=(std::move(other)); copyMembers(other); return *this;} void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) { _isPartOfMessage = true; _messageNumber = messageNumber; _packetPosition = position; _messagePartNumber = messagePartNumber; writeHeader();} void Packet::writeSequenceNumber(SequenceNumber sequenceNumber) const { _sequenceNumber = sequenceNumber; writeHeader();} void Packet::obfuscate(ObfuscationLevel level) { auto obfuscationKey = KEYS[getObfuscationLevel()] ^ KEYS[level]; // Undo old and apply new one. if (obfuscationKey != 0) { xorHelper(getData() + localHeaderSize(isPartOfMessage()), getDataSize() - localHeaderSize(isPartOfMessage()), obfuscationKey); // Update members and header _obfuscationLevel = level; writeHeader(); }} void Packet::copyMembers(const Packet& other) { _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; _obfuscationLevel = other._obfuscationLevel; _sequenceNumber = other._sequenceNumber; _packetPosition = other._packetPosition; _messageNumber = other._messageNumber; _messagePartNumber = other._messagePartNumber; _receiveTime = other._receiveTime;} void Packet::readHeader() const { SequenceNumberAndBitField* seqNumBitField = reinterpret_cast<SequenceNumberAndBitField*>(_packet.get()); Q_ASSERT_X(!(*seqNumBitField & CONTROL_BIT_MASK), "Packet::readHeader()", "This should be a data packet"); _isReliable = (bool) (*seqNumBitField & RELIABILITY_BIT_MASK); // Only keep reliability bit _isPartOfMessage = (bool) (*seqNumBitField & MESSAGE_BIT_MASK); // Only keep message bit _obfuscationLevel = (ObfuscationLevel)((*seqNumBitField & OBFUSCATION_LEVEL_MASK) >> OBFUSCATION_LEVEL_OFFSET); _sequenceNumber = SequenceNumber{ *seqNumBitField & SEQUENCE_NUMBER_MASK }; // Remove the bit field if (_isPartOfMessage) { MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1; _messageNumber = *messageNumberAndBitField & MESSAGE_NUMBER_MASK; _packetPosition = static_cast<PacketPosition>(*messageNumberAndBitField >> PACKET_POSITION_OFFSET); MessagePartNumber* messagePartNumber = messageNumberAndBitField + 1; _messagePartNumber = *messagePartNumber; }} void Packet::writeHeader() const { // grab pointer to current SequenceNumberAndBitField SequenceNumberAndBitField* seqNumBitField = reinterpret_cast<SequenceNumberAndBitField*>(_packet.get()); // Write sequence number and reset bit field Q_ASSERT_X(!((SequenceNumber::Type)_sequenceNumber & BIT_FIELD_MASK), "Packet::writeHeader()", "Sequence number is overflowing into bit field"); *seqNumBitField = ((SequenceNumber::Type)_sequenceNumber); if (_isReliable) { *seqNumBitField |= RELIABILITY_BIT_MASK; } if (_obfuscationLevel != NoObfuscation) { *seqNumBitField |= (_obfuscationLevel << OBFUSCATION_LEVEL_OFFSET); } if (_isPartOfMessage) { *seqNumBitField |= MESSAGE_BIT_MASK; Q_ASSERT_X(!(_messageNumber & PACKET_POSITION_MASK), "Packet::writeHeader()", "Message number is overflowing into bit field"); MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1; *messageNumberAndBitField = _messageNumber; *messageNumberAndBitField |= _packetPosition << PACKET_POSITION_OFFSET; MessagePartNumber* messagePartNumber = messageNumberAndBitField + 1; *messagePartNumber = _messagePartNumber; }}
//
// Packet.cpp
// libraries/networking/src
//
// Created by Clement on 7/2/15.
// Copyright 2015 High Fidelity, Inc.
// Copyright 2021 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Packet.h"
#include <array>
#include <LogHandler.h>
#include "Socket.h"
#include "../NetworkLogging.h"
using namespace udt;
int packetMetaTypeId = qRegisterMetaType<Packet*>("Packet*");
using Key = uint64_t;
static const std::array<Key, 4> KEYS {{
0x0,
0x6362726973736574,
0x7362697261726461,
0x72687566666d616e,
}};
void xorHelper(char* start, int size, Key key) {
auto current = start;
auto xorValue = reinterpret_cast<const char*>(&key);
for (int i = 0; i < size; ++i) {
*(current++) ^= *(xorValue + (i % sizeof(Key)));
}
}
int Packet::localHeaderSize(bool isPartOfMessage) {
return sizeof(Packet::SequenceNumberAndBitField) +
(isPartOfMessage ? sizeof(Packet::MessageNumberAndBitField) + sizeof(MessagePartNumber) : 0);
}
int Packet::totalHeaderSize(bool isPartOfMessage) {
return BasePacket::totalHeaderSize() + Packet::localHeaderSize(isPartOfMessage);
}
int Packet::maxPayloadSize(bool isPartOfMessage) {
return BasePacket::maxPayloadSize() - Packet::localHeaderSize(isPartOfMessage);
}
std::unique_ptr<Packet> Packet::create(qint64 size, bool isReliable, bool isPartOfMessage) {
auto packet = std::unique_ptr<Packet>(new Packet(size, isReliable, isPartOfMessage));
packet->open(QIODevice::ReadWrite);
return packet;
}
std::unique_ptr<Packet> Packet::fromReceivedPacket(std::unique_ptr<char[]> data, qint64 size, const SockAddr& senderSockAddr) {
// Fail with invalid size
Q_ASSERT(size >= 0);
// allocate memory
auto packet = std::unique_ptr<Packet>(new Packet(std::move(data), size, senderSockAddr));
packet->open(QIODevice::ReadOnly);
return packet;
}
std::unique_ptr<Packet> Packet::createCopy(const Packet& other) {
return std::unique_ptr<Packet>(new Packet(other));
}
Packet::Packet(qint64 size, bool isReliable, bool isPartOfMessage) :
BasePacket((size == -1) ? -1 : (Packet::localHeaderSize() + size)),
_isReliable(isReliable),
_isPartOfMessage(isPartOfMessage)
{
adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage));
// set the UDT header to default values
writeHeader();
}
Packet::Packet(std::unique_ptr<char[]> data, qint64 size, const SockAddr& senderSockAddr) :
BasePacket(std::move(data), size, senderSockAddr)
{
readHeader();
adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0);
if (getObfuscationLevel() != Packet::NoObfuscation) {
#ifdef UDT_CONNECTION_DEBUG
QString debugString = "Unobfuscating packet %1 with level %2";
debugString = debugString.arg(QString::number((uint32_t)getSequenceNumber()),
QString::number(getObfuscationLevel()));
if (isPartOfMessage()) {
debugString += "\n";
debugString += " Message Number: %1, Part Number: %2.";
debugString = debugString.arg(QString::number(getMessageNumber()),
QString::number(getMessagePartNumber()));
}
HIFI_FCDEBUG(networking(), debugString);
#endif
obfuscate(NoObfuscation); // Undo obfuscation
}
}
Packet::Packet(const Packet& other) : BasePacket(other) {
copyMembers(other);
}
Packet& Packet::operator=(const Packet& other) {
BasePacket::operator=(other);
copyMembers(other);
return *this;
}
Packet::Packet(Packet&& other) : BasePacket(std::move(other)) {
copyMembers(other);
}
Packet& Packet::operator=(Packet&& other) {
BasePacket::operator=(std::move(other));
copyMembers(other);
return *this;
}
void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) {
_isPartOfMessage = true;
_messageNumber = messageNumber;
_packetPosition = position;
_messagePartNumber = messagePartNumber;
writeHeader();
}
void Packet::writeSequenceNumber(SequenceNumber sequenceNumber) const {
_sequenceNumber = sequenceNumber;
writeHeader();
}
void Packet::obfuscate(ObfuscationLevel level) {
auto obfuscationKey = KEYS[getObfuscationLevel()] ^ KEYS[level]; // Undo old and apply new one.
if (obfuscationKey != 0) {
xorHelper(getData() + localHeaderSize(isPartOfMessage()),
getDataSize() - localHeaderSize(isPartOfMessage()), obfuscationKey);
// Update members and header
_obfuscationLevel = level;
writeHeader();
}
}
void Packet::copyMembers(const Packet& other) {
_isReliable = other._isReliable;
_isPartOfMessage = other._isPartOfMessage;
_obfuscationLevel = other._obfuscationLevel;
_sequenceNumber = other._sequenceNumber;
_packetPosition = other._packetPosition;
_messageNumber = other._messageNumber;
_messagePartNumber = other._messagePartNumber;
_receiveTime = other._receiveTime;
}
void Packet::readHeader() const {
SequenceNumberAndBitField* seqNumBitField = reinterpret_cast<SequenceNumberAndBitField*>(_packet.get());
Q_ASSERT_X(!(*seqNumBitField & CONTROL_BIT_MASK), "Packet::readHeader()", "This should be a data packet");
_isReliable = (bool) (*seqNumBitField & RELIABILITY_BIT_MASK); // Only keep reliability bit
_isPartOfMessage = (bool) (*seqNumBitField & MESSAGE_BIT_MASK); // Only keep message bit
_obfuscationLevel = (ObfuscationLevel)((*seqNumBitField & OBFUSCATION_LEVEL_MASK) >> OBFUSCATION_LEVEL_OFFSET);
_sequenceNumber = SequenceNumber{ *seqNumBitField & SEQUENCE_NUMBER_MASK }; // Remove the bit field
if (_isPartOfMessage) {
MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1;
_messageNumber = *messageNumberAndBitField & MESSAGE_NUMBER_MASK;
_packetPosition = static_cast<PacketPosition>(*messageNumberAndBitField >> PACKET_POSITION_OFFSET);
MessagePartNumber* messagePartNumber = messageNumberAndBitField + 1;
_messagePartNumber = *messagePartNumber;
}
}
void Packet::writeHeader() const {
// grab pointer to current SequenceNumberAndBitField
SequenceNumberAndBitField* seqNumBitField = reinterpret_cast<SequenceNumberAndBitField*>(_packet.get());
// Write sequence number and reset bit field
Q_ASSERT_X(!((SequenceNumber::Type)_sequenceNumber & BIT_FIELD_MASK),
"Packet::writeHeader()", "Sequence number is overflowing into bit field");
*seqNumBitField = ((SequenceNumber::Type)_sequenceNumber);
if (_isReliable) {
*seqNumBitField |= RELIABILITY_BIT_MASK;
}
if (_obfuscationLevel != NoObfuscation) {
*seqNumBitField |= (_obfuscationLevel << OBFUSCATION_LEVEL_OFFSET);
}
if (_isPartOfMessage) {
*seqNumBitField |= MESSAGE_BIT_MASK;
Q_ASSERT_X(!(_messageNumber & PACKET_POSITION_MASK),
"Packet::writeHeader()", "Message number is overflowing into bit field");
MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1;
*messageNumberAndBitField = _messageNumber;
*messageNumberAndBitField |= _packetPosition << PACKET_POSITION_OFFSET;
MessagePartNumber* messagePartNumber = messageNumberAndBitField + 1;
*messagePartNumber = _messagePartNumber;
}
}