mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 12:37:51 +02:00
add a BasePacket class for headerless packets
This commit is contained in:
parent
e5955e39b7
commit
df47f1dd0b
16 changed files with 358 additions and 296 deletions
|
@ -144,8 +144,7 @@ QByteArray AvatarData::toByteArray() {
|
||||||
_headData->_isFaceTrackerConnected = true;
|
_headData->_isFaceTrackerConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray avatarDataByteArray;
|
QByteArray avatarDataByteArray(udt::MAX_PACKET_SIZE, 0);
|
||||||
avatarDataByteArray.resize(MAX_PACKET_SIZE);
|
|
||||||
|
|
||||||
unsigned char* destinationBuffer = reinterpret_cast<unsigned char*>(avatarDataByteArray.data());
|
unsigned char* destinationBuffer = reinterpret_cast<unsigned char*>(avatarDataByteArray.data());
|
||||||
unsigned char* startPosition = destinationBuffer;
|
unsigned char* startPosition = destinationBuffer;
|
||||||
|
|
|
@ -105,9 +105,6 @@ LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short
|
||||||
_nodeSocket.setPacketFilterOperator(std::bind(&LimitedNodeList::isPacketVerified, this, _1));
|
_nodeSocket.setPacketFilterOperator(std::bind(&LimitedNodeList::isPacketVerified, this, _1));
|
||||||
|
|
||||||
_packetStatTimer.start();
|
_packetStatTimer.start();
|
||||||
|
|
||||||
// make sure we handle STUN response packets
|
|
||||||
_packetReceiver->registerListener(PacketType::StunResponse, this, "processSTUNResponse");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimitedNodeList::setSessionUUID(const QUuid& sessionUUID) {
|
void LimitedNodeList::setSessionUUID(const QUuid& sessionUUID) {
|
||||||
|
@ -239,7 +236,7 @@ bool LimitedNodeList::packetSourceAndHashMatch(const udt::Packet& packet) {
|
||||||
static QString repeatedMessage
|
static QString repeatedMessage
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex("Packet of type \\d+ \\([\\sa-zA-Z]+\\) received from unknown node with UUID");
|
= LogHandler::getInstance().addRepeatedMessageRegex("Packet of type \\d+ \\([\\sa-zA-Z]+\\) received from unknown node with UUID");
|
||||||
|
|
||||||
qCDebug(networking) << "Packet of type" << headerType << "(" << qPrintable(nameForPacketType(headerType)) << ")"
|
qCDebug(networking) << "Packet of type" << headerType
|
||||||
<< "received from unknown node with UUID" << qPrintable(uuidStringWithoutCurlyBraces(sourceID));
|
<< "received from unknown node with UUID" << qPrintable(uuidStringWithoutCurlyBraces(sourceID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -611,7 +608,7 @@ void LimitedNodeList::sendSTUNRequest() {
|
||||||
_nodeSocket.writeDatagram(stunRequestPacket, sizeof(stunRequestPacket), _stunSockAddr);
|
_nodeSocket.writeDatagram(stunRequestPacket, sizeof(stunRequestPacket), _stunSockAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LimitedNodeList::processSTUNResponse(QSharedPointer<NLPacket> packet) {
|
void LimitedNodeList::processSTUNResponse(std::unique_ptr<udt::BasePacket> packet) {
|
||||||
// check the cookie to make sure this is actually a STUN response
|
// check the cookie to make sure this is actually a STUN response
|
||||||
// and read the first attribute and make sure it is a XOR_MAPPED_ADDRESS
|
// and read the first attribute and make sure it is a XOR_MAPPED_ADDRESS
|
||||||
const int NUM_BYTES_MESSAGE_TYPE_AND_LENGTH = 4;
|
const int NUM_BYTES_MESSAGE_TYPE_AND_LENGTH = 4;
|
||||||
|
@ -672,8 +669,6 @@ bool LimitedNodeList::processSTUNResponse(QSharedPointer<NLPacket> packet) {
|
||||||
|
|
||||||
flagTimeForConnectionStep(ConnectionStep::SetPublicSocketFromSTUN);
|
flagTimeForConnectionStep(ConnectionStep::SetPublicSocketFromSTUN);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// push forward attributeStartIndex by the length of this attribute
|
// push forward attributeStartIndex by the length of this attribute
|
||||||
|
@ -688,8 +683,6 @@ bool LimitedNodeList::processSTUNResponse(QSharedPointer<NLPacket> packet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimitedNodeList::startSTUNPublicSocketUpdate() {
|
void LimitedNodeList::startSTUNPublicSocketUpdate() {
|
||||||
|
@ -699,7 +692,7 @@ void LimitedNodeList::startSTUNPublicSocketUpdate() {
|
||||||
// if we don't know the STUN IP yet we need to have ourselves be called once it is known
|
// if we don't know the STUN IP yet we need to have ourselves be called once it is known
|
||||||
if (_stunSockAddr.getAddress().isNull()) {
|
if (_stunSockAddr.getAddress().isNull()) {
|
||||||
connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::startSTUNPublicSocketUpdate);
|
connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::startSTUNPublicSocketUpdate);
|
||||||
connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::addSTUNSockAddrToUnfiltered);
|
connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::addSTUNHandlerToUnfiltered);
|
||||||
|
|
||||||
// in case we just completely fail to lookup the stun socket - add a 10s timeout that will trigger the fail case
|
// in case we just completely fail to lookup the stun socket - add a 10s timeout that will trigger the fail case
|
||||||
const quint64 STUN_DNS_LOOKUP_TIMEOUT_MSECS = 10 * 1000;
|
const quint64 STUN_DNS_LOOKUP_TIMEOUT_MSECS = 10 * 1000;
|
||||||
|
@ -730,6 +723,12 @@ void LimitedNodeList::possiblyTimeoutSTUNAddressLookup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LimitedNodeList::addSTUNHandlerToUnfiltered() {
|
||||||
|
// make ourselves the handler of STUN packets when they come in
|
||||||
|
using std::placeholders::_1;
|
||||||
|
_nodeSocket.addUnfilteredHandler(_stunSockAddr, std::bind(&LimitedNodeList::processSTUNResponse, this, _1));
|
||||||
|
}
|
||||||
|
|
||||||
void LimitedNodeList::stopInitialSTUNUpdate(bool success) {
|
void LimitedNodeList::stopInitialSTUNUpdate(bool success) {
|
||||||
_hasCompletedInitialSTUN = true;
|
_hasCompletedInitialSTUN = true;
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,6 @@ public slots:
|
||||||
|
|
||||||
void startSTUNPublicSocketUpdate();
|
void startSTUNPublicSocketUpdate();
|
||||||
virtual void sendSTUNRequest();
|
virtual void sendSTUNRequest();
|
||||||
bool processSTUNResponse(QSharedPointer<NLPacket> packet);
|
|
||||||
|
|
||||||
void killNodeWithUUID(const QUuid& nodeUUID);
|
void killNodeWithUUID(const QUuid& nodeUUID);
|
||||||
|
|
||||||
|
@ -256,6 +255,7 @@ protected:
|
||||||
bool isPacketVerified(const udt::Packet& packet);
|
bool isPacketVerified(const udt::Packet& packet);
|
||||||
bool packetVersionMatch(const udt::Packet& packet);
|
bool packetVersionMatch(const udt::Packet& packet);
|
||||||
bool packetSourceAndHashMatch(const udt::Packet& packet);
|
bool packetSourceAndHashMatch(const udt::Packet& packet);
|
||||||
|
void processSTUNResponse(std::unique_ptr<udt::BasePacket> packet);
|
||||||
|
|
||||||
void handleNodeKill(const SharedNodePointer& node);
|
void handleNodeKill(const SharedNodePointer& node);
|
||||||
|
|
||||||
|
@ -310,7 +310,7 @@ protected:
|
||||||
private slots:
|
private slots:
|
||||||
void flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp);
|
void flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp);
|
||||||
void possiblyTimeoutSTUNAddressLookup();
|
void possiblyTimeoutSTUNAddressLookup();
|
||||||
void addSTUNSockAddrToUnfiltered() { _nodeSocket.addUnfilteredSockAddr(_stunSockAddr); } // called once STUN socket known
|
void addSTUNHandlerToUnfiltered(); // called once STUN socket known
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_LimitedNodeList_h
|
#endif // hifi_LimitedNodeList_h
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
//
|
|
||||||
// NetworkPacket.cpp
|
|
||||||
// libraries/networking/src
|
|
||||||
//
|
|
||||||
// Created by Brad Hefta-Gaub on 8/9/13.
|
|
||||||
// Copyright 2013 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 <cassert>
|
|
||||||
#include <cstring>
|
|
||||||
#include <QtDebug>
|
|
||||||
|
|
||||||
#include "SharedUtil.h"
|
|
||||||
#include "NetworkLogging.h"
|
|
||||||
|
|
||||||
#include "NetworkPacket.h"
|
|
||||||
|
|
||||||
void NetworkPacket::copyContents(const SharedNodePointer& node, const QByteArray& packet) {
|
|
||||||
if (packet.size() && packet.size() <= MAX_PACKET_SIZE) {
|
|
||||||
_node = node;
|
|
||||||
_byteArray = packet;
|
|
||||||
} else {
|
|
||||||
qCDebug(networking, ">>> NetworkPacket::copyContents() unexpected length = %d", packet.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkPacket::NetworkPacket(const NetworkPacket& packet) {
|
|
||||||
copyContents(packet.getNode(), packet.getByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkPacket::NetworkPacket(const SharedNodePointer& node, const QByteArray& packet) {
|
|
||||||
copyContents(node, packet);
|
|
||||||
};
|
|
||||||
|
|
||||||
// copy assignment
|
|
||||||
NetworkPacket& NetworkPacket::operator=(NetworkPacket const& other) {
|
|
||||||
copyContents(other.getNode(), other.getByteArray());
|
|
||||||
return *this;
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
//
|
|
||||||
// NetworkPacket.h
|
|
||||||
// libraries/networking/src
|
|
||||||
//
|
|
||||||
// Created by Brad Hefta-Gaub on 8/9/13.
|
|
||||||
// Copyright 2013 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// A really simple class that stores a network packet between being received and being processed
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_NetworkPacket_h
|
|
||||||
#define hifi_NetworkPacket_h
|
|
||||||
|
|
||||||
#include "NodeList.h"
|
|
||||||
|
|
||||||
/// Storage of not-yet processed inbound, or not yet sent outbound generic UDP network packet
|
|
||||||
class NetworkPacket {
|
|
||||||
public:
|
|
||||||
NetworkPacket() { }
|
|
||||||
NetworkPacket(const NetworkPacket& packet); // copy constructor
|
|
||||||
NetworkPacket& operator= (const NetworkPacket& other); // copy assignment
|
|
||||||
NetworkPacket(const SharedNodePointer& node, const QByteArray& byteArray);
|
|
||||||
|
|
||||||
const SharedNodePointer& getNode() const { return _node; }
|
|
||||||
const QByteArray& getByteArray() const { return _byteArray; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void copyContents(const SharedNodePointer& node, const QByteArray& byteArray);
|
|
||||||
|
|
||||||
SharedNodePointer _node;
|
|
||||||
QByteArray _byteArray;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_NetworkPacket_h
|
|
|
@ -139,8 +139,7 @@ QMetaMethod PacketReceiver::matchingMethodForListener(PacketType type, QObject*
|
||||||
if (methodIndex < 0) {
|
if (methodIndex < 0) {
|
||||||
qDebug() << "PacketReceiver::registerListener expected a slot with one of the following signatures:"
|
qDebug() << "PacketReceiver::registerListener expected a slot with one of the following signatures:"
|
||||||
<< possibleSignatures.toList() << "- but such a slot was not found."
|
<< possibleSignatures.toList() << "- but such a slot was not found."
|
||||||
<< "Could not complete listener registration for type"
|
<< "Could not complete listener registration for type" << type;
|
||||||
<< type << "-" << nameForPacketType(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(methodIndex >= 0);
|
Q_ASSERT(methodIndex >= 0);
|
||||||
|
@ -160,7 +159,6 @@ void PacketReceiver::registerVerifiedListener(PacketType type, QObject* object,
|
||||||
|
|
||||||
if (_packetListenerMap.contains(type)) {
|
if (_packetListenerMap.contains(type)) {
|
||||||
qDebug() << "Warning: Registering a packet listener for packet type" << type
|
qDebug() << "Warning: Registering a packet listener for packet type" << type
|
||||||
<< "(" << qPrintable(nameForPacketType(type)) << ")"
|
|
||||||
<< "that will remove a previously registered listener";
|
<< "that will remove a previously registered listener";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +202,7 @@ void PacketReceiver::handleVerifiedPacket(std::unique_ptr<udt::Packet> packet) {
|
||||||
// setup a HifiSockAddr to read into
|
// setup a HifiSockAddr to read into
|
||||||
HifiSockAddr senderSockAddr;
|
HifiSockAddr senderSockAddr;
|
||||||
|
|
||||||
// setup an NLPacket from the data we just read
|
// setup an NLPacket from the packet we were passed
|
||||||
auto nlPacket = NLPacket::fromBase(std::move(packet));
|
auto nlPacket = NLPacket::fromBase(std::move(packet));
|
||||||
|
|
||||||
_inPacketCount++;
|
_inPacketCount++;
|
||||||
|
@ -286,8 +284,7 @@ void PacketReceiver::handleVerifiedPacket(std::unique_ptr<udt::Packet> packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
qDebug().nospace() << "Error delivering packet " << packetType
|
qDebug().nospace() << "Error delivering packet " << packetType << " to listener "
|
||||||
<< " (" << qPrintable(nameForPacketType(packetType)) << ") to listener "
|
|
||||||
<< listener.first << "::" << qPrintable(listener.second.methodSignature());
|
<< listener.first << "::" << qPrintable(listener.second.methodSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,8 +293,7 @@ void PacketReceiver::handleVerifiedPacket(std::unique_ptr<udt::Packet> packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listenerIsDead) {
|
if (listenerIsDead) {
|
||||||
qDebug().nospace() << "Listener for packet" << nlPacket->getType()
|
qDebug().nospace() << "Listener for packet " << nlPacket->getType()
|
||||||
<< " (" << qPrintable(nameForPacketType(nlPacket->getType())) << ")"
|
|
||||||
<< " has been destroyed. Removing from listener map.";
|
<< " has been destroyed. Removing from listener map.";
|
||||||
it = _packetListenerMap.erase(it);
|
it = _packetListenerMap.erase(it);
|
||||||
|
|
||||||
|
@ -308,7 +304,7 @@ void PacketReceiver::handleVerifiedPacket(std::unique_ptr<udt::Packet> packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "No listener found for packet type " << nameForPacketType(nlPacket->getType());
|
qWarning() << "No listener found for packet type" << nlPacket->getType();
|
||||||
|
|
||||||
// insert a dummy listener so we don't print this again
|
// insert a dummy listener so we don't print this again
|
||||||
_packetListenerMap.insert(nlPacket->getType(), { nullptr, QMetaMethod() });
|
_packetListenerMap.insert(nlPacket->getType(), { nullptr, QMetaMethod() });
|
||||||
|
|
175
libraries/networking/src/udt/BasePacket.cpp
Normal file
175
libraries/networking/src/udt/BasePacket.cpp
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
//
|
||||||
|
// BasePacket.cpp
|
||||||
|
// libraries/networking/src/udt
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 2015-07-23.
|
||||||
|
// 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 "BasePacket.h"
|
||||||
|
|
||||||
|
using namespace udt;
|
||||||
|
|
||||||
|
const qint64 BasePacket::PACKET_WRITE_ERROR = -1;
|
||||||
|
|
||||||
|
std::unique_ptr<BasePacket> BasePacket::create(qint64 size) {
|
||||||
|
auto packet = std::unique_ptr<BasePacket>(new BasePacket(size));
|
||||||
|
|
||||||
|
packet->open(QIODevice::ReadWrite);
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<BasePacket> BasePacket::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<BasePacket>(new BasePacket(std::move(data), size, senderSockAddr));
|
||||||
|
|
||||||
|
packet->open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasePacket::BasePacket(qint64 size) {
|
||||||
|
auto maxPayload = maxPayloadSize();
|
||||||
|
|
||||||
|
if (size == -1) {
|
||||||
|
// default size of -1, means biggest packet possible
|
||||||
|
size = maxPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check
|
||||||
|
Q_ASSERT(size >= 0 || size < maxPayload);
|
||||||
|
|
||||||
|
_packetSize = size;
|
||||||
|
_packet.reset(new char[_packetSize]);
|
||||||
|
_payloadCapacity = _packetSize;
|
||||||
|
_payloadSize = 0;
|
||||||
|
_payloadStart = _packet.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
BasePacket::BasePacket(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr) :
|
||||||
|
_packetSize(size),
|
||||||
|
_packet(std::move(data)),
|
||||||
|
_payloadStart(_packet.get()),
|
||||||
|
_payloadCapacity(size),
|
||||||
|
_payloadSize(size),
|
||||||
|
_senderSockAddr(senderSockAddr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BasePacket::BasePacket(const BasePacket& other) {
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasePacket& BasePacket::operator=(const BasePacket& other) {
|
||||||
|
_packetSize = other._packetSize;
|
||||||
|
_packet = std::unique_ptr<char>(new char[_packetSize]);
|
||||||
|
memcpy(_packet.get(), other._packet.get(), _packetSize);
|
||||||
|
|
||||||
|
_payloadStart = _packet.get() + (other._payloadStart - other._packet.get());
|
||||||
|
_payloadCapacity = other._payloadCapacity;
|
||||||
|
|
||||||
|
_payloadSize = other._payloadSize;
|
||||||
|
|
||||||
|
if (other.isOpen() && !isOpen()) {
|
||||||
|
open(other.openMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
seek(other.pos());
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasePacket::BasePacket(BasePacket&& other) {
|
||||||
|
*this = std::move(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
BasePacket& BasePacket::operator=(BasePacket&& other) {
|
||||||
|
_packetSize = other._packetSize;
|
||||||
|
_packet = std::move(other._packet);
|
||||||
|
|
||||||
|
_payloadStart = other._payloadStart;
|
||||||
|
_payloadCapacity = other._payloadCapacity;
|
||||||
|
|
||||||
|
_payloadSize = other._payloadSize;
|
||||||
|
|
||||||
|
_senderSockAddr = std::move(other._senderSockAddr);
|
||||||
|
|
||||||
|
if (other.isOpen() && !isOpen()) {
|
||||||
|
open(other.openMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
seek(other.pos());
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasePacket::setPayloadSize(qint64 payloadSize) {
|
||||||
|
if (isWritable()) {
|
||||||
|
Q_ASSERT(payloadSize <= _payloadCapacity);
|
||||||
|
_payloadSize = payloadSize;
|
||||||
|
} else {
|
||||||
|
qDebug() << "You can not call setPayloadSize for a non-writeable Packet.";
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray BasePacket::read(qint64 maxSize) {
|
||||||
|
qint64 sizeToRead = std::min(size() - pos(), maxSize);
|
||||||
|
QByteArray data { QByteArray::fromRawData(getPayload() + pos(), sizeToRead) };
|
||||||
|
seek(pos() + sizeToRead);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasePacket::reset() {
|
||||||
|
if (isWritable()) {
|
||||||
|
_payloadSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QIODevice::reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 BasePacket::writeData(const char* data, qint64 maxSize) {
|
||||||
|
|
||||||
|
// make sure we have the space required to write this block
|
||||||
|
if (maxSize <= bytesAvailableForWrite()) {
|
||||||
|
qint64 currentPos = pos();
|
||||||
|
|
||||||
|
Q_ASSERT(currentPos < _payloadCapacity);
|
||||||
|
|
||||||
|
// good to go - write the data
|
||||||
|
memcpy(_payloadStart + currentPos, data, maxSize);
|
||||||
|
|
||||||
|
// keep track of _payloadSize so we can just write the actual data when packet is about to be sent
|
||||||
|
_payloadSize = std::max(currentPos + maxSize, _payloadSize);
|
||||||
|
|
||||||
|
// return the number of bytes written
|
||||||
|
return maxSize;
|
||||||
|
} else {
|
||||||
|
// not enough space left for this write - return an error
|
||||||
|
return PACKET_WRITE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 BasePacket::readData(char* dest, qint64 maxSize) {
|
||||||
|
// we're either reading what is left from the current position or what was asked to be read
|
||||||
|
qint64 numBytesToRead = std::min(bytesLeftToRead(), maxSize);
|
||||||
|
|
||||||
|
if (numBytesToRead > 0) {
|
||||||
|
int currentPosition = pos();
|
||||||
|
|
||||||
|
// read out the data
|
||||||
|
memcpy(dest, _payloadStart + currentPosition, numBytesToRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
return numBytesToRead;
|
||||||
|
}
|
116
libraries/networking/src/udt/BasePacket.h
Normal file
116
libraries/networking/src/udt/BasePacket.h
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
//
|
||||||
|
// BasePacket.h
|
||||||
|
// libraries/networking/src/udt
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 2015-07-23.
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef hifi_BasePacket_h
|
||||||
|
#define hifi_BasePacket_h
|
||||||
|
|
||||||
|
#include <QtCore/QIODevice>
|
||||||
|
|
||||||
|
#include "../HifiSockAddr.h"
|
||||||
|
|
||||||
|
namespace udt {
|
||||||
|
|
||||||
|
static const int MAX_PACKET_SIZE = 1450;
|
||||||
|
|
||||||
|
class BasePacket : public QIODevice {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static const qint64 PACKET_WRITE_ERROR;
|
||||||
|
|
||||||
|
static std::unique_ptr<BasePacket> create(qint64 size = -1);
|
||||||
|
static std::unique_ptr<BasePacket> fromReceivedPacket(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
|
||||||
|
|
||||||
|
static qint64 maxPayloadSize() { return MAX_PACKET_SIZE; } // The maximum payload size this packet can use to fit in MTU
|
||||||
|
static qint64 localHeaderSize() { return 0; } // Current level's header size
|
||||||
|
|
||||||
|
virtual qint64 totalHeadersSize() const { return 0; } // Cumulated size of all the headers
|
||||||
|
|
||||||
|
// Payload direct access to the payload, use responsibly!
|
||||||
|
char* getPayload() { return _payloadStart; }
|
||||||
|
const char* getPayload() const { return _payloadStart; }
|
||||||
|
|
||||||
|
// Return direct access to the entire packet, use responsibly!
|
||||||
|
char* getData() { return _packet.get(); }
|
||||||
|
const char* getData() const { return _packet.get(); }
|
||||||
|
|
||||||
|
// Returns the size of the packet, including the header
|
||||||
|
qint64 getDataSize() const { return totalHeadersSize() + _payloadSize; }
|
||||||
|
|
||||||
|
// Returns the size of the payload only
|
||||||
|
qint64 getPayloadSize() const { return _payloadSize; }
|
||||||
|
|
||||||
|
// Allows a writer to change the size of the payload used when writing directly
|
||||||
|
void setPayloadSize(qint64 payloadSize);
|
||||||
|
|
||||||
|
// Returns the number of bytes allocated for the payload
|
||||||
|
qint64 getPayloadCapacity() const { return _payloadCapacity; }
|
||||||
|
|
||||||
|
qint64 bytesLeftToRead() const { return _payloadSize - pos(); }
|
||||||
|
qint64 bytesAvailableForWrite() const { return _payloadCapacity - pos(); }
|
||||||
|
|
||||||
|
HifiSockAddr& getSenderSockAddr() { return _senderSockAddr; }
|
||||||
|
const HifiSockAddr& getSenderSockAddr() const { return _senderSockAddr; }
|
||||||
|
|
||||||
|
// QIODevice virtual functions
|
||||||
|
// WARNING: Those methods all refer to the payload ONLY and NOT the entire packet
|
||||||
|
virtual bool isSequential() const { return false; }
|
||||||
|
virtual bool reset();
|
||||||
|
virtual qint64 size() const { return _payloadCapacity; }
|
||||||
|
|
||||||
|
using QIODevice::read;
|
||||||
|
QByteArray read(qint64 maxSize);
|
||||||
|
|
||||||
|
template<typename T> qint64 peekPrimitive(T* data);
|
||||||
|
template<typename T> qint64 readPrimitive(T* data);
|
||||||
|
template<typename T> qint64 writePrimitive(const T& data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BasePacket(qint64 size);
|
||||||
|
BasePacket(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
|
||||||
|
BasePacket(const BasePacket& other);
|
||||||
|
BasePacket& operator=(const BasePacket& other);
|
||||||
|
BasePacket(BasePacket&& other);
|
||||||
|
BasePacket& operator=(BasePacket&& other);
|
||||||
|
|
||||||
|
// QIODevice virtual functions
|
||||||
|
virtual qint64 writeData(const char* data, qint64 maxSize);
|
||||||
|
virtual qint64 readData(char* data, qint64 maxSize);
|
||||||
|
|
||||||
|
qint64 _packetSize = 0; // Total size of the allocated memory
|
||||||
|
std::unique_ptr<char> _packet; // Allocated memory
|
||||||
|
|
||||||
|
char* _payloadStart = nullptr; // Start of the payload
|
||||||
|
qint64 _payloadCapacity = 0; // Total capacity of the payload
|
||||||
|
|
||||||
|
qint64 _payloadSize = 0; // How much of the payload is actually used
|
||||||
|
|
||||||
|
HifiSockAddr _senderSockAddr; // sender address for packet (only used on receiving end)
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> qint64 BasePacket::peekPrimitive(T* data) {
|
||||||
|
return QIODevice::peek(reinterpret_cast<char*>(data), sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> qint64 BasePacket::readPrimitive(T* data) {
|
||||||
|
return QIODevice::read(reinterpret_cast<char*>(data), sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> qint64 BasePacket::writePrimitive(const T& data) {
|
||||||
|
static_assert(!std::is_pointer<T>::value, "T must not be a pointer");
|
||||||
|
return QIODevice::write(reinterpret_cast<const char*>(&data), sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace udt
|
||||||
|
|
||||||
|
|
||||||
|
#endif // hifi_BasePacket_h
|
|
@ -13,8 +13,6 @@
|
||||||
|
|
||||||
using namespace udt;
|
using namespace udt;
|
||||||
|
|
||||||
const qint64 Packet::PACKET_WRITE_ERROR = -1;
|
|
||||||
|
|
||||||
std::unique_ptr<Packet> Packet::create(qint64 size, bool isReliable, bool isPartOfMessage) {
|
std::unique_ptr<Packet> Packet::create(qint64 size, bool isReliable, bool isPartOfMessage) {
|
||||||
auto packet = std::unique_ptr<Packet>(new Packet(size, isReliable, isPartOfMessage));
|
auto packet = std::unique_ptr<Packet>(new Packet(size, isReliable, isPartOfMessage));
|
||||||
|
|
||||||
|
@ -60,32 +58,19 @@ qint64 Packet::localHeaderSize() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet::Packet(qint64 size, bool isReliable, bool isPartOfMessage) :
|
Packet::Packet(qint64 size, bool isReliable, bool isPartOfMessage) :
|
||||||
|
BasePacket(size),
|
||||||
_isReliable(isReliable),
|
_isReliable(isReliable),
|
||||||
_isPartOfMessage(isPartOfMessage)
|
_isPartOfMessage(isPartOfMessage)
|
||||||
{
|
{
|
||||||
auto maxPayload = maxPayloadSize();
|
|
||||||
|
|
||||||
if (size == -1) {
|
|
||||||
// default size of -1, means biggest packet possible
|
|
||||||
size = maxPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
_packetSize = localHeaderSize() + size;
|
|
||||||
_packet.reset(new char[_packetSize]);
|
|
||||||
_payloadCapacity = size;
|
_payloadCapacity = size;
|
||||||
_payloadStart = _packet.get() + (_packetSize - _payloadCapacity);
|
_payloadStart = _packet.get() + (_packetSize - _payloadCapacity);
|
||||||
|
|
||||||
// Sanity check
|
|
||||||
Q_ASSERT(size >= 0 || size < maxPayload);
|
|
||||||
|
|
||||||
// set the UDT header to default values
|
// set the UDT header to default values
|
||||||
writeSequenceNumber(0);
|
writeSequenceNumber(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet::Packet(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr) :
|
Packet::Packet(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr) :
|
||||||
_packetSize(size),
|
BasePacket(std::move(data), size, senderSockAddr)
|
||||||
_packet(std::move(data)),
|
|
||||||
_senderSockAddr(senderSockAddr)
|
|
||||||
{
|
{
|
||||||
readIsReliable();
|
readIsReliable();
|
||||||
readIsPartOfMessage();
|
readIsPartOfMessage();
|
||||||
|
@ -97,72 +82,41 @@ Packet::Packet(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& send
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet::Packet(const Packet& other) :
|
Packet::Packet(const Packet& other) :
|
||||||
QIODevice()
|
BasePacket(other)
|
||||||
{
|
{
|
||||||
*this = other;
|
_isReliable = other._isReliable;
|
||||||
|
_isPartOfMessage = other._isPartOfMessage;
|
||||||
|
_sequenceNumber = other._sequenceNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet& Packet::operator=(const Packet& other) {
|
Packet& Packet::operator=(const Packet& other) {
|
||||||
_packetSize = other._packetSize;
|
BasePacket::operator=(other);
|
||||||
_packet = std::unique_ptr<char>(new char[_packetSize]);
|
|
||||||
memcpy(_packet.get(), other._packet.get(), _packetSize);
|
|
||||||
|
|
||||||
_payloadStart = _packet.get() + (other._payloadStart - other._packet.get());
|
|
||||||
_payloadCapacity = other._payloadCapacity;
|
|
||||||
|
|
||||||
_payloadSize = other._payloadSize;
|
|
||||||
|
|
||||||
if (other.isOpen() && !isOpen()) {
|
_isReliable = other._isReliable;
|
||||||
open(other.openMode());
|
_isPartOfMessage = other._isPartOfMessage;
|
||||||
}
|
_sequenceNumber = other._sequenceNumber;
|
||||||
|
|
||||||
seek(other.pos());
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet::Packet(Packet&& other) {
|
Packet::Packet(Packet&& other) :
|
||||||
*this = std::move(other);
|
BasePacket(other)
|
||||||
|
{
|
||||||
|
_isReliable = other._isReliable;
|
||||||
|
_isPartOfMessage = other._isPartOfMessage;
|
||||||
|
_sequenceNumber = other._sequenceNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet& Packet::operator=(Packet&& other) {
|
Packet& Packet::operator=(Packet&& other) {
|
||||||
_packetSize = other._packetSize;
|
BasePacket::operator=(std::move(other));
|
||||||
_packet = std::move(other._packet);
|
|
||||||
|
|
||||||
_payloadStart = other._payloadStart;
|
|
||||||
_payloadCapacity = other._payloadCapacity;
|
|
||||||
|
|
||||||
_payloadSize = other._payloadSize;
|
|
||||||
|
|
||||||
_senderSockAddr = std::move(other._senderSockAddr);
|
_isReliable = other._isReliable;
|
||||||
|
_isPartOfMessage = other._isPartOfMessage;
|
||||||
if (other.isOpen() && !isOpen()) {
|
_sequenceNumber = other._sequenceNumber;
|
||||||
open(other.openMode());
|
|
||||||
}
|
|
||||||
|
|
||||||
seek(other.pos());
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Packet::setPayloadSize(qint64 payloadSize) {
|
|
||||||
if (isWritable()) {
|
|
||||||
Q_ASSERT(payloadSize <= _payloadCapacity);
|
|
||||||
_payloadSize = payloadSize;
|
|
||||||
} else {
|
|
||||||
qDebug() << "You can not call setPayloadSize for a non-writeable Packet.";
|
|
||||||
Q_ASSERT(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Packet::reset() {
|
|
||||||
if (isWritable()) {
|
|
||||||
_payloadSize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QIODevice::reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint32_t CONTROL_BIT_MASK = 1 << (sizeof(Packet::SequenceNumberAndBitField) - 1);
|
static const uint32_t CONTROL_BIT_MASK = 1 << (sizeof(Packet::SequenceNumberAndBitField) - 1);
|
||||||
static const uint32_t RELIABILITY_BIT_MASK = 1 << (sizeof(Packet::SequenceNumberAndBitField) - 2);
|
static const uint32_t RELIABILITY_BIT_MASK = 1 << (sizeof(Packet::SequenceNumberAndBitField) - 2);
|
||||||
static const uint32_t MESSAGE_BIT_MASK = 1 << (sizeof(Packet::SequenceNumberAndBitField) - 3);
|
static const uint32_t MESSAGE_BIT_MASK = 1 << (sizeof(Packet::SequenceNumberAndBitField) - 3);
|
||||||
|
@ -196,46 +150,3 @@ void Packet::writeSequenceNumber(SequenceNumber sequenceNumber) {
|
||||||
// write new value by ORing (old value & BIT_FIELD_MASK) with new seqNum
|
// write new value by ORing (old value & BIT_FIELD_MASK) with new seqNum
|
||||||
*seqNumBitField = (*seqNumBitField & BIT_FIELD_MASK) | sequenceNumber;
|
*seqNumBitField = (*seqNumBitField & BIT_FIELD_MASK) | sequenceNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Packet::read(qint64 maxSize) {
|
|
||||||
qint64 sizeToRead = std::min(size() - pos(), maxSize);
|
|
||||||
QByteArray data { QByteArray::fromRawData(getPayload() + pos(), sizeToRead) };
|
|
||||||
seek(pos() + sizeToRead);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 Packet::writeData(const char* data, qint64 maxSize) {
|
|
||||||
|
|
||||||
// make sure we have the space required to write this block
|
|
||||||
if (maxSize <= bytesAvailableForWrite()) {
|
|
||||||
qint64 currentPos = pos();
|
|
||||||
|
|
||||||
Q_ASSERT(currentPos < _payloadCapacity);
|
|
||||||
|
|
||||||
// good to go - write the data
|
|
||||||
memcpy(_payloadStart + currentPos, data, maxSize);
|
|
||||||
|
|
||||||
// keep track of _payloadSize so we can just write the actual data when packet is about to be sent
|
|
||||||
_payloadSize = std::max(currentPos + maxSize, _payloadSize);
|
|
||||||
|
|
||||||
// return the number of bytes written
|
|
||||||
return maxSize;
|
|
||||||
} else {
|
|
||||||
// not enough space left for this write - return an error
|
|
||||||
return PACKET_WRITE_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 Packet::readData(char* dest, qint64 maxSize) {
|
|
||||||
// we're either reading what is left from the current position or what was asked to be read
|
|
||||||
qint64 numBytesToRead = std::min(bytesLeftToRead(), maxSize);
|
|
||||||
|
|
||||||
if (numBytesToRead > 0) {
|
|
||||||
int currentPosition = pos();
|
|
||||||
|
|
||||||
// read out the data
|
|
||||||
memcpy(dest, _payloadStart + currentPosition, numBytesToRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
return numBytesToRead;
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
|
|
||||||
#include <QtCore/QIODevice>
|
#include <QtCore/QIODevice>
|
||||||
|
|
||||||
#include "../HifiSockAddr.h"
|
#include "BasePacket.h"
|
||||||
#include "PacketHeaders.h"
|
#include "PacketHeaders.h"
|
||||||
|
|
||||||
namespace udt {
|
namespace udt {
|
||||||
|
|
||||||
class Packet : public QIODevice {
|
class Packet : public BasePacket {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
// NOTE: The SequenceNumber is only actually 29 bits to leave room for a bit field
|
// NOTE: The SequenceNumber is only actually 29 bits to leave room for a bit field
|
||||||
|
@ -34,8 +34,6 @@ public:
|
||||||
|
|
||||||
static const uint32_t DEFAULT_SEQUENCE_NUMBER = 0;
|
static const uint32_t DEFAULT_SEQUENCE_NUMBER = 0;
|
||||||
|
|
||||||
static const qint64 PACKET_WRITE_ERROR;
|
|
||||||
|
|
||||||
static std::unique_ptr<Packet> create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false);
|
static std::unique_ptr<Packet> create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false);
|
||||||
static std::unique_ptr<Packet> fromReceivedPacket(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
|
static std::unique_ptr<Packet> fromReceivedPacket(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
|
||||||
|
|
||||||
|
@ -52,47 +50,8 @@ public:
|
||||||
|
|
||||||
virtual qint64 totalHeadersSize() const; // Cumulated size of all the headers
|
virtual qint64 totalHeadersSize() const; // Cumulated size of all the headers
|
||||||
|
|
||||||
// Payload direct access to the payload, use responsibly!
|
|
||||||
char* getPayload() { return _payloadStart; }
|
|
||||||
const char* getPayload() const { return _payloadStart; }
|
|
||||||
|
|
||||||
// Return direct access to the entire packet, use responsibly!
|
|
||||||
char* getData() { return _packet.get(); }
|
|
||||||
const char* getData() const { return _packet.get(); }
|
|
||||||
|
|
||||||
// Returns the size of the packet, including the header
|
|
||||||
qint64 getDataSize() const { return totalHeadersSize() + _payloadSize; }
|
|
||||||
|
|
||||||
// Returns the size of the payload only
|
|
||||||
qint64 getPayloadSize() const { return _payloadSize; }
|
|
||||||
|
|
||||||
// Allows a writer to change the size of the payload used when writing directly
|
|
||||||
void setPayloadSize(qint64 payloadSize);
|
|
||||||
|
|
||||||
// Returns the number of bytes allocated for the payload
|
|
||||||
qint64 getPayloadCapacity() const { return _payloadCapacity; }
|
|
||||||
|
|
||||||
qint64 bytesLeftToRead() const { return _payloadSize - pos(); }
|
|
||||||
qint64 bytesAvailableForWrite() const { return _payloadCapacity - pos(); }
|
|
||||||
|
|
||||||
HifiSockAddr& getSenderSockAddr() { return _senderSockAddr; }
|
|
||||||
const HifiSockAddr& getSenderSockAddr() const { return _senderSockAddr; }
|
|
||||||
|
|
||||||
void writeSequenceNumber(SequenceNumber sequenceNumber);
|
void writeSequenceNumber(SequenceNumber sequenceNumber);
|
||||||
|
|
||||||
// QIODevice virtual functions
|
|
||||||
// WARNING: Those methods all refer to the payload ONLY and NOT the entire packet
|
|
||||||
virtual bool isSequential() const { return false; }
|
|
||||||
virtual bool reset();
|
|
||||||
virtual qint64 size() const { return _payloadCapacity; }
|
|
||||||
|
|
||||||
using QIODevice::read;
|
|
||||||
QByteArray read(qint64 maxSize);
|
|
||||||
|
|
||||||
template<typename T> qint64 peekPrimitive(T* data);
|
|
||||||
template<typename T> qint64 readPrimitive(T* data);
|
|
||||||
template<typename T> qint64 writePrimitive(const T& data);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Packet(qint64 size, bool isReliable = false, bool isPartOfMessage = false);
|
Packet(qint64 size, bool isReliable = false, bool isPartOfMessage = false);
|
||||||
Packet(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
|
Packet(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
|
||||||
|
@ -101,42 +60,15 @@ protected:
|
||||||
Packet(Packet&& other);
|
Packet(Packet&& other);
|
||||||
Packet& operator=(Packet&& other);
|
Packet& operator=(Packet&& other);
|
||||||
|
|
||||||
// QIODevice virtual functions
|
|
||||||
virtual qint64 writeData(const char* data, qint64 maxSize);
|
|
||||||
virtual qint64 readData(char* data, qint64 maxSize);
|
|
||||||
|
|
||||||
// Header readers - these read data to member variables after pulling packet off wire
|
// Header readers - these read data to member variables after pulling packet off wire
|
||||||
void readIsPartOfMessage();
|
void readIsPartOfMessage();
|
||||||
void readIsReliable();
|
void readIsReliable();
|
||||||
void readSequenceNumber();
|
void readSequenceNumber();
|
||||||
|
|
||||||
qint64 _packetSize = 0; // Total size of the allocated memory
|
|
||||||
std::unique_ptr<char> _packet; // Allocated memory
|
|
||||||
|
|
||||||
char* _payloadStart = nullptr; // Start of the payload
|
|
||||||
qint64 _payloadCapacity = 0; // Total capacity of the payload
|
|
||||||
|
|
||||||
qint64 _payloadSize = 0; // How much of the payload is actually used
|
|
||||||
|
|
||||||
bool _isReliable { false };
|
bool _isReliable { false };
|
||||||
bool _isPartOfMessage { false };
|
bool _isPartOfMessage { false };
|
||||||
SequenceNumber _sequenceNumber { 0 };
|
SequenceNumber _sequenceNumber { 0 };
|
||||||
|
|
||||||
HifiSockAddr _senderSockAddr; // sender address for packet (only used on receiving end)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> qint64 Packet::peekPrimitive(T* data) {
|
|
||||||
return QIODevice::peek(reinterpret_cast<char*>(data), sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> qint64 Packet::readPrimitive(T* data) {
|
|
||||||
return QIODevice::read(reinterpret_cast<char*>(data), sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> qint64 Packet::writePrimitive(const T& data) {
|
|
||||||
static_assert(!std::is_pointer<T>::value, "T must not be a pointer");
|
|
||||||
return QIODevice::write(reinterpret_cast<const char*>(&data), sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace udt
|
} // namespace udt
|
||||||
|
|
||||||
|
|
|
@ -65,9 +65,9 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
case PacketType::EntityAdd:
|
case PacketType::EntityAdd:
|
||||||
case PacketType::EntityEdit:
|
case PacketType::EntityEdit:
|
||||||
case PacketType::EntityData:
|
case PacketType::EntityData:
|
||||||
return VERSION_ENTITIES_NEW_PROTOCOL_LAYER;
|
return VERSION_ENTITIES_PROTOCOL_HEADER_SWAP;
|
||||||
default:
|
default:
|
||||||
return 11;
|
return 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,6 @@ enum class PacketType : uint8_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
const int NUM_BYTES_MD5_HASH = 16;
|
const int NUM_BYTES_MD5_HASH = 16;
|
||||||
|
|
||||||
const int MAX_PACKET_SIZE = 1450;
|
|
||||||
const int MAX_PACKET_HEADER_BYTES = 4 + NUM_BYTES_RFC4122_UUID + NUM_BYTES_MD5_HASH;
|
const int MAX_PACKET_HEADER_BYTES = 4 + NUM_BYTES_RFC4122_UUID + NUM_BYTES_MD5_HASH;
|
||||||
|
|
||||||
typedef char PacketVersion;
|
typedef char PacketVersion;
|
||||||
|
@ -135,5 +133,6 @@ const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP = 31;
|
||||||
const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP_FIX = 32;
|
const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP_FIX = 32;
|
||||||
const PacketVersion VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE = 33;
|
const PacketVersion VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE = 33;
|
||||||
const PacketVersion VERSION_ENTITIES_NEW_PROTOCOL_LAYER = 35;
|
const PacketVersion VERSION_ENTITIES_NEW_PROTOCOL_LAYER = 35;
|
||||||
|
const PacketVersion VERSION_ENTITIES_PROTOCOL_HEADER_SWAP = 36;
|
||||||
|
|
||||||
#endif // hifi_PacketHeaders_h
|
#endif // hifi_PacketHeaders_h
|
||||||
|
|
|
@ -88,11 +88,23 @@ void Socket::readPendingDatagrams() {
|
||||||
_udpSocket.readDatagram(buffer.get(), packetSizeWithHeader,
|
_udpSocket.readDatagram(buffer.get(), packetSizeWithHeader,
|
||||||
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
|
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
|
||||||
|
|
||||||
|
auto it = _unfilteredHandlers.find(senderSockAddr);
|
||||||
|
|
||||||
|
if (it != _unfilteredHandlers.end()) {
|
||||||
|
// we have a registered unfiltered handler for this HifiSockAddr - call that and return
|
||||||
|
if (it->second) {
|
||||||
|
auto basePacket = BasePacket::fromReceivedPacket(std::move(buffer), packetSizeWithHeader, senderSockAddr);
|
||||||
|
it->second(std::move(basePacket));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// setup a Packet from the data we just read
|
// setup a Packet from the data we just read
|
||||||
auto packet = Packet::fromReceivedPacket(std::move(buffer), packetSizeWithHeader, senderSockAddr);
|
auto packet = Packet::fromReceivedPacket(std::move(buffer), packetSizeWithHeader, senderSockAddr);
|
||||||
|
|
||||||
// call our verification operator to see if this packet is verified
|
// call our verification operator to see if this packet is verified
|
||||||
if (_unfilteredSockAddrs.contains(senderSockAddr) || !_packetFilterOperator || _packetFilterOperator(*packet)) {
|
if (!_packetFilterOperator || _packetFilterOperator(*packet)) {
|
||||||
if (_packetHandler) {
|
if (_packetHandler) {
|
||||||
// call the verified packet callback to let it handle this packet
|
// call the verified packet callback to let it handle this packet
|
||||||
return _packetHandler(std::move(packet));
|
return _packetHandler(std::move(packet));
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
namespace udt {
|
namespace udt {
|
||||||
|
|
||||||
using PacketFilterOperator = std::function<bool(const Packet&)>;
|
using PacketFilterOperator = std::function<bool(const Packet&)>;
|
||||||
|
|
||||||
|
using BasePacketHandler = std::function<void(std::unique_ptr<BasePacket>)>;
|
||||||
using PacketHandler = std::function<void(std::unique_ptr<Packet>)>;
|
using PacketHandler = std::function<void(std::unique_ptr<Packet>)>;
|
||||||
|
|
||||||
class Socket : public QObject {
|
class Socket : public QObject {
|
||||||
|
@ -49,7 +51,8 @@ public:
|
||||||
|
|
||||||
void setBufferSizes(int numBytes);
|
void setBufferSizes(int numBytes);
|
||||||
|
|
||||||
void addUnfilteredSockAddr(const HifiSockAddr& senderSockAddr) { _unfilteredSockAddrs.insert(senderSockAddr); }
|
void addUnfilteredHandler(const HifiSockAddr& senderSockAddr, BasePacketHandler handler)
|
||||||
|
{ _unfilteredHandlers[senderSockAddr] = handler; }
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void readPendingDatagrams();
|
void readPendingDatagrams();
|
||||||
|
@ -59,7 +62,7 @@ private:
|
||||||
PacketFilterOperator _packetFilterOperator;
|
PacketFilterOperator _packetFilterOperator;
|
||||||
PacketHandler _packetHandler;
|
PacketHandler _packetHandler;
|
||||||
|
|
||||||
QSet<HifiSockAddr> _unfilteredSockAddrs;
|
std::unordered_map<HifiSockAddr, BasePacketHandler> _unfilteredHandlers;
|
||||||
|
|
||||||
std::unordered_map<HifiSockAddr, Packet::SequenceNumber> _packetSequenceNumbers;
|
std::unordered_map<HifiSockAddr, Packet::SequenceNumber> _packetSequenceNumbers;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,11 +26,11 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include <LimitedNodeList.h> // for MAX_PACKET_SIZE
|
#include <BackgroundMode.h>
|
||||||
#include <udt/PacketHeaders.h> // for MAX_PACKET_HEADER_BYTES
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <ShapeInfo.h>
|
#include <ShapeInfo.h>
|
||||||
#include <BackgroundMode.h>
|
#include <udt/BasePacket.h>
|
||||||
|
#include <udt/PacketHeaders.h>
|
||||||
|
|
||||||
#include "OctreeConstants.h"
|
#include "OctreeConstants.h"
|
||||||
#include "OctreeElement.h"
|
#include "OctreeElement.h"
|
||||||
|
@ -40,14 +40,13 @@ typedef uint16_t OCTREE_PACKET_SEQUENCE;
|
||||||
const uint16_t MAX_OCTREE_PACKET_SEQUENCE = 65535;
|
const uint16_t MAX_OCTREE_PACKET_SEQUENCE = 65535;
|
||||||
typedef quint64 OCTREE_PACKET_SENT_TIME;
|
typedef quint64 OCTREE_PACKET_SENT_TIME;
|
||||||
typedef uint16_t OCTREE_PACKET_INTERNAL_SECTION_SIZE;
|
typedef uint16_t OCTREE_PACKET_INTERNAL_SECTION_SIZE;
|
||||||
const int MAX_OCTREE_PACKET_SIZE = MAX_PACKET_SIZE;
|
const int MAX_OCTREE_PACKET_SIZE = udt::MAX_PACKET_SIZE;
|
||||||
|
|
||||||
// this is overly conservative - sizeof(PacketType) is 8 bytes but a packed PacketType could be as small as one byte
|
|
||||||
const unsigned int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS)
|
const unsigned int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS)
|
||||||
+ sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME);
|
+ sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME);
|
||||||
|
|
||||||
const unsigned int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
|
const unsigned int MAX_OCTREE_PACKET_DATA_SIZE =
|
||||||
|
udt::MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
|
||||||
const unsigned int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE;
|
const unsigned int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE;
|
||||||
|
|
||||||
const unsigned int MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40;
|
const unsigned int MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40;
|
||||||
|
|
|
@ -791,6 +791,6 @@ void OctreeSceneStats::trackIncomingOctreePacket(NLPacket& packet, bool wasStats
|
||||||
_incomingPacket++;
|
_incomingPacket++;
|
||||||
_incomingBytes += packet.getDataSize();
|
_incomingBytes += packet.getDataSize();
|
||||||
if (!wasStatsPacket) {
|
if (!wasStatsPacket) {
|
||||||
_incomingWastedBytes += (MAX_PACKET_SIZE - packet.getDataSize());
|
_incomingWastedBytes += (udt::MAX_PACKET_SIZE - packet.getDataSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue