have domain-server reject audio and avatar mixers with bad UUID

This commit is contained in:
Stephen Birarda 2013-09-17 16:40:30 -07:00
parent 89546f7140
commit 001432ec55
8 changed files with 106 additions and 71 deletions

View file

@ -129,7 +129,7 @@ void AudioMixer::run() {
// send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed
if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
gettimeofday(&lastDomainServerCheckIn, NULL); gettimeofday(&lastDomainServerCheckIn, NULL);
NodeList::getInstance()->sendDomainServerCheckIn(); NodeList::getInstance()->sendDomainServerCheckIn(this->getUUID().toRfc4122().constData());
if (Logging::shouldSendStats() && numStatCollections > 0) { if (Logging::shouldSendStats() && numStatCollections > 0) {
// if we should be sending stats to Logstash send the appropriate average now // if we should be sending stats to Logstash send the appropriate average now

View file

@ -119,7 +119,7 @@ void AvatarMixer::run() {
// send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed
if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
gettimeofday(&lastDomainServerCheckIn, NULL); gettimeofday(&lastDomainServerCheckIn, NULL);
NodeList::getInstance()->sendDomainServerCheckIn(); NodeList::getInstance()->sendDomainServerCheckIn(this->getUUID().toRfc4122().constData());
} }
if (nodeList->getNodeSocket()->receive(nodeAddress, packetData, &receivedBytes) && if (nodeList->getNodeSocket()->receive(nodeAddress, packetData, &receivedBytes) &&

View file

@ -247,77 +247,105 @@ int main(int argc, const char* argv[]) {
nodePublicAddress.sin_addr.s_addr = 0; nodePublicAddress.sin_addr.s_addr = 0;
} }
Node* newNode = nodeList->addOrUpdateNode((sockaddr*) &nodePublicAddress, bool matchedUUID = true;
(sockaddr*) &nodeLocalAddress,
nodeType,
nodeList->getLastNodeID());
// if addOrUpdateNode returns NULL this was a solo node we already have, don't talk back to it if ((nodeType == NODE_TYPE_AVATAR_MIXER || nodeType == NODE_TYPE_AUDIO_MIXER) &&
if (newNode) { !nodeList->soloNodeOfType(nodeType)) {
if (newNode->getNodeID() == nodeList->getLastNodeID()) { // if this is an audio-mixer or an avatar-mixer and we don't have one yet
nodeList->increaseNodeID(); // we need to check the GUID of the assignment in the queue
// (if it exists) to make sure there is a match
// reset matchedUUID to false so there is no match by default
matchedUUID = false;
// pull the UUID passed with the check in
QUuid checkInUUID = QUuid::fromRfc4122(QByteArray((const char*) packetData + numBytesSenderHeader +
sizeof(NODE_TYPE),
NUM_BYTES_RFC4122_UUID));
// lock the assignment queue
::assignmentQueueMutex.lock();
std::deque<Assignment*>::iterator assignment = ::assignmentQueue.begin();
Assignment::Type matchType = nodeType == NODE_TYPE_AUDIO_MIXER
? Assignment::AudioMixerType : Assignment::AvatarMixerType;
// enumerate the assignments and see if there is a type and UUID match
while (assignment != ::assignmentQueue.end()) {
if ((*assignment)->getType() == matchType
&& (*assignment)->getUUID() == checkInUUID) {
// type and UUID match
matchedUUID = true;
// remove this assignment from the queue
::assignmentQueue.erase(assignment);
break;
} else {
// no match, keep looking
assignment++;
}
} }
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN); // unlock the assignment queue
::assignmentQueueMutex.unlock();
}
if (matchedUUID) {
Node* newNode = nodeList->addOrUpdateNode((sockaddr*) &nodePublicAddress,
(sockaddr*) &nodeLocalAddress,
nodeType,
nodeList->getLastNodeID());
currentBufferPos = broadcastPacket + numHeaderBytes; // if addOrUpdateNode returns NULL this was a solo node we already have, don't talk back to it
startPointer = currentBufferPos; if (newNode) {
if (newNode->getNodeID() == nodeList->getLastNodeID()) {
unsigned char* nodeTypesOfInterest = packetData + numBytesSenderHeader + sizeof(NODE_TYPE) nodeList->increaseNodeID();
+ numBytesSocket + sizeof(unsigned char); }
int numInterestTypes = *(nodeTypesOfInterest - 1);
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN);
if (numInterestTypes > 0) {
// if the node has sent no types of interest, assume they want nothing but their own ID back currentBufferPos = broadcastPacket + numHeaderBytes;
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { startPointer = currentBufferPos;
if (!node->matches((sockaddr*) &nodePublicAddress, (sockaddr*) &nodeLocalAddress, nodeType) &&
memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { int numBytesUUID = (nodeType == NODE_TYPE_AUDIO_MIXER || nodeType == NODE_TYPE_AVATAR_MIXER)
// this is not the node themselves ? NUM_BYTES_RFC4122_UUID
// and this is an node of a type in the passed node types of interest : 0;
// or the node did not pass us any specific types they are interested in
unsigned char* nodeTypesOfInterest = packetData + numBytesSenderHeader + numBytesUUID +
if (memchr(SOLO_NODE_TYPES, node->getType(), sizeof(SOLO_NODE_TYPES)) == NULL) { sizeof(NODE_TYPE) + numBytesSocket + sizeof(unsigned char);
// this is an node of which there can be multiple, just add them to the packet int numInterestTypes = *(nodeTypesOfInterest - 1);
if (numInterestTypes > 0) {
// if the node has sent no types of interest, assume they want nothing but their own ID back
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
if (!node->matches((sockaddr*) &nodePublicAddress, (sockaddr*) &nodeLocalAddress, nodeType) &&
memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) {
// don't send avatar nodes to other avatars, that will come from avatar mixer // don't send avatar nodes to other avatars, that will come from avatar mixer
if (nodeType != NODE_TYPE_AGENT || node->getType() != NODE_TYPE_AGENT) { if (nodeType != NODE_TYPE_AGENT || node->getType() != NODE_TYPE_AGENT) {
currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, &(*node)); currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, &(*node));
} }
} else {
// solo node, we need to only send newest
if (newestSoloNodes[node->getType()] == NULL ||
newestSoloNodes[node->getType()]->getWakeMicrostamp() < node->getWakeMicrostamp()) {
// we have to set the newer solo node to add it to the broadcast later
newestSoloNodes[node->getType()] = &(*node);
}
} }
} }
} }
for (std::map<char, Node *>::iterator soloNode = newestSoloNodes.begin(); // update last receive to now
soloNode != newestSoloNodes.end(); uint64_t timeNow = usecTimestampNow();
soloNode++) { newNode->setLastHeardMicrostamp(timeNow);
// this is the newest alive solo node, add them to the packet
currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, soloNode->second); // add the node ID to the end of the pointer
} currentBufferPos += packNodeId(currentBufferPos, newNode->getNodeID());
// send the constructed list back to this node
nodeList->getNodeSocket()->send((sockaddr*)&replyDestinationSocket,
broadcastPacket,
(currentBufferPos - startPointer) + numHeaderBytes);
} }
// update last receive to now
uint64_t timeNow = usecTimestampNow();
newNode->setLastHeardMicrostamp(timeNow);
if (packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY
&& memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES))) {
newNode->setWakeMicrostamp(timeNow);
}
// add the node ID to the end of the pointer
currentBufferPos += packNodeId(currentBufferPos, newNode->getNodeID());
// send the constructed list back to this node
nodeList->getNodeSocket()->send((sockaddr*)&replyDestinationSocket,
broadcastPacket,
(currentBufferPos - startPointer) + numHeaderBytes);
} }
} else if (packetData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) { } else if (packetData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) {
@ -355,8 +383,8 @@ int main(int argc, const char* argv[]) {
::assignmentQueue.erase(assignment); ::assignmentQueue.erase(assignment);
delete *assignment; delete *assignment;
} }
} else { } else if ((*assignment)->getType() == Assignment::VoxelServerType) {
// remove the assignment from the queue // this is a voxel-server assignment, remove the assignment from the queue
::assignmentQueue.erase(assignment); ::assignmentQueue.erase(assignment);
} }
@ -398,7 +426,8 @@ int main(int argc, const char* argv[]) {
::assignmentQueue.erase(assignment); ::assignmentQueue.erase(assignment);
delete *assignment; delete *assignment;
} }
} else { } else if ((*assignment)->getType() == Assignment::VoxelServerType) {
// this is a voxel server assignment
// remove the assignment from the queue // remove the assignment from the queue
::assignmentQueue.erase(assignment); ::assignmentQueue.erase(assignment);
} }

View file

@ -14,8 +14,6 @@
const char IPv4_ADDRESS_DESIGNATOR = 4; const char IPv4_ADDRESS_DESIGNATOR = 4;
const char IPv6_ADDRESS_DESIGNATOR = 6; const char IPv6_ADDRESS_DESIGNATOR = 6;
const int NUM_BYTES_RFC4122_UUID = 16;
Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assignment::Location location) : Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assignment::Location location) :
_command(command), _command(command),
_type(type), _type(type),

View file

@ -15,6 +15,8 @@
#include "NodeList.h" #include "NodeList.h"
const int NUM_BYTES_RFC4122_UUID = 16;
/// Holds information used for request, creation, and deployment of assignments /// Holds information used for request, creation, and deployment of assignments
class Assignment : public QObject { class Assignment : public QObject {
Q_OBJECT Q_OBJECT

View file

@ -268,7 +268,7 @@ void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNo
_nodeTypesOfInterest[numNodeTypesOfInterest] = '\0'; _nodeTypesOfInterest[numNodeTypesOfInterest] = '\0';
} }
void NodeList::sendDomainServerCheckIn() { void NodeList::sendDomainServerCheckIn(const char* assignmentUUID) {
static bool printedDomainServerIP = false; static bool printedDomainServerIP = false;
// Lookup the IP address of the domain server if we need to // Lookup the IP address of the domain server if we need to
@ -297,9 +297,9 @@ void NodeList::sendDomainServerCheckIn() {
const int IP_ADDRESS_BYTES = 4; const int IP_ADDRESS_BYTES = 4;
// check in packet has header, node type, port, IP, node types of interest, null termination // check in packet has header, optional UUID, node type, port, IP, node types of interest, null termination
int numPacketBytes = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) + sizeof(NODE_TYPE) + sizeof(uint16_t) + int numPacketBytes = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) + sizeof(NODE_TYPE) +
IP_ADDRESS_BYTES + numBytesNodesOfInterest + sizeof(unsigned char); NUM_BYTES_RFC4122_UUID + sizeof(uint16_t) + IP_ADDRESS_BYTES + numBytesNodesOfInterest + sizeof(unsigned char);
checkInPacket = new unsigned char[numPacketBytes]; checkInPacket = new unsigned char[numPacketBytes];
unsigned char* packetPosition = checkInPacket; unsigned char* packetPosition = checkInPacket;
@ -313,7 +313,13 @@ void NodeList::sendDomainServerCheckIn() {
*(packetPosition++) = _ownerType; *(packetPosition++) = _ownerType;
packetPosition += packSocket(checkInPacket + numHeaderBytes + sizeof(NODE_TYPE), if (assignmentUUID) {
// if we've got an assignment UUID to send add that here
memcpy(packetPosition, assignmentUUID, NUM_BYTES_RFC4122_UUID);
packetPosition += NUM_BYTES_RFC4122_UUID;
}
packetPosition += packSocket(checkInPacket + (packetPosition - checkInPacket),
getLocalAddress(), getLocalAddress(),
htons(_nodeSocket.getListeningPort())); htons(_nodeSocket.getListeningPort()));

View file

@ -97,7 +97,7 @@ public:
void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest); void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest);
void sendDomainServerCheckIn(); void sendDomainServerCheckIn(const char* assignmentUUID = NULL);
int processDomainServerList(unsigned char *packetData, size_t dataBytes); int processDomainServerList(unsigned char *packetData, size_t dataBytes);
void setAssignmentServerSocket(sockaddr* serverSocket) { _assignmentServerSocket = serverSocket; } void setAssignmentServerSocket(sockaddr* serverSocket) { _assignmentServerSocket = serverSocket; }

View file

@ -26,7 +26,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
return 1; return 1;
case PACKET_TYPE_VOXEL_STATS: case PACKET_TYPE_VOXEL_STATS:
return 2; return 2;
default: default:
return 0; return 0;
} }