mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-05 06:36:21 +02:00
Merge branch 'atp' of https://github.com/birarda/hifi into protocol
This commit is contained in:
commit
beba45c8c5
71 changed files with 885 additions and 755 deletions
|
@ -97,7 +97,7 @@ AudioMixer::AudioMixer(NLPacket& packet) :
|
|||
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
|
||||
QSet<PacketType::Value> nodeAudioPackets {
|
||||
QSet<PacketType> nodeAudioPackets {
|
||||
PacketType::MicrophoneAudioNoEcho, PacketType::MicrophoneAudioWithEcho,
|
||||
PacketType::InjectAudio, PacketType::SilentAudioFrame,
|
||||
PacketType::AudioStreamStats
|
||||
|
|
|
@ -50,7 +50,7 @@ AvatarAudioStream* AudioMixerClientData::getAvatarAudioStream() const {
|
|||
}
|
||||
|
||||
int AudioMixerClientData::parseData(NLPacket& packet) {
|
||||
PacketType::Value packetType = packet.getType();
|
||||
PacketType packetType = packet.getType();
|
||||
|
||||
if (packetType == PacketType::AudioStreamStats) {
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ AvatarAudioStream::AvatarAudioStream(bool isStereo, const InboundAudioStream::Se
|
|||
{
|
||||
}
|
||||
|
||||
int AvatarAudioStream::parseStreamProperties(PacketType::Value type, const QByteArray& packetAfterSeqNum, int& numAudioSamples) {
|
||||
int AvatarAudioStream::parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples) {
|
||||
int readBytes = 0;
|
||||
|
||||
if (type == PacketType::SilentAudioFrame) {
|
||||
|
|
|
@ -25,7 +25,7 @@ private:
|
|||
AvatarAudioStream(const AvatarAudioStream&);
|
||||
AvatarAudioStream& operator= (const AvatarAudioStream&);
|
||||
|
||||
int parseStreamProperties(PacketType::Value type, const QByteArray& packetAfterSeqNum, int& numAudioSamples);
|
||||
int parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples);
|
||||
};
|
||||
|
||||
#endif // hifi_AvatarAudioStream_h
|
||||
|
|
|
@ -259,8 +259,8 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
return;
|
||||
}
|
||||
|
||||
PacketSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(otherNode->getUUID());
|
||||
PacketSequenceNumber lastSeqFromSender = otherNode->getLastSequenceNumberForPacketType(PacketType::AvatarData);
|
||||
uint16_t lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(otherNode->getUUID());
|
||||
uint16_t lastSeqFromSender = otherNodeData->getLastReceivedSequenceNumber();
|
||||
|
||||
if (lastSeqToReceiver > lastSeqFromSender) {
|
||||
// Did we somehow get out of order packets from the sender?
|
||||
|
@ -289,7 +289,7 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
|
||||
// set the last sent sequence number for this sender on the receiver
|
||||
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
|
||||
otherNode->getLastSequenceNumberForPacketType(PacketType::AvatarData));
|
||||
otherNodeData->getLastReceivedSequenceNumber());
|
||||
|
||||
// start a new segment in the PacketList for this avatar
|
||||
avatarPacketList.startSegment();
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
#include "AvatarMixerClientData.h"
|
||||
|
||||
int AvatarMixerClientData::parseData(NLPacket& packet) {
|
||||
// compute the offset to the data payload
|
||||
// pull the sequence number from the data first
|
||||
packet.readPrimitive(&_lastReceivedSequenceNumber);
|
||||
|
||||
// read the remaining data
|
||||
return _avatar.parseDataFromBuffer(packet.read(packet.bytesLeftToRead()));
|
||||
}
|
||||
|
||||
|
@ -24,13 +27,13 @@ bool AvatarMixerClientData::checkAndSetHasReceivedFirstPackets() {
|
|||
return oldValue;
|
||||
}
|
||||
|
||||
PacketSequenceNumber AvatarMixerClientData::getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const {
|
||||
uint16_t AvatarMixerClientData::getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const {
|
||||
// return the matching PacketSequenceNumber, or the default if we don't have it
|
||||
auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeUUID);
|
||||
if (nodeMatch != _lastBroadcastSequenceNumbers.end()) {
|
||||
return nodeMatch->second;
|
||||
} else {
|
||||
return DEFAULT_SEQUENCE_NUMBER;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,10 +36,12 @@ public:
|
|||
|
||||
bool checkAndSetHasReceivedFirstPackets();
|
||||
|
||||
PacketSequenceNumber getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const;
|
||||
void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, PacketSequenceNumber sequenceNumber)
|
||||
uint16_t getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const;
|
||||
void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, uint16_t sequenceNumber)
|
||||
{ _lastBroadcastSequenceNumbers[nodeUUID] = sequenceNumber; }
|
||||
Q_INVOKABLE void removeLastBroadcastSequenceNumber(const QUuid& nodeUUID) { _lastBroadcastSequenceNumbers.erase(nodeUUID); }
|
||||
|
||||
uint16_t getLastReceivedSequenceNumber() const { return _lastReceivedSequenceNumber; }
|
||||
|
||||
quint64 getBillboardChangeTimestamp() const { return _billboardChangeTimestamp; }
|
||||
void setBillboardChangeTimestamp(quint64 billboardChangeTimestamp) { _billboardChangeTimestamp = billboardChangeTimestamp; }
|
||||
|
@ -77,8 +79,9 @@ public:
|
|||
void loadJSONStats(QJsonObject& jsonObject) const;
|
||||
private:
|
||||
AvatarData _avatar;
|
||||
|
||||
std::unordered_map<QUuid, PacketSequenceNumber, UUIDHasher> _lastBroadcastSequenceNumbers;
|
||||
|
||||
uint16_t _lastReceivedSequenceNumber { 0 };
|
||||
std::unordered_map<QUuid, uint16_t, UUIDHasher> _lastBroadcastSequenceNumbers;
|
||||
|
||||
bool _hasReceivedFirstPackets = false;
|
||||
quint64 _billboardChangeTimestamp = 0;
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
OctreeQueryNode(),
|
||||
_lastDeletedEntitiesSentAt(0) { }
|
||||
|
||||
virtual PacketType::Value getMyPacketType() const { return PacketType::EntityData; }
|
||||
virtual PacketType getMyPacketType() const { return PacketType::EntityData; }
|
||||
|
||||
quint64 getLastDeletedEntitiesSentAt() const { return _lastDeletedEntitiesSentAt; }
|
||||
void setLastDeletedEntitiesSentAt(quint64 sentAt) { _lastDeletedEntitiesSentAt = sentAt; }
|
||||
|
|
|
@ -28,11 +28,11 @@ public:
|
|||
// Subclasses must implement these methods
|
||||
virtual OctreeQueryNode* createOctreeQueryNode();
|
||||
virtual char getMyNodeType() const { return NodeType::EntityServer; }
|
||||
virtual PacketType::Value getMyQueryMessageType() const { return PacketType::EntityQuery; }
|
||||
virtual PacketType getMyQueryMessageType() const { return PacketType::EntityQuery; }
|
||||
virtual const char* getMyServerName() const { return MODEL_SERVER_NAME; }
|
||||
virtual const char* getMyLoggingServerTargetName() const { return MODEL_SERVER_LOGGING_TARGET_NAME; }
|
||||
virtual const char* getMyDefaultPersistFilename() const { return LOCAL_MODELS_PERSIST_FILE; }
|
||||
virtual PacketType::Value getMyEditNackType() const { return PacketType::EntityEditNack; }
|
||||
virtual PacketType getMyEditNackType() const { return PacketType::EntityEditNack; }
|
||||
virtual QString getMyDomainSettingsKey() const { return QString("entity_server_settings"); }
|
||||
|
||||
// subclass may implement these method
|
||||
|
|
|
@ -89,7 +89,7 @@ void OctreeInboundPacketProcessor::processPacket(QSharedPointer<NLPacket> packet
|
|||
}
|
||||
|
||||
// Ask our tree subclass if it can handle the incoming packet...
|
||||
PacketType::Value packetType = packet->getType();
|
||||
PacketType packetType = packet->getType();
|
||||
|
||||
if (_myServer->getOctree()->handlesEditPacketType(packetType)) {
|
||||
PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE", debugProcessPacket);
|
||||
|
@ -153,7 +153,7 @@ void OctreeInboundPacketProcessor::processPacket(QSharedPointer<NLPacket> packet
|
|||
if (debugProcessPacket) {
|
||||
qDebug() << " --- inside while loop ---";
|
||||
qDebug() << " maxSize=" << maxSize;
|
||||
qDebug("OctreeInboundPacketProcessor::processPacket() %c "
|
||||
qDebug("OctreeInboundPacketProcessor::processPacket() %hhu "
|
||||
"payload=%p payloadLength=%lld editData=%p payloadPosition=%lld maxSize=%d",
|
||||
packetType, packet->getPayload(), packet->getPayloadSize(), editData,
|
||||
packet->pos(), maxSize);
|
||||
|
@ -191,7 +191,7 @@ void OctreeInboundPacketProcessor::processPacket(QSharedPointer<NLPacket> packet
|
|||
}
|
||||
|
||||
if (debugProcessPacket) {
|
||||
qDebug("OctreeInboundPacketProcessor::processPacket() DONE LOOPING FOR %c "
|
||||
qDebug("OctreeInboundPacketProcessor::processPacket() DONE LOOPING FOR %hhu "
|
||||
"payload=%p payloadLength=%lld editData=%p payloadPosition=%lld",
|
||||
packetType, packet->getPayload(), packet->getPayloadSize(), editData, packet->pos());
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ void OctreeInboundPacketProcessor::processPacket(QSharedPointer<NLPacket> packet
|
|||
}
|
||||
trackInboundPacket(nodeUUID, sequence, transitTime, editsInPacket, processTime, lockWaitTime);
|
||||
} else {
|
||||
qDebug("unknown packet ignored... packetType=%d", packetType);
|
||||
qDebug("unknown packet ignored... packetType=%hhu", packetType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ OctreeQueryNode::OctreeQueryNode() :
|
|||
_viewSent(false),
|
||||
_octreePacket(),
|
||||
_octreePacketWaiting(false),
|
||||
_lastOctreePayload(new char[MAX_PACKET_SIZE]),
|
||||
_lastOctreePayload(new char[udt::MAX_PACKET_SIZE]),
|
||||
_lastOctreePacketLength(0),
|
||||
_duplicatePacketCount(0),
|
||||
_firstSuppressedPacket(usecTimestampNow()),
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
virtual ~OctreeQueryNode();
|
||||
|
||||
void init(); // called after creation to set up some virtual items
|
||||
virtual PacketType::Value getMyPacketType() const = 0;
|
||||
virtual PacketType getMyPacketType() const = 0;
|
||||
|
||||
void resetOctreePacket(); // resets octree packet to after "V" header
|
||||
|
||||
|
@ -150,7 +150,7 @@ private:
|
|||
|
||||
quint64 _lastRootTimestamp;
|
||||
|
||||
PacketType::Value _myPacketType;
|
||||
PacketType _myPacketType;
|
||||
bool _isShuttingDown;
|
||||
|
||||
SentPacketHistory _sentPacketHistory;
|
||||
|
|
|
@ -219,7 +219,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes
|
|||
packetSent = true;
|
||||
|
||||
int packetSizeWithHeader = nodeData->getPacket().getDataSize();
|
||||
thisWastedBytes = MAX_PACKET_SIZE - packetSizeWithHeader;
|
||||
thisWastedBytes = udt::MAX_PACKET_SIZE - packetSizeWithHeader;
|
||||
_totalWastedBytes += thisWastedBytes;
|
||||
_totalBytes += nodeData->getPacket().getDataSize();
|
||||
_totalPackets++;
|
||||
|
@ -251,7 +251,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes
|
|||
packetSent = true;
|
||||
|
||||
int packetSizeWithHeader = nodeData->getPacket().getDataSize();
|
||||
int thisWastedBytes = MAX_PACKET_SIZE - packetSizeWithHeader;
|
||||
int thisWastedBytes = udt::MAX_PACKET_SIZE - packetSizeWithHeader;
|
||||
_totalWastedBytes += thisWastedBytes;
|
||||
_totalBytes += packetSizeWithHeader;
|
||||
_totalPackets++;
|
||||
|
@ -598,7 +598,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
|||
|
||||
_totalBytes += packet->getDataSize();
|
||||
_totalPackets++;
|
||||
_totalWastedBytes += MAX_PACKET_SIZE - packet->getDataSize();
|
||||
_totalWastedBytes += udt::MAX_PACKET_SIZE - packet->getDataSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,11 +63,11 @@ public:
|
|||
// Subclasses must implement these methods
|
||||
virtual OctreeQueryNode* createOctreeQueryNode() = 0;
|
||||
virtual char getMyNodeType() const = 0;
|
||||
virtual PacketType::Value getMyQueryMessageType() const = 0;
|
||||
virtual PacketType getMyQueryMessageType() const = 0;
|
||||
virtual const char* getMyServerName() const = 0;
|
||||
virtual const char* getMyLoggingServerTargetName() const = 0;
|
||||
virtual const char* getMyDefaultPersistFilename() const = 0;
|
||||
virtual PacketType::Value getMyEditNackType() const = 0;
|
||||
virtual PacketType getMyEditNackType() const = 0;
|
||||
virtual QString getMyDomainSettingsKey() const { return QString("octree_server_settings"); }
|
||||
|
||||
// subclass may implement these method
|
||||
|
|
|
@ -580,7 +580,6 @@ void DomainServer::processConnectRequestPacket(QSharedPointer<NLPacket> packet)
|
|||
NodeType_t nodeType;
|
||||
HifiSockAddr publicSockAddr, localSockAddr;
|
||||
|
||||
|
||||
if (packet->getPayloadSize() == 0) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -49,26 +49,30 @@ IceServer::IceServer(int argc, char* argv[]) :
|
|||
}
|
||||
|
||||
bool IceServer::packetVersionMatch(const udt::Packet& packet) {
|
||||
if (packet.getVersion() == versionForPacketType(packet.getType())) {
|
||||
PacketType headerType = NLPacket::typeInHeader(packet);
|
||||
PacketVersion headerVersion = NLPacket::versionInHeader(packet);
|
||||
|
||||
if (headerVersion == versionForPacketType(headerType)) {
|
||||
return true;
|
||||
} else {
|
||||
qDebug() << "Packet version mismatch for packet" << packet.getType()
|
||||
<< "(" << nameForPacketType(packet.getType()) << ") from" << packet.getSenderSockAddr();
|
||||
qDebug() << "Packet version mismatch for packet" << headerType
|
||||
<< "(" << nameForPacketType(headerType) << ") from" << packet.getSenderSockAddr();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void IceServer::processPacket(std::unique_ptr<udt::Packet> packet) {
|
||||
PacketType::Value packetType = packet->getType();
|
||||
|
||||
if (packetType == PacketType::ICEServerHeartbeat) {
|
||||
SharedNetworkPeer peer = addOrUpdateHeartbeatingPeer(*packet);
|
||||
auto nlPacket = NLPacket::fromBase(std::move(packet));
|
||||
|
||||
if (nlPacket->getType() == PacketType::ICEServerHeartbeat) {
|
||||
SharedNetworkPeer peer = addOrUpdateHeartbeatingPeer(*nlPacket);
|
||||
|
||||
// so that we can send packets to the heartbeating peer when we need, we need to activate a socket now
|
||||
peer->activateMatchingOrNewSymmetricSocket(packet->getSenderSockAddr());
|
||||
} else if (packetType == PacketType::ICEServerQuery) {
|
||||
QDataStream heartbeatStream(packet.get());
|
||||
peer->activateMatchingOrNewSymmetricSocket(nlPacket->getSenderSockAddr());
|
||||
} else if (nlPacket->getType() == PacketType::ICEServerQuery) {
|
||||
QDataStream heartbeatStream(nlPacket.get());
|
||||
|
||||
// this is a node hoping to connect to a heartbeating peer - do we have the heartbeating peer?
|
||||
QUuid senderUUID;
|
||||
|
@ -89,7 +93,7 @@ void IceServer::processPacket(std::unique_ptr<udt::Packet> packet) {
|
|||
qDebug() << "Sending information for peer" << connectRequestID << "to peer" << senderUUID;
|
||||
|
||||
// we have the peer they want to connect to - send them pack the information for that peer
|
||||
sendPeerInformationPacket(*matchingPeer, &packet->getSenderSockAddr());
|
||||
sendPeerInformationPacket(*matchingPeer, &nlPacket->getSenderSockAddr());
|
||||
|
||||
// we also need to send them to the active peer they are hoping to connect to
|
||||
// create a dummy peer object we can pass to sendPeerInformationPacket
|
||||
|
@ -102,7 +106,7 @@ void IceServer::processPacket(std::unique_ptr<udt::Packet> packet) {
|
|||
}
|
||||
}
|
||||
|
||||
SharedNetworkPeer IceServer::addOrUpdateHeartbeatingPeer(udt::Packet& packet) {
|
||||
SharedNetworkPeer IceServer::addOrUpdateHeartbeatingPeer(NLPacket& packet) {
|
||||
|
||||
// pull the UUID, public and private sock addrs for this peer
|
||||
QUuid senderUUID;
|
||||
|
@ -135,7 +139,7 @@ SharedNetworkPeer IceServer::addOrUpdateHeartbeatingPeer(udt::Packet& packet) {
|
|||
}
|
||||
|
||||
void IceServer::sendPeerInformationPacket(const NetworkPeer& peer, const HifiSockAddr* destinationSockAddr) {
|
||||
auto peerPacket = udt::Packet::create(PacketType::ICEServerPeerInformation);
|
||||
auto peerPacket = NLPacket::create(PacketType::ICEServerPeerInformation);
|
||||
|
||||
// get the byte array for this peer
|
||||
peerPacket->write(peer.toByteArray());
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <NetworkPeer.h>
|
||||
#include <HTTPConnection.h>
|
||||
#include <HTTPManager.h>
|
||||
#include <udt/Packet.h>
|
||||
#include <NLPacket.h>
|
||||
#include <udt/Socket.h>
|
||||
|
||||
typedef QHash<QUuid, SharedNetworkPeer> NetworkPeerHash;
|
||||
|
@ -35,7 +35,7 @@ private:
|
|||
bool packetVersionMatch(const udt::Packet& packet);
|
||||
void processPacket(std::unique_ptr<udt::Packet> packet);
|
||||
|
||||
SharedNetworkPeer addOrUpdateHeartbeatingPeer(udt::Packet& incomingPacket);
|
||||
SharedNetworkPeer addOrUpdateHeartbeatingPeer(NLPacket& incomingPacket);
|
||||
void sendPeerInformationPacket(const NetworkPeer& peer, const HifiSockAddr* destinationSockAddr);
|
||||
|
||||
QUuid _id;
|
||||
|
|
|
@ -2706,7 +2706,7 @@ int Application::sendNackPackets() {
|
|||
return packetsSent;
|
||||
}
|
||||
|
||||
void Application::queryOctree(NodeType_t serverType, PacketType::Value packetType, NodeToJurisdictionMap& jurisdictions) {
|
||||
void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) {
|
||||
|
||||
//qCDebug(interfaceapp) << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView();
|
||||
bool wantExtraDebugging = getLogger()->extraDebugging();
|
||||
|
|
|
@ -478,7 +478,7 @@ private:
|
|||
|
||||
void renderLookatIndicator(glm::vec3 pointOfInterest);
|
||||
|
||||
void queryOctree(NodeType_t serverType, PacketType::Value packetType, NodeToJurisdictionMap& jurisdictions);
|
||||
void queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions);
|
||||
void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum);
|
||||
|
||||
glm::vec3 getSunDirection();
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
OctreePacketProcessor::OctreePacketProcessor() {
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
|
||||
QSet<PacketType::Value> types {
|
||||
QSet<PacketType> types {
|
||||
PacketType::OctreeStats, PacketType::EntityData,
|
||||
PacketType::EntityErase, PacketType::OctreeStats
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ void OctreePacketProcessor::processPacket(QSharedPointer<NLPacket> packet, Share
|
|||
Application* app = Application::getInstance();
|
||||
bool wasStatsPacket = false;
|
||||
|
||||
PacketType::Value octreePacketType = packet->getType();
|
||||
PacketType octreePacketType = packet->getType();
|
||||
|
||||
// note: PacketType_OCTREE_STATS can have PacketType_VOXEL_DATA
|
||||
// immediately following them inside the same packet. So, we process the PacketType_OCTREE_STATS first
|
||||
|
@ -68,11 +68,11 @@ void OctreePacketProcessor::processPacket(QSharedPointer<NLPacket> packet, Share
|
|||
}
|
||||
} // fall through to piggyback message
|
||||
|
||||
PacketType::Value packetType = packet->getType();
|
||||
PacketType packetType = packet->getType();
|
||||
|
||||
// check version of piggyback packet against expected version
|
||||
if (packet->getVersion() != versionForPacketType(packet->getType())) {
|
||||
static QMultiMap<QUuid, PacketType::Value> versionDebugSuppressMap;
|
||||
static QMultiMap<QUuid, PacketType> versionDebugSuppressMap;
|
||||
|
||||
const QUuid& senderUUID = packet->getSourceID();
|
||||
if (!versionDebugSuppressMap.contains(senderUUID, packetType)) {
|
||||
|
|
|
@ -164,7 +164,7 @@ int InboundAudioStream::parseData(NLPacket& packet) {
|
|||
return packet.pos();
|
||||
}
|
||||
|
||||
int InboundAudioStream::parseStreamProperties(PacketType::Value type, const QByteArray& packetAfterSeqNum, int& numAudioSamples) {
|
||||
int InboundAudioStream::parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples) {
|
||||
if (type == PacketType::SilentAudioFrame) {
|
||||
quint16 numSilentSamples = 0;
|
||||
memcpy(&numSilentSamples, packetAfterSeqNum.constData(), sizeof(quint16));
|
||||
|
@ -177,7 +177,7 @@ int InboundAudioStream::parseStreamProperties(PacketType::Value type, const QByt
|
|||
}
|
||||
}
|
||||
|
||||
int InboundAudioStream::parseAudioData(PacketType::Value type, const QByteArray& packetAfterStreamProperties, int numAudioSamples) {
|
||||
int InboundAudioStream::parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int numAudioSamples) {
|
||||
return _ringBuffer.writeData(packetAfterStreamProperties.data(), numAudioSamples * sizeof(int16_t));
|
||||
}
|
||||
|
||||
|
|
|
@ -194,11 +194,11 @@ protected:
|
|||
/// parses the info between the seq num and the audio data in the network packet and calculates
|
||||
/// how many audio samples this packet contains (used when filling in samples for dropped packets).
|
||||
/// default implementation assumes no stream properties and raw audio samples after stream propertiess
|
||||
virtual int parseStreamProperties(PacketType::Value type, const QByteArray& packetAfterSeqNum, int& networkSamples);
|
||||
virtual int parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& networkSamples);
|
||||
|
||||
/// parses the audio data in the network packet.
|
||||
/// default implementation assumes packet contains raw audio samples after stream properties
|
||||
virtual int parseAudioData(PacketType::Value type, const QByteArray& packetAfterStreamProperties, int networkSamples);
|
||||
virtual int parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int networkSamples);
|
||||
|
||||
/// writes silent samples to the buffer that may be dropped to reduce latency caused by the buffer
|
||||
virtual int writeDroppableSilentSamples(int silentSamples);
|
||||
|
|
|
@ -30,7 +30,7 @@ InjectedAudioStream::InjectedAudioStream(const QUuid& streamIdentifier, const bo
|
|||
|
||||
const uchar MAX_INJECTOR_VOLUME = 255;
|
||||
|
||||
int InjectedAudioStream::parseStreamProperties(PacketType::Value type,
|
||||
int InjectedAudioStream::parseStreamProperties(PacketType type,
|
||||
const QByteArray& packetAfterSeqNum,
|
||||
int& numAudioSamples) {
|
||||
// setup a data stream to read from this packet
|
||||
|
|
|
@ -31,7 +31,7 @@ private:
|
|||
InjectedAudioStream& operator= (const InjectedAudioStream&);
|
||||
|
||||
AudioStreamStats getAudioStreamStats() const;
|
||||
int parseStreamProperties(PacketType::Value type, const QByteArray& packetAfterSeqNum, int& numAudioSamples);
|
||||
int parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples);
|
||||
|
||||
const QUuid _streamIdentifier;
|
||||
float _radius;
|
||||
|
|
|
@ -42,7 +42,7 @@ int MixedProcessedAudioStream::writeLastFrameRepeatedWithFade(int samples) {
|
|||
return deviceSamplesWritten;
|
||||
}
|
||||
|
||||
int MixedProcessedAudioStream::parseAudioData(PacketType::Value type, const QByteArray& packetAfterStreamProperties, int networkSamples) {
|
||||
int MixedProcessedAudioStream::parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int networkSamples) {
|
||||
|
||||
emit addedStereoSamples(packetAfterStreamProperties);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
protected:
|
||||
int writeDroppableSilentSamples(int silentSamples);
|
||||
int writeLastFrameRepeatedWithFade(int samples);
|
||||
int parseAudioData(PacketType::Value type, const QByteArray& packetAfterStreamProperties, int networkSamples);
|
||||
int parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int networkSamples);
|
||||
|
||||
private:
|
||||
int networkToDeviceSamples(int networkSamples);
|
||||
|
|
|
@ -144,8 +144,7 @@ QByteArray AvatarData::toByteArray() {
|
|||
_headData->_isFaceTrackerConnected = true;
|
||||
}
|
||||
|
||||
QByteArray avatarDataByteArray;
|
||||
avatarDataByteArray.resize(MAX_PACKET_SIZE);
|
||||
QByteArray avatarDataByteArray(udt::MAX_PACKET_SIZE, 0);
|
||||
|
||||
unsigned char* destinationBuffer = reinterpret_cast<unsigned char*>(avatarDataByteArray.data());
|
||||
unsigned char* startPosition = destinationBuffer;
|
||||
|
@ -1093,8 +1092,11 @@ void AvatarData::sendAvatarDataPacket() {
|
|||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
QByteArray avatarByteArray = toByteArray();
|
||||
|
||||
static uint16_t sequenceNumber = 0;
|
||||
|
||||
auto avatarPacket = NLPacket::create(PacketType::AvatarData, avatarByteArray.size());
|
||||
auto avatarPacket = NLPacket::create(PacketType::AvatarData, avatarByteArray.size() + sizeof(sequenceNumber));
|
||||
avatarPacket->writePrimitive(sequenceNumber++);
|
||||
avatarPacket->write(avatarByteArray);
|
||||
|
||||
nodeList->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer);
|
||||
|
|
|
@ -43,8 +43,8 @@ public:
|
|||
virtual ~EntityTreeRenderer();
|
||||
|
||||
virtual char getMyNodeType() const { return NodeType::EntityServer; }
|
||||
virtual PacketType::Value getMyQueryMessageType() const { return PacketType::EntityQuery; }
|
||||
virtual PacketType::Value getExpectedPacketType() const { return PacketType::EntityData; }
|
||||
virtual PacketType getMyQueryMessageType() const { return PacketType::EntityQuery; }
|
||||
virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; }
|
||||
virtual void renderElement(OctreeElement* element, RenderArgs* args);
|
||||
virtual float getSizeScale() const;
|
||||
virtual int getBoundaryLevelAdjust() const;
|
||||
|
|
|
@ -28,13 +28,13 @@ void EntityEditPacketSender::processEntityEditNackPacket(QSharedPointer<NLPacket
|
|||
}
|
||||
}
|
||||
|
||||
void EntityEditPacketSender::adjustEditPacketForClockSkew(PacketType::Value type, QByteArray& buffer, int clockSkew) {
|
||||
void EntityEditPacketSender::adjustEditPacketForClockSkew(PacketType type, QByteArray& buffer, int clockSkew) {
|
||||
if (type == PacketType::EntityAdd || type == PacketType::EntityEdit) {
|
||||
EntityItem::adjustEditPacketForClockSkew(buffer, clockSkew);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityEditPacketSender::queueEditEntityMessage(PacketType::Value type, EntityItemID modelID,
|
||||
void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityItemID modelID,
|
||||
const EntityItemProperties& properties) {
|
||||
if (!_shouldSend) {
|
||||
return; // bail early
|
||||
|
|
|
@ -26,13 +26,13 @@ public:
|
|||
/// which voxel-server node or nodes the packet should be sent to. Can be called even before voxel servers are known, in
|
||||
/// which case up to MaxPendingMessages will be buffered and processed when voxel servers are known.
|
||||
/// NOTE: EntityItemProperties assumes that all distances are in meter units
|
||||
void queueEditEntityMessage(PacketType::Value type, EntityItemID modelID, const EntityItemProperties& properties);
|
||||
void queueEditEntityMessage(PacketType type, EntityItemID modelID, const EntityItemProperties& properties);
|
||||
|
||||
void queueEraseEntityMessage(const EntityItemID& entityItemID);
|
||||
|
||||
// My server type is the model server
|
||||
virtual char getMyNodeType() const { return NodeType::EntityServer; }
|
||||
virtual void adjustEditPacketForClockSkew(PacketType::Value type, QByteArray& buffer, int clockSkew);
|
||||
virtual void adjustEditPacketForClockSkew(PacketType type, QByteArray& buffer, int clockSkew);
|
||||
|
||||
public slots:
|
||||
void processEntityEditNackPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
|
||||
|
|
|
@ -618,7 +618,7 @@ void EntityItemPropertiesFromScriptValueHonorReadOnly(const QScriptValue &object
|
|||
//
|
||||
// TODO: Implement support for script and visible properties.
|
||||
//
|
||||
bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, EntityItemID id, const EntityItemProperties& properties,
|
||||
bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItemID id, const EntityItemProperties& properties,
|
||||
QByteArray& buffer) {
|
||||
OctreePacketData ourDataPacket(false, buffer.size()); // create a packetData object to add out packet details too.
|
||||
OctreePacketData* packetData = &ourDataPacket; // we want a pointer to this so we can use our APPEND_ENTITY_PROPERTY macro
|
||||
|
|
|
@ -174,7 +174,7 @@ public:
|
|||
void setGlowLevel(float value) { _glowLevel = value; _glowLevelChanged = true; }
|
||||
void setLocalRenderAlpha(float value) { _localRenderAlpha = value; _localRenderAlphaChanged = true; }
|
||||
|
||||
static bool encodeEntityEditPacket(PacketType::Value command, EntityItemID id, const EntityItemProperties& properties,
|
||||
static bool encodeEntityEditPacket(PacketType command, EntityItemID id, const EntityItemProperties& properties,
|
||||
QByteArray& buffer);
|
||||
|
||||
static bool encodeEraseEntityMessage(const EntityItemID& entityItemID, QByteArray& buffer);
|
||||
|
|
|
@ -32,7 +32,7 @@ EntityScriptingInterface::EntityScriptingInterface() :
|
|||
connect(nodeList.data(), &NodeList::canRezChanged, this, &EntityScriptingInterface::canRezChanged);
|
||||
}
|
||||
|
||||
void EntityScriptingInterface::queueEntityMessage(PacketType::Value packetType,
|
||||
void EntityScriptingInterface::queueEntityMessage(PacketType packetType,
|
||||
EntityItemID entityID, const EntityItemProperties& properties) {
|
||||
getEntityPacketSender()->queueEditEntityMessage(packetType, entityID, properties);
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ private:
|
|||
bool actionWorker(const QUuid& entityID, std::function<bool(EntitySimulation*, EntityItemPointer)> actor);
|
||||
bool setVoxels(QUuid entityID, std::function<void(PolyVoxEntityItem&)> actor);
|
||||
bool setPoints(QUuid entityID, std::function<bool(LineEntityItem&)> actor);
|
||||
void queueEntityMessage(PacketType::Value packetType, EntityItemID entityID, const EntityItemProperties& properties);
|
||||
void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties);
|
||||
|
||||
/// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode
|
||||
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
|
||||
|
|
|
@ -63,7 +63,7 @@ void EntityTree::eraseAllOctreeElements(bool createNewRoot) {
|
|||
resetClientEditStats();
|
||||
}
|
||||
|
||||
bool EntityTree::handlesEditPacketType(PacketType::Value packetType) const {
|
||||
bool EntityTree::handlesEditPacketType(PacketType packetType) const {
|
||||
// we handle these types of "edit" packets
|
||||
switch (packetType) {
|
||||
case PacketType::EntityAdd:
|
||||
|
|
|
@ -62,10 +62,10 @@ public:
|
|||
// These methods will allow the OctreeServer to send your tree inbound edit packets of your
|
||||
// own definition. Implement these to allow your octree based server to support editing
|
||||
virtual bool getWantSVOfileVersions() const { return true; }
|
||||
virtual PacketType::Value expectedDataPacketType() const { return PacketType::EntityData; }
|
||||
virtual PacketType expectedDataPacketType() const { return PacketType::EntityData; }
|
||||
virtual bool canProcessVersion(PacketVersion thisVersion) const
|
||||
{ return thisVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS; }
|
||||
virtual bool handlesEditPacketType(PacketType::Value packetType) const;
|
||||
virtual bool handlesEditPacketType(PacketType packetType) const;
|
||||
virtual int processEditPacketData(NLPacket& packet, const unsigned char* editData, int maxLength,
|
||||
const SharedNodePointer& senderNode);
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ public:
|
|||
virtual ~EntityTreeHeadlessViewer();
|
||||
|
||||
virtual char getMyNodeType() const { return NodeType::EntityServer; }
|
||||
virtual PacketType::Value getMyQueryMessageType() const { return PacketType::EntityQuery; }
|
||||
virtual PacketType::Value getExpectedPacketType() const { return PacketType::EntityData; }
|
||||
virtual PacketType getMyQueryMessageType() const { return PacketType::EntityQuery; }
|
||||
virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; }
|
||||
|
||||
void update();
|
||||
|
||||
|
|
|
@ -150,5 +150,5 @@ QHostAddress getLocalAddress() {
|
|||
|
||||
uint qHash(const HifiSockAddr& key, uint seed) {
|
||||
// use the existing QHostAddress and quint16 hash functions to get our hash
|
||||
return qHash(key.getAddress(), seed) + qHash(key.getPort(), seed);
|
||||
return qHash(key.getAddress(), seed) ^ qHash(key.getPort(), seed);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef hifi_HifiSockAddr_h
|
||||
#define hifi_HifiSockAddr_h
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
|
@ -53,6 +55,7 @@ public:
|
|||
friend QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr);
|
||||
friend QDataStream& operator<<(QDataStream& dataStream, const HifiSockAddr& sockAddr);
|
||||
friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr);
|
||||
|
||||
private slots:
|
||||
void handleLookupResult(const QHostInfo& hostInfo);
|
||||
signals:
|
||||
|
@ -65,6 +68,15 @@ private:
|
|||
|
||||
uint qHash(const HifiSockAddr& key, uint seed);
|
||||
|
||||
template <>
|
||||
struct std::hash<HifiSockAddr> {
|
||||
std::size_t operator()(const HifiSockAddr& sockAddr) const {
|
||||
// use XOR of implemented std::hash templates for new hash
|
||||
return std::hash<std::string>()(sockAddr.getAddress().toString().toStdString())
|
||||
^ std::hash<uint16_t>()((uint16_t) sockAddr.getPort());
|
||||
}
|
||||
};
|
||||
|
||||
QHostAddress getLocalAddress();
|
||||
|
||||
Q_DECLARE_METATYPE(HifiSockAddr)
|
||||
|
|
|
@ -105,9 +105,6 @@ LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short
|
|||
_nodeSocket.setPacketFilterOperator(std::bind(&LimitedNodeList::isPacketVerified, this, _1));
|
||||
|
||||
_packetStatTimer.start();
|
||||
|
||||
// make sure we handle STUN response packets
|
||||
_packetReceiver->registerListener(PacketType::StunResponse, this, "processSTUNResponse");
|
||||
}
|
||||
|
||||
void LimitedNodeList::setSessionUUID(const QUuid& sessionUUID) {
|
||||
|
@ -157,40 +154,42 @@ bool LimitedNodeList::isPacketVerified(const udt::Packet& packet) {
|
|||
}
|
||||
|
||||
bool LimitedNodeList::packetVersionMatch(const udt::Packet& packet) {
|
||||
PacketType headerType = NLPacket::typeInHeader(packet);
|
||||
PacketVersion headerVersion = NLPacket::versionInHeader(packet);
|
||||
|
||||
if (packet.getVersion() != versionForPacketType(packet.getType())) {
|
||||
if (headerVersion != versionForPacketType(headerType)) {
|
||||
|
||||
static QMultiHash<QUuid, PacketType::Value> sourcedVersionDebugSuppressMap;
|
||||
static QMultiHash<HifiSockAddr, PacketType::Value> versionDebugSuppressMap;
|
||||
static QMultiHash<QUuid, PacketType> sourcedVersionDebugSuppressMap;
|
||||
static QMultiHash<HifiSockAddr, PacketType> versionDebugSuppressMap;
|
||||
|
||||
bool hasBeenOutput = false;
|
||||
QString senderString;
|
||||
|
||||
if (NON_SOURCED_PACKETS.contains(packet.getType())) {
|
||||
if (NON_SOURCED_PACKETS.contains(headerType)) {
|
||||
const HifiSockAddr& senderSockAddr = packet.getSenderSockAddr();
|
||||
hasBeenOutput = versionDebugSuppressMap.contains(senderSockAddr, packet.getType());
|
||||
hasBeenOutput = versionDebugSuppressMap.contains(senderSockAddr, headerType);
|
||||
|
||||
if (!hasBeenOutput) {
|
||||
versionDebugSuppressMap.insert(senderSockAddr, packet.getType());
|
||||
versionDebugSuppressMap.insert(senderSockAddr, headerType);
|
||||
senderString = QString("%1:%2").arg(senderSockAddr.getAddress().toString()).arg(senderSockAddr.getPort());
|
||||
}
|
||||
} else {
|
||||
QUuid sourceID = QUuid::fromRfc4122(QByteArray::fromRawData(packet.getPayload(), NUM_BYTES_RFC4122_UUID));
|
||||
QUuid sourceID = NLPacket::sourceIDInHeader(packet);
|
||||
|
||||
hasBeenOutput = sourcedVersionDebugSuppressMap.contains(sourceID, packet.getType());
|
||||
hasBeenOutput = sourcedVersionDebugSuppressMap.contains(sourceID, headerType);
|
||||
|
||||
if (!hasBeenOutput) {
|
||||
sourcedVersionDebugSuppressMap.insert(sourceID, packet.getType());
|
||||
sourcedVersionDebugSuppressMap.insert(sourceID, headerType);
|
||||
senderString = uuidStringWithoutCurlyBraces(sourceID.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasBeenOutput) {
|
||||
qCDebug(networking) << "Packet version mismatch on" << packet.getType() << "- Sender"
|
||||
<< senderString << "sent" << qPrintable(QString::number(packet.getVersion())) << "but"
|
||||
<< qPrintable(QString::number(versionForPacketType(packet.getType()))) << "expected.";
|
||||
qCDebug(networking) << "Packet version mismatch on" << headerType << "- Sender"
|
||||
<< senderString << "sent" << qPrintable(QString::number(headerVersion)) << "but"
|
||||
<< qPrintable(QString::number(versionForPacketType(headerType))) << "expected.";
|
||||
|
||||
emit packetVersionMismatch(packet.getType());
|
||||
emit packetVersionMismatch(headerType);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -201,7 +200,9 @@ bool LimitedNodeList::packetVersionMatch(const udt::Packet& packet) {
|
|||
|
||||
bool LimitedNodeList::packetSourceAndHashMatch(const udt::Packet& packet) {
|
||||
|
||||
if (NON_SOURCED_PACKETS.contains(packet.getType())) {
|
||||
PacketType headerType = NLPacket::typeInHeader(packet);
|
||||
|
||||
if (NON_SOURCED_PACKETS.contains(headerType)) {
|
||||
return true;
|
||||
} else {
|
||||
QUuid sourceID = NLPacket::sourceIDInHeader(packet);
|
||||
|
@ -210,19 +211,19 @@ bool LimitedNodeList::packetSourceAndHashMatch(const udt::Packet& packet) {
|
|||
SharedNodePointer matchingNode = nodeWithUUID(sourceID);
|
||||
|
||||
if (matchingNode) {
|
||||
if (!NON_VERIFIED_PACKETS.contains(packet.getType())) {
|
||||
if (!NON_VERIFIED_PACKETS.contains(headerType)) {
|
||||
|
||||
QByteArray packetHeaderHash = NLPacket::verificationHashInHeader(packet);
|
||||
QByteArray expectedHash = NLPacket::hashForPacketAndSecret(packet, matchingNode->getConnectionSecret());
|
||||
|
||||
// check if the md5 hash in the header matches the hash we would expect
|
||||
if (packetHeaderHash != expectedHash) {
|
||||
static QMultiMap<QUuid, PacketType::Value> hashDebugSuppressMap;
|
||||
static QMultiMap<QUuid, PacketType> hashDebugSuppressMap;
|
||||
|
||||
if (!hashDebugSuppressMap.contains(sourceID, packet.getType())) {
|
||||
qCDebug(networking) << "Packet hash mismatch on" << packet.getType() << "- Sender" << sourceID;
|
||||
if (!hashDebugSuppressMap.contains(sourceID, headerType)) {
|
||||
qCDebug(networking) << "Packet hash mismatch on" << headerType << "- Sender" << sourceID;
|
||||
|
||||
hashDebugSuppressMap.insert(sourceID, packet.getType());
|
||||
hashDebugSuppressMap.insert(sourceID, headerType);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -235,7 +236,7 @@ bool LimitedNodeList::packetSourceAndHashMatch(const udt::Packet& packet) {
|
|||
static QString repeatedMessage
|
||||
= LogHandler::getInstance().addRepeatedMessageRegex("Packet of type \\d+ \\([\\sa-zA-Z]+\\) received from unknown node with UUID");
|
||||
|
||||
qCDebug(networking) << "Packet of type" << packet.getType() << "(" << qPrintable(nameForPacketType(packet.getType())) << ")"
|
||||
qCDebug(networking) << "Packet of type" << headerType
|
||||
<< "received from unknown node with UUID" << qPrintable(uuidStringWithoutCurlyBraces(sourceID));
|
||||
}
|
||||
}
|
||||
|
@ -248,12 +249,6 @@ qint64 LimitedNodeList::writePacket(const NLPacket& packet, const Node& destinat
|
|||
return 0;
|
||||
}
|
||||
|
||||
// TODO Move to transport layer when ready
|
||||
if (SEQUENCE_NUMBERED_PACKETS.contains(packet.getType())) {
|
||||
PacketSequenceNumber sequenceNumber = getNextSequenceNumberForPacket(destinationNode.getUUID(), packet.getType());
|
||||
const_cast<NLPacket&>(packet).writeSequenceNumber(sequenceNumber);
|
||||
}
|
||||
|
||||
emit dataSent(destinationNode.getType(), packet.getDataSize());
|
||||
|
||||
return writePacket(packet, *destinationNode.getActiveSocket(), destinationNode.getConnectionSecret());
|
||||
|
@ -344,15 +339,6 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr<NLPacket> packet, const Node&
|
|||
return sendPacket(std::move(packet), destinationSockAddr, destinationNode.getConnectionSecret());
|
||||
}
|
||||
|
||||
PacketSequenceNumber LimitedNodeList::getNextSequenceNumberForPacket(const QUuid& nodeUUID, PacketType::Value packetType) {
|
||||
// Thanks to std::map and std::unordered_map this line either default constructs the
|
||||
// PacketType::SequenceMap and the PacketSequenceNumber or returns the existing value.
|
||||
// We use the postfix increment so that the stored value is incremented and the next
|
||||
// return gives the correct value.
|
||||
|
||||
return _packetSequenceNumbers[nodeUUID][packetType]++;
|
||||
}
|
||||
|
||||
int LimitedNodeList::updateNodeWithDataFromPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
|
||||
QMutexLocker locker(&sendingNode->getMutex());
|
||||
|
||||
|
@ -622,7 +608,7 @@ void LimitedNodeList::sendSTUNRequest() {
|
|||
_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
|
||||
// and read the first attribute and make sure it is a XOR_MAPPED_ADDRESS
|
||||
const int NUM_BYTES_MESSAGE_TYPE_AND_LENGTH = 4;
|
||||
|
@ -638,6 +624,7 @@ bool LimitedNodeList::processSTUNResponse(QSharedPointer<NLPacket> packet) {
|
|||
|
||||
// enumerate the attributes to find XOR_MAPPED_ADDRESS_TYPE
|
||||
while (attributeStartIndex < packet->getDataSize()) {
|
||||
|
||||
if (memcmp(packet->getData() + attributeStartIndex, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0) {
|
||||
const int NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH = 4;
|
||||
const int NUM_BYTES_FAMILY_ALIGN = 1;
|
||||
|
@ -665,8 +652,8 @@ bool LimitedNodeList::processSTUNResponse(QSharedPointer<NLPacket> packet) {
|
|||
|
||||
uint32_t stunAddress = ntohl(xorMappedAddress) ^ ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER);
|
||||
|
||||
QHostAddress newPublicAddress = QHostAddress(stunAddress);
|
||||
|
||||
QHostAddress newPublicAddress(stunAddress);
|
||||
|
||||
if (newPublicAddress != _publicSockAddr.getAddress() || newPublicPort != _publicSockAddr.getPort()) {
|
||||
_publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort);
|
||||
|
||||
|
@ -683,8 +670,9 @@ bool LimitedNodeList::processSTUNResponse(QSharedPointer<NLPacket> packet) {
|
|||
|
||||
flagTimeForConnectionStep(ConnectionStep::SetPublicSocketFromSTUN);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
// we're done reading the packet so we can return now
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// push forward attributeStartIndex by the length of this attribute
|
||||
|
@ -699,8 +687,6 @@ bool LimitedNodeList::processSTUNResponse(QSharedPointer<NLPacket> packet) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LimitedNodeList::startSTUNPublicSocketUpdate() {
|
||||
|
@ -710,7 +696,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 (_stunSockAddr.getAddress().isNull()) {
|
||||
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
|
||||
const quint64 STUN_DNS_LOOKUP_TIMEOUT_MSECS = 10 * 1000;
|
||||
|
@ -741,6 +727,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) {
|
||||
_hasCompletedInitialSTUN = true;
|
||||
|
||||
|
@ -801,7 +793,7 @@ void LimitedNodeList::sendPeerQueryToIceServer(const HifiSockAddr& iceServerSock
|
|||
sendPacketToIceServer(PacketType::ICEServerQuery, iceServerSockAddr, clientID, peerID);
|
||||
}
|
||||
|
||||
void LimitedNodeList::sendPacketToIceServer(PacketType::Value packetType, const HifiSockAddr& iceServerSockAddr,
|
||||
void LimitedNodeList::sendPacketToIceServer(PacketType packetType, const HifiSockAddr& iceServerSockAddr,
|
||||
const QUuid& clientID, const QUuid& peerID) {
|
||||
auto icePacket = NLPacket::create(packetType);
|
||||
|
||||
|
|
|
@ -225,13 +225,12 @@ public slots:
|
|||
|
||||
void startSTUNPublicSocketUpdate();
|
||||
virtual void sendSTUNRequest();
|
||||
bool processSTUNResponse(QSharedPointer<NLPacket> packet);
|
||||
|
||||
void killNodeWithUUID(const QUuid& nodeUUID);
|
||||
|
||||
signals:
|
||||
void dataSent(quint8 channelType, int bytes);
|
||||
void packetVersionMismatch(PacketType::Value type);
|
||||
void packetVersionMismatch(PacketType type);
|
||||
|
||||
void uuidChanged(const QUuid& ownerUUID, const QUuid& oldUUID);
|
||||
void nodeAdded(SharedNodePointer);
|
||||
|
@ -253,17 +252,16 @@ protected:
|
|||
const QUuid& connectionSecret = QUuid());
|
||||
qint64 writePacketAndCollectStats(const NLPacket& packet, const HifiSockAddr& destinationSockAddr);
|
||||
|
||||
PacketSequenceNumber getNextSequenceNumberForPacket(const QUuid& nodeUUID, PacketType::Value packetType);
|
||||
|
||||
bool isPacketVerified(const udt::Packet& packet);
|
||||
bool packetVersionMatch(const udt::Packet& packet);
|
||||
bool packetSourceAndHashMatch(const udt::Packet& packet);
|
||||
void processSTUNResponse(std::unique_ptr<udt::BasePacket> packet);
|
||||
|
||||
void handleNodeKill(const SharedNodePointer& node);
|
||||
|
||||
void stopInitialSTUNUpdate(bool success);
|
||||
|
||||
void sendPacketToIceServer(PacketType::Value packetType, const HifiSockAddr& iceServerSockAddr, const QUuid& clientID,
|
||||
void sendPacketToIceServer(PacketType packetType, const HifiSockAddr& iceServerSockAddr, const QUuid& clientID,
|
||||
const QUuid& peerRequestID = QUuid());
|
||||
|
||||
qint64 sendPacket(std::unique_ptr<NLPacket> packet, const Node& destinationNode,
|
||||
|
@ -289,8 +287,6 @@ protected:
|
|||
bool _thisNodeCanAdjustLocks;
|
||||
bool _thisNodeCanRez;
|
||||
|
||||
std::unordered_map<QUuid, PacketTypeSequenceMap, UUIDHasher> _packetSequenceNumbers;
|
||||
|
||||
QPointer<QTimer> _initialSTUNTimer;
|
||||
int _numInitialSTUNRequests = 0;
|
||||
bool _hasCompletedInitialSTUN = false;
|
||||
|
@ -314,7 +310,7 @@ protected:
|
|||
private slots:
|
||||
void flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp);
|
||||
void possiblyTimeoutSTUNAddressLookup();
|
||||
void addSTUNSockAddrToUnfiltered() { _nodeSocket.addUnfilteredSockAddr(_stunSockAddr); } // called once STUN socket known
|
||||
void addSTUNHandlerToUnfiltered(); // called once STUN socket known
|
||||
};
|
||||
|
||||
#endif // hifi_LimitedNodeList_h
|
||||
|
|
|
@ -11,14 +11,18 @@
|
|||
|
||||
#include "NLPacket.h"
|
||||
|
||||
qint64 NLPacket::localHeaderSize(PacketType::Value type) {
|
||||
qint64 size = ((NON_SOURCED_PACKETS.contains(type)) ? 0 : NUM_BYTES_RFC4122_UUID) +
|
||||
((NON_SOURCED_PACKETS.contains(type) || NON_VERIFIED_PACKETS.contains(type)) ? 0 : NUM_BYTES_MD5_HASH);
|
||||
return size;
|
||||
qint64 NLPacket::maxPayloadSize(PacketType type) {
|
||||
return Packet::maxPayloadSize(false) - localHeaderSize(type);
|
||||
}
|
||||
|
||||
qint64 NLPacket::maxPayloadSize(PacketType::Value type) {
|
||||
return Packet::maxPayloadSize(type) - localHeaderSize(type);
|
||||
qint64 NLPacket::localHeaderSize(PacketType type) {
|
||||
qint64 optionalSize = ((NON_SOURCED_PACKETS.contains(type)) ? 0 : NUM_BYTES_RFC4122_UUID) +
|
||||
((NON_SOURCED_PACKETS.contains(type) || NON_VERIFIED_PACKETS.contains(type)) ? 0 : NUM_BYTES_MD5_HASH);
|
||||
return sizeof(PacketType) + sizeof(PacketVersion) + optionalSize;
|
||||
}
|
||||
|
||||
qint64 NLPacket::maxPayloadSize() const {
|
||||
return Packet::maxPayloadSize() - localHeaderSize();
|
||||
}
|
||||
|
||||
qint64 NLPacket::totalHeadersSize() const {
|
||||
|
@ -29,16 +33,16 @@ qint64 NLPacket::localHeaderSize() const {
|
|||
return localHeaderSize(_type);
|
||||
}
|
||||
|
||||
std::unique_ptr<NLPacket> NLPacket::create(PacketType::Value type, qint64 size) {
|
||||
std::unique_ptr<NLPacket> NLPacket::create(PacketType type, qint64 size, bool isReliable, bool isPartOfMessage) {
|
||||
std::unique_ptr<NLPacket> packet;
|
||||
|
||||
if (size == -1) {
|
||||
packet = std::unique_ptr<NLPacket>(new NLPacket(type));
|
||||
packet = std::unique_ptr<NLPacket>(new NLPacket(type, isReliable, isPartOfMessage));
|
||||
} else {
|
||||
// Fail with invalid size
|
||||
Q_ASSERT(size >= 0);
|
||||
|
||||
packet = std::unique_ptr<NLPacket>(new NLPacket(type, size));
|
||||
packet = std::unique_ptr<NLPacket>(new NLPacket(type, size, isReliable, isPartOfMessage));
|
||||
}
|
||||
|
||||
packet->open(QIODevice::ReadWrite);
|
||||
|
@ -75,52 +79,70 @@ std::unique_ptr<NLPacket> NLPacket::createCopy(const NLPacket& other) {
|
|||
return std::unique_ptr<NLPacket>(new NLPacket(other));
|
||||
}
|
||||
|
||||
NLPacket::NLPacket(PacketType::Value type, qint64 size) :
|
||||
Packet(type, localHeaderSize(type) + size)
|
||||
NLPacket::NLPacket(PacketType type, bool isReliable, bool isPartOfMessage) :
|
||||
Packet(-1, isReliable, isPartOfMessage),
|
||||
_type(type),
|
||||
_version(versionForPacketType(type))
|
||||
{
|
||||
adjustPayloadStartAndCapacity();
|
||||
|
||||
writeTypeAndVersion();
|
||||
}
|
||||
|
||||
NLPacket::NLPacket(PacketType type, qint64 size, bool isReliable, bool isPartOfMessage) :
|
||||
Packet(localHeaderSize(type) + size, isReliable, isPartOfMessage),
|
||||
_type(type),
|
||||
_version(versionForPacketType(type))
|
||||
{
|
||||
Q_ASSERT(size >= 0);
|
||||
|
||||
adjustPayloadStartAndCapacity();
|
||||
}
|
||||
|
||||
NLPacket::NLPacket(PacketType::Value type) :
|
||||
Packet(type, -1)
|
||||
{
|
||||
adjustPayloadStartAndCapacity();
|
||||
|
||||
writeTypeAndVersion();
|
||||
}
|
||||
|
||||
NLPacket::NLPacket(std::unique_ptr<Packet> packet) :
|
||||
Packet(std::move(*packet.release()))
|
||||
{
|
||||
adjustPayloadStartAndCapacity(_payloadSize > 0);
|
||||
|
||||
readType();
|
||||
readVersion();
|
||||
readSourceID();
|
||||
|
||||
adjustPayloadStartAndCapacity(_payloadSize > 0);
|
||||
}
|
||||
|
||||
NLPacket::NLPacket(const NLPacket& other) : Packet(other) {
|
||||
_type = other._type;
|
||||
_version = other._version;
|
||||
_sourceID = other._sourceID;
|
||||
}
|
||||
|
||||
NLPacket::NLPacket(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr) :
|
||||
Packet(std::move(data), size, senderSockAddr)
|
||||
{
|
||||
{
|
||||
// sanity check before we decrease the payloadSize with the payloadCapacity
|
||||
Q_ASSERT(_payloadSize == _payloadCapacity);
|
||||
|
||||
adjustPayloadStartAndCapacity(_payloadSize > 0);
|
||||
|
||||
|
||||
readType();
|
||||
readVersion();
|
||||
readSourceID();
|
||||
}
|
||||
|
||||
NLPacket::NLPacket(NLPacket&& other) :
|
||||
Packet(other)
|
||||
Packet(std::move(other))
|
||||
{
|
||||
_type = other._type;
|
||||
_version = other._version;
|
||||
_sourceID = std::move(other._sourceID);
|
||||
}
|
||||
|
||||
NLPacket& NLPacket::operator=(const NLPacket& other) {
|
||||
Packet::operator=(other);
|
||||
|
||||
_type = other._type;
|
||||
_version = other._version;
|
||||
_sourceID = other._sourceID;
|
||||
|
||||
return *this;
|
||||
|
@ -130,25 +152,38 @@ NLPacket& NLPacket::operator=(NLPacket&& other) {
|
|||
|
||||
Packet::operator=(std::move(other));
|
||||
|
||||
_type = other._type;
|
||||
_version = other._version;
|
||||
_sourceID = std::move(other._sourceID);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PacketType NLPacket::typeInHeader(const udt::Packet& packet) {
|
||||
auto headerOffset = packet.Packet::localHeaderSize();
|
||||
return *reinterpret_cast<const PacketType*>(packet.getData() + headerOffset);
|
||||
}
|
||||
|
||||
PacketVersion NLPacket::versionInHeader(const udt::Packet& packet) {
|
||||
auto headerOffset = packet.Packet::localHeaderSize();
|
||||
return *reinterpret_cast<const PacketVersion*>(packet.getData() + headerOffset + sizeof(PacketType));
|
||||
}
|
||||
|
||||
QUuid NLPacket::sourceIDInHeader(const udt::Packet& packet) {
|
||||
int offset = packet.Packet::localHeaderSize();
|
||||
int offset = packet.Packet::localHeaderSize() + sizeof(PacketType) + sizeof(PacketVersion);
|
||||
return QUuid::fromRfc4122(QByteArray::fromRawData(packet.getData() + offset, NUM_BYTES_RFC4122_UUID));
|
||||
}
|
||||
|
||||
QByteArray NLPacket::verificationHashInHeader(const udt::Packet& packet) {
|
||||
int offset = packet.Packet::localHeaderSize() + NUM_BYTES_RFC4122_UUID;
|
||||
int offset = packet.Packet::localHeaderSize() + sizeof(PacketType) + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;
|
||||
return QByteArray(packet.getData() + offset, NUM_BYTES_MD5_HASH);
|
||||
}
|
||||
|
||||
QByteArray NLPacket::hashForPacketAndSecret(const udt::Packet& packet, const QUuid& connectionSecret) {
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
int offset = packet.Packet::localHeaderSize() + NUM_BYTES_RFC4122_UUID + NUM_BYTES_MD5_HASH;
|
||||
int offset = packet.Packet::localHeaderSize() + sizeof(PacketType) + sizeof(PacketVersion)
|
||||
+ NUM_BYTES_RFC4122_UUID + NUM_BYTES_MD5_HASH;
|
||||
|
||||
// add the packet payload and the connection UUID
|
||||
hash.addData(packet.getData() + offset, packet.getDataSize() - offset);
|
||||
|
@ -158,14 +193,35 @@ QByteArray NLPacket::hashForPacketAndSecret(const udt::Packet& packet, const QUu
|
|||
return hash.result();
|
||||
}
|
||||
|
||||
void NLPacket::adjustPayloadStartAndCapacity(bool shouldDecreasePayloadSize) {
|
||||
qint64 headerSize = localHeaderSize(_type);
|
||||
_payloadStart += headerSize;
|
||||
_payloadCapacity -= headerSize;
|
||||
void NLPacket::writeTypeAndVersion() {
|
||||
auto headerOffset = Packet::localHeaderSize();
|
||||
|
||||
if (shouldDecreasePayloadSize) {
|
||||
_payloadSize -= headerSize;
|
||||
}
|
||||
// Pack the packet type
|
||||
memcpy(_packet.get() + headerOffset, &_type, sizeof(PacketType));
|
||||
|
||||
// Pack the packet version
|
||||
memcpy(_packet.get() + headerOffset + sizeof(PacketType), &_version, sizeof(_version));
|
||||
}
|
||||
|
||||
void NLPacket::setType(PacketType type) {
|
||||
auto currentHeaderSize = totalHeadersSize();
|
||||
|
||||
_type = type;
|
||||
_version = versionForPacketType(_type);
|
||||
|
||||
writeTypeAndVersion();
|
||||
|
||||
// Setting new packet type with a different header size not currently supported
|
||||
Q_ASSERT(currentHeaderSize == totalHeadersSize());
|
||||
Q_UNUSED(currentHeaderSize);
|
||||
}
|
||||
|
||||
void NLPacket::readType() {
|
||||
_type = NLPacket::typeInHeader(*this);
|
||||
}
|
||||
|
||||
void NLPacket::readVersion() {
|
||||
_version = NLPacket::versionInHeader(*this);
|
||||
}
|
||||
|
||||
void NLPacket::readSourceID() {
|
||||
|
@ -177,7 +233,7 @@ void NLPacket::readSourceID() {
|
|||
void NLPacket::writeSourceID(const QUuid& sourceID) {
|
||||
Q_ASSERT(!NON_SOURCED_PACKETS.contains(_type));
|
||||
|
||||
auto offset = Packet::localHeaderSize();
|
||||
auto offset = Packet::localHeaderSize() + sizeof(PacketType) + sizeof(PacketVersion);
|
||||
memcpy(_packet.get() + offset, sourceID.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID);
|
||||
|
||||
_sourceID = sourceID;
|
||||
|
@ -186,7 +242,7 @@ void NLPacket::writeSourceID(const QUuid& sourceID) {
|
|||
void NLPacket::writeVerificationHashGivenSecret(const QUuid& connectionSecret) {
|
||||
Q_ASSERT(!NON_SOURCED_PACKETS.contains(_type) && !NON_VERIFIED_PACKETS.contains(_type));
|
||||
|
||||
auto offset = Packet::localHeaderSize() + NUM_BYTES_RFC4122_UUID;
|
||||
auto offset = Packet::localHeaderSize() + sizeof(PacketType) + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;
|
||||
QByteArray verificationHash = hashForPacketAndSecret(*this, connectionSecret);
|
||||
|
||||
memcpy(_packet.get() + offset, verificationHash.data(), verificationHash.size());
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
class NLPacket : public udt::Packet {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static std::unique_ptr<NLPacket> create(PacketType::Value type, qint64 size = -1);
|
||||
static std::unique_ptr<NLPacket> create(PacketType type, qint64 size = -1,
|
||||
bool isReliable = false, bool isPartOfMessage = false);
|
||||
|
||||
static std::unique_ptr<NLPacket> fromReceivedPacket(std::unique_ptr<char> data, qint64 size,
|
||||
const HifiSockAddr& senderSockAddr);
|
||||
static std::unique_ptr<NLPacket> fromBase(std::unique_ptr<Packet> packet);
|
||||
|
@ -27,15 +29,24 @@ public:
|
|||
// Provided for convenience, try to limit use
|
||||
static std::unique_ptr<NLPacket> createCopy(const NLPacket& other);
|
||||
|
||||
static PacketType typeInHeader(const udt::Packet& packet);
|
||||
static PacketVersion versionInHeader(const udt::Packet& packet);
|
||||
|
||||
static QUuid sourceIDInHeader(const udt::Packet& packet);
|
||||
static QByteArray verificationHashInHeader(const udt::Packet& packet);
|
||||
static QByteArray hashForPacketAndSecret(const udt::Packet& packet, const QUuid& connectionSecret);
|
||||
|
||||
static qint64 localHeaderSize(PacketType::Value type);
|
||||
static qint64 maxPayloadSize(PacketType::Value type);
|
||||
|
||||
|
||||
static qint64 maxPayloadSize(PacketType type);
|
||||
static qint64 localHeaderSize(PacketType type);
|
||||
|
||||
virtual qint64 maxPayloadSize() const; // The maximum payload size this packet can use to fit in MTU
|
||||
virtual qint64 totalHeadersSize() const; // Cumulated size of all the headers
|
||||
virtual qint64 localHeaderSize() const; // Current level's header size
|
||||
|
||||
PacketType getType() const { return _type; }
|
||||
void setType(PacketType type);
|
||||
|
||||
PacketVersion getVersion() const { return _version; }
|
||||
|
||||
const QUuid& getSourceID() const { return _sourceID; }
|
||||
|
||||
|
@ -44,10 +55,8 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
void adjustPayloadStartAndCapacity(bool shouldDecreasePayloadSize = false);
|
||||
|
||||
NLPacket(PacketType::Value type);
|
||||
NLPacket(PacketType::Value type, qint64 size);
|
||||
NLPacket(PacketType type, bool forceReliable = false, bool isPartOfMessage = false);
|
||||
NLPacket(PacketType type, qint64 size, bool forceReliable = false, bool isPartOfMessage = false);
|
||||
NLPacket(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
|
||||
NLPacket(std::unique_ptr<Packet> packet);
|
||||
NLPacket(const NLPacket& other);
|
||||
|
@ -55,9 +64,17 @@ protected:
|
|||
|
||||
NLPacket& operator=(const NLPacket& other);
|
||||
NLPacket& operator=(NLPacket&& other);
|
||||
|
||||
// Header writers
|
||||
void writeTypeAndVersion();
|
||||
|
||||
// Header readers, used to set member variables after getting a packet from the network
|
||||
void readType();
|
||||
void readVersion();
|
||||
void readSourceID();
|
||||
|
||||
|
||||
PacketType _type;
|
||||
PacketVersion _version;
|
||||
QUuid _sourceID;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "NLPacket.h"
|
||||
|
||||
NLPacketList::NLPacketList(PacketType::Value packetType, QByteArray extendedHeader) :
|
||||
NLPacketList::NLPacketList(PacketType packetType, QByteArray extendedHeader) :
|
||||
PacketList(packetType, extendedHeader)
|
||||
{
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
class NLPacketList : public udt::PacketList {
|
||||
public:
|
||||
NLPacketList(PacketType::Value packetType, QByteArray extendedHeader = QByteArray());
|
||||
NLPacketList(PacketType packetType, QByteArray extendedHeader = QByteArray());
|
||||
|
||||
private:
|
||||
NLPacketList(const NLPacketList& other) = delete;
|
||||
|
|
|
@ -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
|
|
@ -67,14 +67,6 @@ void Node::updateClockSkewUsec(int clockSkewSample) {
|
|||
_clockSkewUsec = (int)_clockSkewMovingPercentile.getValueAtPercentile();
|
||||
}
|
||||
|
||||
PacketSequenceNumber Node::getLastSequenceNumberForPacketType(PacketType::Value packetType) const {
|
||||
auto typeMatch = _lastSequenceNumbers.find(packetType);
|
||||
if (typeMatch != _lastSequenceNumbers.end()) {
|
||||
return typeMatch->second;
|
||||
} else {
|
||||
return DEFAULT_SEQUENCE_NUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const Node& node) {
|
||||
out << node._type;
|
||||
|
@ -98,7 +90,7 @@ QDataStream& operator>>(QDataStream& in, Node& node) {
|
|||
return in;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const Node &node) {
|
||||
QDebug operator<<(QDebug debug, const Node& node) {
|
||||
debug.nospace() << NodeType::getNodeTypeName(node.getType());
|
||||
if (node.getType() == NodeType::Unassigned) {
|
||||
debug.nospace() << " (1)";
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "NetworkPeer.h"
|
||||
#include "NodeData.h"
|
||||
#include "NodeType.h"
|
||||
#include "udt/PacketHeaders.h"
|
||||
#include "udt/Packet.h"
|
||||
#include "SimpleMovingAverage.h"
|
||||
#include "MovingPercentile.h"
|
||||
|
||||
|
@ -65,10 +65,6 @@ public:
|
|||
void setCanRez(bool canRez) { _canRez = canRez; }
|
||||
bool getCanRez() { return _canRez; }
|
||||
|
||||
void setLastSequenceNumberForPacketType(PacketSequenceNumber sequenceNumber, PacketType::Value packetType)
|
||||
{ _lastSequenceNumbers[packetType] = sequenceNumber; }
|
||||
PacketSequenceNumber getLastSequenceNumberForPacketType(PacketType::Value packetType) const;
|
||||
|
||||
friend QDataStream& operator<<(QDataStream& out, const Node& node);
|
||||
friend QDataStream& operator>>(QDataStream& in, Node& node);
|
||||
|
||||
|
@ -89,12 +85,12 @@ private:
|
|||
bool _canAdjustLocks;
|
||||
bool _canRez;
|
||||
|
||||
PacketTypeSequenceMap _lastSequenceNumbers;
|
||||
std::map<PacketType, udt::Packet::SequenceNumber> _lastSequenceNumbers;
|
||||
};
|
||||
|
||||
typedef QSharedPointer<Node> SharedNodePointer;
|
||||
Q_DECLARE_METATYPE(SharedNodePointer)
|
||||
|
||||
QDebug operator<<(QDebug debug, const Node &message);
|
||||
QDebug operator<<(QDebug debug, const Node& node);
|
||||
|
||||
#endif // hifi_Node_h
|
||||
|
|
|
@ -231,7 +231,7 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
} else if (!_domainHandler.getIP().isNull()) {
|
||||
bool isUsingDTLS = false;
|
||||
|
||||
PacketType::Value domainPacketType = !_domainHandler.isConnected()
|
||||
PacketType domainPacketType = !_domainHandler.isConnected()
|
||||
? PacketType::DomainConnectRequest : PacketType::DomainListRequest;
|
||||
|
||||
if (!_domainHandler.isConnected()) {
|
||||
|
@ -525,7 +525,7 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) {
|
|||
|
||||
void NodeList::sendAssignment(Assignment& assignment) {
|
||||
|
||||
PacketType::Value assignmentPacketType = assignment.getCommand() == Assignment::CreateCommand
|
||||
PacketType assignmentPacketType = assignment.getCommand() == Assignment::CreateCommand
|
||||
? PacketType::CreateAssignment
|
||||
: PacketType::RequestAssignment;
|
||||
|
||||
|
@ -533,8 +533,7 @@ void NodeList::sendAssignment(Assignment& assignment) {
|
|||
|
||||
QDataStream packetStream(assignmentPacket.get());
|
||||
packetStream << assignment;
|
||||
|
||||
// TODO: should this be a non sourced packet?
|
||||
|
||||
sendPacket(std::move(assignmentPacket), _assignmentServerSocket);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,11 @@ PacketReceiver::PacketReceiver(QObject* parent) :
|
|||
qRegisterMetaType<QSharedPointer<NLPacket>>();
|
||||
}
|
||||
|
||||
bool PacketReceiver::registerListenerForTypes(const QSet<PacketType::Value>& types, QObject* listener, const char* slot) {
|
||||
QSet<PacketType::Value> nonSourcedTypes;
|
||||
QSet<PacketType::Value> sourcedTypes;
|
||||
bool PacketReceiver::registerListenerForTypes(const QSet<PacketType>& types, QObject* listener, const char* slot) {
|
||||
QSet<PacketType> nonSourcedTypes;
|
||||
QSet<PacketType> sourcedTypes;
|
||||
|
||||
foreach(PacketType::Value type, types) {
|
||||
foreach(PacketType type, types) {
|
||||
if (NON_SOURCED_PACKETS.contains(type)) {
|
||||
nonSourcedTypes << type;
|
||||
} else {
|
||||
|
@ -41,7 +41,7 @@ bool PacketReceiver::registerListenerForTypes(const QSet<PacketType::Value>& typ
|
|||
if (nonSourcedTypes.size() > 0) {
|
||||
QMetaMethod nonSourcedMethod = matchingMethodForListener(*nonSourcedTypes.begin(), listener, slot);
|
||||
if (nonSourcedMethod.isValid()) {
|
||||
foreach(PacketType::Value type, nonSourcedTypes) {
|
||||
foreach(PacketType type, nonSourcedTypes) {
|
||||
registerVerifiedListener(type, listener, nonSourcedMethod);
|
||||
}
|
||||
} else {
|
||||
|
@ -52,7 +52,7 @@ bool PacketReceiver::registerListenerForTypes(const QSet<PacketType::Value>& typ
|
|||
if (sourcedTypes.size() > 0) {
|
||||
QMetaMethod sourcedMethod = matchingMethodForListener(*sourcedTypes.begin(), listener, slot);
|
||||
if (sourcedMethod.isValid()) {
|
||||
foreach(PacketType::Value type, sourcedTypes) {
|
||||
foreach(PacketType type, sourcedTypes) {
|
||||
registerVerifiedListener(type, listener, sourcedMethod);
|
||||
}
|
||||
} else {
|
||||
|
@ -63,7 +63,7 @@ bool PacketReceiver::registerListenerForTypes(const QSet<PacketType::Value>& typ
|
|||
return true;
|
||||
}
|
||||
|
||||
void PacketReceiver::registerDirectListener(PacketType::Value type, QObject* listener, const char* slot) {
|
||||
void PacketReceiver::registerDirectListener(PacketType type, QObject* listener, const char* slot) {
|
||||
bool success = registerListener(type, listener, slot);
|
||||
if (success) {
|
||||
_directConnectSetMutex.lock();
|
||||
|
@ -75,7 +75,7 @@ void PacketReceiver::registerDirectListener(PacketType::Value type, QObject* lis
|
|||
}
|
||||
}
|
||||
|
||||
void PacketReceiver::registerDirectListenerForTypes(const QSet<PacketType::Value>& types,
|
||||
void PacketReceiver::registerDirectListenerForTypes(const QSet<PacketType>& types,
|
||||
QObject* listener, const char* slot) {
|
||||
// just call register listener for types to start
|
||||
bool success = registerListenerForTypes(types, listener, slot);
|
||||
|
@ -89,7 +89,7 @@ void PacketReceiver::registerDirectListenerForTypes(const QSet<PacketType::Value
|
|||
}
|
||||
}
|
||||
|
||||
bool PacketReceiver::registerListener(PacketType::Value type, QObject* listener, const char* slot) {
|
||||
bool PacketReceiver::registerListener(PacketType type, QObject* listener, const char* slot) {
|
||||
Q_ASSERT(listener);
|
||||
|
||||
QMetaMethod matchingMethod = matchingMethodForListener(type, listener, slot);
|
||||
|
@ -102,7 +102,7 @@ bool PacketReceiver::registerListener(PacketType::Value type, QObject* listener,
|
|||
}
|
||||
}
|
||||
|
||||
QMetaMethod PacketReceiver::matchingMethodForListener(PacketType::Value type, QObject* object, const char* slot) const {
|
||||
QMetaMethod PacketReceiver::matchingMethodForListener(PacketType type, QObject* object, const char* slot) const {
|
||||
Q_ASSERT(object);
|
||||
|
||||
// normalize the slot with the expected parameters
|
||||
|
@ -139,8 +139,7 @@ QMetaMethod PacketReceiver::matchingMethodForListener(PacketType::Value type, QO
|
|||
if (methodIndex < 0) {
|
||||
qDebug() << "PacketReceiver::registerListener expected a slot with one of the following signatures:"
|
||||
<< possibleSignatures.toList() << "- but such a slot was not found."
|
||||
<< "Could not complete listener registration for type"
|
||||
<< type << "-" << nameForPacketType(type);
|
||||
<< "Could not complete listener registration for type" << type;
|
||||
}
|
||||
|
||||
Q_ASSERT(methodIndex >= 0);
|
||||
|
@ -155,12 +154,11 @@ QMetaMethod PacketReceiver::matchingMethodForListener(PacketType::Value type, QO
|
|||
}
|
||||
}
|
||||
|
||||
void PacketReceiver::registerVerifiedListener(PacketType::Value type, QObject* object, const QMetaMethod& slot) {
|
||||
void PacketReceiver::registerVerifiedListener(PacketType type, QObject* object, const QMetaMethod& slot) {
|
||||
_packetListenerLock.lock();
|
||||
|
||||
if (_packetListenerMap.contains(type)) {
|
||||
qDebug() << "Warning: Registering a packet listener for packet type" << type
|
||||
<< "(" << qPrintable(nameForPacketType(type)) << ")"
|
||||
<< "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
|
||||
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));
|
||||
|
||||
_inPacketCount++;
|
||||
|
@ -243,15 +241,9 @@ void PacketReceiver::handleVerifiedPacket(std::unique_ptr<udt::Packet> packet) {
|
|||
|
||||
_directConnectSetMutex.unlock();
|
||||
|
||||
PacketType::Value packetType = nlPacket->getType();
|
||||
PacketType packetType = nlPacket->getType();
|
||||
|
||||
if (matchingNode) {
|
||||
// if this was a sequence numbered packet we should store the last seq number for
|
||||
// a packet of this type for this node
|
||||
if (SEQUENCE_NUMBERED_PACKETS.contains(nlPacket->getType())) {
|
||||
matchingNode->setLastSequenceNumberForPacketType(nlPacket->readSequenceNumber(), nlPacket->getType());
|
||||
}
|
||||
|
||||
emit dataReceived(matchingNode->getType(), nlPacket->getDataSize());
|
||||
QMetaMethod metaMethod = listener.second;
|
||||
|
||||
|
@ -292,8 +284,7 @@ void PacketReceiver::handleVerifiedPacket(std::unique_ptr<udt::Packet> packet) {
|
|||
}
|
||||
|
||||
if (!success) {
|
||||
qDebug().nospace() << "Error delivering packet " << packetType
|
||||
<< " (" << qPrintable(nameForPacketType(packetType)) << ") to listener "
|
||||
qDebug().nospace() << "Error delivering packet " << packetType << " to listener "
|
||||
<< listener.first << "::" << qPrintable(listener.second.methodSignature());
|
||||
}
|
||||
|
||||
|
@ -302,8 +293,7 @@ void PacketReceiver::handleVerifiedPacket(std::unique_ptr<udt::Packet> packet) {
|
|||
}
|
||||
|
||||
if (listenerIsDead) {
|
||||
qDebug().nospace() << "Listener for packet" << nlPacket->getType()
|
||||
<< " (" << qPrintable(nameForPacketType(nlPacket->getType())) << ")"
|
||||
qDebug().nospace() << "Listener for packet " << nlPacket->getType()
|
||||
<< " has been destroyed. Removing from listener map.";
|
||||
it = _packetListenerMap.erase(it);
|
||||
|
||||
|
@ -314,10 +304,10 @@ void PacketReceiver::handleVerifiedPacket(std::unique_ptr<udt::Packet> packet) {
|
|||
}
|
||||
|
||||
} 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
|
||||
_packetListenerMap.insert(packet->getType(), { nullptr, QMetaMethod() });
|
||||
_packetListenerMap.insert(nlPacket->getType(), { nullptr, QMetaMethod() });
|
||||
}
|
||||
|
||||
_packetListenerLock.unlock();
|
||||
|
|
|
@ -41,8 +41,8 @@ public:
|
|||
|
||||
void resetCounters() { _inPacketCount = 0; _inByteCount = 0; }
|
||||
|
||||
bool registerListenerForTypes(const QSet<PacketType::Value>& types, QObject* listener, const char* slot);
|
||||
bool registerListener(PacketType::Value type, QObject* listener, const char* slot);
|
||||
bool registerListenerForTypes(const QSet<PacketType>& types, QObject* listener, const char* slot);
|
||||
bool registerListener(PacketType type, QObject* listener, const char* slot);
|
||||
void unregisterListener(QObject* listener);
|
||||
|
||||
void handleVerifiedPacket(std::unique_ptr<udt::Packet> packet);
|
||||
|
@ -53,16 +53,16 @@ signals:
|
|||
private:
|
||||
// these are brutal hacks for now - ideally GenericThread / ReceivedPacketProcessor
|
||||
// should be changed to have a true event loop and be able to handle our QMetaMethod::invoke
|
||||
void registerDirectListenerForTypes(const QSet<PacketType::Value>& types, QObject* listener, const char* slot);
|
||||
void registerDirectListener(PacketType::Value type, QObject* listener, const char* slot);
|
||||
void registerDirectListenerForTypes(const QSet<PacketType>& types, QObject* listener, const char* slot);
|
||||
void registerDirectListener(PacketType type, QObject* listener, const char* slot);
|
||||
|
||||
QMetaMethod matchingMethodForListener(PacketType::Value type, QObject* object, const char* slot) const;
|
||||
void registerVerifiedListener(PacketType::Value type, QObject* listener, const QMetaMethod& slot);
|
||||
QMetaMethod matchingMethodForListener(PacketType type, QObject* object, const char* slot) const;
|
||||
void registerVerifiedListener(PacketType type, QObject* listener, const QMetaMethod& slot);
|
||||
|
||||
using ObjectMethodPair = std::pair<QPointer<QObject>, QMetaMethod>;
|
||||
|
||||
QMutex _packetListenerLock;
|
||||
QHash<PacketType::Value, ObjectMethodPair> _packetListenerMap;
|
||||
QHash<PacketType, ObjectMethodPair> _packetListenerMap;
|
||||
int _inPacketCount = 0;
|
||||
int _inByteCount = 0;
|
||||
bool _shouldDropPackets = false;
|
||||
|
|
|
@ -26,4 +26,4 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
#endif // hifi_UUIDHasher_h
|
||||
#endif // hifi_UUIDHasher_h
|
||||
|
|
177
libraries/networking/src/udt/BasePacket.cpp
Normal file
177
libraries/networking/src/udt/BasePacket.cpp
Normal file
|
@ -0,0 +1,177 @@
|
|||
//
|
||||
// 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;
|
||||
|
||||
_senderSockAddr = other._senderSockAddr;
|
||||
|
||||
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,20 +13,8 @@
|
|||
|
||||
using namespace udt;
|
||||
|
||||
const qint64 Packet::PACKET_WRITE_ERROR = -1;
|
||||
|
||||
qint64 Packet::localHeaderSize(PacketType::Value type) {
|
||||
qint64 size = numBytesForArithmeticCodedPacketType(type) + sizeof(PacketVersion) +
|
||||
((SEQUENCE_NUMBERED_PACKETS.contains(type)) ? sizeof(SequenceNumber) : 0);
|
||||
return size;
|
||||
}
|
||||
|
||||
qint64 Packet::maxPayloadSize(PacketType::Value type) {
|
||||
return MAX_PACKET_SIZE - localHeaderSize(type);
|
||||
}
|
||||
|
||||
std::unique_ptr<Packet> Packet::create(PacketType::Value type, qint64 size) {
|
||||
auto packet = std::unique_ptr<Packet>(new Packet(type, size));
|
||||
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);
|
||||
|
||||
|
@ -49,220 +37,123 @@ std::unique_ptr<Packet> Packet::createCopy(const Packet& other) {
|
|||
return std::unique_ptr<Packet>(new Packet(other));
|
||||
}
|
||||
|
||||
qint64 Packet::maxPayloadSize(bool isPartOfMessage) {
|
||||
return MAX_PACKET_SIZE - localHeaderSize(isPartOfMessage);
|
||||
}
|
||||
|
||||
qint64 Packet::localHeaderSize(bool isPartOfMessage) {
|
||||
return sizeof(SequenceNumberAndBitField) + (isPartOfMessage ? sizeof(MessageNumberAndBitField) : 0);
|
||||
}
|
||||
|
||||
qint64 Packet::maxPayloadSize() const {
|
||||
return MAX_PACKET_SIZE - localHeaderSize();
|
||||
}
|
||||
|
||||
qint64 Packet::totalHeadersSize() const {
|
||||
return localHeaderSize();
|
||||
}
|
||||
|
||||
qint64 Packet::localHeaderSize() const {
|
||||
return localHeaderSize(_type);
|
||||
return localHeaderSize(_isPartOfMessage);
|
||||
}
|
||||
|
||||
Packet::Packet(PacketType::Value type, qint64 size) :
|
||||
_type(type),
|
||||
_version(0)
|
||||
Packet::Packet(qint64 size, bool isReliable, bool isPartOfMessage) :
|
||||
BasePacket(size),
|
||||
_isReliable(isReliable),
|
||||
_isPartOfMessage(isPartOfMessage)
|
||||
{
|
||||
auto maxPayload = maxPayloadSize(type);
|
||||
if (size == -1) {
|
||||
// default size of -1, means biggest packet possible
|
||||
size = maxPayload;
|
||||
}
|
||||
|
||||
_packetSize = localHeaderSize(type) + size;
|
||||
_packet.reset(new char[_packetSize]);
|
||||
_payloadCapacity = size;
|
||||
_payloadStart = _packet.get() + (_packetSize - _payloadCapacity);
|
||||
adjustPayloadStartAndCapacity();
|
||||
|
||||
// Sanity check
|
||||
Q_ASSERT(size >= 0 || size < maxPayload);
|
||||
|
||||
// copy packet type and version in header
|
||||
writePacketTypeAndVersion(type);
|
||||
|
||||
// Set control bit and sequence number to 0 if necessary
|
||||
if (SEQUENCE_NUMBERED_PACKETS.contains(type)) {
|
||||
writeSequenceNumber(0);
|
||||
}
|
||||
// set the UDT header to default values
|
||||
writeSequenceNumber(0);
|
||||
}
|
||||
|
||||
Packet::Packet(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr) :
|
||||
_packetSize(size),
|
||||
_packet(std::move(data)),
|
||||
_senderSockAddr(senderSockAddr)
|
||||
BasePacket(std::move(data), size, senderSockAddr)
|
||||
{
|
||||
_type = readType();
|
||||
_version = readVersion();
|
||||
_payloadCapacity = _packetSize - localHeaderSize(_type);
|
||||
_payloadSize = _payloadCapacity;
|
||||
_payloadStart = _packet.get() + (_packetSize - _payloadCapacity);
|
||||
readIsReliable();
|
||||
readIsPartOfMessage();
|
||||
readSequenceNumber();
|
||||
|
||||
adjustPayloadStartAndCapacity(_payloadSize > 0);
|
||||
}
|
||||
|
||||
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) {
|
||||
_type = other._type;
|
||||
_version = other._version;
|
||||
BasePacket::operator=(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());
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet::Packet(Packet&& other) {
|
||||
*this = std::move(other);
|
||||
Packet::Packet(Packet&& other) :
|
||||
BasePacket(std::move(other))
|
||||
{
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
}
|
||||
|
||||
Packet& Packet::operator=(Packet&& other) {
|
||||
_type = other._type;
|
||||
_version = other._version;
|
||||
BasePacket::operator=(std::move(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());
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
|
||||
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;
|
||||
}
|
||||
void Packet::adjustPayloadStartAndCapacity(bool shouldDecreasePayloadSize) {
|
||||
qint64 headerSize = localHeaderSize();
|
||||
_payloadStart += headerSize;
|
||||
_payloadCapacity -= headerSize;
|
||||
|
||||
return QIODevice::reset();
|
||||
}
|
||||
|
||||
void Packet::setType(PacketType::Value type) {
|
||||
auto currentHeaderSize = totalHeadersSize();
|
||||
_type = type;
|
||||
writePacketTypeAndVersion(_type);
|
||||
|
||||
// Setting new packet type with a different header size not currently supported
|
||||
Q_ASSERT(currentHeaderSize == totalHeadersSize());
|
||||
Q_UNUSED(currentHeaderSize);
|
||||
}
|
||||
|
||||
PacketType::Value Packet::readType() const {
|
||||
return (PacketType::Value)arithmeticCodingValueFromBuffer(_packet.get());
|
||||
}
|
||||
|
||||
PacketVersion Packet::readVersion() const {
|
||||
return *reinterpret_cast<PacketVersion*>(_packet.get() + numBytesForArithmeticCodedPacketType(_type));
|
||||
}
|
||||
|
||||
Packet::SequenceNumber Packet::readSequenceNumber() const {
|
||||
if (SEQUENCE_NUMBERED_PACKETS.contains(_type)) {
|
||||
SequenceNumber seqNum = *reinterpret_cast<SequenceNumber*>(_packet.get() +
|
||||
numBytesForArithmeticCodedPacketType(_type) +
|
||||
sizeof(PacketVersion));
|
||||
return seqNum & ~(1 << 15); // remove control bit
|
||||
if (shouldDecreasePayloadSize) {
|
||||
_payloadSize -= headerSize;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Packet::readIsControlPacket() const {
|
||||
if (SEQUENCE_NUMBERED_PACKETS.contains(_type)) {
|
||||
SequenceNumber seqNum = *reinterpret_cast<SequenceNumber*>(_packet.get() +
|
||||
numBytesForArithmeticCodedPacketType(_type) +
|
||||
sizeof(PacketVersion));
|
||||
return seqNum & (1 << 15); // Only keep control bit
|
||||
}
|
||||
return false;
|
||||
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 MESSAGE_BIT_MASK = 1 << (sizeof(Packet::SequenceNumberAndBitField) - 3);
|
||||
static const int BIT_FIELD_LENGTH = 3;
|
||||
static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK;
|
||||
|
||||
void Packet::readIsReliable() {
|
||||
SequenceNumberAndBitField seqNumBitField = *reinterpret_cast<SequenceNumberAndBitField*>(_packet.get());
|
||||
_isReliable = (bool) (seqNumBitField & RELIABILITY_BIT_MASK); // Only keep reliability bit
|
||||
}
|
||||
|
||||
void Packet::writePacketTypeAndVersion(PacketType::Value type) {
|
||||
// Pack the packet type
|
||||
auto offset = packArithmeticallyCodedValue(type, _packet.get());
|
||||
|
||||
// Pack the packet version
|
||||
auto version = versionForPacketType(type);
|
||||
memcpy(_packet.get() + offset, &version, sizeof(version));
|
||||
void Packet::readIsPartOfMessage() {
|
||||
SequenceNumberAndBitField seqNumBitField = *reinterpret_cast<SequenceNumberAndBitField*>(_packet.get());
|
||||
_isReliable = (bool) (seqNumBitField & MESSAGE_BIT_MASK); // Only keep message bit
|
||||
}
|
||||
|
||||
void Packet::writeSequenceNumber(SequenceNumber seqNum) {
|
||||
// Here we are overriding the control bit to 0.
|
||||
// But that is not an issue since we should only ever set the seqNum
|
||||
// for data packets going out
|
||||
memcpy(_packet.get() + numBytesForArithmeticCodedPacketType(_type) + sizeof(PacketVersion),
|
||||
&seqNum, sizeof(seqNum));
|
||||
void Packet::readSequenceNumber() {
|
||||
SequenceNumberAndBitField seqNumBitField = *reinterpret_cast<SequenceNumberAndBitField*>(_packet.get());
|
||||
_sequenceNumber = (seqNumBitField & ~BIT_FIELD_MASK); // Remove the bit field
|
||||
}
|
||||
|
||||
QByteArray Packet::read(qint64 maxSize) {
|
||||
qint64 sizeToRead = std::min(size() - pos(), maxSize);
|
||||
QByteArray data { QByteArray::fromRawData(getPayload() + pos(), sizeToRead) };
|
||||
seek(pos() + sizeToRead);
|
||||
return data;
|
||||
}
|
||||
static const uint32_t MAX_SEQUENCE_NUMBER = UINT32_MAX >> BIT_FIELD_LENGTH;
|
||||
|
||||
qint64 Packet::writeData(const char* data, qint64 maxSize) {
|
||||
void Packet::writeSequenceNumber(SequenceNumber sequenceNumber) {
|
||||
// make sure this is a sequence number <= 29 bit unsigned max (536,870,911)
|
||||
Q_ASSERT(sequenceNumber <= MAX_SEQUENCE_NUMBER);
|
||||
|
||||
// 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;
|
||||
// grab pointer to current SequenceNumberAndBitField
|
||||
SequenceNumberAndBitField* seqNumBitField = reinterpret_cast<SequenceNumberAndBitField*>(_packet.get());
|
||||
|
||||
// write new value by ORing (old value & BIT_FIELD_MASK) with new seqNum
|
||||
*seqNumBitField = (*seqNumBitField & BIT_FIELD_MASK) | sequenceNumber;
|
||||
}
|
||||
|
|
|
@ -16,123 +16,62 @@
|
|||
|
||||
#include <QtCore/QIODevice>
|
||||
|
||||
#include "../HifiSockAddr.h"
|
||||
#include "BasePacket.h"
|
||||
#include "PacketHeaders.h"
|
||||
|
||||
namespace udt {
|
||||
|
||||
class Packet : public QIODevice {
|
||||
class Packet : public BasePacket {
|
||||
Q_OBJECT
|
||||
public:
|
||||
using SequenceNumber = uint16_t;
|
||||
// NOTE: The SequenceNumber is only actually 29 bits to leave room for a bit field
|
||||
using SequenceNumber = uint32_t;
|
||||
using SequenceNumberAndBitField = uint32_t;
|
||||
|
||||
// NOTE: The MessageNumber is only actually 29 bits to leave room for a bit field
|
||||
using MessageNumber = uint32_t;
|
||||
using MessageNumberAndBitField = uint32_t;
|
||||
|
||||
static const uint32_t DEFAULT_SEQUENCE_NUMBER = 0;
|
||||
|
||||
static const qint64 PACKET_WRITE_ERROR;
|
||||
|
||||
static std::unique_ptr<Packet> create(PacketType::Value type, qint64 size = -1);
|
||||
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);
|
||||
|
||||
// Provided for convenience, try to limit use
|
||||
static std::unique_ptr<Packet> createCopy(const Packet& other);
|
||||
|
||||
static qint64 localHeaderSize(PacketType::Value type);
|
||||
static qint64 maxPayloadSize(PacketType::Value type);
|
||||
|
||||
|
||||
// The maximum payload size this packet can use to fit in MTU
|
||||
static qint64 maxPayloadSize(bool isPartOfMessage);
|
||||
virtual qint64 maxPayloadSize() const;
|
||||
|
||||
// Current level's header size
|
||||
static qint64 localHeaderSize(bool isPartOfMessage);
|
||||
virtual qint64 localHeaderSize() const;
|
||||
|
||||
virtual qint64 totalHeadersSize() const; // Cumulated size of all the headers
|
||||
virtual qint64 localHeaderSize() const; // Current level's header size
|
||||
|
||||
// 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(); }
|
||||
|
||||
PacketType::Value getType() const { return _type; }
|
||||
void setType(PacketType::Value type);
|
||||
|
||||
PacketVersion getVersion() const { return _version; }
|
||||
|
||||
// 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 seqNum);
|
||||
SequenceNumber readSequenceNumber() const;
|
||||
bool readIsControlPacket() const;
|
||||
|
||||
// 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);
|
||||
void writeSequenceNumber(SequenceNumber sequenceNumber);
|
||||
|
||||
protected:
|
||||
Packet(PacketType::Value type, qint64 size);
|
||||
Packet(qint64 size, bool isReliable = false, bool isPartOfMessage = false);
|
||||
Packet(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
|
||||
Packet(const Packet& other);
|
||||
Packet& operator=(const Packet& other);
|
||||
Packet(Packet&& other);
|
||||
|
||||
Packet& operator=(const Packet& other);
|
||||
Packet& operator=(Packet&& other);
|
||||
|
||||
virtual void adjustPayloadStartAndCapacity(bool shouldDecreasePayloadSize = false);
|
||||
|
||||
// Header readers
|
||||
PacketType::Value readType() const;
|
||||
PacketVersion readVersion() const;
|
||||
// Header readers - these read data to member variables after pulling packet off wire
|
||||
void readIsPartOfMessage();
|
||||
void readIsReliable();
|
||||
void readSequenceNumber();
|
||||
|
||||
// QIODevice virtual functions
|
||||
virtual qint64 writeData(const char* data, qint64 maxSize);
|
||||
virtual qint64 readData(char* data, qint64 maxSize);
|
||||
|
||||
// Header writers
|
||||
void writePacketTypeAndVersion(PacketType::Value type);
|
||||
|
||||
PacketType::Value _type; // Packet type
|
||||
PacketVersion _version; // Packet version
|
||||
|
||||
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)
|
||||
bool _isReliable { false };
|
||||
bool _isPartOfMessage { false };
|
||||
SequenceNumber _sequenceNumber { 0 };
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -15,24 +15,22 @@
|
|||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace PacketType;
|
||||
const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
|
||||
<< PacketType::NodeJsonStats << PacketType::EntityQuery
|
||||
<< PacketType::OctreeDataNack << PacketType::EntityEditNack
|
||||
<< PacketType::DomainListRequest << PacketType::StopNode;
|
||||
|
||||
const QSet<PacketType::Value> NON_VERIFIED_PACKETS = QSet<PacketType::Value>()
|
||||
<< NodeJsonStats << EntityQuery
|
||||
<< OctreeDataNack << EntityEditNack
|
||||
<< DomainListRequest << StopNode;
|
||||
const QSet<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>()
|
||||
<< PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment
|
||||
<< PacketType::DomainServerRequireDTLS << PacketType::DomainConnectRequest
|
||||
<< PacketType::DomainList << PacketType::DomainConnectionDenied
|
||||
<< PacketType::DomainServerPathQuery << PacketType::DomainServerPathResponse
|
||||
<< PacketType::DomainServerAddedNode
|
||||
<< PacketType::ICEServerPeerInformation << PacketType::ICEServerQuery << PacketType::ICEServerHeartbeat
|
||||
<< PacketType::ICEPing << PacketType::ICEPingReply
|
||||
<< PacketType::AssignmentClientStatus << PacketType::StopNode;
|
||||
|
||||
const QSet<PacketType::Value> SEQUENCE_NUMBERED_PACKETS = QSet<PacketType::Value>() << AvatarData;
|
||||
|
||||
const QSet<PacketType::Value> NON_SOURCED_PACKETS = QSet<PacketType::Value>()
|
||||
<< StunResponse << CreateAssignment << RequestAssignment
|
||||
<< DomainServerRequireDTLS << DomainConnectRequest
|
||||
<< DomainList << DomainConnectionDenied
|
||||
<< DomainServerPathQuery << DomainServerPathResponse
|
||||
<< DomainServerAddedNode
|
||||
<< ICEServerPeerInformation << ICEServerQuery << ICEServerHeartbeat
|
||||
<< ICEPing << ICEPingReply
|
||||
<< AssignmentClientStatus << StopNode;
|
||||
const QSet<PacketType> RELIABLE_PACKETS = QSet<PacketType>();
|
||||
|
||||
int arithmeticCodingValueFromBuffer(const char* checkValue) {
|
||||
if (((uchar) *checkValue) < 255) {
|
||||
|
@ -62,69 +60,80 @@ int packArithmeticallyCodedValue(int value, char* destination) {
|
|||
}
|
||||
}
|
||||
|
||||
PacketVersion versionForPacketType(PacketType::Value packetType) {
|
||||
PacketVersion versionForPacketType(PacketType packetType) {
|
||||
switch (packetType) {
|
||||
case EntityAdd:
|
||||
case EntityEdit:
|
||||
case EntityData:
|
||||
return VERSION_ENTITIES_NEW_PROTOCOL_LAYER;
|
||||
case PacketType::EntityAdd:
|
||||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
return VERSION_ENTITIES_PROTOCOL_HEADER_SWAP;
|
||||
default:
|
||||
return 11;
|
||||
return 12;
|
||||
}
|
||||
}
|
||||
|
||||
#define PACKET_TYPE_NAME_LOOKUP(x) case x: return QString(#x);
|
||||
|
||||
QString nameForPacketType(PacketType::Value packetType) {
|
||||
QString nameForPacketType(PacketType packetType) {
|
||||
switch (packetType) {
|
||||
PACKET_TYPE_NAME_LOOKUP(Unknown);
|
||||
PACKET_TYPE_NAME_LOOKUP(StunResponse);
|
||||
PACKET_TYPE_NAME_LOOKUP(DomainList);
|
||||
PACKET_TYPE_NAME_LOOKUP(Ping);
|
||||
PACKET_TYPE_NAME_LOOKUP(PingReply);
|
||||
PACKET_TYPE_NAME_LOOKUP(KillAvatar);
|
||||
PACKET_TYPE_NAME_LOOKUP(AvatarData);
|
||||
PACKET_TYPE_NAME_LOOKUP(InjectAudio);
|
||||
PACKET_TYPE_NAME_LOOKUP(MixedAudio);
|
||||
PACKET_TYPE_NAME_LOOKUP(MicrophoneAudioNoEcho);
|
||||
PACKET_TYPE_NAME_LOOKUP(MicrophoneAudioWithEcho);
|
||||
PACKET_TYPE_NAME_LOOKUP(BulkAvatarData);
|
||||
PACKET_TYPE_NAME_LOOKUP(SilentAudioFrame);
|
||||
PACKET_TYPE_NAME_LOOKUP(DomainListRequest);
|
||||
PACKET_TYPE_NAME_LOOKUP(RequestAssignment);
|
||||
PACKET_TYPE_NAME_LOOKUP(CreateAssignment);
|
||||
PACKET_TYPE_NAME_LOOKUP(DomainConnectionDenied);
|
||||
PACKET_TYPE_NAME_LOOKUP(MuteEnvironment);
|
||||
PACKET_TYPE_NAME_LOOKUP(AudioStreamStats);
|
||||
PACKET_TYPE_NAME_LOOKUP(OctreeStats);
|
||||
PACKET_TYPE_NAME_LOOKUP(Jurisdiction);
|
||||
PACKET_TYPE_NAME_LOOKUP(JurisdictionRequest);
|
||||
PACKET_TYPE_NAME_LOOKUP(AvatarIdentity);
|
||||
PACKET_TYPE_NAME_LOOKUP(AvatarBillboard);
|
||||
PACKET_TYPE_NAME_LOOKUP(DomainConnectRequest);
|
||||
PACKET_TYPE_NAME_LOOKUP(DomainServerRequireDTLS);
|
||||
PACKET_TYPE_NAME_LOOKUP(NodeJsonStats);
|
||||
PACKET_TYPE_NAME_LOOKUP(EntityQuery);
|
||||
PACKET_TYPE_NAME_LOOKUP(EntityData);
|
||||
PACKET_TYPE_NAME_LOOKUP(EntityErase);
|
||||
PACKET_TYPE_NAME_LOOKUP(OctreeDataNack);
|
||||
PACKET_TYPE_NAME_LOOKUP(StopNode);
|
||||
PACKET_TYPE_NAME_LOOKUP(AudioEnvironment);
|
||||
PACKET_TYPE_NAME_LOOKUP(EntityEditNack);
|
||||
PACKET_TYPE_NAME_LOOKUP(ICEServerHeartbeat);
|
||||
PACKET_TYPE_NAME_LOOKUP(DomainServerAddedNode);
|
||||
PACKET_TYPE_NAME_LOOKUP(ICEServerQuery);
|
||||
PACKET_TYPE_NAME_LOOKUP(ICEServerPeerInformation);
|
||||
PACKET_TYPE_NAME_LOOKUP(ICEPing);
|
||||
PACKET_TYPE_NAME_LOOKUP(ICEPingReply);
|
||||
PACKET_TYPE_NAME_LOOKUP(EntityAdd);
|
||||
PACKET_TYPE_NAME_LOOKUP(EntityEdit);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::Unknown);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::StunResponse);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::DomainList);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::Ping);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::PingReply);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::KillAvatar);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::AvatarData);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::InjectAudio);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::MixedAudio);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::MicrophoneAudioNoEcho);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::MicrophoneAudioWithEcho);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::BulkAvatarData);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::SilentAudioFrame);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::DomainListRequest);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::RequestAssignment);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::CreateAssignment);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::DomainConnectionDenied);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::MuteEnvironment);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::AudioStreamStats);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::OctreeStats);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::Jurisdiction);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::JurisdictionRequest);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::AvatarIdentity);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::AvatarBillboard);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::DomainConnectRequest);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::DomainServerRequireDTLS);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::NodeJsonStats);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::EntityQuery);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::EntityData);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::EntityErase);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::OctreeDataNack);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::StopNode);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::AudioEnvironment);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::EntityEditNack);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::ICEServerHeartbeat);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::DomainServerAddedNode);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::ICEServerQuery);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::ICEServerPeerInformation);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::ICEPing);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::ICEPingReply);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::EntityAdd);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketType::EntityEdit);
|
||||
default:
|
||||
return QString("Type: ") + QString::number((int)packetType);
|
||||
}
|
||||
return QString("unexpected");
|
||||
}
|
||||
|
||||
int numBytesForArithmeticCodedPacketType(PacketType::Value packetType) {
|
||||
int numBytesForArithmeticCodedPacketType(PacketType packetType) {
|
||||
return (int) ceilf((float) packetType / 255);
|
||||
}
|
||||
|
||||
uint qHash(const PacketType& key, uint seed) {
|
||||
// seems odd that Qt couldn't figure out this cast itself, but this fixes a compile error after switch to
|
||||
// strongly typed enum for PacketType
|
||||
return qHash((quint8) key, seed);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const PacketType& type) {
|
||||
debug.nospace() << (uint8_t) type << " (" << qPrintable(nameForPacketType(type)) << ")";
|
||||
return debug.space();
|
||||
}
|
||||
|
|
|
@ -26,83 +26,77 @@
|
|||
// NOTE: if adding a new packet packetType, you can replace one marked usable or add at the end
|
||||
// NOTE: if you want the name of the packet packetType to be available for debugging or logging, update nameForPacketType() as well
|
||||
|
||||
namespace PacketType {
|
||||
enum Value {
|
||||
Unknown,
|
||||
StunResponse,
|
||||
DomainList,
|
||||
Ping,
|
||||
PingReply,
|
||||
KillAvatar,
|
||||
AvatarData,
|
||||
InjectAudio,
|
||||
MixedAudio,
|
||||
MicrophoneAudioNoEcho,
|
||||
MicrophoneAudioWithEcho,
|
||||
BulkAvatarData,
|
||||
SilentAudioFrame,
|
||||
DomainListRequest,
|
||||
RequestAssignment,
|
||||
CreateAssignment,
|
||||
DomainConnectionDenied,
|
||||
MuteEnvironment,
|
||||
AudioStreamStats,
|
||||
DomainServerPathQuery,
|
||||
DomainServerPathResponse,
|
||||
DomainServerAddedNode,
|
||||
ICEServerPeerInformation,
|
||||
ICEServerQuery,
|
||||
OctreeStats,
|
||||
Jurisdiction,
|
||||
JurisdictionRequest,
|
||||
AssignmentClientStatus,
|
||||
NoisyMute,
|
||||
AvatarIdentity,
|
||||
AvatarBillboard,
|
||||
DomainConnectRequest,
|
||||
DomainServerRequireDTLS,
|
||||
NodeJsonStats,
|
||||
OctreeDataNack,
|
||||
StopNode,
|
||||
AudioEnvironment,
|
||||
EntityEditNack,
|
||||
ICEServerHeartbeat,
|
||||
ICEPing,
|
||||
ICEPingReply,
|
||||
EntityData,
|
||||
EntityQuery,
|
||||
EntityAdd,
|
||||
EntityErase,
|
||||
EntityEdit
|
||||
};
|
||||
enum class PacketType : uint8_t {
|
||||
Unknown,
|
||||
StunResponse,
|
||||
DomainList,
|
||||
Ping,
|
||||
PingReply,
|
||||
KillAvatar,
|
||||
AvatarData,
|
||||
InjectAudio,
|
||||
MixedAudio,
|
||||
MicrophoneAudioNoEcho,
|
||||
MicrophoneAudioWithEcho,
|
||||
BulkAvatarData,
|
||||
SilentAudioFrame,
|
||||
DomainListRequest,
|
||||
RequestAssignment,
|
||||
CreateAssignment,
|
||||
DomainConnectionDenied,
|
||||
MuteEnvironment,
|
||||
AudioStreamStats,
|
||||
DomainServerPathQuery,
|
||||
DomainServerPathResponse,
|
||||
DomainServerAddedNode,
|
||||
ICEServerPeerInformation,
|
||||
ICEServerQuery,
|
||||
OctreeStats,
|
||||
Jurisdiction,
|
||||
JurisdictionRequest,
|
||||
AssignmentClientStatus,
|
||||
NoisyMute,
|
||||
AvatarIdentity,
|
||||
AvatarBillboard,
|
||||
DomainConnectRequest,
|
||||
DomainServerRequireDTLS,
|
||||
NodeJsonStats,
|
||||
OctreeDataNack,
|
||||
StopNode,
|
||||
AudioEnvironment,
|
||||
EntityEditNack,
|
||||
ICEServerHeartbeat,
|
||||
ICEPing,
|
||||
ICEPingReply,
|
||||
EntityData,
|
||||
EntityQuery,
|
||||
EntityAdd,
|
||||
EntityErase,
|
||||
EntityEdit
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
typedef char PacketVersion;
|
||||
|
||||
typedef uint16_t PacketSequenceNumber;
|
||||
const PacketSequenceNumber DEFAULT_SEQUENCE_NUMBER = 0;
|
||||
extern const QSet<PacketType> NON_VERIFIED_PACKETS;
|
||||
extern const QSet<PacketType> NON_SOURCED_PACKETS;
|
||||
extern const QSet<PacketType> RELIABLE_PACKETS;
|
||||
|
||||
typedef std::map<PacketType::Value, PacketSequenceNumber> PacketTypeSequenceMap;
|
||||
QString nameForPacketType(PacketType packetType);
|
||||
PacketVersion versionForPacketType(PacketType packetType);
|
||||
|
||||
extern const QSet<PacketType::Value> NON_VERIFIED_PACKETS;
|
||||
extern const QSet<PacketType::Value> SEQUENCE_NUMBERED_PACKETS;
|
||||
extern const QSet<PacketType::Value> NON_SOURCED_PACKETS;
|
||||
|
||||
QString nameForPacketType(PacketType::Value packetType);
|
||||
PacketVersion versionForPacketType(PacketType::Value packetType);
|
||||
|
||||
int numBytesForArithmeticCodedPacketType(PacketType::Value packetType);
|
||||
int numBytesForPacketHeaderGivenPacketType(PacketType::Value packetType);
|
||||
int numBytesForArithmeticCodedPacketType(PacketType packetType);
|
||||
int numBytesForPacketHeaderGivenPacketType(PacketType packetType);
|
||||
int packArithmeticallyCodedValue(int value, char* destination);
|
||||
|
||||
int arithmeticCodingValueFromBuffer(const char* checkValue);
|
||||
int numBytesArithmeticCodingFromBuffer(const char* checkValue);
|
||||
|
||||
uint qHash(const PacketType& key, uint seed);
|
||||
QDebug operator<<(QDebug debug, const PacketType& type);
|
||||
|
||||
const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_ANIMATION = 1;
|
||||
const PacketVersion VERSION_ROOT_ELEMENT_HAS_DATA = 2;
|
||||
|
@ -139,5 +133,6 @@ const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP = 31;
|
|||
const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP_FIX = 32;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE = 33;
|
||||
const PacketVersion VERSION_ENTITIES_NEW_PROTOCOL_LAYER = 35;
|
||||
const PacketVersion VERSION_ENTITIES_PROTOCOL_HEADER_SWAP = 36;
|
||||
|
||||
#endif // hifi_PacketHeaders_h
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
using namespace udt;
|
||||
|
||||
PacketList::PacketList(PacketType::Value packetType, QByteArray extendedHeader) :
|
||||
PacketList::PacketList(PacketType packetType, QByteArray extendedHeader) :
|
||||
_packetType(packetType),
|
||||
_extendedHeader(extendedHeader)
|
||||
{
|
||||
|
@ -34,7 +34,8 @@ void PacketList::endSegment() {
|
|||
|
||||
std::unique_ptr<Packet> PacketList::createPacket() {
|
||||
// use the static create method to create a new packet
|
||||
return Packet::create(getType());
|
||||
// TODO: create a packet with correct reliability and messaging
|
||||
return Packet::create();
|
||||
}
|
||||
|
||||
std::unique_ptr<Packet> PacketList::createPacketWithExtendedHeader() {
|
||||
|
|
|
@ -27,14 +27,14 @@ class Packet;
|
|||
class PacketList : public QIODevice {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PacketList(PacketType::Value packetType, QByteArray extendedHeader = QByteArray());
|
||||
PacketList(PacketType packetType, QByteArray extendedHeader = QByteArray());
|
||||
|
||||
virtual bool isSequential() const { return true; }
|
||||
|
||||
void startSegment();
|
||||
void endSegment();
|
||||
|
||||
PacketType::Value getType() const { return _packetType; }
|
||||
PacketType getType() const { return _packetType; }
|
||||
int getNumPackets() const { return _packets.size() + (_currentPacket ? 1 : 0); }
|
||||
|
||||
void closeCurrentPacket(bool shouldSendEmpty = false);
|
||||
|
@ -58,7 +58,7 @@ private:
|
|||
virtual std::unique_ptr<Packet> createPacket();
|
||||
std::unique_ptr<Packet> createPacketWithExtendedHeader();
|
||||
|
||||
PacketType::Value _packetType;
|
||||
PacketType _packetType;
|
||||
bool _isOrdered = false;
|
||||
|
||||
std::unique_ptr<Packet> _currentPacket;
|
||||
|
|
|
@ -65,6 +65,9 @@ qint64 Socket::writeDatagram(const QByteArray& datagram, const HifiSockAddr& soc
|
|||
|
||||
qint64 bytesWritten = _udpSocket.writeDatagram(datagram, sockAddr.getAddress(), sockAddr.getPort());
|
||||
|
||||
// TODO::
|
||||
// const_cast<NLPacket&>(packet).writeSequenceNumber(sequenceNumber);
|
||||
|
||||
if (bytesWritten < 0) {
|
||||
qCDebug(networking) << "ERROR in writeDatagram:" << _udpSocket.error() << "-" << _udpSocket.errorString();
|
||||
}
|
||||
|
@ -80,16 +83,28 @@ void Socket::readPendingDatagrams() {
|
|||
// setup a buffer to read the packet into
|
||||
int packetSizeWithHeader = _udpSocket.pendingDatagramSize();
|
||||
std::unique_ptr<char> buffer = std::unique_ptr<char>(new char[packetSizeWithHeader]);
|
||||
|
||||
|
||||
// pull the datagram
|
||||
_udpSocket.readDatagram(buffer.get(), packetSizeWithHeader,
|
||||
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
|
||||
auto packet = Packet::fromReceivedPacket(std::move(buffer), packetSizeWithHeader, senderSockAddr);
|
||||
|
||||
// call our verification operator to see if this packet is verified
|
||||
if (_unfilteredSockAddrs.contains(senderSockAddr) || !_packetFilterOperator || _packetFilterOperator(*packet)) {
|
||||
if (!_packetFilterOperator || _packetFilterOperator(*packet)) {
|
||||
if (_packetHandler) {
|
||||
// call the verified packet callback to let it handle this packet
|
||||
return _packetHandler(std::move(packet));
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#define hifi_Socket_h
|
||||
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtNetwork/QUdpSocket>
|
||||
|
@ -25,6 +26,8 @@
|
|||
namespace udt {
|
||||
|
||||
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>)>;
|
||||
|
||||
class Socket : public QObject {
|
||||
|
@ -48,7 +51,8 @@ public:
|
|||
|
||||
void setBufferSizes(int numBytes);
|
||||
|
||||
void addUnfilteredSockAddr(const HifiSockAddr& senderSockAddr) { _unfilteredSockAddrs.insert(senderSockAddr); }
|
||||
void addUnfilteredHandler(const HifiSockAddr& senderSockAddr, BasePacketHandler handler)
|
||||
{ _unfilteredHandlers[senderSockAddr] = handler; }
|
||||
|
||||
private slots:
|
||||
void readPendingDatagrams();
|
||||
|
@ -58,7 +62,9 @@ private:
|
|||
PacketFilterOperator _packetFilterOperator;
|
||||
PacketHandler _packetHandler;
|
||||
|
||||
QSet<HifiSockAddr> _unfilteredSockAddrs;
|
||||
std::unordered_map<HifiSockAddr, BasePacketHandler> _unfilteredHandlers;
|
||||
|
||||
std::unordered_map<HifiSockAddr, Packet::SequenceNumber> _packetSequenceNumbers;
|
||||
};
|
||||
|
||||
} // namespace udt
|
||||
|
|
|
@ -1894,7 +1894,7 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
|||
|
||||
bool wantImportProgress = true;
|
||||
|
||||
PacketType::Value expectedType = expectedDataPacketType();
|
||||
PacketType expectedType = expectedDataPacketType();
|
||||
PacketVersion expectedVersion = versionForPacketType(expectedType);
|
||||
bool hasBufferBreaks = versionHasSVOfileBreaks(expectedVersion);
|
||||
|
||||
|
@ -1902,7 +1902,7 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
|||
if (getWantSVOfileVersions()) {
|
||||
|
||||
// read just enough of the file to parse the header...
|
||||
const unsigned long HEADER_LENGTH = sizeof(PacketType::Value) + sizeof(PacketVersion);
|
||||
const unsigned long HEADER_LENGTH = sizeof(PacketType) + sizeof(PacketVersion);
|
||||
unsigned char fileHeader[HEADER_LENGTH];
|
||||
inputStream.readRawData((char*)&fileHeader, HEADER_LENGTH);
|
||||
|
||||
|
@ -1912,7 +1912,7 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
|||
unsigned long dataLength = HEADER_LENGTH;
|
||||
|
||||
// if so, read the first byte of the file and see if it matches the expected version code
|
||||
PacketType::Value gotType;
|
||||
PacketType gotType;
|
||||
memcpy(&gotType, dataAt, sizeof(gotType));
|
||||
|
||||
dataAt += sizeof(expectedType);
|
||||
|
@ -2055,7 +2055,7 @@ void Octree::writeToJSONFile(const char* fileName, OctreeElement* element) {
|
|||
}
|
||||
|
||||
// include the "bitstream" version
|
||||
PacketType::Value expectedType = expectedDataPacketType();
|
||||
PacketType expectedType = expectedDataPacketType();
|
||||
PacketVersion expectedVersion = versionForPacketType(expectedType);
|
||||
entityDescription["Version"] = (int) expectedVersion;
|
||||
|
||||
|
@ -2076,7 +2076,7 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) {
|
|||
if(file.is_open()) {
|
||||
qCDebug(octree, "Saving binary SVO to file %s...", fileName);
|
||||
|
||||
PacketType::Value expectedType = expectedDataPacketType();
|
||||
PacketType expectedType = expectedDataPacketType();
|
||||
PacketVersion expectedVersion = versionForPacketType(expectedType);
|
||||
bool hasBufferBreaks = versionHasSVOfileBreaks(expectedVersion);
|
||||
|
||||
|
|
|
@ -228,11 +228,11 @@ public:
|
|||
// These methods will allow the OctreeServer to send your tree inbound edit packets of your
|
||||
// own definition. Implement these to allow your octree based server to support editing
|
||||
virtual bool getWantSVOfileVersions() const { return false; }
|
||||
virtual PacketType::Value expectedDataPacketType() const { return PacketType::Unknown; }
|
||||
virtual PacketType expectedDataPacketType() const { return PacketType::Unknown; }
|
||||
virtual bool canProcessVersion(PacketVersion thisVersion) const {
|
||||
return thisVersion == versionForPacketType(expectedDataPacketType()); }
|
||||
virtual PacketVersion expectedVersion() const { return versionForPacketType(expectedDataPacketType()); }
|
||||
virtual bool handlesEditPacketType(PacketType::Value packetType) const { return false; }
|
||||
virtual bool handlesEditPacketType(PacketType packetType) const { return false; }
|
||||
virtual int processEditPacketData(NLPacket& packet, const unsigned char* editData, int maxLength,
|
||||
const SharedNodePointer& sourceNode) { return 0; }
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ void OctreeEditPacketSender::queuePacketToNodes(std::unique_ptr<NLPacket> packet
|
|||
|
||||
|
||||
// NOTE: editMessage - is JUST the octcode/color and does not contain the packet header
|
||||
void OctreeEditPacketSender::queueOctreeEditMessage(PacketType::Value type, QByteArray& editMessage) {
|
||||
void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, QByteArray& editMessage) {
|
||||
|
||||
if (!_shouldSend) {
|
||||
return; // bail early
|
||||
|
@ -315,7 +315,7 @@ void OctreeEditPacketSender::releaseQueuedPacket(const QUuid& nodeID, std::uniqu
|
|||
_releaseQueuedPacketMutex.unlock();
|
||||
}
|
||||
|
||||
std::unique_ptr<NLPacket> OctreeEditPacketSender::initializePacket(PacketType::Value type, int nodeClockSkew) {
|
||||
std::unique_ptr<NLPacket> OctreeEditPacketSender::initializePacket(PacketType type, int nodeClockSkew) {
|
||||
auto newPacket = NLPacket::create(type);
|
||||
|
||||
// skip over sequence number for now; will be packed when packet is ready to be sent out
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
/// Queues a single edit message. Will potentially send a pending multi-command packet. Determines which server
|
||||
/// node or nodes the packet should be sent to. Can be called even before servers are known, in which case up to
|
||||
/// MaxPendingMessages will be buffered and processed when servers are known.
|
||||
void queueOctreeEditMessage(PacketType::Value type, QByteArray& editMessage);
|
||||
void queueOctreeEditMessage(PacketType type, QByteArray& editMessage);
|
||||
|
||||
/// Releases all queued messages even if those messages haven't filled an MTU packet. This will move the packed message
|
||||
/// packets onto the send queue. If running in threaded mode, the caller does not need to do any further processing to
|
||||
|
@ -81,7 +81,7 @@ public:
|
|||
|
||||
// you must override these...
|
||||
virtual char getMyNodeType() const = 0;
|
||||
virtual void adjustEditPacketForClockSkew(PacketType::Value type, QByteArray& buffer, int clockSkew) { }
|
||||
virtual void adjustEditPacketForClockSkew(PacketType type, QByteArray& buffer, int clockSkew) { }
|
||||
|
||||
void processNackPacket(NLPacket& packet, SharedNodePointer sendingNode);
|
||||
|
||||
|
@ -89,13 +89,13 @@ public slots:
|
|||
void nodeKilled(SharedNodePointer node);
|
||||
|
||||
protected:
|
||||
using EditMessagePair = std::pair<PacketType::Value, QByteArray>;
|
||||
using EditMessagePair = std::pair<PacketType, QByteArray>;
|
||||
|
||||
bool _shouldSend;
|
||||
void queuePacketToNode(const QUuid& nodeID, std::unique_ptr<NLPacket> packet);
|
||||
void queuePendingPacketToNodes(std::unique_ptr<NLPacket> packet);
|
||||
void queuePacketToNodes(std::unique_ptr<NLPacket> packet);
|
||||
std::unique_ptr<NLPacket> initializePacket(PacketType::Value type, int nodeClockSkew);
|
||||
std::unique_ptr<NLPacket> initializePacket(PacketType type, int nodeClockSkew);
|
||||
void releaseQueuedPacket(const QUuid& nodeUUID, std::unique_ptr<NLPacket> packetBuffer); // releases specific queued packet
|
||||
|
||||
void processPreServerExistsPackets();
|
||||
|
|
|
@ -33,7 +33,7 @@ void OctreeHeadlessViewer::init() {
|
|||
|
||||
void OctreeHeadlessViewer::queryOctree() {
|
||||
char serverType = getMyNodeType();
|
||||
PacketType::Value packetType = getMyQueryMessageType();
|
||||
PacketType packetType = getMyQueryMessageType();
|
||||
NodeToJurisdictionMap& jurisdictions = *_jurisdictionListener->getJurisdictions();
|
||||
|
||||
bool wantExtraDebugging = false;
|
||||
|
|
|
@ -26,11 +26,11 @@
|
|||
#include <QString>
|
||||
#include <QUuid>
|
||||
|
||||
#include <LimitedNodeList.h> // for MAX_PACKET_SIZE
|
||||
#include <udt/PacketHeaders.h> // for MAX_PACKET_HEADER_BYTES
|
||||
#include <BackgroundMode.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <ShapeInfo.h>
|
||||
#include <BackgroundMode.h>
|
||||
#include <udt/BasePacket.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
|
||||
#include "OctreeConstants.h"
|
||||
#include "OctreeElement.h"
|
||||
|
@ -40,14 +40,13 @@ typedef uint16_t OCTREE_PACKET_SEQUENCE;
|
|||
const uint16_t MAX_OCTREE_PACKET_SEQUENCE = 65535;
|
||||
typedef quint64 OCTREE_PACKET_SENT_TIME;
|
||||
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::Value could be as small as one byte
|
||||
const unsigned int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS)
|
||||
+ 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 MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40;
|
||||
|
|
|
@ -36,8 +36,8 @@ public:
|
|||
virtual ~OctreeRenderer();
|
||||
|
||||
virtual char getMyNodeType() const = 0;
|
||||
virtual PacketType::Value getMyQueryMessageType() const = 0;
|
||||
virtual PacketType::Value getExpectedPacketType() const = 0;
|
||||
virtual PacketType getMyQueryMessageType() const = 0;
|
||||
virtual PacketType getExpectedPacketType() const = 0;
|
||||
virtual void renderElement(OctreeElement* element, RenderArgs* args) = 0;
|
||||
virtual float getSizeScale() const { return DEFAULT_OCTREE_SIZE_SCALE; }
|
||||
virtual int getBoundaryLevelAdjust() const { return 0; }
|
||||
|
|
|
@ -791,6 +791,6 @@ void OctreeSceneStats::trackIncomingOctreePacket(NLPacket& packet, bool wasStats
|
|||
_incomingPacket++;
|
||||
_incomingBytes += packet.getDataSize();
|
||||
if (!wasStatsPacket) {
|
||||
_incomingWastedBytes += (MAX_PACKET_SIZE - packet.getDataSize());
|
||||
_incomingWastedBytes += (udt::MAX_PACKET_SIZE - packet.getDataSize());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue