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
if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
gettimeofday(&lastDomainServerCheckIn, NULL);
NodeList::getInstance()->sendDomainServerCheckIn();
NodeList::getInstance()->sendDomainServerCheckIn(this->getUUID().toRfc4122().constData());
if (Logging::shouldSendStats() && numStatCollections > 0) {
// 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
if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
gettimeofday(&lastDomainServerCheckIn, NULL);
NodeList::getInstance()->sendDomainServerCheckIn();
NodeList::getInstance()->sendDomainServerCheckIn(this->getUUID().toRfc4122().constData());
}
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;
}
Node* newNode = nodeList->addOrUpdateNode((sockaddr*) &nodePublicAddress,
(sockaddr*) &nodeLocalAddress,
nodeType,
nodeList->getLastNodeID());
bool matchedUUID = true;
// if addOrUpdateNode returns NULL this was a solo node we already have, don't talk back to it
if (newNode) {
if (newNode->getNodeID() == nodeList->getLastNodeID()) {
nodeList->increaseNodeID();
if ((nodeType == NODE_TYPE_AVATAR_MIXER || nodeType == NODE_TYPE_AUDIO_MIXER) &&
!nodeList->soloNodeOfType(nodeType)) {
// if this is an audio-mixer or an avatar-mixer and we don't have one yet
// 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;
startPointer = currentBufferPos;
unsigned char* nodeTypesOfInterest = packetData + numBytesSenderHeader + sizeof(NODE_TYPE)
+ numBytesSocket + sizeof(unsigned char);
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)) {
// this is not the node themselves
// and this is an node of a type in the passed node types of interest
// or the node did not pass us any specific types they are interested in
if (memchr(SOLO_NODE_TYPES, node->getType(), sizeof(SOLO_NODE_TYPES)) == NULL) {
// this is an node of which there can be multiple, just add them to the packet
// if addOrUpdateNode returns NULL this was a solo node we already have, don't talk back to it
if (newNode) {
if (newNode->getNodeID() == nodeList->getLastNodeID()) {
nodeList->increaseNodeID();
}
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN);
currentBufferPos = broadcastPacket + numHeaderBytes;
startPointer = currentBufferPos;
int numBytesUUID = (nodeType == NODE_TYPE_AUDIO_MIXER || nodeType == NODE_TYPE_AVATAR_MIXER)
? NUM_BYTES_RFC4122_UUID
: 0;
unsigned char* nodeTypesOfInterest = packetData + numBytesSenderHeader + numBytesUUID +
sizeof(NODE_TYPE) + numBytesSocket + sizeof(unsigned char);
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
if (nodeType != NODE_TYPE_AGENT || node->getType() != NODE_TYPE_AGENT) {
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();
soloNode != newestSoloNodes.end();
soloNode++) {
// this is the newest alive solo node, add them to the packet
currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, soloNode->second);
}
// update last receive to now
uint64_t timeNow = usecTimestampNow();
newNode->setLastHeardMicrostamp(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);
}
// 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) {
@ -355,8 +383,8 @@ int main(int argc, const char* argv[]) {
::assignmentQueue.erase(assignment);
delete *assignment;
}
} else {
// remove the assignment from the queue
} else if ((*assignment)->getType() == Assignment::VoxelServerType) {
// this is a voxel-server assignment, remove the assignment from the queue
::assignmentQueue.erase(assignment);
}
@ -398,7 +426,8 @@ int main(int argc, const char* argv[]) {
::assignmentQueue.erase(assignment);
delete *assignment;
}
} else {
} else if ((*assignment)->getType() == Assignment::VoxelServerType) {
// this is a voxel server assignment
// remove the assignment from the queue
::assignmentQueue.erase(assignment);
}

View file

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

View file

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

View file

@ -268,7 +268,7 @@ void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNo
_nodeTypesOfInterest[numNodeTypesOfInterest] = '\0';
}
void NodeList::sendDomainServerCheckIn() {
void NodeList::sendDomainServerCheckIn(const char* assignmentUUID) {
static bool printedDomainServerIP = false;
// 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;
// check in packet has header, node type, port, IP, node types of interest, null termination
int numPacketBytes = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) + sizeof(NODE_TYPE) + sizeof(uint16_t) +
IP_ADDRESS_BYTES + numBytesNodesOfInterest + sizeof(unsigned char);
// 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) +
NUM_BYTES_RFC4122_UUID + sizeof(uint16_t) + IP_ADDRESS_BYTES + numBytesNodesOfInterest + sizeof(unsigned char);
checkInPacket = new unsigned char[numPacketBytes];
unsigned char* packetPosition = checkInPacket;
@ -313,7 +313,13 @@ void NodeList::sendDomainServerCheckIn() {
*(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(),
htons(_nodeSocket.getListeningPort()));

View file

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

View file

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