Merge pull request #12743 from SimonWalton-HiFi/short-id

Use 16-bit local IDs for Nodes in NL packets
This commit is contained in:
John Conklin II 2018-04-20 15:28:18 -07:00 committed by GitHub
commit 39ad8be1b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 209 additions and 94 deletions

View file

@ -901,7 +901,7 @@ void AssetServer::handleAssetUpload(QSharedPointer<ReceivedMessage> message, Sha
if (canWriteToAssetServer) {
qCDebug(asset_server) << "Starting an UploadAssetTask for upload from" << uuidStringWithoutCurlyBraces(message->getSourceID());
qCDebug(asset_server) << "Starting an UploadAssetTask for upload from" << message->getSourceID();
auto task = new UploadAssetTask(message, senderNode, _filesDirectory, _filesizeLimit);
_transferTaskPool.start(task);

View file

@ -117,12 +117,13 @@ void AudioMixer::queueAudioPacket(QSharedPointer<ReceivedMessage> message, Share
void AudioMixer::queueReplicatedAudioPacket(QSharedPointer<ReceivedMessage> message) {
// make sure we have a replicated node for the original sender of the packet
auto nodeList = DependencyManager::get<NodeList>();
QUuid nodeID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
// Node ID is now part of user data, since replicated audio packets are non-sourced.
QUuid nodeID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
auto replicatedNode = nodeList->addOrUpdateNode(nodeID, NodeType::Agent,
message->getSenderSockAddr(), message->getSenderSockAddr(),
true, true);
Node::NULL_LOCAL_ID, true, true);
replicatedNode->setLastHeardMicrostamp(usecTimestampNow());
// construct a "fake" audio received message from the byte array and packet list information
@ -136,7 +137,7 @@ void AudioMixer::queueReplicatedAudioPacket(QSharedPointer<ReceivedMessage> mess
auto replicatedMessage = QSharedPointer<ReceivedMessage>::create(audioData, rewrittenType,
versionForPacketType(rewrittenType),
message->getSenderSockAddr(), nodeID);
message->getSenderSockAddr(), Node::NULL_LOCAL_ID);
getOrCreateClientData(replicatedNode.data())->queuePacket(replicatedMessage, replicatedNode);
}

View file

@ -74,7 +74,7 @@ SharedNodePointer addOrUpdateReplicatedNode(const QUuid& nodeID, const HifiSockA
auto replicatedNode = DependencyManager::get<NodeList>()->addOrUpdateNode(nodeID, NodeType::Agent,
senderSockAddr,
senderSockAddr,
true, true);
Node::NULL_LOCAL_ID, true, true);
replicatedNode->setLastHeardMicrostamp(usecTimestampNow());
@ -112,8 +112,8 @@ void AvatarMixer::handleReplicatedPacket(QSharedPointer<ReceivedMessage> message
void AvatarMixer::handleReplicatedBulkAvatarPacket(QSharedPointer<ReceivedMessage> message) {
while (message->getBytesLeftToRead()) {
// first, grab the node ID for this replicated avatar
// Node ID is now part of user data, since ReplicatedBulkAvatarPacket is non-sourced.
auto nodeID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
// make sure we have an upstream replicated node that matches
auto replicatedNode = addOrUpdateReplicatedNode(nodeID, message->getSenderSockAddr());
@ -127,7 +127,7 @@ void AvatarMixer::handleReplicatedBulkAvatarPacket(QSharedPointer<ReceivedMessag
// construct a "fake" avatar data received message from the byte array and packet list information
auto replicatedMessage = QSharedPointer<ReceivedMessage>::create(avatarByteArray, PacketType::AvatarData,
versionForPacketType(PacketType::AvatarData),
message->getSenderSockAddr(), nodeID);
message->getSenderSockAddr(), Node::NULL_LOCAL_ID);
// queue up the replicated avatar data with the client data for the replicated node
auto start = usecTimestampNow();

View file

@ -14,6 +14,7 @@
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <random>
#include <AccountManager.h>
#include <Assignment.h>
@ -26,7 +27,7 @@ using SharedAssignmentPointer = QSharedPointer<Assignment>;
DomainGatekeeper::DomainGatekeeper(DomainServer* server) :
_server(server)
{
initLocalIDManagement();
}
void DomainGatekeeper::addPendingAssignedNode(const QUuid& nodeUUID, const QUuid& assignmentUUID,
@ -529,8 +530,10 @@ SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const Node
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
Node::LocalID newLocalID = findOrCreateLocalID(nodeID);
SharedNodePointer newNode = limitedNodeList->addOrUpdateNode(nodeID, nodeConnection.nodeType,
nodeConnection.publicSockAddr, nodeConnection.localSockAddr);
nodeConnection.publicSockAddr, nodeConnection.localSockAddr,
newLocalID);
// So that we can send messages to this node at will - we need to activate the correct socket on this node now
newNode->activateMatchingOrNewSymmetricSocket(discoveredSocket);
@ -1020,3 +1023,31 @@ void DomainGatekeeper::refreshGroupsCache() {
_server->_settingsManager.debugDumpGroupsState();
#endif
}
void DomainGatekeeper::initLocalIDManagement() {
std::uniform_int_distribution<quint16> sixteenBitRand;
std::random_device randomDevice;
std::default_random_engine engine { randomDevice() };
_currentLocalID = sixteenBitRand(engine);
// Ensure increment is odd.
_idIncrement = sixteenBitRand(engine) | 1;
}
Node::LocalID DomainGatekeeper::findOrCreateLocalID(const QUuid& uuid) {
auto existingLocalIDIt = _uuidToLocalID.find(uuid);
if (existingLocalIDIt != _uuidToLocalID.end()) {
return existingLocalIDIt->second;
}
assert(_localIDs.size() < std::numeric_limits<LocalIDs::value_type>::max() - 2);
Node::LocalID newLocalID;
do {
newLocalID = _currentLocalID;
_currentLocalID += _idIncrement;
} while (newLocalID == Node::NULL_LOCAL_ID || _localIDs.find(newLocalID) != _localIDs.end());
_uuidToLocalID.emplace(uuid, newLocalID);
_localIDs.insert(newLocalID);
return newLocalID;
}

View file

@ -15,6 +15,7 @@
#define hifi_DomainGatekeeper_h
#include <unordered_map>
#include <unordered_set>
#include <QtCore/QObject>
#include <QtNetwork/QNetworkReply>
@ -41,6 +42,8 @@ public:
void removeICEPeer(const QUuid& peerUUID) { _icePeers.remove(peerUUID); }
Node::LocalID findOrCreateLocalID(const QUuid& uuid);
static void sendProtocolMismatchConnectionDenial(const HifiSockAddr& senderSockAddr);
public slots:
void processConnectRequestPacket(QSharedPointer<ReceivedMessage> message);
@ -120,6 +123,16 @@ private:
void getGroupMemberships(const QString& username);
// void getIsGroupMember(const QString& username, const QUuid groupID);
void getDomainOwnerFriendsList();
// Local ID management.
void initLocalIDManagement();
using UUIDToLocalID = std::unordered_map<QUuid, Node::LocalID> ;
using LocalIDs = std::unordered_set<Node::LocalID>;
LocalIDs _localIDs;
UUIDToLocalID _uuidToLocalID;
Node::LocalID _currentLocalID;
Node::LocalID _idIncrement;
};

View file

@ -593,8 +593,8 @@ bool DomainServer::isPacketVerified(const udt::Packet& packet) {
if (!PacketTypeEnum::getNonSourcedPackets().contains(headerType)) {
// this is a sourced packet - first check if we have a node that matches
QUuid sourceID = NLPacket::sourceIDInHeader(packet);
SharedNodePointer sourceNode = nodeList->nodeWithUUID(sourceID);
Node::LocalID localSourceID = NLPacket::sourceIDInHeader(packet);
SharedNodePointer sourceNode = nodeList->nodeWithLocalID(localSourceID);
if (sourceNode) {
// unverified DS packets (due to a lack of connection secret between DS + node)
@ -612,14 +612,12 @@ bool DomainServer::isPacketVerified(const udt::Packet& packet) {
return nodeList->isPacketVerifiedWithSource(packet, sourceNode.data());
} else {
HIFI_FDEBUG("Packet of type" << headerType
<< "received from unmatched IP for UUID" << uuidStringWithoutCurlyBraces(sourceID));
<< "received from unmatched IP for UUID" << uuidStringWithoutCurlyBraces(sourceNode->getUUID()));
return false;
}
} else {
HIFI_FDEBUG("Packet of type" << headerType
<< "received from unknown node with UUID" << uuidStringWithoutCurlyBraces(sourceID));
<< "received from unknown node with UUID" << uuidStringWithoutCurlyBraces(sourceNode->getUUID()));
return false;
}
}
@ -683,6 +681,10 @@ void DomainServer::setupNodeListAndAssignments() {
}
}
// Create our own short session ID.
Node::LocalID serverSessionLocalID = _gatekeeper.findOrCreateLocalID(nodeList->getSessionUUID());
nodeList->setSessionLocalID(serverSessionLocalID);
if (isMetaverseDomain) {
// see if we think we're a temp domain (we have an API key) or a full domain
const auto& temporaryDomainKey = DependencyManager::get<AccountManager>()->getTemporaryDomainKey(getID());
@ -1112,7 +1114,8 @@ void DomainServer::handleConnectedNode(SharedNodePointer newNode) {
}
void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr &senderSockAddr) {
const int NUM_DOMAIN_LIST_EXTENDED_HEADER_BYTES = NUM_BYTES_RFC4122_UUID + NUM_BYTES_RFC4122_UUID + 2;
const int NUM_DOMAIN_LIST_EXTENDED_HEADER_BYTES = NUM_BYTES_RFC4122_UUID + NLPacket::NUM_BYTES_LOCALID +
NUM_BYTES_RFC4122_UUID + NLPacket::NUM_BYTES_LOCALID + 4;
// setup the extended header for the domain list packets
// this data is at the beginning of each of the domain list packets
@ -1122,7 +1125,9 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
extendedHeaderStream << limitedNodeList->getSessionUUID();
extendedHeaderStream << limitedNodeList->getSessionLocalID();
extendedHeaderStream << node->getUUID();
extendedHeaderStream << node->getLocalID();
extendedHeaderStream << node->getPermissions();
auto domainListPackets = NLPacketList::create(PacketType::DomainList, extendedHeader);
@ -2841,7 +2846,7 @@ void DomainServer::updateReplicationNodes(ReplicationServerDirection direction)
// manually add the replication node to our node list
auto node = nodeList->addOrUpdateNode(QUuid::createUuid(), replicationServer.nodeType,
replicationServer.sockAddr, replicationServer.sockAddr,
false, direction == Upstream);
Node::NULL_LOCAL_ID, false, direction == Upstream);
node->setIsForcedNeverSilent(true);
qDebug() << "Adding" << (direction == Upstream ? "upstream" : "downstream")
@ -3141,13 +3146,12 @@ void DomainServer::processNodeDisconnectRequestPacket(QSharedPointer<ReceivedMes
// This packet has been matched to a source node and they're asking not to be in the domain anymore
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
const QUuid& nodeUUID = message->getSourceID();
qDebug() << "Received a disconnect request from node with UUID" << nodeUUID;
auto localID = message->getSourceID();
qDebug() << "Received a disconnect request from node with local ID" << localID;
// we want to check what type this node was before going to kill it so that we can avoid sending the RemovedNode
// packet to nodes that don't care about this type
auto nodeToKill = limitedNodeList->nodeWithUUID(nodeUUID);
auto nodeToKill = limitedNodeList->nodeWithLocalID(localID);
if (nodeToKill) {
handleKillNode(nodeToKill);
@ -3415,7 +3419,7 @@ void DomainServer::handleDomainContentReplacementFromURLRequest(QSharedPointer<R
}
void DomainServer::handleOctreeFileReplacementRequest(QSharedPointer<ReceivedMessage> message) {
auto node = DependencyManager::get<NodeList>()->nodeWithUUID(message->getSourceID());
auto node = DependencyManager::get<NodeList>()->nodeWithLocalID(message->getSourceID());
if (node->getCanReplaceContent()) {
handleOctreeFileReplacement(message->readAll());
}

View file

@ -71,7 +71,7 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
if (message->getVersion() != versionForPacketType(message->getType())) {
static QMultiMap<QUuid, PacketType> versionDebugSuppressMap;
const QUuid& senderUUID = message->getSourceID();
const QUuid& senderUUID = sendingNode->getUUID();
if (!versionDebugSuppressMap.contains(senderUUID, packetType)) {
qDebug() << "Was stats packet? " << wasStatsPacket;

View file

@ -120,8 +120,8 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
// parse sequence number and track it
quint16 sequence;
message.readPrimitive(&sequence);
SequenceNumberStats::ArrivalInfo arrivalInfo = _incomingSequenceNumberStats.sequenceNumberReceived(sequence,
message.getSourceID());
SequenceNumberStats::ArrivalInfo arrivalInfo =
_incomingSequenceNumberStats.sequenceNumberReceived(sequence, message.getSourceID());
QString codecInPacket = message.readString();
packetReceivedUpdateTimingStats();
@ -186,7 +186,7 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
_mismatchedAudioCodecCount = 0;
// inform others of the mismatch
auto sendingNode = DependencyManager::get<NodeList>()->nodeWithUUID(message.getSourceID());
auto sendingNode = DependencyManager::get<NodeList>()->nodeWithLocalID(message.getSourceID());
if (sendingNode) {
emit mismatchedAudioCodec(sendingNode, _selectedCodecName, codecInPacket);
qDebug(audio) << "Codec mismatch threshold exceeded, SelectedAudioFormat(" << _selectedCodecName << " ) sent";

View file

@ -45,6 +45,9 @@ public:
const QUuid& getUUID() const { return _uuid; }
void setUUID(const QUuid& uuid);
Node::LocalID getLocalID() const { return _localID; }
void setLocalID(Node::LocalID localID) { _localID = localID; }
QString getHostname() const { return _domainURL.host(); }
const QHostAddress& getIP() const { return _sockAddr.getAddress(); }
@ -185,6 +188,7 @@ private:
void hardReset();
QUuid _uuid;
Node::LocalID _localID;
QUrl _domainURL;
HifiSockAddr _sockAddr;
QUuid _assignmentUUID;

View file

@ -132,6 +132,16 @@ void LimitedNodeList::setSessionUUID(const QUuid& sessionUUID) {
}
}
Node::LocalID LimitedNodeList::getSessionLocalID() const {
QReadLocker readLock { &_sessionUUIDLock };
return _sessionLocalID;
}
void LimitedNodeList::setSessionLocalID(Node::LocalID sessionLocalID) {
QWriteLocker lock { &_sessionUUIDLock };
_sessionLocalID = sessionLocalID;
}
void LimitedNodeList::setPermissions(const NodePermissions& newPermissions) {
NodePermissions originalPermissions = _permissions;
@ -230,13 +240,16 @@ bool LimitedNodeList::packetVersionMatch(const udt::Packet& packet) {
senderString = QString("%1:%2").arg(senderSockAddr.getAddress().toString()).arg(senderSockAddr.getPort());
}
} else {
sourceID = NLPacket::sourceIDInHeader(packet);
SharedNodePointer sourceNode = nodeWithLocalID(NLPacket::sourceIDInHeader(packet));
if (sourceNode) {
sourceID = sourceNode->getUUID();
hasBeenOutput = sourcedVersionDebugSuppressMap.contains(sourceID, headerType);
hasBeenOutput = sourcedVersionDebugSuppressMap.contains(sourceID, headerType);
if (!hasBeenOutput) {
sourcedVersionDebugSuppressMap.insert(sourceID, headerType);
senderString = uuidStringWithoutCurlyBraces(sourceID.toString());
if (!hasBeenOutput) {
sourcedVersionDebugSuppressMap.insert(sourceID, headerType);
senderString = uuidStringWithoutCurlyBraces(sourceID.toString());
}
}
}
@ -289,17 +302,20 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
return true;
}
} else {
QUuid sourceID = NLPacket::sourceIDInHeader(packet);
NLPacket::LocalID sourceLocalID = Node::NULL_LOCAL_ID;
// check if we were passed a sourceNode hint or if we need to look it up
if (!sourceNode) {
// figure out which node this is from
SharedNodePointer matchingNode = nodeWithUUID(sourceID);
sourceLocalID = NLPacket::sourceIDInHeader(packet);
SharedNodePointer matchingNode = nodeWithLocalID(sourceLocalID);
sourceNode = matchingNode.data();
}
QUuid sourceID = sourceNode ? sourceNode->getUUID() : QUuid();
if (!sourceNode &&
sourceID == getDomainUUID() &&
sourceLocalID == getDomainLocalID() &&
packet.getSenderSockAddr() == getDomainSockAddr() &&
PacketTypeEnum::getDomainSourcedPackets().contains(headerType)) {
// This is a packet sourced by the domain server
@ -357,7 +373,7 @@ void LimitedNodeList::collectPacketStats(const NLPacket& packet) {
void LimitedNodeList::fillPacketHeader(const NLPacket& packet, HMACAuth* hmacAuth) {
if (!PacketTypeEnum::getNonSourcedPackets().contains(packet.getType())) {
packet.writeSourceID(getSessionUUID());
packet.writeSourceID(getSessionLocalID());
}
if (hmacAuth
@ -541,6 +557,13 @@ SharedNodePointer LimitedNodeList::nodeWithUUID(const QUuid& nodeUUID) {
return it == _nodeHash.cend() ? SharedNodePointer() : it->second;
}
SharedNodePointer LimitedNodeList::nodeWithLocalID(Node::LocalID localID) const {
QReadLocker readLocker(&_nodeMutex);
LocalIDMapping::const_iterator idIter = _localIDMap.find(localID);
return idIter == _localIDMap.cend() ? nullptr : idIter->second;
}
void LimitedNodeList::eraseAllNodes() {
QSet<SharedNodePointer> killedNodes;
@ -549,6 +572,8 @@ void LimitedNodeList::eraseAllNodes() {
// and then remove them from the hash
QWriteLocker writeLocker(&_nodeMutex);
_localIDMap.clear();
if (_nodeHash.size() > 0) {
qCDebug(networking) << "LimitedNodeList::eraseAllNodes() removing all nodes from NodeList.";
@ -624,7 +649,7 @@ void LimitedNodeList::handleNodeKill(const SharedNodePointer& node, ConnectionID
SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType,
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
bool isReplicated, bool isUpstream,
Node::LocalID localID, bool isReplicated, bool isUpstream,
const QUuid& connectionSecret, const NodePermissions& permissions) {
QReadLocker readLocker(&_nodeMutex);
NodeHash::const_iterator it = _nodeHash.find(uuid);
@ -638,6 +663,7 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
matchingNode->setConnectionSecret(connectionSecret);
matchingNode->setIsReplicated(isReplicated);
matchingNode->setIsUpstream(isUpstream || NodeType::isUpstream(nodeType));
matchingNode->setLocalID(localID);
return matchingNode;
} else {
@ -652,6 +678,7 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
newNode->setIsUpstream(isUpstream || NodeType::isUpstream(nodeType));
newNode->setConnectionSecret(connectionSecret);
newNode->setPermissions(permissions);
newNode->setLocalID(localID);
// move the newly constructed node to the LNL thread
newNode->moveToThread(thread());
@ -677,6 +704,7 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
auto oldSoloNode = previousSoloIt->second;
_localIDMap.unsafe_erase(oldSoloNode->getLocalID());
_nodeHash.unsafe_erase(previousSoloIt);
handleNodeKill(oldSoloNode);
@ -692,6 +720,7 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
#else
_nodeHash.emplace(newNode->getUUID(), newNodePointer);
#endif
_localIDMap.emplace(localID, newNodePointer);
readLocker.unlock();
qCDebug(networking) << "Added" << *newNode;
@ -819,6 +848,7 @@ void LimitedNodeList::removeSilentNodes() {
if (!node->isForcedNeverSilent()
&& (usecTimestampNow() - node->getLastHeardMicrostamp()) > (NODE_SILENCE_THRESHOLD_MSECS * USECS_PER_MSEC)) {
// call the NodeHash erase to get rid of this node
_localIDMap.unsafe_erase(node->getLocalID());
it = _nodeHash.unsafe_erase(it);
killedNodes.insert(node);

View file

@ -110,6 +110,8 @@ public:
Q_ENUM(ConnectionStep);
QUuid getSessionUUID() const;
void setSessionUUID(const QUuid& sessionUUID);
Node::LocalID getSessionLocalID() const;
void setSessionLocalID(Node::LocalID localID);
void setPermissions(const NodePermissions& newPermissions);
bool isAllowedEditor() const { return _permissions.can(NodePermissions::Permission::canAdjustLocks); }
@ -130,6 +132,7 @@ public:
virtual bool isDomainServer() const { return true; }
virtual QUuid getDomainUUID() const { assert(false); return QUuid(); }
virtual Node::LocalID getDomainLocalID() const { assert(false); return Node::NULL_LOCAL_ID; }
virtual HifiSockAddr getDomainSockAddr() const { assert(false); return HifiSockAddr(); }
// use sendUnreliablePacket to send an unreliable packet (that you do not need to move)
@ -157,11 +160,12 @@ public:
size_t size() const { QReadLocker readLock(&_nodeMutex); return _nodeHash.size(); }
SharedNodePointer nodeWithUUID(const QUuid& nodeUUID);
SharedNodePointer nodeWithLocalID(Node::LocalID localID) const;
SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType,
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
bool isReplicated = false, bool isUpstream = false,
const QUuid& connectionSecret = QUuid(),
Node::LocalID localID = Node::NULL_LOCAL_ID, bool isReplicated = false,
bool isUpstream = false, const QUuid& connectionSecret = QUuid(),
const NodePermissions& permissions = DEFAULT_AGENT_PERMISSIONS);
static bool parseSTUNResponse(udt::BasePacket* packet, QHostAddress& newPublicAddress, uint16_t& newPublicPort);
@ -430,6 +434,9 @@ private slots:
private:
mutable QReadWriteLock _sessionUUIDLock;
QUuid _sessionUUID;
using LocalIDMapping = tbb::concurrent_unordered_map<Node::LocalID, SharedNodePointer>;
LocalIDMapping _localIDMap;
Node::LocalID _sessionLocalID { 0 };
};
#endif // hifi_LimitedNodeList_h

View file

@ -16,7 +16,7 @@
int NLPacket::localHeaderSize(PacketType type) {
bool nonSourced = PacketTypeEnum::getNonSourcedPackets().contains(type);
bool nonVerified = PacketTypeEnum::getNonVerifiedPackets().contains(type);
qint64 optionalSize = (nonSourced ? 0 : NUM_BYTES_RFC4122_UUID) + ((nonSourced || nonVerified) ? 0 : NUM_BYTES_MD5_HASH);
qint64 optionalSize = (nonSourced ? 0 : NUM_BYTES_LOCALID) + ((nonSourced || nonVerified) ? 0 : NUM_BYTES_MD5_HASH);
return sizeof(PacketType) + sizeof(PacketVersion) + optionalSize;
}
int NLPacket::totalHeaderSize(PacketType type, bool isPartOfMessage) {
@ -141,19 +141,22 @@ PacketVersion NLPacket::versionInHeader(const udt::Packet& packet) {
return *reinterpret_cast<const PacketVersion*>(packet.getData() + headerOffset + sizeof(PacketType));
}
QUuid NLPacket::sourceIDInHeader(const udt::Packet& packet) {
NLPacket::LocalID NLPacket::sourceIDInHeader(const udt::Packet& packet) {
int offset = Packet::totalHeaderSize(packet.isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion);
return QUuid::fromRfc4122(QByteArray::fromRawData(packet.getData() + offset, NUM_BYTES_RFC4122_UUID));
return *reinterpret_cast<const LocalID*>(packet.getData() + offset);
}
QByteArray NLPacket::verificationHashInHeader(const udt::Packet& packet) {
int offset = Packet::totalHeaderSize(packet.isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;
int offset = Packet::totalHeaderSize(packet.isPartOfMessage()) + sizeof(PacketType) +
sizeof(PacketVersion) + NUM_BYTES_LOCALID;
return QByteArray(packet.getData() + offset, NUM_BYTES_MD5_HASH);
}
QByteArray NLPacket::hashForPacketAndHMAC(const udt::Packet& packet, HMACAuth& hash) {
int offset = Packet::totalHeaderSize(packet.isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion)
+ NUM_BYTES_RFC4122_UUID + NUM_BYTES_MD5_HASH;
+ NUM_BYTES_LOCALID + NUM_BYTES_MD5_HASH;
// add the packet payload and the connection UUID
hash.addData(packet.getData() + offset, packet.getDataSize() - offset);
auto hashResult { hash.result() };
return QByteArray((const char*) hashResult.data(), (int) hashResult.size());
@ -199,11 +202,12 @@ void NLPacket::readSourceID() {
}
}
void NLPacket::writeSourceID(const QUuid& sourceID) const {
void NLPacket::writeSourceID(LocalID sourceID) const {
Q_ASSERT(!PacketTypeEnum::getNonSourcedPackets().contains(_type));
auto offset = Packet::totalHeaderSize(isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion);
memcpy(_packet.get() + offset, sourceID.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID);
memcpy(_packet.get() + offset, &sourceID, sizeof(sourceID));
_sourceID = sourceID;
}
@ -213,7 +217,7 @@ void NLPacket::writeVerificationHash(HMACAuth& hmacAuth) const {
!PacketTypeEnum::getNonVerifiedPackets().contains(_type));
auto offset = Packet::totalHeaderSize(isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion)
+ NUM_BYTES_RFC4122_UUID;
+ NUM_BYTES_LOCALID;
QByteArray verificationHash = hashForPacketAndHMAC(*this, hmacAuth);

View file

@ -24,31 +24,29 @@ class NLPacket : public udt::Packet {
Q_OBJECT
public:
//
// | BYTE | BYTE | BYTE | BYTE |
// NLPacket format:
//
// | BYTE | BYTE | BYTE | BYTE |
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Packet Type | Version | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
// | Packet Type | Version | Local Node ID - sourced only |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// | Node UUID - 16 bytes |
// | (ONLY FOR SOURCED PACKETS) |
// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
// | MD5 Verification - 16 bytes |
// | (ONLY FOR VERIFIED PACKETS) |
// | |
// | MD5 Verification - 16 bytes |
// | (ONLY FOR VERIFIED PACKETS) |
// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
// NLPacket Header Format
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
using LocalID = NetworkLocalID;
static const LocalID NULL_LOCAL_ID = 0;
static const int NUM_BYTES_LOCALID = sizeof(LocalID);
// this is used by the Octree classes - must be known at compile time
static const int MAX_PACKET_HEADER_SIZE =
sizeof(udt::Packet::SequenceNumberAndBitField) + sizeof(udt::Packet::MessageNumberAndBitField) +
sizeof(PacketType) + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID + NUM_BYTES_MD5_HASH;
sizeof(PacketType) + sizeof(PacketVersion) + NUM_BYTES_LOCALID + NUM_BYTES_MD5_HASH;
static std::unique_ptr<NLPacket> create(PacketType type, qint64 size = -1,
bool isReliable = false, bool isPartOfMessage = false, PacketVersion version = 0);
@ -71,7 +69,7 @@ public:
static PacketType typeInHeader(const udt::Packet& packet);
static PacketVersion versionInHeader(const udt::Packet& packet);
static QUuid sourceIDInHeader(const udt::Packet& packet);
static LocalID sourceIDInHeader(const udt::Packet& packet);
static QByteArray verificationHashInHeader(const udt::Packet& packet);
static QByteArray hashForPacketAndHMAC(const udt::Packet& packet, HMACAuth& hash);
@ -81,9 +79,9 @@ public:
PacketVersion getVersion() const { return _version; }
void setVersion(PacketVersion version);
const QUuid& getSourceID() const { return _sourceID; }
LocalID getSourceID() const { return _sourceID; }
void writeSourceID(const QUuid& sourceID) const;
void writeSourceID(LocalID sourceID) const;
void writeVerificationHash(HMACAuth& hmacAuth) const;
protected:
@ -108,7 +106,7 @@ protected:
PacketType _type;
PacketVersion _version;
mutable QUuid _sourceID;
mutable LocalID _sourceID;
};
#endif // hifi_NLPacket_h

View file

@ -22,7 +22,7 @@ public:
bool isReliable = false, bool isOrdered = false);
PacketVersion getVersion() const { return _packetVersion; }
const QUuid& getSourceID() const { return _sourceID; }
NLPacket::LocalID getSourceID() const { return _sourceID; }
qint64 getMaxSegmentSize() const override { return NLPacket::maxPayloadSize(_packetType, _isOrdered); }
@ -37,7 +37,7 @@ private:
PacketVersion _packetVersion;
QUuid _sourceID;
NLPacket::LocalID _sourceID;
};
Q_DECLARE_METATYPE(QSharedPointer<NLPacketList>)

View file

@ -23,6 +23,7 @@
#include <Trace.h>
#include "NodeType.h"
const NetworkPeer::LocalID NetworkPeer::NULL_LOCAL_ID;
NetworkPeer::NetworkPeer(QObject* parent) :
QObject(parent),

View file

@ -18,6 +18,7 @@
#include <QtCore/QTimer>
#include <QtCore/QUuid>
#include "UUID.h"
#include "HifiSockAddr.h"
const QString ICE_SERVER_HOSTNAME = "localhost";
@ -39,6 +40,12 @@ public:
const QUuid& getUUID() const { return _uuid; }
void setUUID(const QUuid& uuid) { _uuid = uuid; }
using LocalID = NetworkLocalID;
static const LocalID NULL_LOCAL_ID = 0;
LocalID getLocalID() const { return _localID; }
void setLocalID(LocalID localID) { _localID = localID; }
void softReset();
void reset();
@ -99,6 +106,7 @@ protected:
void setActiveSocket(HifiSockAddr* discoveredSocket);
QUuid _uuid;
LocalID _localID { 0 };
HifiSockAddr _publicSocket;
HifiSockAddr _localSocket;

View file

@ -169,6 +169,7 @@ QDataStream& operator<<(QDataStream& out, const Node& node) {
out << node._localSocket;
out << node._permissions;
out << node._isReplicated;
out << node._localID;
return out;
}
@ -179,6 +180,7 @@ QDataStream& operator>>(QDataStream& in, Node& node) {
in >> node._localSocket;
in >> node._permissions;
in >> node._isReplicated;
in >> node._localID;
return in;
}
@ -189,7 +191,7 @@ QDebug operator<<(QDebug debug, const Node& node) {
} else {
debug.nospace() << " (" << node.getType() << ")";
}
debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " ";
debug << " " << node.getUUID().toString().toLocal8Bit().constData() << "(" << node.getLocalID() << ") ";
debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket();
return debug.nospace();
}

View file

@ -624,13 +624,21 @@ void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message)
return;
}
// pull our owner UUID from the packet, it's always the first thing
Node::LocalID domainLocalID;
packetStream >> domainLocalID;
// pull our owner (ie. session) UUID from the packet, it's always the first thing
// The short (16 bit) ID comes next.
QUuid newUUID;
Node::LocalID newLocalID;
packetStream >> newUUID;
packetStream >> newLocalID;
setSessionLocalID(newLocalID);
setSessionUUID(newUUID);
// if this was the first domain-server list from this domain, we've now connected
if (!_domainHandler.isConnected()) {
_domainHandler.setLocalID(newLocalID);
_domainHandler.setUUID(domainUUID);
_domainHandler.setIsConnected(true);
@ -668,12 +676,14 @@ void NodeList::processDomainServerRemovedNode(QSharedPointer<ReceivedMessage> me
void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) {
// setup variables to read into from QDataStream
qint8 nodeType;
QUuid nodeUUID, connectionUUID;
QUuid nodeUUID, connectionSecretUUID;
HifiSockAddr nodePublicSocket, nodeLocalSocket;
NodePermissions permissions;
bool isReplicated;
Node::LocalID sessionLocalID;
packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> permissions >> isReplicated;
packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> permissions
>> isReplicated >> sessionLocalID;
// if the public socket address is 0 then it's reachable at the same IP
// as the domain server
@ -681,10 +691,10 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) {
nodePublicSocket.setAddress(_domainHandler.getIP());
}
packetStream >> connectionUUID;
packetStream >> connectionSecretUUID;
SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket,
nodeLocalSocket, isReplicated, false, connectionUUID, permissions);
SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket,
sessionLocalID, isReplicated, false, connectionSecretUUID, permissions);
// nodes that are downstream or upstream of our own type are kept alive when we hear about them from the domain server
// and always have their public socket as their active socket

View file

@ -94,6 +94,7 @@ public:
virtual bool isDomainServer() const override { return false; }
virtual QUuid getDomainUUID() const override { return _domainHandler.getUUID(); }
virtual Node::LocalID getDomainLocalID() const override { return _domainHandler.getLocalID(); }
virtual HifiSockAddr getDomainSockAddr() const override { return _domainHandler.getSockAddr(); }
public slots:

View file

@ -261,10 +261,9 @@ void PacketReceiver::handleVerifiedMessage(QSharedPointer<ReceivedMessage> recei
SharedNodePointer matchingNode;
if (!receivedMessage->getSourceID().isNull()) {
matchingNode = nodeList->nodeWithUUID(receivedMessage->getSourceID());
if (receivedMessage->getSourceID() != Node::NULL_LOCAL_ID) {
matchingNode = nodeList->nodeWithLocalID(receivedMessage->getSourceID());
}
QMutexLocker packetListenerLocker(&_packetListenerLock);
auto it = _messageListenerMap.find(receivedMessage->getType());

View file

@ -43,7 +43,7 @@ ReceivedMessage::ReceivedMessage(NLPacket& packet)
}
ReceivedMessage::ReceivedMessage(QByteArray byteArray, PacketType packetType, PacketVersion packetVersion,
const HifiSockAddr& senderSockAddr, QUuid sourceID) :
const HifiSockAddr& senderSockAddr, NLPacket::LocalID sourceID) :
_data(byteArray),
_headData(_data.mid(0, HEAD_DATA_SIZE)),
_numPackets(1),

View file

@ -25,7 +25,7 @@ public:
ReceivedMessage(const NLPacketList& packetList);
ReceivedMessage(NLPacket& packet);
ReceivedMessage(QByteArray byteArray, PacketType packetType, PacketVersion packetVersion,
const HifiSockAddr& senderSockAddr, QUuid sourceID = QUuid());
const HifiSockAddr& senderSockAddr, NLPacket::LocalID sourceID = NLPacket::NULL_LOCAL_ID);
QByteArray getMessage() const { return _data; }
const char* getRawMessage() const { return _data.constData(); }
@ -40,7 +40,7 @@ public:
bool failed() const { return _failed; }
bool isComplete() const { return _isComplete; }
const QUuid& getSourceID() const { return _sourceID; }
NLPacket::LocalID getSourceID() const { return _sourceID; }
const HifiSockAddr& getSenderSockAddr() { return _senderSockAddr; }
qint64 getPosition() const { return _position; }
@ -93,7 +93,7 @@ private:
std::atomic<qint64> _position { 0 };
std::atomic<qint64> _numPackets { 0 };
QUuid _sourceID;
NLPacket::LocalID _sourceID { NLPacket::NULL_LOCAL_ID };
PacketType _packetType;
PacketVersion _packetVersion;
HifiSockAddr _senderSockAddr;

View file

@ -25,7 +25,7 @@ SequenceNumberStats::SequenceNumberStats(int statsHistoryLength, bool canDetectO
: _lastReceivedSequence(0),
_missingSet(),
_stats(),
_lastSenderUUID(),
_lastSenderID(NULL_LOCAL_ID),
_statsHistory(statsHistoryLength),
_lastUnreasonableSequence(0),
_consecutiveUnreasonableOnTime(0)
@ -35,7 +35,7 @@ SequenceNumberStats::SequenceNumberStats(int statsHistoryLength, bool canDetectO
void SequenceNumberStats::reset() {
_missingSet.clear();
_stats = PacketStreamStats();
_lastSenderUUID = QUuid();
_lastSenderID = NULL_LOCAL_ID;
_statsHistory.clear();
_lastUnreasonableSequence = 0;
_consecutiveUnreasonableOnTime = 0;
@ -43,18 +43,18 @@ void SequenceNumberStats::reset() {
static const int UINT16_RANGE = std::numeric_limits<uint16_t>::max() + 1;
SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderUUID, const bool wantExtraDebugging) {
SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(quint16 incoming, NetworkLocalID senderID, const bool wantExtraDebugging) {
SequenceNumberStats::ArrivalInfo arrivalInfo;
// if the sender node has changed, reset all stats
if (senderUUID != _lastSenderUUID) {
if (senderID != _lastSenderID) {
if (_stats._received > 0) {
qCDebug(networking) << "sequence number stats was reset due to new sender node";
qCDebug(networking) << "previous:" << _lastSenderUUID << "current:" << senderUUID;
qCDebug(networking) << "previous:" << _lastSenderID << "current:" << senderID;
reset();
}
_lastSenderUUID = senderUUID;
_lastSenderID = senderID;
}
// determine our expected sequence number... handle rollover appropriately

View file

@ -14,7 +14,7 @@
#include "SharedUtil.h"
#include "RingBufferHistory.h"
#include <quuid.h>
#include "UUID.h"
const int MAX_REASONABLE_SEQUENCE_GAP = 1000;
@ -73,7 +73,7 @@ public:
SequenceNumberStats(int statsHistoryLength = 0, bool canDetectOutOfSync = true);
void reset();
ArrivalInfo sequenceNumberReceived(quint16 incoming, QUuid senderUUID = QUuid(), const bool wantExtraDebugging = false);
ArrivalInfo sequenceNumberReceived(quint16 incoming, NetworkLocalID senderID = NULL_LOCAL_ID, const bool wantExtraDebugging = false);
void pruneMissingSet(const bool wantExtraDebugging = false);
void pushStatsToHistory() { _statsHistory.insert(_stats); }
@ -100,7 +100,8 @@ private:
PacketStreamStats _stats;
QUuid _lastSenderUUID;
NetworkLocalID _lastSenderID;
static const NetworkLocalID NULL_LOCAL_ID = (NetworkLocalID) 0;
RingBufferHistory<PacketStreamStats> _statsHistory;

View file

@ -91,7 +91,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::Ping:
return static_cast<PacketVersion>(PingVersion::IncludeConnectionID);
default:
return 18;
return 19;
}
}

View file

@ -96,7 +96,7 @@ void OctreeProcessor::processDatagram(ReceivedMessage& message, SharedNodePointe
quint64 totalUncompress = 0;
quint64 totalReadBitsteam = 0;
const QUuid& sourceUUID = message.getSourceID();
const QUuid& sourceUUID = sourceNode->getUUID();
int subsection = 1;

View file

@ -15,6 +15,7 @@
#include <QtCore/QUuid>
const int NUM_BYTES_RFC4122_UUID = 16;
using NetworkLocalID = quint16;
QString uuidStringWithoutCurlyBraces(const QUuid& uuid);