get rid of arpa/inet.h and netdb.h

This commit is contained in:
Brad Hefta-Gaub 2014-01-10 18:13:23 -08:00
parent 9bc4a3df41
commit 5725a92cfe
6 changed files with 227 additions and 225 deletions

View file

@ -6,7 +6,7 @@
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
// //
#include <arpa/inet.h> //#include <arpa/inet.h> // not available on windows, apparently not needed on mac
#include <signal.h> #include <signal.h>
#include <QtCore/QJsonDocument> #include <QtCore/QJsonDocument>
@ -41,86 +41,86 @@ DomainServer::DomainServer(int argc, char* argv[]) :
_hasCompletedRestartHold(false) _hasCompletedRestartHold(false)
{ {
DomainServer::setDomainServerInstance(this); DomainServer::setDomainServerInstance(this);
signal(SIGINT, signalhandler); signal(SIGINT, signalhandler);
const char CUSTOM_PORT_OPTION[] = "-p"; const char CUSTOM_PORT_OPTION[] = "-p";
const char* customPortString = getCmdOption(argc, (const char**) argv, CUSTOM_PORT_OPTION); const char* customPortString = getCmdOption(argc, (const char**) argv, CUSTOM_PORT_OPTION);
unsigned short domainServerPort = customPortString ? atoi(customPortString) : DEFAULT_DOMAIN_SERVER_PORT; unsigned short domainServerPort = customPortString ? atoi(customPortString) : DEFAULT_DOMAIN_SERVER_PORT;
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_DOMAIN, domainServerPort); NodeList* nodeList = NodeList::createInstance(NODE_TYPE_DOMAIN, domainServerPort);
const char VOXEL_CONFIG_OPTION[] = "--voxelServerConfig"; const char VOXEL_CONFIG_OPTION[] = "--voxelServerConfig";
_voxelServerConfig = getCmdOption(argc, (const char**) argv, VOXEL_CONFIG_OPTION); _voxelServerConfig = getCmdOption(argc, (const char**) argv, VOXEL_CONFIG_OPTION);
const char PARTICLE_CONFIG_OPTION[] = "--particleServerConfig"; const char PARTICLE_CONFIG_OPTION[] = "--particleServerConfig";
_particleServerConfig = getCmdOption(argc, (const char**) argv, PARTICLE_CONFIG_OPTION); _particleServerConfig = getCmdOption(argc, (const char**) argv, PARTICLE_CONFIG_OPTION);
const char METAVOXEL_CONFIG_OPTION[] = "--metavoxelServerConfig"; const char METAVOXEL_CONFIG_OPTION[] = "--metavoxelServerConfig";
_metavoxelServerConfig = getCmdOption(argc, (const char**)argv, METAVOXEL_CONFIG_OPTION); _metavoxelServerConfig = getCmdOption(argc, (const char**)argv, METAVOXEL_CONFIG_OPTION);
// setup the mongoose web server // setup the mongoose web server
struct mg_callbacks callbacks = {}; struct mg_callbacks callbacks = {};
QString documentRootString = QString("%1/resources/web").arg(QCoreApplication::applicationDirPath()); QString documentRootString = QString("%1/resources/web").arg(QCoreApplication::applicationDirPath());
char documentRoot[documentRootString.size() + 1]; char documentRoot[documentRootString.size() + 1];
strcpy(documentRoot, documentRootString.toLocal8Bit().constData()); strcpy(documentRoot, documentRootString.toLocal8Bit().constData());
// list of options. Last element must be NULL. // list of options. Last element must be NULL.
const char* options[] = {"listening_ports", "8080", const char* options[] = {"listening_ports", "8080",
"document_root", documentRoot, NULL}; "document_root", documentRoot, NULL};
callbacks.begin_request = civetwebRequestHandler; callbacks.begin_request = civetwebRequestHandler;
callbacks.upload = civetwebUploadHandler; callbacks.upload = civetwebUploadHandler;
// Start the web server. // Start the web server.
mg_start(&callbacks, NULL, options); mg_start(&callbacks, NULL, options);
nodeList->addHook(this); nodeList->addHook(this);
if (!_staticAssignmentFile.exists() || _voxelServerConfig) { if (!_staticAssignmentFile.exists() || _voxelServerConfig) {
if (_voxelServerConfig) { if (_voxelServerConfig) {
// we have a new VS config, clear the existing file to start fresh // we have a new VS config, clear the existing file to start fresh
_staticAssignmentFile.remove(); _staticAssignmentFile.remove();
} }
prepopulateStaticAssignmentFile(); prepopulateStaticAssignmentFile();
} }
_staticAssignmentFile.open(QIODevice::ReadWrite); _staticAssignmentFile.open(QIODevice::ReadWrite);
_staticAssignmentFileData = _staticAssignmentFile.map(0, _staticAssignmentFile.size()); _staticAssignmentFileData = _staticAssignmentFile.map(0, _staticAssignmentFile.size());
_staticAssignments = (Assignment*) _staticAssignmentFileData; _staticAssignments = (Assignment*) _staticAssignmentFileData;
QTimer* silentNodeTimer = new QTimer(this); QTimer* silentNodeTimer = new QTimer(this);
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(readAvailableDatagrams())); connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(readAvailableDatagrams()));
// fire a single shot timer to add static assignments back into the queue after a restart // fire a single shot timer to add static assignments back into the queue after a restart
QTimer::singleShot(RESTART_HOLD_TIME_MSECS, this, SLOT(addStaticAssignmentsBackToQueueAfterRestart())); QTimer::singleShot(RESTART_HOLD_TIME_MSECS, this, SLOT(addStaticAssignmentsBackToQueueAfterRestart()));
connect(this, SIGNAL(aboutToQuit()), SLOT(cleanup())); connect(this, SIGNAL(aboutToQuit()), SLOT(cleanup()));
} }
void DomainServer::readAvailableDatagrams() { void DomainServer::readAvailableDatagrams() {
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
HifiSockAddr senderSockAddr, nodePublicAddress, nodeLocalAddress; HifiSockAddr senderSockAddr, nodePublicAddress, nodeLocalAddress;
static unsigned char packetData[MAX_PACKET_SIZE]; static unsigned char packetData[MAX_PACKET_SIZE];
static unsigned char broadcastPacket[MAX_PACKET_SIZE]; static unsigned char broadcastPacket[MAX_PACKET_SIZE];
static unsigned char* currentBufferPos; static unsigned char* currentBufferPos;
static unsigned char* startPointer; static unsigned char* startPointer;
int receivedBytes = 0; int receivedBytes = 0;
while (nodeList->getNodeSocket().hasPendingDatagrams()) { while (nodeList->getNodeSocket().hasPendingDatagrams()) {
if ((receivedBytes = nodeList->getNodeSocket().readDatagram((char*) packetData, MAX_PACKET_SIZE, if ((receivedBytes = nodeList->getNodeSocket().readDatagram((char*) packetData, MAX_PACKET_SIZE,
senderSockAddr.getAddressPointer(), senderSockAddr.getAddressPointer(),
@ -128,22 +128,22 @@ void DomainServer::readAvailableDatagrams() {
&& packetVersionMatch((unsigned char*) packetData)) { && packetVersionMatch((unsigned char*) packetData)) {
if (packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY || packetData[0] == PACKET_TYPE_DOMAIN_LIST_REQUEST) { if (packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY || packetData[0] == PACKET_TYPE_DOMAIN_LIST_REQUEST) {
// this is an RFD or domain list request packet, and there is a version match // this is an RFD or domain list request packet, and there is a version match
int numBytesSenderHeader = numBytesForPacketHeader((unsigned char*) packetData); int numBytesSenderHeader = numBytesForPacketHeader((unsigned char*) packetData);
NODE_TYPE nodeType = *(packetData + numBytesSenderHeader); NODE_TYPE nodeType = *(packetData + numBytesSenderHeader);
int packetIndex = numBytesSenderHeader + sizeof(NODE_TYPE); int packetIndex = numBytesSenderHeader + sizeof(NODE_TYPE);
QUuid nodeUUID = QUuid::fromRfc4122(QByteArray(((char*) packetData + packetIndex), NUM_BYTES_RFC4122_UUID)); QUuid nodeUUID = QUuid::fromRfc4122(QByteArray(((char*) packetData + packetIndex), NUM_BYTES_RFC4122_UUID));
packetIndex += NUM_BYTES_RFC4122_UUID; packetIndex += NUM_BYTES_RFC4122_UUID;
int numBytesPrivateSocket = HifiSockAddr::unpackSockAddr(packetData + packetIndex, nodePublicAddress); int numBytesPrivateSocket = HifiSockAddr::unpackSockAddr(packetData + packetIndex, nodePublicAddress);
packetIndex += numBytesPrivateSocket; packetIndex += numBytesPrivateSocket;
if (nodePublicAddress.getAddress().isNull()) { if (nodePublicAddress.getAddress().isNull()) {
// this node wants to use us its STUN server // this node wants to use us its STUN server
// so set the node public address to whatever we perceive the public address to be // so set the node public address to whatever we perceive the public address to be
// if the sender is on our box then leave its public address to 0 so that // if the sender is on our box then leave its public address to 0 so that
// other users attempt to reach it on the same address they have for the domain-server // other users attempt to reach it on the same address they have for the domain-server
if (senderSockAddr.getAddress().isLoopback()) { if (senderSockAddr.getAddress().isLoopback()) {
@ -152,19 +152,19 @@ void DomainServer::readAvailableDatagrams() {
nodePublicAddress.setAddress(senderSockAddr.getAddress()); nodePublicAddress.setAddress(senderSockAddr.getAddress());
} }
} }
int numBytesPublicSocket = HifiSockAddr::unpackSockAddr(packetData + packetIndex, nodeLocalAddress); int numBytesPublicSocket = HifiSockAddr::unpackSockAddr(packetData + packetIndex, nodeLocalAddress);
packetIndex += numBytesPublicSocket; packetIndex += numBytesPublicSocket;
const char STATICALLY_ASSIGNED_NODES[] = { const char STATICALLY_ASSIGNED_NODES[] = {
NODE_TYPE_AUDIO_MIXER, NODE_TYPE_AUDIO_MIXER,
NODE_TYPE_AVATAR_MIXER, NODE_TYPE_AVATAR_MIXER,
NODE_TYPE_VOXEL_SERVER, NODE_TYPE_VOXEL_SERVER,
NODE_TYPE_METAVOXEL_SERVER NODE_TYPE_METAVOXEL_SERVER
}; };
Assignment* matchingStaticAssignment = NULL; Assignment* matchingStaticAssignment = NULL;
if (memchr(STATICALLY_ASSIGNED_NODES, nodeType, sizeof(STATICALLY_ASSIGNED_NODES)) == NULL if (memchr(STATICALLY_ASSIGNED_NODES, nodeType, sizeof(STATICALLY_ASSIGNED_NODES)) == NULL
|| ((matchingStaticAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType)) || ((matchingStaticAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType))
|| checkInWithUUIDMatchesExistingNode(nodePublicAddress, || checkInWithUUIDMatchesExistingNode(nodePublicAddress,
@ -175,79 +175,79 @@ void DomainServer::readAvailableDatagrams() {
nodeType, nodeType,
nodePublicAddress, nodePublicAddress,
nodeLocalAddress); nodeLocalAddress);
if (matchingStaticAssignment) { if (matchingStaticAssignment) {
// this was a newly added node with a matching static assignment // this was a newly added node with a matching static assignment
if (_hasCompletedRestartHold) { if (_hasCompletedRestartHold) {
// remove the matching assignment from the assignment queue so we don't take the next check in // remove the matching assignment from the assignment queue so we don't take the next check in
removeAssignmentFromQueue(matchingStaticAssignment); removeAssignmentFromQueue(matchingStaticAssignment);
} }
// set the linked data for this node to a copy of the matching assignment // set the linked data for this node to a copy of the matching assignment
// so we can re-queue it should the node die // so we can re-queue it should the node die
Assignment* nodeCopyOfMatchingAssignment = new Assignment(*matchingStaticAssignment); Assignment* nodeCopyOfMatchingAssignment = new Assignment(*matchingStaticAssignment);
checkInNode->setLinkedData(nodeCopyOfMatchingAssignment); checkInNode->setLinkedData(nodeCopyOfMatchingAssignment);
} }
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN); int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN);
currentBufferPos = broadcastPacket + numHeaderBytes; currentBufferPos = broadcastPacket + numHeaderBytes;
startPointer = currentBufferPos; startPointer = currentBufferPos;
unsigned char* nodeTypesOfInterest = packetData + packetIndex + sizeof(unsigned char); unsigned char* nodeTypesOfInterest = packetData + packetIndex + sizeof(unsigned char);
int numInterestTypes = *(nodeTypesOfInterest - 1); int numInterestTypes = *(nodeTypesOfInterest - 1);
if (numInterestTypes > 0) { if (numInterestTypes > 0) {
// if the node has sent no types of interest, assume they want nothing but their own ID back // 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++) { for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
if (node->getUUID() != nodeUUID && if (node->getUUID() != nodeUUID &&
memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { 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));
} }
} }
} }
} }
// update last receive to now // update last receive to now
uint64_t timeNow = usecTimestampNow(); uint64_t timeNow = usecTimestampNow();
checkInNode->setLastHeardMicrostamp(timeNow); checkInNode->setLastHeardMicrostamp(timeNow);
// send the constructed list back to this node // send the constructed list back to this node
nodeList->getNodeSocket().writeDatagram((char*) broadcastPacket, nodeList->getNodeSocket().writeDatagram((char*) broadcastPacket,
(currentBufferPos - startPointer) + numHeaderBytes, (currentBufferPos - startPointer) + numHeaderBytes,
senderSockAddr.getAddress(), senderSockAddr.getPort()); senderSockAddr.getAddress(), senderSockAddr.getPort());
} }
} else if (packetData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) { } else if (packetData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) {
if (_assignmentQueue.size() > 0) { if (_assignmentQueue.size() > 0) {
// construct the requested assignment from the packet data // construct the requested assignment from the packet data
Assignment requestAssignment(packetData, receivedBytes); Assignment requestAssignment(packetData, receivedBytes);
qDebug("Received a request for assignment type %i from %s.\n", requestAssignment.getType(), qPrintable(senderSockAddr.getAddress().toString())); qDebug("Received a request for assignment type %i from %s.\n", requestAssignment.getType(), qPrintable(senderSockAddr.getAddress().toString()));
Assignment* assignmentToDeploy = deployableAssignmentForRequest(requestAssignment); Assignment* assignmentToDeploy = deployableAssignmentForRequest(requestAssignment);
if (assignmentToDeploy) { if (assignmentToDeploy) {
// give this assignment out, either the type matches or the requestor said they will take any // give this assignment out, either the type matches or the requestor said they will take any
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT); int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT);
int numAssignmentBytes = assignmentToDeploy->packToBuffer(broadcastPacket + numHeaderBytes); int numAssignmentBytes = assignmentToDeploy->packToBuffer(broadcastPacket + numHeaderBytes);
nodeList->getNodeSocket().writeDatagram((char*) broadcastPacket, numHeaderBytes + numAssignmentBytes, nodeList->getNodeSocket().writeDatagram((char*) broadcastPacket, numHeaderBytes + numAssignmentBytes,
senderSockAddr.getAddress(), senderSockAddr.getPort()); senderSockAddr.getAddress(), senderSockAddr.getPort());
if (assignmentToDeploy->getNumberOfInstances() == 0) { if (assignmentToDeploy->getNumberOfInstances() == 0) {
// there are no more instances of this script to send out, delete it // there are no more instances of this script to send out, delete it
delete assignmentToDeploy; delete assignmentToDeploy;
} }
} }
} else { } else {
qDebug("Received an invalid assignment request from %s.\n", qPrintable(senderSockAddr.getAddress().toString())); qDebug("Received an invalid assignment request from %s.\n", qPrintable(senderSockAddr.getAddress().toString()));
} }
@ -262,10 +262,10 @@ void DomainServer::setDomainServerInstance(DomainServer* domainServer) {
QJsonObject jsonForSocket(const HifiSockAddr& socket) { QJsonObject jsonForSocket(const HifiSockAddr& socket) {
QJsonObject socketJSON; QJsonObject socketJSON;
socketJSON["ip"] = socket.getAddress().toString(); socketJSON["ip"] = socket.getAddress().toString();
socketJSON["port"] = ntohs(socket.getPort()); socketJSON["port"] = ntohs(socket.getPort());
return socketJSON; return socketJSON;
} }
@ -281,14 +281,14 @@ QJsonObject jsonObjectForNode(Node* node) {
QString nodeTypeName(node->getTypeName()); QString nodeTypeName(node->getTypeName());
nodeTypeName = nodeTypeName.toLower(); nodeTypeName = nodeTypeName.toLower();
nodeTypeName.replace(' ', '-'); nodeTypeName.replace(' ', '-');
// add the node type // add the node type
nodeJson[JSON_KEY_TYPE] = nodeTypeName; nodeJson[JSON_KEY_TYPE] = nodeTypeName;
// add the node socket information // add the node socket information
nodeJson[JSON_KEY_PUBLIC_SOCKET] = jsonForSocket(node->getPublicSocket()); nodeJson[JSON_KEY_PUBLIC_SOCKET] = jsonForSocket(node->getPublicSocket());
nodeJson[JSON_KEY_LOCAL_SOCKET] = jsonForSocket(node->getLocalSocket()); nodeJson[JSON_KEY_LOCAL_SOCKET] = jsonForSocket(node->getLocalSocket());
// if the node has pool information, add it // if the node has pool information, add it
if (node->getLinkedData() && ((Assignment*) node->getLinkedData())->hasPool()) { if (node->getLinkedData() && ((Assignment*) node->getLinkedData())->hasPool()) {
nodeJson[JSON_KEY_POOL] = QString(((Assignment*) node->getLinkedData())->getPool()); nodeJson[JSON_KEY_POOL] = QString(((Assignment*) node->getLinkedData())->getPool());
@ -299,27 +299,27 @@ QJsonObject jsonObjectForNode(Node* node) {
int DomainServer::civetwebRequestHandler(struct mg_connection *connection) { int DomainServer::civetwebRequestHandler(struct mg_connection *connection) {
const struct mg_request_info* ri = mg_get_request_info(connection); const struct mg_request_info* ri = mg_get_request_info(connection);
const char RESPONSE_200[] = "HTTP/1.0 200 OK\r\n\r\n"; const char RESPONSE_200[] = "HTTP/1.0 200 OK\r\n\r\n";
const char RESPONSE_400[] = "HTTP/1.0 400 Bad Request\r\n\r\n"; const char RESPONSE_400[] = "HTTP/1.0 400 Bad Request\r\n\r\n";
const char URI_ASSIGNMENT[] = "/assignment"; const char URI_ASSIGNMENT[] = "/assignment";
const char URI_NODE[] = "/node"; const char URI_NODE[] = "/node";
if (strcmp(ri->request_method, "GET") == 0) { if (strcmp(ri->request_method, "GET") == 0) {
if (strcmp(ri->uri, "/assignments.json") == 0) { if (strcmp(ri->uri, "/assignments.json") == 0) {
// user is asking for json list of assignments // user is asking for json list of assignments
// start with a 200 response // start with a 200 response
mg_printf(connection, "%s", RESPONSE_200); mg_printf(connection, "%s", RESPONSE_200);
// setup the JSON // setup the JSON
QJsonObject assignmentJSON; QJsonObject assignmentJSON;
QJsonObject assignedNodesJSON; QJsonObject assignedNodesJSON;
// enumerate the NodeList to find the assigned nodes // enumerate the NodeList to find the assigned nodes
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
if (node->getLinkedData()) { if (node->getLinkedData()) {
// add the node using the UUID as the key // add the node using the UUID as the key
@ -327,67 +327,67 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) {
assignedNodesJSON[uuidString] = jsonObjectForNode(&(*node)); assignedNodesJSON[uuidString] = jsonObjectForNode(&(*node));
} }
} }
assignmentJSON["fulfilled"] = assignedNodesJSON; assignmentJSON["fulfilled"] = assignedNodesJSON;
QJsonObject queuedAssignmentsJSON; QJsonObject queuedAssignmentsJSON;
// add the queued but unfilled assignments to the json // add the queued but unfilled assignments to the json
std::deque<Assignment*>::iterator assignment = domainServerInstance->_assignmentQueue.begin(); std::deque<Assignment*>::iterator assignment = domainServerInstance->_assignmentQueue.begin();
while (assignment != domainServerInstance->_assignmentQueue.end()) { while (assignment != domainServerInstance->_assignmentQueue.end()) {
QJsonObject queuedAssignmentJSON; QJsonObject queuedAssignmentJSON;
QString uuidString = uuidStringWithoutCurlyBraces((*assignment)->getUUID()); QString uuidString = uuidStringWithoutCurlyBraces((*assignment)->getUUID());
queuedAssignmentJSON[JSON_KEY_TYPE] = QString((*assignment)->getTypeName()); queuedAssignmentJSON[JSON_KEY_TYPE] = QString((*assignment)->getTypeName());
// if the assignment has a pool, add it // if the assignment has a pool, add it
if ((*assignment)->hasPool()) { if ((*assignment)->hasPool()) {
queuedAssignmentJSON[JSON_KEY_POOL] = QString((*assignment)->getPool()); queuedAssignmentJSON[JSON_KEY_POOL] = QString((*assignment)->getPool());
} }
// add this queued assignment to the JSON // add this queued assignment to the JSON
queuedAssignmentsJSON[uuidString] = queuedAssignmentJSON; queuedAssignmentsJSON[uuidString] = queuedAssignmentJSON;
// push forward the iterator to check the next assignment // push forward the iterator to check the next assignment
assignment++; assignment++;
} }
assignmentJSON["queued"] = queuedAssignmentsJSON; assignmentJSON["queued"] = queuedAssignmentsJSON;
// print out the created JSON // print out the created JSON
QJsonDocument assignmentDocument(assignmentJSON); QJsonDocument assignmentDocument(assignmentJSON);
mg_printf(connection, "%s", assignmentDocument.toJson().constData()); mg_printf(connection, "%s", assignmentDocument.toJson().constData());
// we've processed this request // we've processed this request
return 1; return 1;
} else if (strcmp(ri->uri, "/nodes.json") == 0) { } else if (strcmp(ri->uri, "/nodes.json") == 0) {
// start with a 200 response // start with a 200 response
mg_printf(connection, "%s", RESPONSE_200); mg_printf(connection, "%s", RESPONSE_200);
// setup the JSON // setup the JSON
QJsonObject rootJSON; QJsonObject rootJSON;
QJsonObject nodesJSON; QJsonObject nodesJSON;
// enumerate the NodeList to find the assigned nodes // enumerate the NodeList to find the assigned nodes
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
// add the node using the UUID as the key // add the node using the UUID as the key
QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID()); QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID());
nodesJSON[uuidString] = jsonObjectForNode(&(*node)); nodesJSON[uuidString] = jsonObjectForNode(&(*node));
} }
rootJSON["nodes"] = nodesJSON; rootJSON["nodes"] = nodesJSON;
// print out the created JSON // print out the created JSON
QJsonDocument nodesDocument(rootJSON); QJsonDocument nodesDocument(rootJSON);
mg_printf(connection, "%s", nodesDocument.toJson().constData()); mg_printf(connection, "%s", nodesDocument.toJson().constData());
// we've processed this request // we've processed this request
return 1; return 1;
} }
// not processed, pass to document root // not processed, pass to document root
return 0; return 0;
} else if (strcmp(ri->request_method, "POST") == 0) { } else if (strcmp(ri->request_method, "POST") == 0) {
@ -396,38 +396,38 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) {
mg_printf(connection, "%s", RESPONSE_200); mg_printf(connection, "%s", RESPONSE_200);
// upload the file // upload the file
mg_upload(connection, "/tmp"); mg_upload(connection, "/tmp");
return 1; return 1;
} }
return 0; return 0;
} else if (strcmp(ri->request_method, "DELETE") == 0) { } else if (strcmp(ri->request_method, "DELETE") == 0) {
// this is a DELETE request // this is a DELETE request
// check if it is for an assignment // check if it is for an assignment
if (memcmp(ri->uri, URI_NODE, strlen(URI_NODE)) == 0) { if (memcmp(ri->uri, URI_NODE, strlen(URI_NODE)) == 0) {
// pull the UUID from the url // pull the UUID from the url
QUuid deleteUUID = QUuid(QString(ri->uri + strlen(URI_NODE) + sizeof('/'))); QUuid deleteUUID = QUuid(QString(ri->uri + strlen(URI_NODE) + sizeof('/')));
if (!deleteUUID.isNull()) { if (!deleteUUID.isNull()) {
Node *nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID); Node *nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID);
if (nodeToKill) { if (nodeToKill) {
// start with a 200 response // start with a 200 response
mg_printf(connection, "%s", RESPONSE_200); mg_printf(connection, "%s", RESPONSE_200);
// we have a valid UUID and node - kill the node that has this assignment // we have a valid UUID and node - kill the node that has this assignment
NodeList::getInstance()->killNode(nodeToKill); NodeList::getInstance()->killNode(nodeToKill);
// successfully processed request // successfully processed request
return 1; return 1;
} }
} }
} }
// request not processed - bad request // request not processed - bad request
mg_printf(connection, "%s", RESPONSE_400); mg_printf(connection, "%s", RESPONSE_400);
// this was processed by civetweb // this was processed by civetweb
return 1; return 1;
} else { } else {
@ -439,33 +439,33 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) {
const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "resources/web/assignment"; const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "resources/web/assignment";
void DomainServer::civetwebUploadHandler(struct mg_connection *connection, const char *path) { void DomainServer::civetwebUploadHandler(struct mg_connection *connection, const char *path) {
// create an assignment for this saved script, for now make it local only // create an assignment for this saved script, for now make it local only
Assignment* scriptAssignment = new Assignment(Assignment::CreateCommand, Assignment* scriptAssignment = new Assignment(Assignment::CreateCommand,
Assignment::AgentType, Assignment::AgentType,
NULL, NULL,
Assignment::LocalLocation); Assignment::LocalLocation);
// check how many instances of this assignment the user wants by checking the ASSIGNMENT-INSTANCES header // check how many instances of this assignment the user wants by checking the ASSIGNMENT-INSTANCES header
const char ASSIGNMENT_INSTANCES_HTTP_HEADER[] = "ASSIGNMENT-INSTANCES"; const char ASSIGNMENT_INSTANCES_HTTP_HEADER[] = "ASSIGNMENT-INSTANCES";
const char* requestInstancesHeader = mg_get_header(connection, ASSIGNMENT_INSTANCES_HTTP_HEADER); const char* requestInstancesHeader = mg_get_header(connection, ASSIGNMENT_INSTANCES_HTTP_HEADER);
if (requestInstancesHeader) { if (requestInstancesHeader) {
// the user has requested a number of instances greater than 1 // the user has requested a number of instances greater than 1
// so set that on the created assignment // so set that on the created assignment
scriptAssignment->setNumberOfInstances(atoi(requestInstancesHeader)); scriptAssignment->setNumberOfInstances(atoi(requestInstancesHeader));
} }
QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION); QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION);
newPath += "/"; newPath += "/";
// append the UUID for this script as the new filename, remove the curly braces // append the UUID for this script as the new filename, remove the curly braces
newPath += uuidStringWithoutCurlyBraces(scriptAssignment->getUUID()); newPath += uuidStringWithoutCurlyBraces(scriptAssignment->getUUID());
// rename the saved script to the GUID of the assignment and move it to the script host locaiton // rename the saved script to the GUID of the assignment and move it to the script host locaiton
rename(path, newPath.toLocal8Bit().constData()); rename(path, newPath.toLocal8Bit().constData());
qDebug("Saved a script for assignment at %s\n", newPath.toLocal8Bit().constData()); qDebug("Saved a script for assignment at %s\n", newPath.toLocal8Bit().constData());
// add the script assigment to the assignment queue // add the script assigment to the assignment queue
// lock the assignment queue mutex since we're operating on a different thread than DS main // lock the assignment queue mutex since we're operating on a different thread than DS main
domainServerInstance->_assignmentQueueMutex.lock(); domainServerInstance->_assignmentQueueMutex.lock();
@ -475,18 +475,18 @@ void DomainServer::civetwebUploadHandler(struct mg_connection *connection, const
void DomainServer::addReleasedAssignmentBackToQueue(Assignment* releasedAssignment) { void DomainServer::addReleasedAssignmentBackToQueue(Assignment* releasedAssignment) {
qDebug() << "Adding assignment" << *releasedAssignment << " back to queue.\n"; qDebug() << "Adding assignment" << *releasedAssignment << " back to queue.\n";
// find this assignment in the static file // find this assignment in the static file
for (int i = 0; i < MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS; i++) { for (int i = 0; i < MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS; i++) {
if (_staticAssignments[i].getUUID() == releasedAssignment->getUUID()) { if (_staticAssignments[i].getUUID() == releasedAssignment->getUUID()) {
// reset the UUID on the static assignment // reset the UUID on the static assignment
_staticAssignments[i].resetUUID(); _staticAssignments[i].resetUUID();
// put this assignment back in the queue so it goes out // put this assignment back in the queue so it goes out
_assignmentQueueMutex.lock(); _assignmentQueueMutex.lock();
_assignmentQueue.push_back(&_staticAssignments[i]); _assignmentQueue.push_back(&_staticAssignments[i]);
_assignmentQueueMutex.unlock(); _assignmentQueueMutex.unlock();
} else if (_staticAssignments[i].getUUID().isNull()) { } else if (_staticAssignments[i].getUUID().isNull()) {
// we are at the blank part of the static assignments - break out // we are at the blank part of the static assignments - break out
break; break;
@ -495,79 +495,79 @@ void DomainServer::addReleasedAssignmentBackToQueue(Assignment* releasedAssignme
} }
void DomainServer::nodeAdded(Node* node) { void DomainServer::nodeAdded(Node* node) {
} }
void DomainServer::nodeKilled(Node* node) { void DomainServer::nodeKilled(Node* node) {
// if this node has linked data it was from an assignment // if this node has linked data it was from an assignment
if (node->getLinkedData()) { if (node->getLinkedData()) {
Assignment* nodeAssignment = (Assignment*) node->getLinkedData(); Assignment* nodeAssignment = (Assignment*) node->getLinkedData();
addReleasedAssignmentBackToQueue(nodeAssignment); addReleasedAssignmentBackToQueue(nodeAssignment);
} }
} }
unsigned char* DomainServer::addNodeToBroadcastPacket(unsigned char* currentPosition, Node* nodeToAdd) { unsigned char* DomainServer::addNodeToBroadcastPacket(unsigned char* currentPosition, Node* nodeToAdd) {
*currentPosition++ = nodeToAdd->getType(); *currentPosition++ = nodeToAdd->getType();
QByteArray rfcUUID = nodeToAdd->getUUID().toRfc4122(); QByteArray rfcUUID = nodeToAdd->getUUID().toRfc4122();
memcpy(currentPosition, rfcUUID.constData(), rfcUUID.size()); memcpy(currentPosition, rfcUUID.constData(), rfcUUID.size());
currentPosition += rfcUUID.size(); currentPosition += rfcUUID.size();
currentPosition += HifiSockAddr::packSockAddr(currentPosition, nodeToAdd->getPublicSocket()); currentPosition += HifiSockAddr::packSockAddr(currentPosition, nodeToAdd->getPublicSocket());
currentPosition += HifiSockAddr::packSockAddr(currentPosition, nodeToAdd->getLocalSocket()); currentPosition += HifiSockAddr::packSockAddr(currentPosition, nodeToAdd->getLocalSocket());
// return the new unsigned char * for broadcast packet // return the new unsigned char * for broadcast packet
return currentPosition; return currentPosition;
} }
void DomainServer::prepopulateStaticAssignmentFile() { void DomainServer::prepopulateStaticAssignmentFile() {
int numFreshStaticAssignments = 0; int numFreshStaticAssignments = 0;
// write a fresh static assignment array to file // write a fresh static assignment array to file
Assignment freshStaticAssignments[MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS]; Assignment freshStaticAssignments[MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS];
// pre-populate the first static assignment list with assignments for root AuM, AvM, VS // pre-populate the first static assignment list with assignments for root AuM, AvM, VS
freshStaticAssignments[numFreshStaticAssignments++] = Assignment(Assignment::CreateCommand, Assignment::AudioMixerType); freshStaticAssignments[numFreshStaticAssignments++] = Assignment(Assignment::CreateCommand, Assignment::AudioMixerType);
freshStaticAssignments[numFreshStaticAssignments++] = Assignment(Assignment::CreateCommand, Assignment::AvatarMixerType); freshStaticAssignments[numFreshStaticAssignments++] = Assignment(Assignment::CreateCommand, Assignment::AvatarMixerType);
// Handle Domain/Voxel Server configuration command line arguments // Handle Domain/Voxel Server configuration command line arguments
if (_voxelServerConfig) { if (_voxelServerConfig) {
qDebug("Reading Voxel Server Configuration.\n"); qDebug("Reading Voxel Server Configuration.\n");
qDebug() << "config: " << _voxelServerConfig << "\n"; qDebug() << "config: " << _voxelServerConfig << "\n";
QString multiConfig((const char*) _voxelServerConfig); QString multiConfig((const char*) _voxelServerConfig);
QStringList multiConfigList = multiConfig.split(";"); QStringList multiConfigList = multiConfig.split(";");
// read each config to a payload for a VS assignment // read each config to a payload for a VS assignment
for (int i = 0; i < multiConfigList.size(); i++) { for (int i = 0; i < multiConfigList.size(); i++) {
QString config = multiConfigList.at(i); QString config = multiConfigList.at(i);
qDebug("config[%d]=%s\n", i, config.toLocal8Bit().constData()); qDebug("config[%d]=%s\n", i, config.toLocal8Bit().constData());
// Now, parse the config to check for a pool // Now, parse the config to check for a pool
const char ASSIGNMENT_CONFIG_POOL_OPTION[] = "--pool"; const char ASSIGNMENT_CONFIG_POOL_OPTION[] = "--pool";
QString assignmentPool; QString assignmentPool;
int poolIndex = config.indexOf(ASSIGNMENT_CONFIG_POOL_OPTION); int poolIndex = config.indexOf(ASSIGNMENT_CONFIG_POOL_OPTION);
if (poolIndex >= 0) { if (poolIndex >= 0) {
int spaceBeforePoolIndex = config.indexOf(' ', poolIndex); int spaceBeforePoolIndex = config.indexOf(' ', poolIndex);
int spaceAfterPoolIndex = config.indexOf(' ', spaceBeforePoolIndex); int spaceAfterPoolIndex = config.indexOf(' ', spaceBeforePoolIndex);
assignmentPool = config.mid(spaceBeforePoolIndex + 1, spaceAfterPoolIndex); assignmentPool = config.mid(spaceBeforePoolIndex + 1, spaceAfterPoolIndex);
qDebug() << "The pool for this voxel-assignment is" << assignmentPool << "\n"; qDebug() << "The pool for this voxel-assignment is" << assignmentPool << "\n";
} }
Assignment voxelServerAssignment(Assignment::CreateCommand, Assignment voxelServerAssignment(Assignment::CreateCommand,
Assignment::VoxelServerType, Assignment::VoxelServerType,
(assignmentPool.isEmpty() ? NULL : assignmentPool.toLocal8Bit().constData())); (assignmentPool.isEmpty() ? NULL : assignmentPool.toLocal8Bit().constData()));
int payloadLength = config.length() + sizeof(char); int payloadLength = config.length() + sizeof(char);
voxelServerAssignment.setPayload((uchar*)config.toLocal8Bit().constData(), payloadLength); voxelServerAssignment.setPayload((uchar*)config.toLocal8Bit().constData(), payloadLength);
freshStaticAssignments[numFreshStaticAssignments++] = voxelServerAssignment; freshStaticAssignments[numFreshStaticAssignments++] = voxelServerAssignment;
} }
} else { } else {
@ -579,53 +579,53 @@ void DomainServer::prepopulateStaticAssignmentFile() {
if (_particleServerConfig) { if (_particleServerConfig) {
qDebug("Reading Particle Server Configuration.\n"); qDebug("Reading Particle Server Configuration.\n");
qDebug() << "config: " << _particleServerConfig << "\n"; qDebug() << "config: " << _particleServerConfig << "\n";
QString multiConfig((const char*) _particleServerConfig); QString multiConfig((const char*) _particleServerConfig);
QStringList multiConfigList = multiConfig.split(";"); QStringList multiConfigList = multiConfig.split(";");
// read each config to a payload for a VS assignment // read each config to a payload for a VS assignment
for (int i = 0; i < multiConfigList.size(); i++) { for (int i = 0; i < multiConfigList.size(); i++) {
QString config = multiConfigList.at(i); QString config = multiConfigList.at(i);
qDebug("config[%d]=%s\n", i, config.toLocal8Bit().constData()); qDebug("config[%d]=%s\n", i, config.toLocal8Bit().constData());
// Now, parse the config to check for a pool // Now, parse the config to check for a pool
const char ASSIGNMENT_CONFIG_POOL_OPTION[] = "--pool"; const char ASSIGNMENT_CONFIG_POOL_OPTION[] = "--pool";
QString assignmentPool; QString assignmentPool;
int poolIndex = config.indexOf(ASSIGNMENT_CONFIG_POOL_OPTION); int poolIndex = config.indexOf(ASSIGNMENT_CONFIG_POOL_OPTION);
if (poolIndex >= 0) { if (poolIndex >= 0) {
int spaceBeforePoolIndex = config.indexOf(' ', poolIndex); int spaceBeforePoolIndex = config.indexOf(' ', poolIndex);
int spaceAfterPoolIndex = config.indexOf(' ', spaceBeforePoolIndex); int spaceAfterPoolIndex = config.indexOf(' ', spaceBeforePoolIndex);
assignmentPool = config.mid(spaceBeforePoolIndex + 1, spaceAfterPoolIndex); assignmentPool = config.mid(spaceBeforePoolIndex + 1, spaceAfterPoolIndex);
qDebug() << "The pool for this particle-assignment is" << assignmentPool << "\n"; qDebug() << "The pool for this particle-assignment is" << assignmentPool << "\n";
} }
Assignment particleServerAssignment(Assignment::CreateCommand, Assignment particleServerAssignment(Assignment::CreateCommand,
Assignment::ParticleServerType, Assignment::ParticleServerType,
(assignmentPool.isEmpty() ? NULL : assignmentPool.toLocal8Bit().constData())); (assignmentPool.isEmpty() ? NULL : assignmentPool.toLocal8Bit().constData()));
int payloadLength = config.length() + sizeof(char); int payloadLength = config.length() + sizeof(char);
particleServerAssignment.setPayload((uchar*)config.toLocal8Bit().constData(), payloadLength); particleServerAssignment.setPayload((uchar*)config.toLocal8Bit().constData(), payloadLength);
freshStaticAssignments[numFreshStaticAssignments++] = particleServerAssignment; freshStaticAssignments[numFreshStaticAssignments++] = particleServerAssignment;
} }
} else { } else {
Assignment rootParticleServerAssignment(Assignment::CreateCommand, Assignment::ParticleServerType); Assignment rootParticleServerAssignment(Assignment::CreateCommand, Assignment::ParticleServerType);
freshStaticAssignments[numFreshStaticAssignments++] = rootParticleServerAssignment; freshStaticAssignments[numFreshStaticAssignments++] = rootParticleServerAssignment;
} }
// handle metavoxel configuration command line argument // handle metavoxel configuration command line argument
Assignment& metavoxelAssignment = (freshStaticAssignments[numFreshStaticAssignments++] = Assignment& metavoxelAssignment = (freshStaticAssignments[numFreshStaticAssignments++] =
Assignment(Assignment::CreateCommand, Assignment::MetavoxelServerType)); Assignment(Assignment::CreateCommand, Assignment::MetavoxelServerType));
if (_metavoxelServerConfig) { if (_metavoxelServerConfig) {
metavoxelAssignment.setPayload((const unsigned char*)_metavoxelServerConfig, strlen(_metavoxelServerConfig)); metavoxelAssignment.setPayload((const unsigned char*)_metavoxelServerConfig, strlen(_metavoxelServerConfig));
} }
qDebug() << "Adding" << numFreshStaticAssignments << "static assignments to fresh file.\n"; qDebug() << "Adding" << numFreshStaticAssignments << "static assignments to fresh file.\n";
_staticAssignmentFile.open(QIODevice::WriteOnly); _staticAssignmentFile.open(QIODevice::WriteOnly);
_staticAssignmentFile.write((char*) &freshStaticAssignments, sizeof(freshStaticAssignments)); _staticAssignmentFile.write((char*) &freshStaticAssignments, sizeof(freshStaticAssignments));
_staticAssignmentFile.resize(MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS * sizeof(Assignment)); _staticAssignmentFile.resize(MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS * sizeof(Assignment));
@ -634,10 +634,10 @@ void DomainServer::prepopulateStaticAssignmentFile() {
Assignment* DomainServer::matchingStaticAssignmentForCheckIn(const QUuid& checkInUUID, NODE_TYPE nodeType) { Assignment* DomainServer::matchingStaticAssignmentForCheckIn(const QUuid& checkInUUID, NODE_TYPE nodeType) {
// pull the UUID passed with the check in // pull the UUID passed with the check in
if (_hasCompletedRestartHold) { if (_hasCompletedRestartHold) {
_assignmentQueueMutex.lock(); _assignmentQueueMutex.lock();
// iterate the assignment queue to check for a match // iterate the assignment queue to check for a match
std::deque<Assignment*>::iterator assignment = _assignmentQueue.begin(); std::deque<Assignment*>::iterator assignment = _assignmentQueue.begin();
while (assignment != _assignmentQueue.end()) { while (assignment != _assignmentQueue.end()) {
@ -650,7 +650,7 @@ Assignment* DomainServer::matchingStaticAssignmentForCheckIn(const QUuid& checkI
assignment++; assignment++;
} }
} }
_assignmentQueueMutex.unlock(); _assignmentQueueMutex.unlock();
} else { } else {
for (int i = 0; i < MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS; i++) { for (int i = 0; i < MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS; i++) {
@ -663,17 +663,17 @@ Assignment* DomainServer::matchingStaticAssignmentForCheckIn(const QUuid& checkI
} }
} }
} }
return NULL; return NULL;
} }
Assignment* DomainServer::deployableAssignmentForRequest(Assignment& requestAssignment) { Assignment* DomainServer::deployableAssignmentForRequest(Assignment& requestAssignment) {
_assignmentQueueMutex.lock(); _assignmentQueueMutex.lock();
// this is an unassigned client talking to us directly for an assignment // this is an unassigned client talking to us directly for an assignment
// go through our queue and see if there are any assignments to give out // go through our queue and see if there are any assignments to give out
std::deque<Assignment*>::iterator assignment = _assignmentQueue.begin(); std::deque<Assignment*>::iterator assignment = _assignmentQueue.begin();
while (assignment != _assignmentQueue.end()) { while (assignment != _assignmentQueue.end()) {
bool requestIsAllTypes = requestAssignment.getType() == Assignment::AllTypes; bool requestIsAllTypes = requestAssignment.getType() == Assignment::AllTypes;
bool assignmentTypesMatch = (*assignment)->getType() == requestAssignment.getType(); bool assignmentTypesMatch = (*assignment)->getType() == requestAssignment.getType();
@ -681,29 +681,29 @@ Assignment* DomainServer::deployableAssignmentForRequest(Assignment& requestAssi
bool assignmentPoolsMatch = memcmp((*assignment)->getPool(), bool assignmentPoolsMatch = memcmp((*assignment)->getPool(),
requestAssignment.getPool(), requestAssignment.getPool(),
MAX_ASSIGNMENT_POOL_BYTES) == 0; MAX_ASSIGNMENT_POOL_BYTES) == 0;
if ((requestIsAllTypes || assignmentTypesMatch) && (nietherHasPool || assignmentPoolsMatch)) { if ((requestIsAllTypes || assignmentTypesMatch) && (nietherHasPool || assignmentPoolsMatch)) {
Assignment* deployableAssignment = *assignment; Assignment* deployableAssignment = *assignment;
if ((*assignment)->getType() == Assignment::AgentType) { if ((*assignment)->getType() == Assignment::AgentType) {
// if there is more than one instance to send out, simply decrease the number of instances // if there is more than one instance to send out, simply decrease the number of instances
if ((*assignment)->getNumberOfInstances() == 1) { if ((*assignment)->getNumberOfInstances() == 1) {
_assignmentQueue.erase(assignment); _assignmentQueue.erase(assignment);
} }
deployableAssignment->decrementNumberOfInstances(); deployableAssignment->decrementNumberOfInstances();
} else { } else {
// remove the assignment from the queue // remove the assignment from the queue
_assignmentQueue.erase(assignment); _assignmentQueue.erase(assignment);
// until we get a check-in from that GUID // until we get a check-in from that GUID
// put assignment back in queue but stick it at the back so the others have a chance to go out // put assignment back in queue but stick it at the back so the others have a chance to go out
_assignmentQueue.push_back(deployableAssignment); _assignmentQueue.push_back(deployableAssignment);
} }
// stop looping, we've handed out an assignment // stop looping, we've handed out an assignment
_assignmentQueueMutex.unlock(); _assignmentQueueMutex.unlock();
return deployableAssignment; return deployableAssignment;
@ -712,17 +712,17 @@ Assignment* DomainServer::deployableAssignmentForRequest(Assignment& requestAssi
assignment++; assignment++;
} }
} }
_assignmentQueueMutex.unlock(); _assignmentQueueMutex.unlock();
return NULL; return NULL;
} }
void DomainServer::removeAssignmentFromQueue(Assignment* removableAssignment) { void DomainServer::removeAssignmentFromQueue(Assignment* removableAssignment) {
_assignmentQueueMutex.lock(); _assignmentQueueMutex.lock();
std::deque<Assignment*>::iterator assignment = _assignmentQueue.begin(); std::deque<Assignment*>::iterator assignment = _assignmentQueue.begin();
while (assignment != _assignmentQueue.end()) { while (assignment != _assignmentQueue.end()) {
if ((*assignment)->getUUID() == removableAssignment->getUUID()) { if ((*assignment)->getUUID() == removableAssignment->getUUID()) {
_assignmentQueue.erase(assignment); _assignmentQueue.erase(assignment);
@ -732,7 +732,7 @@ void DomainServer::removeAssignmentFromQueue(Assignment* removableAssignment) {
assignment++; assignment++;
} }
} }
_assignmentQueueMutex.unlock(); _assignmentQueueMutex.unlock();
} }
@ -740,7 +740,7 @@ bool DomainServer::checkInWithUUIDMatchesExistingNode(const HifiSockAddr& nodePu
const HifiSockAddr& nodeLocalSocket, const HifiSockAddr& nodeLocalSocket,
const QUuid& checkInUUID) { const QUuid& checkInUUID) {
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
if (node->getLinkedData() if (node->getLinkedData()
&& nodePublicSocket == node->getPublicSocket() && nodePublicSocket == node->getPublicSocket()
@ -750,28 +750,28 @@ bool DomainServer::checkInWithUUIDMatchesExistingNode(const HifiSockAddr& nodePu
return true; return true;
} }
} }
return false; return false;
} }
void DomainServer::addStaticAssignmentsBackToQueueAfterRestart() { void DomainServer::addStaticAssignmentsBackToQueueAfterRestart() {
_hasCompletedRestartHold = true; _hasCompletedRestartHold = true;
// if the domain-server has just restarted, // if the domain-server has just restarted,
// check if there are static assignments in the file that we need to // check if there are static assignments in the file that we need to
// throw into the assignment queue // throw into the assignment queue
// pull anything in the static assignment file that isn't spoken for and add to the assignment queue // pull anything in the static assignment file that isn't spoken for and add to the assignment queue
for (int i = 0; i < MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS; i++) { for (int i = 0; i < MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS; i++) {
if (_staticAssignments[i].getUUID().isNull()) { if (_staticAssignments[i].getUUID().isNull()) {
// reached the end of static assignments, bail // reached the end of static assignments, bail
break; break;
} }
bool foundMatchingAssignment = false; bool foundMatchingAssignment = false;
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
// enumerate the nodes and check if there is one with an attached assignment with matching UUID // enumerate the nodes and check if there is one with an attached assignment with matching UUID
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
if (node->getLinkedData()) { if (node->getLinkedData()) {
@ -782,13 +782,13 @@ void DomainServer::addStaticAssignmentsBackToQueueAfterRestart() {
} }
} }
} }
if (!foundMatchingAssignment) { if (!foundMatchingAssignment) {
// this assignment has not been fulfilled - reset the UUID and add it to the assignment queue // this assignment has not been fulfilled - reset the UUID and add it to the assignment queue
_staticAssignments[i].resetUUID(); _staticAssignments[i].resetUUID();
qDebug() << "Adding static assignment to queue -" << _staticAssignments[i] << "\n"; qDebug() << "Adding static assignment to queue -" << _staticAssignments[i] << "\n";
_assignmentQueueMutex.lock(); _assignmentQueueMutex.lock();
_assignmentQueue.push_back(&_staticAssignments[i]); _assignmentQueue.push_back(&_staticAssignments[i]);
_assignmentQueueMutex.unlock(); _assignmentQueueMutex.unlock();

View file

@ -6,7 +6,7 @@
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
// //
#include <arpa/inet.h> //#include <arpa/inet.h> // not available on windows, apparently not needed on mac
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -22,23 +22,23 @@ const int PAIRING_SERVER_PORT = 7247;
PairingHandler* PairingHandler::getInstance() { PairingHandler* PairingHandler::getInstance() {
static PairingHandler* instance = NULL; static PairingHandler* instance = NULL;
if (!instance) { if (!instance) {
instance = new PairingHandler(); instance = new PairingHandler();
} }
return instance; return instance;
} }
void PairingHandler::sendPairRequest() { void PairingHandler::sendPairRequest() {
// prepare the pairing request packet // prepare the pairing request packet
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
// use the getLocalAddress helper to get this client's listening address // use the getLocalAddress helper to get this client's listening address
quint32 localAddress = htonl(getHostOrderLocalAddress()); quint32 localAddress = htonl(getHostOrderLocalAddress());
char pairPacket[24] = {}; char pairPacket[24] = {};
sprintf(pairPacket, "Find %d.%d.%d.%d:%hu", sprintf(pairPacket, "Find %d.%d.%d.%d:%hu",
localAddress & 0xFF, localAddress & 0xFF,
@ -46,11 +46,11 @@ void PairingHandler::sendPairRequest() {
(localAddress >> 16) & 0xFF, (localAddress >> 16) & 0xFF,
(localAddress >> 24) & 0xFF, (localAddress >> 24) & 0xFF,
NodeList::getInstance()->getNodeSocket().localPort()); NodeList::getInstance()->getNodeSocket().localPort());
qDebug("Sending pair packet: %s\n", pairPacket); qDebug("Sending pair packet: %s\n", pairPacket);
HifiSockAddr pairingServerSocket(PAIRING_SERVER_HOSTNAME, PAIRING_SERVER_PORT); HifiSockAddr pairingServerSocket(PAIRING_SERVER_HOSTNAME, PAIRING_SERVER_PORT);
// send the pair request to the pairing server // send the pair request to the pairing server
nodeList->getNodeSocket().writeDatagram((char*) pairPacket, strlen(pairPacket), nodeList->getNodeSocket().writeDatagram((char*) pairPacket, strlen(pairPacket),
pairingServerSocket.getAddress(), pairingServerSocket.getPort()); pairingServerSocket.getAddress(), pairingServerSocket.getPort());

View file

@ -9,7 +9,7 @@
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
#include <netdb.h> //#include <netdb.h> // not available on windows, apparently not needed on mac
#include <QtNetwork/QHostInfo> #include <QtNetwork/QHostInfo>
@ -23,12 +23,12 @@ HifiSockAddr Logging::logstashSocket = HifiSockAddr();
char* Logging::targetName = NULL; char* Logging::targetName = NULL;
const HifiSockAddr& Logging::socket() { const HifiSockAddr& Logging::socket() {
if (logstashSocket.getAddress().isNull()) { if (logstashSocket.getAddress().isNull()) {
// we need to construct the socket object // we need to construct the socket object
// use the constant port // use the constant port
logstashSocket.setPort(htons(LOGSTASH_UDP_PORT)); logstashSocket.setPort(htons(LOGSTASH_UDP_PORT));
// lookup the IP address for the constant hostname // lookup the IP address for the constant hostname
QHostInfo hostInfo = QHostInfo::fromName(LOGSTASH_HOSTNAME); QHostInfo hostInfo = QHostInfo::fromName(LOGSTASH_HOSTNAME);
if (!hostInfo.addresses().isEmpty()) { if (!hostInfo.addresses().isEmpty()) {
@ -38,7 +38,7 @@ const HifiSockAddr& Logging::socket() {
printf("Failed to lookup logstash IP - will try again on next log attempt.\n"); printf("Failed to lookup logstash IP - will try again on next log attempt.\n");
} }
} }
return logstashSocket; return logstashSocket;
} }
@ -49,13 +49,13 @@ bool Logging::shouldSendStats() {
void Logging::stashValue(char statType, const char* key, float value) { void Logging::stashValue(char statType, const char* key, float value) {
static char logstashPacket[MAX_PACKET_SIZE]; static char logstashPacket[MAX_PACKET_SIZE];
// load up the logstash packet with the key and the passed float value // load up the logstash packet with the key and the passed float value
// send it to 4 decimal places // send it to 4 decimal places
int numPacketBytes = sprintf(logstashPacket, "%c %s %.4f", statType, key, value); int numPacketBytes = sprintf(logstashPacket, "%c %s %.4f", statType, key, value);
NodeList *nodeList = NodeList::getInstance(); NodeList *nodeList = NodeList::getInstance();
if (nodeList) { if (nodeList) {
nodeList->getNodeSocket().writeDatagram(logstashPacket, numPacketBytes, nodeList->getNodeSocket().writeDatagram(logstashPacket, numPacketBytes,
logstashSocket.getAddress(), logstashSocket.getPort()); logstashSocket.getAddress(), logstashSocket.getPort());
@ -65,7 +65,7 @@ void Logging::stashValue(char statType, const char* key, float value) {
void Logging::setTargetName(const char* targetName) { void Logging::setTargetName(const char* targetName) {
// remove the old target name, if it exists // remove the old target name, if it exists
delete Logging::targetName; delete Logging::targetName;
// copy over the new target name // copy over the new target name
Logging::targetName = new char[strlen(targetName)]; Logging::targetName = new char[strlen(targetName)];
strcpy(Logging::targetName, targetName); strcpy(Logging::targetName, targetName);
@ -92,30 +92,30 @@ const char DATE_STRING_FORMAT[] = "%F %H:%M:%S %z";
void Logging::verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { void Logging::verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
// log prefix is in the following format // log prefix is in the following format
// [DEBUG] [TIMESTAMP] [PID:PARENT_PID] [TARGET] logged string // [DEBUG] [TIMESTAMP] [PID:PARENT_PID] [TARGET] logged string
QString prefixString = QString("[%1]").arg(stringForLogType(type)); QString prefixString = QString("[%1]").arg(stringForLogType(type));
time_t rawTime; time_t rawTime;
time(&rawTime); time(&rawTime);
struct tm* localTime = localtime(&rawTime); struct tm* localTime = localtime(&rawTime);
char dateString[100]; char dateString[100];
strftime(dateString, sizeof(dateString), DATE_STRING_FORMAT, localTime); strftime(dateString, sizeof(dateString), DATE_STRING_FORMAT, localTime);
prefixString.append(QString(" [%1]").arg(dateString)); prefixString.append(QString(" [%1]").arg(dateString));
prefixString.append(QString(" [%1").arg(getpid())); prefixString.append(QString(" [%1").arg(getpid()));
pid_t parentProcessID = getppid(); pid_t parentProcessID = getppid();
if (parentProcessID != 0) { if (parentProcessID != 0) {
prefixString.append(QString(":%1]").arg(parentProcessID)); prefixString.append(QString(":%1]").arg(parentProcessID));
} else { } else {
prefixString.append("]"); prefixString.append("]");
} }
if (Logging::targetName) { if (Logging::targetName) {
prefixString.append(QString(" [%1]").arg(Logging::targetName)); prefixString.append(QString(" [%1]").arg(Logging::targetName));
} }
fprintf(stdout, "%s %s", prefixString.toLocal8Bit().constData(), message.toLocal8Bit().constData()); fprintf(stdout, "%s %s", prefixString.toLocal8Bit().constData(), message.toLocal8Bit().constData());
} }

View file

@ -12,7 +12,7 @@
#define __shared_NetworkPacket__ #define __shared_NetworkPacket__
#include <stdlib.h> #include <stdlib.h>
#include <arpa/inet.h> //#include <arpa/inet.h> // not available on windows, apparently not needed on mac
#include <ifaddrs.h> #include <ifaddrs.h>
#include "HifiSockAddr.h" #include "HifiSockAddr.h"
@ -43,7 +43,7 @@ public:
private: private:
void copyContents(const HifiSockAddr& sockAddr, const unsigned char* packetData, ssize_t packetLength); void copyContents(const HifiSockAddr& sockAddr, const unsigned char* packetData, ssize_t packetLength);
HifiSockAddr _sockAddr; HifiSockAddr _sockAddr;
ssize_t _packetLength; ssize_t _packetLength;
unsigned char _packetData[MAX_PACKET_SIZE]; unsigned char _packetData[MAX_PACKET_SIZE];

View file

@ -12,7 +12,7 @@
#ifdef _WIN32 #ifdef _WIN32
#include "Syssocket.h" #include "Syssocket.h"
#else #else
#include <arpa/inet.h> //#include <arpa/inet.h> // not available on windows, apparently not needed on mac
#endif #endif
#include "Node.h" #include "Node.h"

View file

@ -11,7 +11,9 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <arpa/inet.h> //#include <arpa/inet.h> // not available on windows, apparently not needed on mac
const int INET_ADDR_STRLEN = 16;
#include <QtNetwork/QUdpSocket> #include <QtNetwork/QUdpSocket>
@ -28,7 +30,7 @@ struct PairableDevice {
}; };
struct RequestingClient { struct RequestingClient {
char address[INET_ADDRSTRLEN]; char address[INET_ADDR_STRLEN];
int port; int port;
}; };
@ -38,67 +40,67 @@ RequestingClient* lastClient = NULL;
int indexOfFirstOccurenceOfCharacter(char* haystack, char needle) { int indexOfFirstOccurenceOfCharacter(char* haystack, char needle) {
int currentIndex = 0; int currentIndex = 0;
while (haystack[currentIndex] != '\0' && haystack[currentIndex] != needle) { while (haystack[currentIndex] != '\0' && haystack[currentIndex] != needle) {
currentIndex++; currentIndex++;
} }
return currentIndex; return currentIndex;
} }
void sendLastClientToLastDevice() { void sendLastClientToLastDevice() {
char pairData[INET_ADDRSTRLEN + 6] = {}; char pairData[INET_ADDR_STRLEN + 6] = {};
int bytesWritten = sprintf(pairData, "%s:%d", ::lastClient->address, ::lastClient->port); int bytesWritten = sprintf(pairData, "%s:%d", ::lastClient->address, ::lastClient->port);
::serverSocket.writeDatagram(pairData, bytesWritten, ::serverSocket.writeDatagram(pairData, bytesWritten,
::lastDevice->sendingSocket.getAddress(), ::lastDevice->sendingSocket.getPort()); ::lastDevice->sendingSocket.getAddress(), ::lastDevice->sendingSocket.getPort());
} }
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
serverSocket.bind(QHostAddress::LocalHost, PAIRING_SERVER_LISTEN_PORT); serverSocket.bind(QHostAddress::LocalHost, PAIRING_SERVER_LISTEN_PORT);
HifiSockAddr senderSockAddr; HifiSockAddr senderSockAddr;
char senderData[MAX_PACKET_SIZE_BYTES] = {}; char senderData[MAX_PACKET_SIZE_BYTES] = {};
while (true) { while (true) {
if (::serverSocket.hasPendingDatagrams() if (::serverSocket.hasPendingDatagrams()
&& ::serverSocket.readDatagram(senderData, MAX_PACKET_SIZE_BYTES, && ::serverSocket.readDatagram(senderData, MAX_PACKET_SIZE_BYTES,
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer())) { senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer())) {
if (senderData[0] == 'A') { if (senderData[0] == 'A') {
// this is a device reporting itself as available // this is a device reporting itself as available
PairableDevice tempDevice = {}; PairableDevice tempDevice = {};
char deviceAddress[INET_ADDRSTRLEN] = {}; char deviceAddress[INET_ADDR_STRLEN] = {};
int socketPort = 0; int socketPort = 0;
int numMatches = sscanf(senderData, "Available %s %[^:]:%d %s", int numMatches = sscanf(senderData, "Available %s %[^:]:%d %s",
tempDevice.identifier, tempDevice.identifier,
deviceAddress, deviceAddress,
&socketPort, &socketPort,
tempDevice.name); tempDevice.name);
if (numMatches >= 3) { if (numMatches >= 3) {
// if we have fewer than 3 matches the packet wasn't properly formatted // if we have fewer than 3 matches the packet wasn't properly formatted
// setup the localSocket for the pairing device // setup the localSocket for the pairing device
tempDevice.localSocket.setAddress(QHostAddress(deviceAddress)); tempDevice.localSocket.setAddress(QHostAddress(deviceAddress));
tempDevice.localSocket.setPort(socketPort); tempDevice.localSocket.setPort(socketPort);
// store this device's sending socket so we can talk back to it // store this device's sending socket so we can talk back to it
tempDevice.sendingSocket = senderSockAddr; tempDevice.sendingSocket = senderSockAddr;
// push this new device into the vector // push this new device into the vector
printf("New last device is %s (%s) at %s:%d\n", printf("New last device is %s (%s) at %s:%d\n",
tempDevice.identifier, tempDevice.identifier,
tempDevice.name, tempDevice.name,
deviceAddress, deviceAddress,
socketPort); socketPort);
// copy the tempDevice to the persisting lastDevice // copy the tempDevice to the persisting lastDevice
::lastDevice = new PairableDevice(tempDevice); ::lastDevice = new PairableDevice(tempDevice);
if (::lastClient) { if (::lastClient) {
sendLastClientToLastDevice(); sendLastClientToLastDevice();
} }
@ -106,21 +108,21 @@ int main(int argc, const char* argv[]) {
} else if (senderData[0] == 'F') { } else if (senderData[0] == 'F') {
// this is a client looking to pair with a device // this is a client looking to pair with a device
// send the most recent device this address so it can attempt to pair // send the most recent device this address so it can attempt to pair
RequestingClient tempClient = {}; RequestingClient tempClient = {};
int requestorMatches = sscanf(senderData, "Find %[^:]:%d", int requestorMatches = sscanf(senderData, "Find %[^:]:%d",
tempClient.address, tempClient.address,
&tempClient.port); &tempClient.port);
if (requestorMatches == 2) { if (requestorMatches == 2) {
// good data, copy the tempClient to the persisting lastInterfaceClient // good data, copy the tempClient to the persisting lastInterfaceClient
::lastClient = new RequestingClient(tempClient); ::lastClient = new RequestingClient(tempClient);
printf("New last client is at %s:%d\n", printf("New last client is at %s:%d\n",
::lastClient->address, ::lastClient->address,
::lastClient->port); ::lastClient->port);
if (::lastDevice) { if (::lastDevice) {
sendLastClientToLastDevice(); sendLastClientToLastDevice();
} }