Merge pull request #1930 from birarda/authentication

groundwork for more secure node communication
This commit is contained in:
AndrewMeadows 2014-02-07 14:44:23 -08:00
commit 64efdb2ffb
32 changed files with 385 additions and 324 deletions

View file

@ -830,7 +830,7 @@ void AnimationServer::readPendingDatagrams() {
receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(),
nodeSockAddr.getAddressPointer(), nodeSockAddr.getPortPointer());
if (packetVersionMatch(receivedPacket)) {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
if (packetTypeForPacket(receivedPacket) == PacketTypeJurisdiction) {
int headerBytes = numBytesForPacketHeader(receivedPacket);
// PacketType_JURISDICTION, first byte is the node type...

View file

@ -31,36 +31,43 @@ Agent::Agent(const QByteArray& packet) :
_scriptEngine.getParticlesScriptingInterface()->setPacketSender(&_particleEditSender);
}
void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) {
PacketType datagramPacketType = packetTypeForPacket(dataByteArray);
if (datagramPacketType == PacketTypeJurisdiction) {
int headerBytes = numBytesForPacketHeader(dataByteArray);
QUuid nodeUUID;
SharedNodePointer matchedNode = NodeList::getInstance()->nodeWithUUID(nodeUUID);
if (matchedNode) {
// PacketType_JURISDICTION, first byte is the node type...
switch (dataByteArray[headerBytes]) {
case NodeType::VoxelServer:
_scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode,
dataByteArray);
break;
case NodeType::ParticleServer:
_scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode,
dataByteArray);
break;
void Agent::readPendingDatagrams() {
QByteArray receivedPacket;
HifiSockAddr senderSockAddr;
NodeList* nodeList = NodeList::getInstance();
while (readAvailableDatagram(receivedPacket, senderSockAddr)) {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
PacketType datagramPacketType = packetTypeForPacket(receivedPacket);
if (datagramPacketType == PacketTypeJurisdiction) {
int headerBytes = numBytesForPacketHeader(receivedPacket);
SharedNodePointer matchedNode = nodeList->sendingNodeForPacket(receivedPacket);
if (matchedNode) {
// PacketType_JURISDICTION, first byte is the node type...
switch (receivedPacket[headerBytes]) {
case NodeType::VoxelServer:
_scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode,
receivedPacket);
break;
case NodeType::ParticleServer:
_scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode,
receivedPacket);
break;
}
}
} else if (datagramPacketType == PacketTypeParticleAddResponse) {
// this will keep creatorTokenIDs to IDs mapped correctly
Particle::handleAddParticleResponse(receivedPacket);
// also give our local particle tree a chance to remap any internal locally created particles
_particleTree.handleAddParticleResponse(receivedPacket);
} else {
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket);
}
}
} else if (datagramPacketType == PacketTypeParticleAddResponse) {
// this will keep creatorTokenIDs to IDs mapped correctly
Particle::handleAddParticleResponse(dataByteArray);
// also give our local particle tree a chance to remap any internal locally created particles
_particleTree.handleAddParticleResponse(dataByteArray);
} else {
NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray);
}
}
@ -100,10 +107,6 @@ void Agent::run() {
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
QTimer* pingNodesTimer = new QTimer(this);
connect(pingNodesTimer, SIGNAL(timeout()), nodeList, SLOT(pingInactiveNodes()));
pingNodesTimer->start(PING_INACTIVE_NODE_INTERVAL_USECS / 1000);
// tell our script engine about our local particle tree
_scriptEngine.getParticlesScriptingInterface()->setParticleTree(&_particleTree);

View file

@ -35,7 +35,7 @@ public:
public slots:
void run();
void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);
void readPendingDatagrams();
signals:
void willSendAudioDataCallback();
void willSendVisualDataCallback();

View file

@ -90,8 +90,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS);
// connect our readPendingDatagrams method to the readyRead() signal of the socket
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams,
Qt::QueuedConnection);
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
}
void AssignmentClient::sendAssignmentRequest() {
@ -111,50 +110,45 @@ void AssignmentClient::readPendingDatagrams() {
nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(),
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
if (packetVersionMatch(receivedPacket)) {
if (_currentAssignment) {
// have the threaded current assignment handle this datagram
QMetaObject::invokeMethod(_currentAssignment, "processDatagram", Qt::QueuedConnection,
Q_ARG(QByteArray, receivedPacket),
Q_ARG(HifiSockAddr, senderSockAddr));
} else if (packetTypeForPacket(receivedPacket) == PacketTypeCreateAssignment) {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
if (packetTypeForPacket(receivedPacket) == PacketTypeCreateAssignment) {
// construct the deployed assignment from the packet data
_currentAssignment = AssignmentFactory::unpackAssignment(receivedPacket);
if (_currentAssignment) {
qDebug() << "Dropping received assignment since we are currently running one.";
} else {
// construct the deployed assignment from the packet data
_currentAssignment = AssignmentFactory::unpackAssignment(receivedPacket);
qDebug() << "Received an assignment -" << *_currentAssignment;
if (_currentAssignment) {
qDebug() << "Received an assignment -" << *_currentAssignment;
// switch our nodelist domain IP and port to whoever sent us the assignment
nodeList->setDomainSockAddr(senderSockAddr);
nodeList->setSessionUUID(_currentAssignment->getUUID());
qDebug() << "Destination IP for assignment is" << nodeList->getDomainIP().toString();
// start the deployed assignment
QThread* workerThread = new QThread(this);
connect(workerThread, SIGNAL(started()), _currentAssignment, SLOT(run()));
connect(_currentAssignment, SIGNAL(finished()), this, SLOT(assignmentCompleted()));
connect(_currentAssignment, SIGNAL(finished()), workerThread, SLOT(quit()));
connect(_currentAssignment, SIGNAL(finished()), _currentAssignment, SLOT(deleteLater()));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
_currentAssignment->moveToThread(workerThread);
// move the NodeList to the thread used for the _current assignment
nodeList->moveToThread(workerThread);
// Starts an event loop, and emits workerThread->started()
workerThread->start();
} else {
qDebug() << "Received an assignment that could not be unpacked. Re-requesting.";
}
// switch our nodelist domain IP and port to whoever sent us the assignment
nodeList->setDomainSockAddr(senderSockAddr);
nodeList->setSessionUUID(_currentAssignment->getUUID());
qDebug() << "Destination IP for assignment is" << nodeList->getDomainIP().toString();
// start the deployed assignment
QThread* workerThread = new QThread(this);
connect(workerThread, SIGNAL(started()), _currentAssignment, SLOT(run()));
connect(_currentAssignment, SIGNAL(finished()), this, SLOT(assignmentCompleted()));
connect(_currentAssignment, SIGNAL(finished()), workerThread, SLOT(quit()));
connect(_currentAssignment, SIGNAL(finished()), _currentAssignment, SLOT(deleteLater()));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
_currentAssignment->moveToThread(workerThread);
// move the NodeList to the thread used for the _current assignment
nodeList->moveToThread(workerThread);
// let the assignment handle the incoming datagrams for its duration
disconnect(&nodeList->getNodeSocket(), 0, this, 0);
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, _currentAssignment,
&ThreadedAssignment::readPendingDatagrams);
// Starts an event loop, and emits workerThread->started()
workerThread->start();
} else {
qDebug() << "Received an assignment that could not be unpacked. Re-requesting.";
}
} else {
// have the NodeList attempt to handle it
@ -170,10 +164,14 @@ void AssignmentClient::assignmentCompleted() {
qDebug("Assignment finished or never started - waiting for new assignment.");
_currentAssignment = NULL;
NodeList* nodeList = NodeList::getInstance();
// have us handle incoming NodeList datagrams again
disconnect(&nodeList->getNodeSocket(), 0, _currentAssignment, 0);
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
_currentAssignment = NULL;
// reset our NodeList by switching back to unassigned and clearing the list
nodeList->setOwnerType(NodeType::Unassigned);
nodeList->reset();

View file

@ -207,29 +207,25 @@ void AudioMixer::prepareMixForListeningNode(Node* node) {
}
void AudioMixer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) {
// pull any new audio data from nodes off of the network stack
PacketType mixerPacketType = packetTypeForPacket(dataByteArray);
if (mixerPacketType == PacketTypeMicrophoneAudioNoEcho
|| mixerPacketType == PacketTypeMicrophoneAudioWithEcho
|| mixerPacketType == PacketTypeInjectAudio) {
NodeList* nodeList = NodeList::getInstance();
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(dataByteArray);
if (matchingNode) {
nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, dataByteArray);
if (!matchingNode->getActiveSocket()) {
// we don't have an active socket for this node, but they're talking to us
// this means they've heard from us and can reply, let's assume public is active
matchingNode->activatePublicSocket();
void AudioMixer::readPendingDatagrams() {
QByteArray receivedPacket;
HifiSockAddr senderSockAddr;
NodeList* nodeList = NodeList::getInstance();
while (readAvailableDatagram(receivedPacket, senderSockAddr)) {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
// pull any new audio data from nodes off of the network stack
PacketType mixerPacketType = packetTypeForPacket(receivedPacket);
if (mixerPacketType == PacketTypeMicrophoneAudioNoEcho
|| mixerPacketType == PacketTypeMicrophoneAudioWithEcho
|| mixerPacketType == PacketTypeInjectAudio) {
nodeList->findNodeAndUpdateWithDataFromPacket(receivedPacket);
} else {
// let processNodeData handle it.
nodeList->processNodeData(senderSockAddr, receivedPacket);
}
}
} else {
// let processNodeData handle it.
NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray);
}
}

View file

@ -25,7 +25,7 @@ public slots:
/// threaded run of assignment
void run();
void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);
void readPendingDatagrams();
private:
/// adds one buffer to the mix for a listening node
void addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd,

View file

@ -136,55 +136,52 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
}
}
void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) {
void AvatarMixer::readPendingDatagrams() {
QByteArray receivedPacket;
HifiSockAddr senderSockAddr;
NodeList* nodeList = NodeList::getInstance();
switch (packetTypeForPacket(dataByteArray)) {
case PacketTypeAvatarData: {
// add or update the node in our list
SharedNodePointer avatarNode = nodeList->sendingNodeForPacket(dataByteArray);
if (avatarNode) {
// parse positional data from an node
nodeList->updateNodeWithData(avatarNode.data(), senderSockAddr, dataByteArray);
}
break;
}
case PacketTypeAvatarIdentity: {
// check if we have a matching node in our list
SharedNodePointer avatarNode = nodeList->sendingNodeForPacket(dataByteArray);
if (avatarNode && avatarNode->getLinkedData()) {
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(avatarNode->getLinkedData());
if (nodeData->hasIdentityChangedAfterParsing(dataByteArray)
&& !nodeData->hasSentIdentityBetweenKeyFrames()) {
// this avatar changed their identity in some way and we haven't sent a packet in this keyframe
QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity);
QByteArray individualByteArray = nodeData->identityByteArray();
individualByteArray.replace(0, NUM_BYTES_RFC4122_UUID, avatarNode->getUUID().toRfc4122());
identityPacket.append(individualByteArray);
nodeData->setHasSentIdentityBetweenKeyFrames(true);
nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::Agent);
while (readAvailableDatagram(receivedPacket, senderSockAddr)) {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
switch (packetTypeForPacket(receivedPacket)) {
case PacketTypeAvatarData: {
nodeList->findNodeAndUpdateWithDataFromPacket(receivedPacket);
break;
}
case PacketTypeAvatarIdentity: {
// check if we have a matching node in our list
SharedNodePointer avatarNode = nodeList->sendingNodeForPacket(receivedPacket);
if (avatarNode && avatarNode->getLinkedData()) {
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(avatarNode->getLinkedData());
if (nodeData->hasIdentityChangedAfterParsing(receivedPacket)
&& !nodeData->hasSentIdentityBetweenKeyFrames()) {
// this avatar changed their identity in some way and we haven't sent a packet in this keyframe
QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity);
QByteArray individualByteArray = nodeData->identityByteArray();
individualByteArray.replace(0, NUM_BYTES_RFC4122_UUID, avatarNode->getUUID().toRfc4122());
identityPacket.append(individualByteArray);
nodeData->setHasSentIdentityBetweenKeyFrames(true);
nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::Agent);
}
}
}
case PacketTypeKillAvatar: {
nodeList->processKillNode(receivedPacket);
break;
}
default:
// hand this off to the NodeList
nodeList->processNodeData(senderSockAddr, receivedPacket);
break;
}
}
case PacketTypeKillAvatar: {
nodeList->processKillNode(dataByteArray);
break;
}
default:
// hand this off to the NodeList
nodeList->processNodeData(senderSockAddr, dataByteArray);
break;
}
}
const qint64 AVATAR_IDENTITY_KEYFRAME_MSECS = 5000;

View file

@ -23,7 +23,7 @@ public slots:
void nodeAdded(SharedNodePointer nodeAdded);
void nodeKilled(SharedNodePointer killedNode);
void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);
void readPendingDatagrams();
};
#endif /* defined(__hifi__AvatarMixer__) */

View file

@ -41,15 +41,27 @@ void MetavoxelServer::run() {
_sendTimer.start(SEND_INTERVAL);
}
void MetavoxelServer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) {
switch (dataByteArray.at(0)) {
case PacketTypeMetavoxelData:
processData(dataByteArray, senderSockAddr);
break;
default:
NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray);
break;
void MetavoxelServer::readPendingDatagrams() {
QByteArray receivedPacket;
HifiSockAddr senderSockAddr;
NodeList* nodeList = NodeList::getInstance();
while (readAvailableDatagram(receivedPacket, senderSockAddr)) {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
switch (packetTypeForPacket(receivedPacket)) {
case PacketTypeMetavoxelData: {
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket);
if (matchingNode) {
processData(receivedPacket, matchingNode);
}
break;
}
default:
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket);
break;
}
}
}
}
@ -67,10 +79,10 @@ void MetavoxelServer::sendDeltas() {
_sendTimer.start(qMax(0, 2 * SEND_INTERVAL - elapsed));
}
void MetavoxelServer::processData(const QByteArray& data, const HifiSockAddr& sender) {
void MetavoxelServer::processData(const QByteArray& data, const SharedNodePointer& sendingNode) {
// read the session id
int headerPlusIDSize;
QUuid sessionID = readSessionID(data, sender, headerPlusIDSize);
QUuid sessionID = readSessionID(data, sendingNode, headerPlusIDSize);
if (sessionID.isNull()) {
return;
}
@ -78,18 +90,19 @@ void MetavoxelServer::processData(const QByteArray& data, const HifiSockAddr& se
// forward to session, creating if necessary
MetavoxelSession*& session = _sessions[sessionID];
if (!session) {
session = new MetavoxelSession(this, sessionID, QByteArray::fromRawData(data.constData(), headerPlusIDSize), sender);
session = new MetavoxelSession(this, sessionID, QByteArray::fromRawData(data.constData(), headerPlusIDSize),
sendingNode);
}
session->receivedData(data, sender);
session->receivedData(data, sendingNode);
}
MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId,
const QByteArray& datagramHeader, const HifiSockAddr& sender) :
const QByteArray& datagramHeader, const SharedNodePointer& sendingNode) :
QObject(server),
_server(server),
_sessionId(sessionId),
_sequencer(datagramHeader),
_sender(sender) {
_sendingNode(sendingNode) {
const int TIMEOUT_INTERVAL = 30 * 1000;
_timeoutTimer.setInterval(TIMEOUT_INTERVAL);
@ -105,15 +118,15 @@ MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& session
SendRecord record = { 0 };
_sendRecords.append(record);
qDebug() << "Opened session [sessionId=" << _sessionId << ", sender=" << _sender << "]";
qDebug() << "Opened session [sessionId=" << _sessionId << ", sendingNode=" << sendingNode << "]";
}
void MetavoxelSession::receivedData(const QByteArray& data, const HifiSockAddr& sender) {
void MetavoxelSession::receivedData(const QByteArray& data, const SharedNodePointer& sendingNode) {
// reset the timeout timer
_timeoutTimer.start();
// save the most recent sender
_sender = sender;
_sendingNode = sendingNode;
// process through sequencer
_sequencer.receivedDatagram(data);
@ -131,12 +144,12 @@ void MetavoxelSession::sendDelta() {
}
void MetavoxelSession::timedOut() {
qDebug() << "Session timed out [sessionId=" << _sessionId << ", sender=" << _sender << "]";
qDebug() << "Session timed out [sessionId=" << _sessionId << ", sendingNode=" << _sendingNode << "]";
_server->removeSession(_sessionId);
}
void MetavoxelSession::sendData(const QByteArray& data) {
NodeList::getInstance()->getNodeSocket().writeDatagram(data, _sender.getAddress(), _sender.getPort());
NodeList::getInstance()->writeDatagram(data, _sendingNode);
}
void MetavoxelSession::readPacket(Bitstream& in) {
@ -152,7 +165,7 @@ void MetavoxelSession::clearSendRecordsBefore(int index) {
void MetavoxelSession::handleMessage(const QVariant& message) {
int userType = message.userType();
if (userType == CloseSessionMessage::Type) {
qDebug() << "Session closed [sessionId=" << _sessionId << ", sender=" << _sender << "]";
qDebug() << "Session closed [sessionId=" << _sessionId << ", sendingNode=" << _sendingNode << "]";
_server->removeSession(_sessionId);
} else if (userType == ClientStateMessage::Type) {

View file

@ -39,7 +39,7 @@ public:
virtual void run();
virtual void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);
virtual void readPendingDatagrams();
private slots:
@ -47,7 +47,7 @@ private slots:
private:
void processData(const QByteArray& data, const HifiSockAddr& sender);
void processData(const QByteArray& data, const SharedNodePointer& sendingNode);
QTimer _sendTimer;
qint64 _lastSend;
@ -64,9 +64,9 @@ class MetavoxelSession : public QObject {
public:
MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId,
const QByteArray& datagramHeader, const HifiSockAddr& sender);
const QByteArray& datagramHeader, const SharedNodePointer& sendingNode);
void receivedData(const QByteArray& data, const HifiSockAddr& sender);
void receivedData(const QByteArray& data, const SharedNodePointer& sendingNode);
void sendDelta();
@ -96,7 +96,7 @@ private:
QTimer _timeoutTimer;
DatagramSequencer _sequencer;
HifiSockAddr _sender;
SharedNodePointer _sendingNode;
glm::vec3 _position;

View file

@ -458,42 +458,43 @@ void OctreeServer::parsePayload() {
}
}
void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) {
NodeList* nodeList = NodeList::getInstance();
PacketType packetType = packetTypeForPacket(dataByteArray);
void OctreeServer::readPendingDatagrams() {
QByteArray receivedPacket;
HifiSockAddr senderSockAddr;
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(dataByteArray);
if (packetType == getMyQueryMessageType()) {
bool debug = false;
if (debug) {
qDebug() << "Got PacketType_VOXEL_QUERY at" << usecTimestampNow();
}
// If we got a PacketType_VOXEL_QUERY, then we're talking to an NodeType_t_AVATAR, and we
// need to make sure we have it in our nodeList.
if (matchingNode) {
nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, dataByteArray);
if (!matchingNode->getActiveSocket()) {
// we don't have an active socket for this node, but they're talking to us
// this means they've heard from us and can reply, let's assume public is active
matchingNode->activatePublicSocket();
}
OctreeQueryNode* nodeData = (OctreeQueryNode*) matchingNode->getLinkedData();
if (nodeData && !nodeData->isOctreeSendThreadInitalized()) {
nodeData->initializeOctreeSendThread(this, matchingNode->getUUID());
NodeList* nodeList = NodeList::getInstance();
while (readAvailableDatagram(receivedPacket, senderSockAddr)) {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
PacketType packetType = packetTypeForPacket(receivedPacket);
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket);
if (packetType == getMyQueryMessageType()) {
bool debug = false;
if (debug) {
qDebug() << "Got PacketTypeVoxelQuery at" << usecTimestampNow();
}
// If we got a PacketType_VOXEL_QUERY, then we're talking to an NodeType_t_AVATAR, and we
// need to make sure we have it in our nodeList.
if (matchingNode) {
nodeList->updateNodeWithDataFromPacket(matchingNode, receivedPacket);
OctreeQueryNode* nodeData = (OctreeQueryNode*) matchingNode->getLinkedData();
if (nodeData && !nodeData->isOctreeSendThreadInitalized()) {
nodeData->initializeOctreeSendThread(this, matchingNode->getUUID());
}
}
} else if (packetType == PacketTypeJurisdictionRequest) {
_jurisdictionSender->queueReceivedPacket(matchingNode, receivedPacket);
} else if (_octreeInboundPacketProcessor && getOctree()->handlesEditPacketType(packetType)) {
_octreeInboundPacketProcessor->queueReceivedPacket(matchingNode, receivedPacket);
} else {
// let processNodeData handle it.
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket);
}
}
} else if (packetType == PacketTypeJurisdictionRequest) {
_jurisdictionSender->queueReceivedPacket(matchingNode, dataByteArray);
} else if (_octreeInboundPacketProcessor && getOctree()->handlesEditPacketType(packetType)) {
_octreeInboundPacketProcessor->queueReceivedPacket(matchingNode, dataByteArray);
} else {
// let processNodeData handle it.
NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray);
}
}
@ -654,8 +655,4 @@ void OctreeServer::run() {
QTimer* silentNodeTimer = new QTimer(this);
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
QTimer* pingNodesTimer = new QTimer(this);
connect(pingNodesTimer, SIGNAL(timeout()), nodeList, SLOT(pingInactiveNodes()));
pingNodesTimer->start(PING_INACTIVE_NODE_INTERVAL_USECS / 1000);
}

View file

@ -67,7 +67,7 @@ public:
public slots:
/// runs the voxel server assignment
void run();
void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);
void readPendingDatagrams();
protected:
void parsePayload();

View file

@ -66,7 +66,7 @@ void DataServer::readPendingDatagrams() {
PacketType requestType = packetTypeForPacket(receivedPacket);
if ((requestType == PacketTypeDataServerPut || requestType == PacketTypeDataServerGet) &&
packetVersionMatch(receivedPacket)) {
receivedPacket[numBytesArithmeticCodingFromBuffer(receivedPacket.data())] == versionForPacketType(requestType)) {
QDataStream packetStream(receivedPacket);
int numReceivedHeaderBytes = numBytesForPacketHeader(receivedPacket);

View file

@ -236,7 +236,7 @@ void DomainServer::readAvailableDatagrams() {
nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(),
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
if (packetVersionMatch(receivedPacket)) {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
PacketType requestType = packetTypeForPacket(receivedPacket);
if (requestType == PacketTypeDomainListRequest) {

View file

@ -388,7 +388,7 @@ void Audio::handleAudioInput() {
NodeList* nodeList = NodeList::getInstance();
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer)) {
if (audioMixer && audioMixer->getActiveSocket()) {
MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar();
glm::vec3 headPosition = interfaceAvatar->getHead().getPosition();
glm::quat headOrientation = interfaceAvatar->getHead().getOrientation();

View file

@ -40,7 +40,7 @@ void DatagramProcessor::processDatagrams() {
_packetCount++;
_byteCount += incomingPacket.size();
if (packetVersionMatch(incomingPacket)) {
if (nodeList->packetVersionAndHashMatch(incomingPacket)) {
// only process this packet if we have a match on the packet version
switch (packetTypeForPacket(incomingPacket)) {
case PacketTypeTransmitterData:
@ -121,7 +121,7 @@ void DatagramProcessor::processDatagrams() {
DataServerClient::processMessageFromDataServer(incomingPacket);
break;
default:
NodeList::getInstance()->processNodeData(senderSockAddr, incomingPacket);
nodeList->processNodeData(senderSockAddr, incomingPacket);
break;
}
}

View file

@ -144,9 +144,9 @@ void MetavoxelSystem::removeClient(const QUuid& uuid) {
delete client;
}
void MetavoxelSystem::receivedData(const QByteArray& data, const HifiSockAddr& sender) {
void MetavoxelSystem::receivedData(const QByteArray& data, const SharedNodePointer& sendingNode) {
int headerPlusIDSize;
QUuid sessionID = readSessionID(data, sender, headerPlusIDSize);
QUuid sessionID = readSessionID(data, sendingNode, headerPlusIDSize);
if (sessionID.isNull()) {
return;
}

View file

@ -52,7 +52,7 @@ private:
Q_INVOKABLE void addClient(const SharedNodePointer& node);
Q_INVOKABLE void removeClient(const QUuid& uuid);
Q_INVOKABLE void receivedData(const QByteArray& data, const HifiSockAddr& sender);
Q_INVOKABLE void receivedData(const QByteArray& data, const SharedNodePointer& sendingNode);
class Point {
public:

View file

@ -48,7 +48,7 @@ void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, c
wasStatsPacket = true;
if (messageLength > statsMessageLength) {
mutablePacket = mutablePacket.mid(statsMessageLength);
if (!packetVersionMatch(packet)) {
if (!NodeList::getInstance()->packetVersionAndHashMatch(packet)) {
return; // bail since piggyback data doesn't match our versioning
}
} else {

View file

@ -265,7 +265,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t serv
std::stringstream extraDetails("");
std::stringstream linkDetails("");
if (nodeList->getNodeActiveSocketOrPing(node)) {
if (node->getActiveSocket()) {
serverDetails << "active ";
} else {
serverDetails << "inactive ";

View file

@ -106,7 +106,7 @@ static QItemEditorCreatorBase* qColorEditorCreator = createQColorEditorCreator()
static QItemEditorCreatorBase* vec3EditorCreator = createVec3EditorCreator();
static QItemEditorCreatorBase* parameterizedURLEditorCreator = createParameterizedURLEditorCreator();
QUuid readSessionID(const QByteArray& data, const HifiSockAddr& sender, int& headerPlusIDSize) {
QUuid readSessionID(const QByteArray& data, const SharedNodePointer& sendingNode, int& headerPlusIDSize) {
// get the header size
int headerSize = numBytesForPacketHeader(data);
@ -114,7 +114,7 @@ QUuid readSessionID(const QByteArray& data, const HifiSockAddr& sender, int& hea
const int UUID_BYTES = 16;
headerPlusIDSize = headerSize + UUID_BYTES;
if (data.size() < headerPlusIDSize) {
qWarning() << "Metavoxel data too short [size=" << data.size() << ", sender=" << sender << "]\n";
qWarning() << "Metavoxel data too short [size=" << data.size() << ", sendingNode=" << sendingNode << "]\n";
return QUuid();
}
return QUuid::fromRfc4122(QByteArray::fromRawData(data.constData() + headerSize, UUID_BYTES));

View file

@ -15,6 +15,7 @@
#include <QUuid>
#include <QWidget>
#include <NodeList.h>
#include <RegisteredMetaTypes.h>
#include "Bitstream.h"
@ -30,7 +31,7 @@ class NetworkProgram;
/// Reads and returns the session ID from a datagram.
/// \param[out] headerPlusIDSize the size of the header (including the session ID) within the data
/// \return the session ID, or a null ID if invalid (in which case a warning will be logged)
QUuid readSessionID(const QByteArray& data, const HifiSockAddr& sender, int& headerPlusIDSize);
QUuid readSessionID(const QByteArray& data, const SharedNodePointer& sendingNode, int& headerPlusIDSize);
/// A streamable axis-aligned bounding box.
class Box {

View file

@ -45,7 +45,7 @@ bool JurisdictionListener::queueJurisdictionRequest() {
NodeList* nodeList = NodeList::getInstance();
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
if (nodeList->getNodeActiveSocketOrPing(node) && node->getType() == getNodeType()) {
if (node->getType() == getNodeType() && node->getActiveSocket()) {
_packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast<char*>(bufferOut), sizeOut));
nodeCount++;
}

View file

@ -60,19 +60,17 @@ bool OctreeEditPacketSender::serversExist() const {
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
// only send to the NodeTypes that are getMyNodeType()
if (node->getType() == getMyNodeType()) {
if (nodeList->getNodeActiveSocketOrPing(node)) {
QUuid nodeUUID = node->getUUID();
// If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server
if (_serverJurisdictions) {
// lookup our nodeUUID in the jurisdiction map, if it's missing then we're
// missing at least one jurisdiction
if ((*_serverJurisdictions).find(nodeUUID) == (*_serverJurisdictions).end()) {
atLeastOnJurisdictionMissing = true;
}
if (node->getType() == getMyNodeType() && node->getActiveSocket()) {
QUuid nodeUUID = node->getUUID();
// If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server
if (_serverJurisdictions) {
// lookup our nodeUUID in the jurisdiction map, if it's missing then we're
// missing at least one jurisdiction
if ((*_serverJurisdictions).find(nodeUUID) == (*_serverJurisdictions).end()) {
atLeastOnJurisdictionMissing = true;
}
hasServers = true;
}
hasServers = true;
}
if (atLeastOnJurisdictionMissing) {
break; // no point in looking further...
@ -91,7 +89,7 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c
// only send to the NodeTypes that are getMyNodeType()
if (node->getType() == getMyNodeType() &&
((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) {
if (nodeList->getNodeActiveSocketOrPing(node)) {
if (node->getActiveSocket()) {
queuePacketForSending(node, QByteArray(reinterpret_cast<char*>(buffer), length));
// debugging output...

View file

@ -21,7 +21,7 @@ quint8 DataServerClient::_sequenceNumber = 0;
const char MULTI_KEY_VALUE_SEPARATOR = '|';
const char DATA_SERVER_HOSTNAME[] = "data.highfidelity.io";
const char DATA_SERVER_HOSTNAME[] = "localhost";
const unsigned short DATA_SERVER_PORT = 3282;
const HifiSockAddr& DataServerClient::dataServerSockAddr() {

View file

@ -45,8 +45,6 @@ HifiSockAddr::HifiSockAddr(const QString& hostname, quint16 hostOrderPort) {
}
HifiSockAddr& HifiSockAddr::operator=(const HifiSockAddr& rhsSockAddr) {
//HifiSockAddr temp(rhsSockAddr);
//swap(temp);
_address = rhsSockAddr._address;
_port = rhsSockAddr._port;

View file

@ -80,30 +80,71 @@ NodeList::~NodeList() {
clear();
}
qint64 NodeList::writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
const HifiSockAddr& overridenSockAddr) {
bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) {
// currently this just checks if the version in the packet matches our return from versionForPacketType
// may need to be expanded in the future for types and versions that take > than 1 byte
// setup the MD5 hash for source verification in the header
int numBytesPacketHeader = numBytesForPacketHeader(datagram);
QByteArray dataSecretHash = QCryptographicHash::hash(datagram.mid(numBytesPacketHeader)
+ destinationNode->getConnectionSecret().toRfc4122(),
QCryptographicHash::Md5);
QByteArray datagramWithHash = datagram;
datagramWithHash.replace(numBytesPacketHeader - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH, dataSecretHash);
// if we don't have an ovveriden address, assume they want to send to the node's active socket
const HifiSockAddr* destinationSockAddr = &overridenSockAddr;
if (overridenSockAddr.isNull()) {
if (getNodeActiveSocketOrPing(destinationNode)) {
// use the node's active socket as the destination socket
destinationSockAddr = destinationNode->getActiveSocket();
} else {
// we don't have a socket to send to, return 0
return 0;
}
if (packet[1] != versionForPacketType(packetTypeForPacket(packet))
&& packetTypeForPacket(packet) != PacketTypeStunResponse) {
PacketType mismatchType = packetTypeForPacket(packet);
int numPacketTypeBytes = arithmeticCodingValueFromBuffer(packet.data());
qDebug() << "Packet version mismatch on" << packetTypeForPacket(packet) << "- Sender"
<< uuidFromPacketHeader(packet) << "sent" << qPrintable(QString::number(packet[numPacketTypeBytes])) << "but"
<< qPrintable(QString::number(versionForPacketType(mismatchType))) << "expected.";
}
return _nodeSocket.writeDatagram(datagramWithHash, destinationSockAddr->getAddress(), destinationSockAddr->getPort());
const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>() << PacketTypeDomainList
<< PacketTypeDomainListRequest << PacketTypeStunResponse << PacketTypeDataServerConfirm
<< PacketTypeDataServerGet << PacketTypeDataServerPut << PacketTypeDataServerSend
<< PacketTypeCreateAssignment << PacketTypeRequestAssignment;
if (!NON_VERIFIED_PACKETS.contains(packetTypeForPacket(packet))) {
// figure out which node this is from
SharedNodePointer sendingNode = sendingNodeForPacket(packet);
if (sendingNode) {
// check if the md5 hash in the header matches the hash we would expect
if (hashFromPacketHeader(packet) == hashForPacketAndConnectionUUID(packet, sendingNode->getConnectionSecret())) {
return true;
} else {
qDebug() << "Packet hash mismatch on" << packetTypeForPacket(packet) << "- Sender"
<< uuidFromPacketHeader(packet);
}
} else {
qDebug() << "Packet of type" << packetTypeForPacket(packet) << "received from unknown node with UUID"
<< uuidFromPacketHeader(packet);
}
} else {
return true;
}
return false;
}
qint64 NodeList::writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
const HifiSockAddr& overridenSockAddr) {
if (destinationNode) {
// if we don't have an ovveriden address, assume they want to send to the node's active socket
const HifiSockAddr* destinationSockAddr = &overridenSockAddr;
if (overridenSockAddr.isNull()) {
if (destinationNode->getActiveSocket()) {
// use the node's active socket as the destination socket
destinationSockAddr = destinationNode->getActiveSocket();
} else {
// we don't have a socket to send to, return 0
return 0;
}
}
QByteArray datagramCopy = datagram;
// setup the MD5 hash for source verification in the header
replaceHashInPacketGivenConnectionUUID(datagramCopy, destinationNode->getConnectionSecret());
return _nodeSocket.writeDatagram(datagramCopy, destinationSockAddr->getAddress(), destinationSockAddr->getPort());
}
// didn't have a destinationNode to send to, return 0
return 0;
}
qint64 NodeList::writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode,
@ -191,8 +232,12 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
}
case PacketTypePing: {
// send back a reply
QByteArray replyPacket = constructPingReplyPacket(packet);
writeDatagram(replyPacket, sendingNodeForPacket(packet), senderSockAddr);
SharedNodePointer matchingNode = sendingNodeForPacket(packet);
if (matchingNode) {
QByteArray replyPacket = constructPingReplyPacket(packet);
writeDatagram(replyPacket, matchingNode, senderSockAddr);
}
break;
}
case PacketTypePingReply: {
@ -219,32 +264,28 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
}
}
int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, const QByteArray& packet) {
QMutexLocker locker(&node->getMutex());
node->setLastHeardMicrostamp(usecTimestampNow());
if (!senderSockAddr.isNull() && !node->getActiveSocket()) {
if (senderSockAddr == node->getPublicSocket()) {
node->activatePublicSocket();
} else if (senderSockAddr == node->getLocalSocket()) {
node->activateLocalSocket();
}
int NodeList::updateNodeWithDataFromPacket(const SharedNodePointer& matchingNode, const QByteArray &packet) {
QMutexLocker locker(&matchingNode->getMutex());
matchingNode->setLastHeardMicrostamp(usecTimestampNow());
matchingNode->recordBytesReceived(packet.size());
if (!matchingNode->getLinkedData() && linkedDataCreateCallback) {
linkedDataCreateCallback(matchingNode.data());
}
return matchingNode->getLinkedData()->parseData(packet);
}
if (node->getActiveSocket() || senderSockAddr.isNull()) {
node->recordBytesReceived(packet.size());
if (!node->getLinkedData() && linkedDataCreateCallback) {
linkedDataCreateCallback(node);
}
int numParsedBytes = node->getLinkedData()->parseData(packet);
return numParsedBytes;
} else {
// we weren't able to match the sender address to the address we have for this node, unlock and don't parse
return 0;
int NodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packet) {
SharedNodePointer matchingNode = sendingNodeForPacket(packet);
if (matchingNode) {
updateNodeWithDataFromPacket(matchingNode, packet);
}
// we weren't able to match the sender address to the address we have for this node, unlock and don't parse
return 0;
}
SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) {
@ -566,6 +607,10 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
packetStream >> connectionUUID;
node->setConnectionSecret(connectionUUID);
}
// ping inactive nodes in conjunction with receipt of list from domain-server
// this makes it happen every second and also pings any newly added nodes
pingInactiveNodes();
return readNodes;
}
@ -639,9 +684,9 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType,
// we didn't have this node, so add them
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket);
SharedNodePointer newNodeSharedPointer(newNode, &QObject::deleteLater);
_nodeHash.insert(newNode->getUUID(), newNodeSharedPointer);
_nodeHashMutex.unlock();
qDebug() << "Added" << *newNode;
@ -700,16 +745,6 @@ void NodeList::pingInactiveNodes() {
}
}
const HifiSockAddr* NodeList::getNodeActiveSocketOrPing(const SharedNodePointer& node) {
if (node && node->getActiveSocket()) {
return node->getActiveSocket();
} else if (node) {
pingPublicAndLocalSocketsForInactiveNode(node);
}
return NULL;
}
void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode) {
// deconstruct this ping packet to see if it is a public or local reply
QDataStream packetStream(packet);
@ -720,9 +755,9 @@ void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, con
// if this is a local or public ping then we can activate a socket
// we do nothing with agnostic pings, those are simply for timing
if (pingType == PingType::Local) {
if (pingType == PingType::Local && sendingNode->getActiveSocket() != &sendingNode->getLocalSocket()) {
sendingNode->activateLocalSocket();
} else if (pingType == PingType::Public) {
} else if (pingType == PingType::Public && !sendingNode->getActiveSocket()) {
sendingNode->activatePublicSocket();
}
}

View file

@ -82,6 +82,8 @@ public:
QUdpSocket& getNodeSocket() { return _nodeSocket; }
bool packetVersionAndHashMatch(const QByteArray& packet);
qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
const HifiSockAddr& overridenSockAddr = HifiSockAddr());
qint64 writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode,
@ -112,20 +114,20 @@ public:
SharedNodePointer nodeWithUUID(const QUuid& nodeUUID);
SharedNodePointer sendingNodeForPacket(const QByteArray& packet);
SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket);
SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType,
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket);
void processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet);
void processKillNode(const QByteArray& datagram);
int updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, const QByteArray& packet);
int updateNodeWithDataFromPacket(const SharedNodePointer& matchingNode, const QByteArray& packet);
int findNodeAndUpdateWithDataFromPacket(const QByteArray& packet);
unsigned broadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes);
SharedNodePointer soloNodeOfType(char nodeType);
void loadData(QSettings* settings);
void saveData(QSettings* settings);
const HifiSockAddr* getNodeActiveSocketOrPing(const SharedNodePointer& node);
public slots:
void sendDomainServerCheckIn();
void pingInactiveNodes();

View file

@ -46,6 +46,17 @@ PacketVersion versionForPacketType(PacketType type) {
switch (type) {
case PacketTypeParticleData:
return 1;
case PacketTypeDomainList:
case PacketTypeDomainListRequest:
return 1;
case PacketTypeCreateAssignment:
case PacketTypeRequestAssignment:
return 1;
case PacketTypeDataServerGet:
case PacketTypeDataServerPut:
case PacketTypeDataServerConfirm:
case PacketTypeDataServerSend:
return 1;
default:
return 0;
}
@ -85,26 +96,6 @@ int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionU
return position - packet;
}
bool packetVersionMatch(const QByteArray& packet) {
// currently this just checks if the version in the packet matches our return from versionForPacketType
// may need to be expanded in the future for types and versions that take > than 1 byte
if (packet[1] == versionForPacketType(packetTypeForPacket(packet)) || packetTypeForPacket(packet) == PacketTypeStunResponse) {
return true;
} else {
PacketType mismatchType = packetTypeForPacket(packet);
int numPacketTypeBytes = arithmeticCodingValueFromBuffer(packet.data());
QUuid nodeUUID = uuidFromPacketHeader(packet);
qDebug() << "Packet mismatch on" << packetTypeForPacket(packet) << "- Sender"
<< nodeUUID << "sent" << qPrintable(QString::number(packet[numPacketTypeBytes])) << "but"
<< qPrintable(QString::number(versionForPacketType(mismatchType))) << "expected.";
return false;
}
}
int numBytesForPacketHeader(const QByteArray& packet) {
// returns the number of bytes used for the type, version, and UUID
return numBytesArithmeticCodingFromBuffer(packet.data()) + NUM_STATIC_HEADER_BYTES;
@ -124,6 +115,20 @@ QUuid uuidFromPacketHeader(const QByteArray& packet) {
NUM_BYTES_RFC4122_UUID));
}
QByteArray hashFromPacketHeader(const QByteArray& packet) {
return packet.mid(numBytesForPacketHeader(packet) - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH);
}
QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID) {
return QCryptographicHash::hash(packet.mid(numBytesForPacketHeader(packet)) + connectionUUID.toRfc4122(),
QCryptographicHash::Md5);
}
void replaceHashInPacketGivenConnectionUUID(QByteArray& packet, const QUuid& connectionUUID) {
packet.replace(numBytesForPacketHeader(packet) - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH,
hashForPacketAndConnectionUUID(packet, connectionUUID));
}
PacketType packetTypeForPacket(const QByteArray& packet) {
return (PacketType) arithmeticCodingValueFromBuffer(packet.data());
}

View file

@ -70,17 +70,20 @@ QByteArray byteArrayWithPopluatedHeader(PacketType type, const QUuid& connection
int populatePacketHeader(QByteArray& packet, PacketType type, const QUuid& connectionUUID = nullUUID);
int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionUUID = nullUUID);
bool packetVersionMatch(const QByteArray& packet);
int numBytesForPacketHeader(const QByteArray& packet);
int numBytesForPacketHeader(const char* packet);
int numBytesForPacketHeaderGivenPacketType(PacketType type);
QUuid uuidFromPacketHeader(const QByteArray& packet);
QByteArray hashFromPacketHeader(const QByteArray& packet);
QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID);
void replaceHashInPacketGivenConnectionUUID(QByteArray& packet, const QUuid& connectionUUID);
PacketType packetTypeForPacket(const QByteArray& packet);
PacketType packetTypeForPacket(const char* packet);
int arithmeticCodingValueFromBuffer(const char* checkValue);
int numBytesArithmeticCodingFromBuffer(const char* checkValue);
#endif

View file

@ -60,3 +60,16 @@ void ThreadedAssignment::checkInWithDomainServerOrExit() {
NodeList::getInstance()->sendDomainServerCheckIn();
}
}
bool ThreadedAssignment::readAvailableDatagram(QByteArray& destinationByteArray, HifiSockAddr& senderSockAddr) {
NodeList* nodeList = NodeList::getInstance();
if (nodeList->getNodeSocket().hasPendingDatagrams()) {
destinationByteArray.resize(nodeList->getNodeSocket().pendingDatagramSize());
nodeList->getNodeSocket().readDatagram(destinationByteArray.data(), destinationByteArray.size(),
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
return true;
} else {
return false;
}
}

View file

@ -23,8 +23,10 @@ public slots:
virtual void deleteLater();
virtual void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) = 0;
virtual void readPendingDatagrams() = 0;
protected:
bool readAvailableDatagram(QByteArray& destinationByteArray, HifiSockAddr& senderSockAddr);
void commonInit(const char* targetName, NodeType_t nodeType);
bool _isFinished;
private slots: