mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-29 08:21:58 +02:00
228 lines
7.4 KiB
C++
228 lines
7.4 KiB
C++
//
|
|
// Packet.cpp
|
|
// libraries/networking/src
|
|
//
|
|
// Created by Clement on 7/2/15.
|
|
// Copyright 2015 High Fidelity, Inc.
|
|
//
|
|
// 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 HifiSockAddr& 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 HifiSockAddr& 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;
|
|
}
|
|
}
|