diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 27ef8f6540..828e91e93f 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -27,6 +27,7 @@ link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR}) +link_hifi_library(octree-server ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(voxel-server-library ${TARGET_NAME} ${ROOT_DIR}) include_directories(${ROOT_DIR}/externals/civetweb/include) diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 36588efb9e..564184caf5 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -180,6 +180,10 @@ public: virtual OctreeElement* createNewElement(unsigned char * octalCode = NULL) const = 0; + virtual bool handlesEditPacketType(PACKET_TYPE packetType) const { return false; } + virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength, + unsigned char* editData, int maxLength) { return 0; } + OctreeElement* getRoot() { return _rootNode; } void eraseAllOctreeElements(); diff --git a/libraries/voxel-server-library/src/NodeWatcher.cpp b/libraries/voxel-server-library/src/NodeWatcher.cpp deleted file mode 100644 index 03384569b8..0000000000 --- a/libraries/voxel-server-library/src/NodeWatcher.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// NodeWatcher.h -// voxel-server -// -// Created by Brad Hefta-Gaub on 8/21/13 -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// -// Node List Hook that watches for Node's being killed in order to clean up node specific memory and threads -// - -#include <NodeList.h> -#include "NodeWatcher.h" -#include "VoxelNodeData.h" - -void NodeWatcher::nodeAdded(Node* node) { - // do nothing -} - -void NodeWatcher::nodeKilled(Node* node) { - // Use this to cleanup our node - if (node->getType() == NODE_TYPE_AGENT) { - VoxelNodeData* nodeData = (VoxelNodeData*)node->getLinkedData(); - if (nodeData) { - node->setLinkedData(NULL); - delete nodeData; - } - } -}; diff --git a/libraries/voxel-server-library/src/NodeWatcher.h b/libraries/voxel-server-library/src/NodeWatcher.h deleted file mode 100644 index a730f7d575..0000000000 --- a/libraries/voxel-server-library/src/NodeWatcher.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// NodeWatcher.h -// voxel-server -// -// Created by Brad Hefta-Gaub on 8/21/13 -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// -// Node List Hook that watches for Node's being killed in order to clean up node specific memory and threads -// - -#ifndef __voxel_server__NodeWatcher__ -#define __voxel_server__NodeWatcher__ - -#include <NodeList.h> - -/// Voxel server's node watcher, which watches for nodes being killed and cleans up their data and threads -class NodeWatcher : public virtual NodeListHook { -public: - virtual void nodeAdded(Node* node); - virtual void nodeKilled(Node* node); -}; - -#endif // __voxel_server__NodeWatcher__ diff --git a/libraries/voxel-server-library/src/VoxelNodeData.cpp b/libraries/voxel-server-library/src/VoxelNodeData.cpp index a4c4bfebe2..2df418c82f 100644 --- a/libraries/voxel-server-library/src/VoxelNodeData.cpp +++ b/libraries/voxel-server-library/src/VoxelNodeData.cpp @@ -1,3 +1,6 @@ +/*** + + // // VoxelNodeData.cpp // hifi @@ -274,3 +277,5 @@ void VoxelNodeData::dumpOutOfView() { } } + +**/ diff --git a/libraries/voxel-server-library/src/VoxelNodeData.h b/libraries/voxel-server-library/src/VoxelNodeData.h index 7a39fb4362..92a5230567 100644 --- a/libraries/voxel-server-library/src/VoxelNodeData.h +++ b/libraries/voxel-server-library/src/VoxelNodeData.h @@ -9,114 +9,13 @@ #ifndef __hifi__VoxelNodeData__ #define __hifi__VoxelNodeData__ -#include <iostream> -#include <NodeData.h> -#include <VoxelPacketData.h> -#include <VoxelQuery.h> +#include <OctreeQueryNode.h> +#include <PacketHeaders.h> -#include <CoverageMap.h> -#include <VoxelConstants.h> -#include <OctreeElementBag.h> -#include <VoxelSceneStats.h> - -class VoxelSendThread; -class VoxelServer; - -class VoxelNodeData : public VoxelQuery { +class VoxelNodeData : public OctreeQueryNode { public: - VoxelNodeData(Node* owningNode); - virtual ~VoxelNodeData(); - - void resetVoxelPacket(bool lastWasSurpressed = false); // resets voxel packet to after "V" header - - void writeToPacket(const unsigned char* buffer, int bytes); // writes to end of packet - - const unsigned char* getPacket() const { return _voxelPacket; } - int getPacketLength() const { return (MAX_PACKET_SIZE - _voxelPacketAvailableBytes); } - bool isPacketWaiting() const { return _voxelPacketWaiting; } - - bool packetIsDuplicate() const; - bool shouldSuppressDuplicatePacket(); - - int getAvailable() const { return _voxelPacketAvailableBytes; } - int getMaxSearchLevel() const { return _maxSearchLevel; } - void resetMaxSearchLevel() { _maxSearchLevel = 1; } - void incrementMaxSearchLevel() { _maxSearchLevel++; } - - int getMaxLevelReached() const { return _maxLevelReachedInLastSearch; } - void setMaxLevelReached(int maxLevelReached) { _maxLevelReachedInLastSearch = maxLevelReached; } - - OctreeElementBag nodeBag; - CoverageMap map; - - ViewFrustum& getCurrentViewFrustum() { return _currentViewFrustum; } - ViewFrustum& getLastKnownViewFrustum() { return _lastKnownViewFrustum; } - - // These are not classic setters because they are calculating and maintaining state - // which is set asynchronously through the network receive - bool updateCurrentViewFrustum(); - void updateLastKnownViewFrustum(); - - bool getViewSent() const { return _viewSent; } - void setViewSent(bool viewSent); - - bool getViewFrustumChanging() const { return _viewFrustumChanging; } - bool getViewFrustumJustStoppedChanging() const { return _viewFrustumJustStoppedChanging; } - - bool moveShouldDump() const; - - uint64_t getLastTimeBagEmpty() const { return _lastTimeBagEmpty; } - void setLastTimeBagEmpty(uint64_t lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; } - - bool getCurrentPacketIsColor() const { return _currentPacketIsColor; } - bool getCurrentPacketIsCompressed() const { return _currentPacketIsCompressed; } - bool getCurrentPacketFormatMatches() { - return (getCurrentPacketIsColor() == getWantColor() && getCurrentPacketIsCompressed() == getWantCompression()); - } - - bool hasLodChanged() const { return _lodChanged; }; - - VoxelSceneStats stats; - - void initializeVoxelSendThread(VoxelServer* voxelServer); - bool isVoxelSendThreadInitalized() { return _voxelSendThread; } - - void dumpOutOfView(); - -private: - VoxelNodeData(const VoxelNodeData &); - VoxelNodeData& operator= (const VoxelNodeData&); - - bool _viewSent; - unsigned char* _voxelPacket; - unsigned char* _voxelPacketAt; - int _voxelPacketAvailableBytes; - bool _voxelPacketWaiting; - - unsigned char* _lastVoxelPacket; - int _lastVoxelPacketLength; - int _duplicatePacketCount; - uint64_t _firstSuppressedPacket; - - int _maxSearchLevel; - int _maxLevelReachedInLastSearch; - ViewFrustum _currentViewFrustum; - ViewFrustum _lastKnownViewFrustum; - uint64_t _lastTimeBagEmpty; - bool _viewFrustumChanging; - bool _viewFrustumJustStoppedChanging; - bool _currentPacketIsColor; - bool _currentPacketIsCompressed; - - VoxelSendThread* _voxelSendThread; - - // watch for LOD changes - int _lastClientBoundaryLevelAdjust; - float _lastClientVoxelSizeScale; - bool _lodChanged; - bool _lodInitialized; - - VOXEL_PACKET_SEQUENCE _sequenceNumber; + VoxelNodeData(Node* owningNode) : OctreeQueryNode(owningNode) { }; + virtual PACKET_TYPE getMyPacketType() const { return PACKET_TYPE_VOXEL_DATA; } }; #endif /* defined(__hifi__VoxelNodeData__) */ diff --git a/libraries/voxel-server-library/src/VoxelPersistThread.cpp b/libraries/voxel-server-library/src/VoxelPersistThread.cpp index 6f0d8d6b1c..13176857a1 100644 --- a/libraries/voxel-server-library/src/VoxelPersistThread.cpp +++ b/libraries/voxel-server-library/src/VoxelPersistThread.cpp @@ -1,3 +1,6 @@ + +/***** + // // VoxelPersistThread.cpp // voxel-server @@ -84,3 +87,7 @@ bool VoxelPersistThread::process() { } return isStillRunning(); // keep running till they terminate us } + + + +****/ \ No newline at end of file diff --git a/libraries/voxel-server-library/src/VoxelPersistThread.h b/libraries/voxel-server-library/src/VoxelPersistThread.h index de6b4ab094..68d0efa86d 100644 --- a/libraries/voxel-server-library/src/VoxelPersistThread.h +++ b/libraries/voxel-server-library/src/VoxelPersistThread.h @@ -1,3 +1,5 @@ +/**** + // // VoxelPersistThread.h // voxel-server @@ -42,3 +44,6 @@ private: }; #endif // __voxel_server__VoxelPersistThread__ + + +***/ \ No newline at end of file diff --git a/libraries/voxel-server-library/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp index 669979e0b0..4af48f3299 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.cpp +++ b/libraries/voxel-server-library/src/VoxelSendThread.cpp @@ -1,3 +1,5 @@ +/***** + // // VoxelSendThread.cpp // voxel-server @@ -578,3 +580,4 @@ int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nod return truePacketsSent; } +****/ \ No newline at end of file diff --git a/libraries/voxel-server-library/src/VoxelSendThread.h b/libraries/voxel-server-library/src/VoxelSendThread.h index 5fc41fbc72..797eb142fa 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.h +++ b/libraries/voxel-server-library/src/VoxelSendThread.h @@ -1,3 +1,5 @@ +/**** + // // VoxelSendThread.h // voxel-server @@ -46,3 +48,6 @@ private: }; #endif // __voxel_server__VoxelSendThread__ + + +****/ \ No newline at end of file diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 96323f7d1a..6e68b05170 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -6,44 +6,45 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#include <cmath> -#include <cstdlib> -#include <cstring> -#include <cstdio> -#include <time.h> - -#include <QtCore/QDebug> -#include <QtCore/QString> -#include <QtCore/QTimer> -#include <QtCore/QUuid> - -#include <Logging.h> -#include <OctalCode.h> -#include <NodeList.h> -#include <NodeTypes.h> #include <VoxelTree.h> -#include "VoxelNodeData.h" -#include <SharedUtil.h> -#include <PacketHeaders.h> -#include <SceneUtils.h> -#include <PerfStat.h> -#include <JurisdictionSender.h> -#include <UUID.h> - -#ifdef _WIN32 -#include "Syssocket.h" -#include "Systime.h" -#else -#include <sys/time.h> -#include <arpa/inet.h> -#include <ifaddrs.h> -#endif #include "VoxelServer.h" #include "VoxelServerConsts.h" +#include "VoxelNodeData.h" + + +VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : OctreeServer(dataBuffer, numBytes) { + // nothing special to do here... +} + +VoxelServer::~VoxelServer() { + // nothing special to do here... +} + +OctreeQueryNode* VoxelServer::createOctreeQueryNode(Node* newNode) { + return new VoxelNodeData(newNode); +} + +Octree* VoxelServer::createTree() { + return new VoxelTree(true); +} + +unsigned char VoxelServer::getMyNodeType() { + return NODE_TYPE_VOXEL_SERVER; +} + +const char* VOXEL_SERVER_LOGGING_TARGET_NAME = "voxel-server"; +const char* VoxelServer::getMyLoggingServerTargetName() { + return VOXEL_SERVER_LOGGING_TARGET_NAME; +} const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; -const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; +const char* VoxelServer::getMyDefaultPersistFilename() { + return LOCAL_VOXELS_PERSIST_FILE; +} + +/***** + void attachVoxelNodeDataToNode(Node* newNode) { if (newNode->getLinkedData() == NULL) { @@ -785,4 +786,5 @@ void VoxelServer::run() { qDebug() << "VoxelServer::run()... DONE\n"; } +**/ diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index f4923778c1..a456d3c38f 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -17,87 +17,37 @@ #include <ThreadedAssignment.h> #include <EnvironmentData.h> +#include <OctreeServer.h> #include "civetweb.h" -#include "NodeWatcher.h" + #include "VoxelPersistThread.h" #include "VoxelSendThread.h" #include "VoxelServerConsts.h" #include "VoxelServerPacketProcessor.h" /// Handles assignments of type VoxelServer - sending voxels to various clients. -class VoxelServer : public ThreadedAssignment { +class VoxelServer : public OctreeServer { public: VoxelServer(const unsigned char* dataBuffer, int numBytes); - ~VoxelServer(); - - - - /// allows setting of run arguments - void setArguments(int argc, char** argv); - bool wantsDebugVoxelSending() const { return _debugVoxelSending; } - bool wantsDebugVoxelReceiving() const { return _debugVoxelReceiving; } - bool wantsVerboseDebug() const { return _verboseDebug; } - bool wantShowAnimationDebug() const { return _shouldShowAnimationDebug; } bool wantSendEnvironments() const { return _sendEnvironments; } - bool wantDumpVoxelsOnMove() const { return _dumpVoxelsOnMove; } - bool wantDisplayVoxelStats() const { return _displayVoxelStats; } - - VoxelTree& getServerTree() { return _serverTree; } - JurisdictionMap* getJurisdiction() { return _jurisdiction; } - - int getPacketsPerClientPerInterval() const { return _packetsPerClientPerInterval; } bool getSendMinimalEnvironment() const { return _sendMinimalEnvironment; } EnvironmentData* getEnvironmentData(int i) { return &_environmentData[i]; } int getEnvironmentDataCount() const { return sizeof(_environmentData)/sizeof(EnvironmentData); } - - static VoxelServer* GetInstance() { return _theInstance; } - - bool isInitialLoadComplete() const { return (_voxelPersistThread) ? _voxelPersistThread->isInitialLoadComplete() : true; } - time_t* getLoadCompleted() { return (_voxelPersistThread) ? _voxelPersistThread->getLoadCompleted() : NULL; } - uint64_t getLoadElapsedTime() const { return (_voxelPersistThread) ? _voxelPersistThread->getLoadElapsedTime() : 0; } -public slots: - /// runs the voxel server assignment - void run(); - - void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr); -private: - int _argc; - const char** _argv; - char** _parsedArgV; - char _voxelPersistFilename[MAX_FILENAME_LENGTH]; - int _packetsPerClientPerInterval; - VoxelTree _serverTree; // this IS a reaveraging tree - bool _wantVoxelPersist; - bool _wantLocalDomain; - bool _debugVoxelSending; - bool _shouldShowAnimationDebug; - bool _displayVoxelStats; - bool _debugVoxelReceiving; + // Subclasses must implement these methods + virtual OctreeQueryNode* createOctreeQueryNode(Node* newNode); + virtual Octree* createTree(); + virtual unsigned char getMyNodeType(); + virtual const char* getMyLoggingServerTargetName(); + virtual const char* getMyDefaultPersistFilename(); + +private: bool _sendEnvironments; bool _sendMinimalEnvironment; - bool _dumpVoxelsOnMove; - bool _verboseDebug; - JurisdictionMap* _jurisdiction; - JurisdictionSender* _jurisdictionSender; - VoxelServerPacketProcessor* _voxelServerPacketProcessor; - VoxelPersistThread* _voxelPersistThread; EnvironmentData _environmentData[3]; - - NodeWatcher _nodeWatcher; // used to cleanup AGENT data when agents are killed - - void parsePayload(); - - void initMongoose(int port); - - static int civetwebRequestHandler(struct mg_connection *connection); - static VoxelServer* _theInstance; - - time_t _started; - uint64_t _startedUSecs; }; #endif // __voxel_server__VoxelServer__ diff --git a/libraries/voxel-server-library/src/VoxelServerConsts.h b/libraries/voxel-server-library/src/VoxelServerConsts.h index 216ecd8f80..e6973812f9 100644 --- a/libraries/voxel-server-library/src/VoxelServerConsts.h +++ b/libraries/voxel-server-library/src/VoxelServerConsts.h @@ -9,21 +9,6 @@ #ifndef __voxel_server__VoxelServerConsts__ #define __voxel_server__VoxelServerConsts__ -#include <SharedUtil.h> -#include <NodeList.h> // for MAX_PACKET_SIZE -#include <JurisdictionSender.h> -#include <VoxelTree.h> - -#include "VoxelServerPacketProcessor.h" - - -const int MAX_FILENAME_LENGTH = 1024; -const int INTERVALS_PER_SECOND = 60; -const int VOXEL_SEND_INTERVAL_USECS = (1000 * 1000)/INTERVALS_PER_SECOND; -const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000; -extern const char* LOCAL_VOXELS_PERSIST_FILE; -extern const char* VOXELS_PERSIST_FILE; - #endif // __voxel_server__VoxelServerConsts__ diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp index 3a0bc70f42..ac303d3c89 100644 --- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp +++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp @@ -1,3 +1,5 @@ +/****** + // // VoxelServerPacketProcessor.cpp // voxel-server @@ -221,3 +223,4 @@ SingleSenderStats::SingleSenderStats() { } +****/ \ No newline at end of file diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h index 4abdbad284..7249fff4ca 100644 --- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h +++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h @@ -1,3 +1,6 @@ +/****** + + // // VoxelServerPacketProcessor.h // voxel-server @@ -81,3 +84,6 @@ private: NodeToSenderStatsMap _singleSenderStats; }; #endif // __voxel_server__VoxelServerPacketProcessor__ + + +***/ diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index ff722143c4..b12a386a19 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -638,3 +638,54 @@ void VoxelTree::readCodeColorBufferToTreeRecursion(VoxelTreeElement* node, ReadC node->handleSubtreeChanged(this); } } + +bool VoxelTree::handlesEditPacketType(PACKET_TYPE packetType) const { + // we handle these types of "edit" packets + switch (packetType) { + case PACKET_TYPE_SET_VOXEL: + case PACKET_TYPE_SET_VOXEL_DESTRUCTIVE: + case PACKET_TYPE_ERASE_VOXEL: + return true; + } + return false; +} + +int VoxelTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength, + unsigned char* editData, int maxLength) { + + int processedBytes = 0; + // we handle these types of "edit" packets + switch (packetType) { + case PACKET_TYPE_SET_VOXEL: + case PACKET_TYPE_SET_VOXEL_DESTRUCTIVE: { + bool destructive = (packetType == PACKET_TYPE_SET_VOXEL_DESTRUCTIVE); + int octets = numberOfThreeBitSectionsInCode(editData, maxLength); + + if (octets == OVERFLOWED_OCTCODE_BUFFER) { + printf("WARNING! Got voxel edit record that would overflow buffer in numberOfThreeBitSectionsInCode(), "); + printf("bailing processing of packet!\n"); + return processedBytes; + } + + const int COLOR_SIZE_IN_BYTES = 3; + int voxelCodeSize = bytesRequiredForCodeLength(octets); + int voxelDataSize = voxelCodeSize + COLOR_SIZE_IN_BYTES; + + if (voxelDataSize > maxLength) { + printf("WARNING! Got voxel edit record that would overflow buffer, bailing processing of packet!\n"); + printf("bailing processing of packet!\n"); + return processedBytes; + } + + readCodeColorBufferToTree(editData, destructive); + + return voxelDataSize; + } break; + + case PACKET_TYPE_ERASE_VOXEL: + processRemoveOctreeElementsBitstream((unsigned char*)packetData, packetLength); + return maxLength; + } + return processedBytes; +} + diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 2654663101..eae47885b2 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -53,6 +53,11 @@ public: void readCodeColorBufferToTree(const unsigned char* codeColorBuffer, bool destructive = false); + virtual bool handlesEditPacketType(PACKET_TYPE packetType) const; + virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength, + unsigned char* editData, int maxLength); + void processSetVoxelsBitstream(const unsigned char* bitstream, int bufferSizeBytes); + /** signals: void importSize(float x, float y, float z);