From c1e93b4bf1d854788b3ce468a1cdede71fe88b4f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Sep 2013 12:26:06 -0700 Subject: [PATCH] first cut at making VoxelServer a class and library --- libraries/voxel-server-library/CMakeLists.txt | 27 ++ .../voxel-server-library}/src/NodeWatcher.cpp | 0 .../voxel-server-library}/src/NodeWatcher.h | 0 .../src/VoxelNodeData.cpp | 0 .../voxel-server-library}/src/VoxelNodeData.h | 0 .../src/VoxelPersistThread.cpp | 0 .../src/VoxelPersistThread.h | 0 .../src/VoxelSendThread.cpp | 0 .../src/VoxelSendThread.h | 0 .../voxel-server-library/src/VoxelServer.cpp | 347 ++++++++++++++++++ .../voxel-server-library}/src/VoxelServer.h | 14 + .../src/VoxelServerPacketProcessor.cpp | 0 .../src/VoxelServerPacketProcessor.h | 0 voxel-server/CMakeLists.txt | 2 + voxel-server/src/main.cpp | 329 +---------------- 15 files changed, 393 insertions(+), 326 deletions(-) create mode 100644 libraries/voxel-server-library/CMakeLists.txt rename {voxel-server => libraries/voxel-server-library}/src/NodeWatcher.cpp (100%) rename {voxel-server => libraries/voxel-server-library}/src/NodeWatcher.h (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelNodeData.cpp (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelNodeData.h (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelPersistThread.cpp (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelPersistThread.h (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelSendThread.cpp (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelSendThread.h (100%) create mode 100644 libraries/voxel-server-library/src/VoxelServer.cpp rename {voxel-server => libraries/voxel-server-library}/src/VoxelServer.h (84%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelServerPacketProcessor.cpp (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelServerPacketProcessor.h (100%) diff --git a/libraries/voxel-server-library/CMakeLists.txt b/libraries/voxel-server-library/CMakeLists.txt new file mode 100644 index 0000000000..8612f63c24 --- /dev/null +++ b/libraries/voxel-server-library/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 2.8) + +set(ROOT_DIR ../..) +set(MACRO_DIR ${ROOT_DIR}/cmake/macros) + +# setup for find modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") + +set(TARGET_NAME voxel-server-library) + +find_package(Qt5Widgets REQUIRED) + +include(${MACRO_DIR}/SetupHifiLibrary.cmake) +setup_hifi_library(${TARGET_NAME}) + +qt5_use_modules(${TARGET_NAME} Widgets) + +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) + +include(${MACRO_DIR}/LinkHifiLibrary.cmake) +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) + +# link ZLIB +find_package(ZLIB) +include_directories(${ZLIB_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) diff --git a/voxel-server/src/NodeWatcher.cpp b/libraries/voxel-server-library/src/NodeWatcher.cpp similarity index 100% rename from voxel-server/src/NodeWatcher.cpp rename to libraries/voxel-server-library/src/NodeWatcher.cpp diff --git a/voxel-server/src/NodeWatcher.h b/libraries/voxel-server-library/src/NodeWatcher.h similarity index 100% rename from voxel-server/src/NodeWatcher.h rename to libraries/voxel-server-library/src/NodeWatcher.h diff --git a/voxel-server/src/VoxelNodeData.cpp b/libraries/voxel-server-library/src/VoxelNodeData.cpp similarity index 100% rename from voxel-server/src/VoxelNodeData.cpp rename to libraries/voxel-server-library/src/VoxelNodeData.cpp diff --git a/voxel-server/src/VoxelNodeData.h b/libraries/voxel-server-library/src/VoxelNodeData.h similarity index 100% rename from voxel-server/src/VoxelNodeData.h rename to libraries/voxel-server-library/src/VoxelNodeData.h diff --git a/voxel-server/src/VoxelPersistThread.cpp b/libraries/voxel-server-library/src/VoxelPersistThread.cpp similarity index 100% rename from voxel-server/src/VoxelPersistThread.cpp rename to libraries/voxel-server-library/src/VoxelPersistThread.cpp diff --git a/voxel-server/src/VoxelPersistThread.h b/libraries/voxel-server-library/src/VoxelPersistThread.h similarity index 100% rename from voxel-server/src/VoxelPersistThread.h rename to libraries/voxel-server-library/src/VoxelPersistThread.h diff --git a/voxel-server/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp similarity index 100% rename from voxel-server/src/VoxelSendThread.cpp rename to libraries/voxel-server-library/src/VoxelSendThread.cpp diff --git a/voxel-server/src/VoxelSendThread.h b/libraries/voxel-server-library/src/VoxelSendThread.h similarity index 100% rename from voxel-server/src/VoxelSendThread.h rename to libraries/voxel-server-library/src/VoxelSendThread.h diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp new file mode 100644 index 0000000000..c4633ee1fe --- /dev/null +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -0,0 +1,347 @@ +// +// VoxelServer.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 9/16/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "VoxelNodeData.h" +#include +#include +#include +#include +#include + +#include "NodeWatcher.h" +#include "VoxelPersistThread.h" +#include "VoxelSendThread.h" +#include "VoxelServerPacketProcessor.h" + +#ifdef _WIN32 +#include "Syssocket.h" +#include "Systime.h" +#else +#include +#include +#include +#endif + +#include "VoxelServer.h" + +const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; +const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; +char voxelPersistFilename[MAX_FILENAME_LENGTH]; +int PACKETS_PER_CLIENT_PER_INTERVAL = 10; +VoxelTree serverTree(true); // this IS a reaveraging tree +bool wantVoxelPersist = true; +bool wantLocalDomain = false; +bool debugVoxelSending = false; +bool shouldShowAnimationDebug = false; +bool displayVoxelStats = false; +bool debugVoxelReceiving = false; +bool sendEnvironments = true; +bool sendMinimalEnvironment = false; +bool dumpVoxelsOnMove = false; +EnvironmentData environmentData[3]; +int receivedPacketCount = 0; +JurisdictionMap* jurisdiction = NULL; +JurisdictionSender* jurisdictionSender = NULL; +VoxelServerPacketProcessor* voxelServerPacketProcessor = NULL; +VoxelPersistThread* voxelPersistThread = NULL; +pthread_mutex_t treeLock; +NodeWatcher nodeWatcher; // used to cleanup AGENT data when agents are killed + +int VoxelServer::_argc = 0; +char** VoxelServer::_argv = NULL; + +void attachVoxelNodeDataToNode(Node* newNode) { + if (newNode->getLinkedData() == NULL) { + newNode->setLinkedData(new VoxelNodeData(newNode)); + } +} + +void VoxelServer::setArguments(int argc, char** argv) { + _argc = argc; + _argv = argv; +} + + +//int main(int argc, const char * argv[]) { +void VoxelServer::run() { + pthread_mutex_init(&::treeLock, NULL); + + qInstallMessageHandler(sharedMessageHandler); + + int listenPort = VOXEL_LISTEN_PORT; + // Check to see if the user passed in a command line option for setting listen port + const char* PORT_PARAMETER = "--port"; + const char* portParameter = getCmdOption(_argc, (const char*[])_argv, PORT_PARAMETER); + if (portParameter) { + listenPort = atoi(portParameter); + if (listenPort < 1) { + listenPort = VOXEL_LISTEN_PORT; + } + printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); + } + + const char* JURISDICTION_FILE = "--jurisdictionFile"; + const char* jurisdictionFile = getCmdOption(_argc, _argv, JURISDICTION_FILE); + if (jurisdictionFile) { + printf("jurisdictionFile=%s\n", jurisdictionFile); + + printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + jurisdiction = new JurisdictionMap(jurisdictionFile); + printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + } else { + const char* JURISDICTION_ROOT = "--jurisdictionRoot"; + const char* jurisdictionRoot = getCmdOption(_argc, _argv, JURISDICTION_ROOT); + if (jurisdictionRoot) { + printf("jurisdictionRoot=%s\n", jurisdictionRoot); + } + + const char* JURISDICTION_ENDNODES = "--jurisdictionEndNodes"; + const char* jurisdictionEndNodes = getCmdOption(_argc, _argv, JURISDICTION_ENDNODES); + if (jurisdictionEndNodes) { + printf("jurisdictionEndNodes=%s\n", jurisdictionEndNodes); + } + + if (jurisdictionRoot || jurisdictionEndNodes) { + ::jurisdiction = new JurisdictionMap(jurisdictionRoot, jurisdictionEndNodes); + } + } + + // should we send environments? Default is yes, but this command line suppresses sending + const char* DUMP_VOXELS_ON_MOVE = "--dumpVoxelsOnMove"; + ::dumpVoxelsOnMove = cmdOptionExists(_argc, _argv, DUMP_VOXELS_ON_MOVE); + printf("dumpVoxelsOnMove=%s\n", debug::valueOf(::dumpVoxelsOnMove)); + + // should we send environments? Default is yes, but this command line suppresses sending + const char* DONT_SEND_ENVIRONMENTS = "--dontSendEnvironments"; + bool dontSendEnvironments = getCmdOption(_argc, _argv, DONT_SEND_ENVIRONMENTS); + if (dontSendEnvironments) { + printf("Sending environments suppressed...\n"); + ::sendEnvironments = false; + } else { + // should we send environments? Default is yes, but this command line suppresses sending + const char* MINIMAL_ENVIRONMENT = "--MinimalEnvironment"; + ::sendMinimalEnvironment = getCmdOption(_argc, _argv, MINIMAL_ENVIRONMENT); + printf("Using Minimal Environment=%s\n", debug::valueOf(::sendMinimalEnvironment)); + } + printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments)); + + NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); + setvbuf(stdout, NULL, _IOLBF, 0); + + // tell our NodeList about our desire to get notifications + nodeList->addHook(&nodeWatcher); + + // Handle Local Domain testing with the --local command line + const char* local = "--local"; + ::wantLocalDomain = getCmdOption(_argc, _argv,local); + if (::wantLocalDomain) { + printf("Local Domain MODE!\n"); + nodeList->setDomainIPToLocalhost(); + } else { + const char* domainIP = getCmdOption(_argc, _argv, "--domain"); + if (domainIP) { + NodeList::getInstance()->setDomainHostname(domainIP); + } + } + + nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; + nodeList->startSilentNodeRemovalThread(); + + srand((unsigned)time(0)); + + const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; + ::displayVoxelStats = getCmdOption(_argc, _argv, DISPLAY_VOXEL_STATS); + printf("displayVoxelStats=%s\n", debug::valueOf(::displayVoxelStats)); + + const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; + ::debugVoxelSending = getCmdOption(_argc, _argv, DEBUG_VOXEL_SENDING); + printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending)); + + const char* DEBUG_VOXEL_RECEIVING = "--debugVoxelReceiving"; + ::debugVoxelReceiving = getCmdOption(_argc, _argv, DEBUG_VOXEL_RECEIVING); + printf("debugVoxelReceiving=%s\n", debug::valueOf(::debugVoxelReceiving)); + + const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug"; + ::shouldShowAnimationDebug = getCmdOption(_argc, _argv, WANT_ANIMATION_DEBUG); + printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug)); + + // By default we will voxel persist, if you want to disable this, then pass in this parameter + const char* NO_VOXEL_PERSIST = "--NoVoxelPersist"; + if ( getCmdOption(_argc, _argv, NO_VOXEL_PERSIST)) { + ::wantVoxelPersist = false; + } + printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist)); + + // if we want Voxel Persistence, load the local file now... + bool persistantFileRead = false; + if (::wantVoxelPersist) { + + // Check to see if the user passed in a command line option for setting packet send rate + const char* VOXELS_PERSIST_FILENAME = "--voxelsPersistFilename"; + const char* voxelsPersistFilenameParameter = getCmdOption(_argc, _argv, VOXELS_PERSIST_FILENAME); + if (voxelsPersistFilenameParameter) { + strcpy(voxelPersistFilename, voxelsPersistFilenameParameter); + } else { + strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + } + + printf("loading voxels from file: %s...\n", voxelPersistFilename); + + persistantFileRead = ::serverTree.readFromSVOFile(::voxelPersistFilename); + if (persistantFileRead) { + PerformanceWarning warn(::shouldShowAnimationDebug, + "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); + + // after done inserting all these voxels, then reaverage colors + serverTree.reaverageVoxelColors(serverTree.rootNode); + printf("Voxels reAveraged\n"); + } + + ::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it + printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead)); + unsigned long nodeCount = ::serverTree.rootNode->getSubTreeNodeCount(); + unsigned long internalNodeCount = ::serverTree.rootNode->getSubTreeInternalNodeCount(); + unsigned long leafNodeCount = ::serverTree.rootNode->getSubTreeLeafNodeCount(); + printf("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount); + + // now set up VoxelPersistThread + ::voxelPersistThread = new VoxelPersistThread(&::serverTree, ::voxelPersistFilename); + if (::voxelPersistThread) { + ::voxelPersistThread->initialize(true); + } + } + + // Check to see if the user passed in a command line option for loading an old style local + // Voxel File. If so, load it now. This is not the same as a voxel persist file + const char* INPUT_FILE = "-i"; + const char* voxelsFilename = getCmdOption(_argc, _argv, INPUT_FILE); + if (voxelsFilename) { + serverTree.readFromSVOFile(voxelsFilename); + } + + // Check to see if the user passed in a command line option for setting packet send rate + const char* PACKETS_PER_SECOND = "--packetsPerSecond"; + const char* packetsPerSecond = getCmdOption(_argc, _argv, PACKETS_PER_SECOND); + if (packetsPerSecond) { + PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/INTERVALS_PER_SECOND; + if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { + PACKETS_PER_CLIENT_PER_INTERVAL = 1; + } + printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL); + } + + // for now, initialize the environments with fixed values + environmentData[1].setID(1); + environmentData[1].setGravity(1.0f); + environmentData[1].setAtmosphereCenter(glm::vec3(0.5, 0.5, (0.25 - 0.06125)) * (float)TREE_SCALE); + environmentData[1].setAtmosphereInnerRadius(0.030625f * TREE_SCALE); + environmentData[1].setAtmosphereOuterRadius(0.030625f * TREE_SCALE * 1.05f); + environmentData[2].setID(2); + environmentData[2].setGravity(1.0f); + environmentData[2].setAtmosphereCenter(glm::vec3(0.5f, 0.5f, 0.5f) * (float)TREE_SCALE); + environmentData[2].setAtmosphereInnerRadius(0.1875f * TREE_SCALE); + environmentData[2].setAtmosphereOuterRadius(0.1875f * TREE_SCALE * 1.05f); + environmentData[2].setScatteringWavelengths(glm::vec3(0.475f, 0.570f, 0.650f)); // swaps red and blue + + sockaddr senderAddress; + + unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; + ssize_t packetLength; + + timeval lastDomainServerCheckIn = {}; + + // set up our jurisdiction broadcaster... + ::jurisdictionSender = new JurisdictionSender(::jurisdiction); + if (::jurisdictionSender) { + ::jurisdictionSender->initialize(true); + } + + // set up our VoxelServerPacketProcessor + ::voxelServerPacketProcessor = new VoxelServerPacketProcessor(); + if (::voxelServerPacketProcessor) { + ::voxelServerPacketProcessor->initialize(true); + } + + // loop to send to nodes requesting data + while (true) { + + // 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(); + } + + if (nodeList->getNodeSocket()->receive(&senderAddress, packetData, &packetLength) && + packetVersionMatch(packetData)) { + + int numBytesPacketHeader = numBytesForPacketHeader(packetData); + + if (packetData[0] == PACKET_TYPE_HEAD_DATA) { + // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we + // need to make sure we have it in our nodeList. + uint16_t nodeID = 0; + unpackNodeId(packetData + numBytesPacketHeader, &nodeID); + Node* node = NodeList::getInstance()->addOrUpdateNode(&senderAddress, + &senderAddress, + NODE_TYPE_AGENT, + nodeID); + + NodeList::getInstance()->updateNodeWithData(node, packetData, packetLength); + } else if (packetData[0] == PACKET_TYPE_PING) { + // If the packet is a ping, let processNodeData handle it. + NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); + } else if (packetData[0] == PACKET_TYPE_DOMAIN) { + NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); + } else if (packetData[0] == PACKET_TYPE_VOXEL_JURISDICTION_REQUEST) { + if (::jurisdictionSender) { + ::jurisdictionSender->queueReceivedPacket(senderAddress, packetData, packetLength); + } + } else if (::voxelServerPacketProcessor) { + ::voxelServerPacketProcessor->queueReceivedPacket(senderAddress, packetData, packetLength); + } else { + printf("unknown packet ignored... packetData[0]=%c\n", packetData[0]); + } + } + } + + if (::jurisdiction) { + delete ::jurisdiction; + } + + if (::jurisdictionSender) { + ::jurisdictionSender->terminate(); + delete ::jurisdictionSender; + } + + if (::voxelServerPacketProcessor) { + ::voxelServerPacketProcessor->terminate(); + delete ::voxelServerPacketProcessor; + } + + if (::voxelPersistThread) { + ::voxelPersistThread->terminate(); + delete ::voxelPersistThread; + } + + // tell our NodeList we're done with notifications + nodeList->removeHook(&nodeWatcher); + + pthread_mutex_destroy(&::treeLock); +} + + diff --git a/voxel-server/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h similarity index 84% rename from voxel-server/src/VoxelServer.h rename to libraries/voxel-server-library/src/VoxelServer.h index 0f4c8577db..a778e96296 100644 --- a/voxel-server/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -53,6 +53,20 @@ extern JurisdictionSender* jurisdictionSender; extern VoxelServerPacketProcessor* voxelServerPacketProcessor; extern pthread_mutex_t treeLock; +/// Handles assignments of type VoxelServer - sending voxels to various clients. +class VoxelServer { +public: + /// runs the voxel server assignment + static void run(); + + /// allows setting of run arguments + static void setArguments(int argc, char** argv); + +private: + static int _argc; + static char** _argv; +}; + #endif // __voxel_server__VoxelServer__ diff --git a/voxel-server/src/VoxelServerPacketProcessor.cpp b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp similarity index 100% rename from voxel-server/src/VoxelServerPacketProcessor.cpp rename to libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp diff --git a/voxel-server/src/VoxelServerPacketProcessor.h b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h similarity index 100% rename from voxel-server/src/VoxelServerPacketProcessor.h rename to libraries/voxel-server-library/src/VoxelServerPacketProcessor.h diff --git a/voxel-server/CMakeLists.txt b/voxel-server/CMakeLists.txt index c401a8033c..f759db0d89 100644 --- a/voxel-server/CMakeLists.txt +++ b/voxel-server/CMakeLists.txt @@ -26,3 +26,5 @@ link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) # link in the hifi avatars library link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) +# link in the hifi voxel-server-library +link_hifi_library(voxel-server-library ${TARGET_NAME} ${ROOT_DIR}) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 56ea5003e1..0e26de1f52 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -6,334 +6,11 @@ // Copyright (c) 2012 High Fidelity, Inc. All rights reserved. // -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "VoxelNodeData.h" -#include -#include -#include -#include -#include - -#include "NodeWatcher.h" -#include "VoxelPersistThread.h" -#include "VoxelSendThread.h" -#include "VoxelServerPacketProcessor.h" - -#ifdef _WIN32 -#include "Syssocket.h" -#include "Systime.h" -#else -#include -#include -#include -#endif - -#include "VoxelServer.h" - -const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; -const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; -char voxelPersistFilename[MAX_FILENAME_LENGTH]; -int PACKETS_PER_CLIENT_PER_INTERVAL = 10; -VoxelTree serverTree(true); // this IS a reaveraging tree -bool wantVoxelPersist = true; -bool wantLocalDomain = false; -bool debugVoxelSending = false; -bool shouldShowAnimationDebug = false; -bool displayVoxelStats = false; -bool debugVoxelReceiving = false; -bool sendEnvironments = true; -bool sendMinimalEnvironment = false; -bool dumpVoxelsOnMove = false; -EnvironmentData environmentData[3]; -int receivedPacketCount = 0; -JurisdictionMap* jurisdiction = NULL; -JurisdictionSender* jurisdictionSender = NULL; -VoxelServerPacketProcessor* voxelServerPacketProcessor = NULL; -VoxelPersistThread* voxelPersistThread = NULL; -pthread_mutex_t treeLock; -NodeWatcher nodeWatcher; // used to cleanup AGENT data when agents are killed - -void attachVoxelNodeDataToNode(Node* newNode) { - if (newNode->getLinkedData() == NULL) { - newNode->setLinkedData(new VoxelNodeData(newNode)); - } -} +#include int main(int argc, const char * argv[]) { - pthread_mutex_init(&::treeLock, NULL); - - qInstallMessageHandler(sharedMessageHandler); - - int listenPort = VOXEL_LISTEN_PORT; - // Check to see if the user passed in a command line option for setting listen port - const char* PORT_PARAMETER = "--port"; - const char* portParameter = getCmdOption(argc, argv, PORT_PARAMETER); - if (portParameter) { - listenPort = atoi(portParameter); - if (listenPort < 1) { - listenPort = VOXEL_LISTEN_PORT; - } - printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); - } - - const char* JURISDICTION_FILE = "--jurisdictionFile"; - const char* jurisdictionFile = getCmdOption(argc, argv, JURISDICTION_FILE); - if (jurisdictionFile) { - printf("jurisdictionFile=%s\n", jurisdictionFile); - - printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); - jurisdiction = new JurisdictionMap(jurisdictionFile); - printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); - } else { - const char* JURISDICTION_ROOT = "--jurisdictionRoot"; - const char* jurisdictionRoot = getCmdOption(argc, argv, JURISDICTION_ROOT); - if (jurisdictionRoot) { - printf("jurisdictionRoot=%s\n", jurisdictionRoot); - } - - const char* JURISDICTION_ENDNODES = "--jurisdictionEndNodes"; - const char* jurisdictionEndNodes = getCmdOption(argc, argv, JURISDICTION_ENDNODES); - if (jurisdictionEndNodes) { - printf("jurisdictionEndNodes=%s\n", jurisdictionEndNodes); - } - - if (jurisdictionRoot || jurisdictionEndNodes) { - ::jurisdiction = new JurisdictionMap(jurisdictionRoot, jurisdictionEndNodes); - } - } - - // should we send environments? Default is yes, but this command line suppresses sending - const char* DUMP_VOXELS_ON_MOVE = "--dumpVoxelsOnMove"; - ::dumpVoxelsOnMove = cmdOptionExists(argc, argv, DUMP_VOXELS_ON_MOVE); - printf("dumpVoxelsOnMove=%s\n", debug::valueOf(::dumpVoxelsOnMove)); - - // should we send environments? Default is yes, but this command line suppresses sending - const char* DONT_SEND_ENVIRONMENTS = "--dontSendEnvironments"; - bool dontSendEnvironments = cmdOptionExists(argc, argv, DONT_SEND_ENVIRONMENTS); - if (dontSendEnvironments) { - printf("Sending environments suppressed...\n"); - ::sendEnvironments = false; - } else { - // should we send environments? Default is yes, but this command line suppresses sending - const char* MINIMAL_ENVIRONMENT = "--MinimalEnvironment"; - ::sendMinimalEnvironment = cmdOptionExists(argc, argv, MINIMAL_ENVIRONMENT); - printf("Using Minimal Environment=%s\n", debug::valueOf(::sendMinimalEnvironment)); - } - printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments)); - - NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); - setvbuf(stdout, NULL, _IOLBF, 0); - - // tell our NodeList about our desire to get notifications - nodeList->addHook(&nodeWatcher); - - // Handle Local Domain testing with the --local command line - const char* local = "--local"; - ::wantLocalDomain = cmdOptionExists(argc, argv,local); - if (::wantLocalDomain) { - printf("Local Domain MODE!\n"); - nodeList->setDomainIPToLocalhost(); - } else { - const char* domainIP = getCmdOption(argc, argv, "--domain"); - if (domainIP) { - NodeList::getInstance()->setDomainHostname(domainIP); - } - } - - nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; - nodeList->startSilentNodeRemovalThread(); - - srand((unsigned)time(0)); - - const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; - ::displayVoxelStats = cmdOptionExists(argc, argv, DISPLAY_VOXEL_STATS); - printf("displayVoxelStats=%s\n", debug::valueOf(::displayVoxelStats)); - - const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; - ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); - printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending)); - - const char* DEBUG_VOXEL_RECEIVING = "--debugVoxelReceiving"; - ::debugVoxelReceiving = cmdOptionExists(argc, argv, DEBUG_VOXEL_RECEIVING); - printf("debugVoxelReceiving=%s\n", debug::valueOf(::debugVoxelReceiving)); - - const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug"; - ::shouldShowAnimationDebug = cmdOptionExists(argc, argv, WANT_ANIMATION_DEBUG); - printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug)); - - // By default we will voxel persist, if you want to disable this, then pass in this parameter - const char* NO_VOXEL_PERSIST = "--NoVoxelPersist"; - if (cmdOptionExists(argc, argv, NO_VOXEL_PERSIST)) { - ::wantVoxelPersist = false; - } - printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist)); - - // if we want Voxel Persistence, load the local file now... - bool persistantFileRead = false; - if (::wantVoxelPersist) { - - // Check to see if the user passed in a command line option for setting packet send rate - const char* VOXELS_PERSIST_FILENAME = "--voxelsPersistFilename"; - const char* voxelsPersistFilenameParameter = getCmdOption(argc, argv, VOXELS_PERSIST_FILENAME); - if (voxelsPersistFilenameParameter) { - strcpy(voxelPersistFilename, voxelsPersistFilenameParameter); - } else { - strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); - } - - printf("loading voxels from file: %s...\n", voxelPersistFilename); - - persistantFileRead = ::serverTree.readFromSVOFile(::voxelPersistFilename); - if (persistantFileRead) { - PerformanceWarning warn(::shouldShowAnimationDebug, - "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); - - // after done inserting all these voxels, then reaverage colors - serverTree.reaverageVoxelColors(serverTree.rootNode); - printf("Voxels reAveraged\n"); - } - - ::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it - printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead)); - unsigned long nodeCount = ::serverTree.rootNode->getSubTreeNodeCount(); - unsigned long internalNodeCount = ::serverTree.rootNode->getSubTreeInternalNodeCount(); - unsigned long leafNodeCount = ::serverTree.rootNode->getSubTreeLeafNodeCount(); - printf("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount); - - // now set up VoxelPersistThread - ::voxelPersistThread = new VoxelPersistThread(&::serverTree, ::voxelPersistFilename); - if (::voxelPersistThread) { - ::voxelPersistThread->initialize(true); - } - } - - // Check to see if the user passed in a command line option for loading an old style local - // Voxel File. If so, load it now. This is not the same as a voxel persist file - const char* INPUT_FILE = "-i"; - const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE); - if (voxelsFilename) { - serverTree.readFromSVOFile(voxelsFilename); - } - - // Check to see if the user passed in a command line option for setting packet send rate - const char* PACKETS_PER_SECOND = "--packetsPerSecond"; - const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND); - if (packetsPerSecond) { - PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/INTERVALS_PER_SECOND; - if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { - PACKETS_PER_CLIENT_PER_INTERVAL = 1; - } - printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL); - } - - // for now, initialize the environments with fixed values - environmentData[1].setID(1); - environmentData[1].setGravity(1.0f); - environmentData[1].setAtmosphereCenter(glm::vec3(0.5, 0.5, (0.25 - 0.06125)) * (float)TREE_SCALE); - environmentData[1].setAtmosphereInnerRadius(0.030625f * TREE_SCALE); - environmentData[1].setAtmosphereOuterRadius(0.030625f * TREE_SCALE * 1.05f); - environmentData[2].setID(2); - environmentData[2].setGravity(1.0f); - environmentData[2].setAtmosphereCenter(glm::vec3(0.5f, 0.5f, 0.5f) * (float)TREE_SCALE); - environmentData[2].setAtmosphereInnerRadius(0.1875f * TREE_SCALE); - environmentData[2].setAtmosphereOuterRadius(0.1875f * TREE_SCALE * 1.05f); - environmentData[2].setScatteringWavelengths(glm::vec3(0.475f, 0.570f, 0.650f)); // swaps red and blue - - sockaddr senderAddress; - - unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; - ssize_t packetLength; - - timeval lastDomainServerCheckIn = {}; - - // set up our jurisdiction broadcaster... - ::jurisdictionSender = new JurisdictionSender(::jurisdiction); - if (::jurisdictionSender) { - ::jurisdictionSender->initialize(true); - } - - // set up our VoxelServerPacketProcessor - ::voxelServerPacketProcessor = new VoxelServerPacketProcessor(); - if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->initialize(true); - } - - // loop to send to nodes requesting data - while (true) { - - // 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(); - } - - if (nodeList->getNodeSocket()->receive(&senderAddress, packetData, &packetLength) && - packetVersionMatch(packetData)) { - - int numBytesPacketHeader = numBytesForPacketHeader(packetData); - - if (packetData[0] == PACKET_TYPE_HEAD_DATA) { - // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we - // need to make sure we have it in our nodeList. - uint16_t nodeID = 0; - unpackNodeId(packetData + numBytesPacketHeader, &nodeID); - Node* node = NodeList::getInstance()->addOrUpdateNode(&senderAddress, - &senderAddress, - NODE_TYPE_AGENT, - nodeID); - - NodeList::getInstance()->updateNodeWithData(node, packetData, packetLength); - } else if (packetData[0] == PACKET_TYPE_PING) { - // If the packet is a ping, let processNodeData handle it. - NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); - } else if (packetData[0] == PACKET_TYPE_DOMAIN) { - NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); - } else if (packetData[0] == PACKET_TYPE_VOXEL_JURISDICTION_REQUEST) { - if (::jurisdictionSender) { - ::jurisdictionSender->queueReceivedPacket(senderAddress, packetData, packetLength); - } - } else if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->queueReceivedPacket(senderAddress, packetData, packetLength); - } else { - printf("unknown packet ignored... packetData[0]=%c\n", packetData[0]); - } - } - } - - if (::jurisdiction) { - delete ::jurisdiction; - } - - if (::jurisdictionSender) { - ::jurisdictionSender->terminate(); - delete ::jurisdictionSender; - } - - if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->terminate(); - delete ::voxelServerPacketProcessor; - } - - if (::voxelPersistThread) { - ::voxelPersistThread->terminate(); - delete ::voxelPersistThread; - } - - // tell our NodeList we're done with notifications - nodeList->removeHook(&nodeWatcher); - - pthread_mutex_destroy(&::treeLock); - - return 0; + VoxelServer::setArguments(argc, argv[]); + VoxelServer::run(); }