From df862c152b078abbd380a8c1e3984d7a853dd0f7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 10:24:15 -0700 Subject: [PATCH 01/47] add a VoxelScriptingInterface to accept voxel addition in JS --- VoxelScriptingInterface.cpp | 9 +++++++ assignment-client/CMakeLists.txt | 3 ++- assignment-client/src/Agent.cpp | 18 ++++++------- .../src/VoxelScriptingInterface.cpp | 15 +++++++++++ .../src/VoxelScriptingInterface.h | 26 +++++++++++++++++++ 5 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 VoxelScriptingInterface.cpp create mode 100644 assignment-client/src/VoxelScriptingInterface.cpp create mode 100644 assignment-client/src/VoxelScriptingInterface.h diff --git a/VoxelScriptingInterface.cpp b/VoxelScriptingInterface.cpp new file mode 100644 index 0000000000..901bb06750 --- /dev/null +++ b/VoxelScriptingInterface.cpp @@ -0,0 +1,9 @@ +// +// VoxelScriptingInterface.cpp +// hifi +// +// Created by Stephen Birarda on 9/17/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include "VoxelScriptingInterface.h" diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 1315b0ce84..f1a8566af3 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -23,4 +23,5 @@ include_glm(${TARGET_NAME} ${ROOT_DIR}) include(${MACRO_DIR}/LinkHifiLibrary.cmake) link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file +link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) +link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 3b56a6b0b7..147314ab9d 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -9,11 +9,11 @@ #include #include +#include #include -#include "AvatarData.h" - #include "Agent.h" +#include "VoxelScriptingInterface.h" Agent::Agent() : _shouldStop(false) @@ -39,14 +39,13 @@ void Agent::run(QUrl scriptURL) { QScriptEngine engine; - AvatarData *testAvatarData = new AvatarData; - - QScriptValue avatarDataValue = engine.newQObject(testAvatarData); - engine.globalObject().setProperty("Avatar", avatarDataValue); - QScriptValue agentValue = engine.newQObject(this); engine.globalObject().setProperty("Agent", agentValue); + VoxelScriptingInterface voxelScripter; + QScriptValue voxelScripterValue = engine.newQObject(&voxelScripter); + engine.globalObject().setProperty("Voxels", voxelScripterValue); + qDebug() << "Downloaded script:" << scriptString << "\n"; qDebug() << "Evaluated script:" << engine.evaluate(scriptString).toString() << "\n"; @@ -75,9 +74,10 @@ void Agent::run(QUrl scriptURL) { NodeList::getInstance()->sendDomainServerCheckIn(); } + // allow the scripter's call back to setup visual data emit preSendCallback(); - - testAvatarData->sendData(); + // flush the voxel packet queue + voxelScripter.getVoxelPacketSender()->flushQueue(); if (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes)) { NodeList::getInstance()->processNodeData((sockaddr*) &senderAddress, receivedData, receivedBytes); diff --git a/assignment-client/src/VoxelScriptingInterface.cpp b/assignment-client/src/VoxelScriptingInterface.cpp new file mode 100644 index 0000000000..9dce6a7c11 --- /dev/null +++ b/assignment-client/src/VoxelScriptingInterface.cpp @@ -0,0 +1,15 @@ +// +// VoxelScriptingInterface.cpp +// hifi +// +// Created by Stephen Birarda on 9/17/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include "VoxelScriptingInterface.h" + +void VoxelScriptingInterface::queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue) { + // setup a VoxelDetail struct with the data + VoxelDetail addVoxelDetail = {x, y, z, scale, red, green, blue}; + _voxelPacketSender.queueVoxelEditMessages(PACKET_TYPE_SET_VOXEL, 1, &addVoxelDetail); +} diff --git a/assignment-client/src/VoxelScriptingInterface.h b/assignment-client/src/VoxelScriptingInterface.h new file mode 100644 index 0000000000..e78dce5ff1 --- /dev/null +++ b/assignment-client/src/VoxelScriptingInterface.h @@ -0,0 +1,26 @@ +// +// VoxelScriptingInterface.h +// hifi +// +// Created by Stephen Birarda on 9/17/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__VoxelScriptingInterface__ +#define __hifi__VoxelScriptingInterface__ + +#include + +#include + +class VoxelScriptingInterface : public QObject { + Q_OBJECT +public: + VoxelEditPacketSender* getVoxelPacketSender() { return &_voxelPacketSender; } +public slots: + void queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue); +private: + VoxelEditPacketSender _voxelPacketSender; +}; + +#endif /* defined(__hifi__VoxelScriptingInterface__) */ From a45d64a214a8021e4ac5c24e73139769b4b56abe Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 10:49:51 -0700 Subject: [PATCH 02/47] add ability to send a voxel in JS via VoxelScriptingInterface --- assignment-client/src/Agent.cpp | 4 +-- .../src/VoxelScriptingInterface.cpp | 2 +- domain-server/src/main.cpp | 30 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 147314ab9d..98f0a0e525 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -23,7 +23,7 @@ Agent::Agent() : void Agent::run(QUrl scriptURL) { NodeList::getInstance()->setOwnerType(NODE_TYPE_AGENT); - NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_AVATAR_MIXER, 1); + NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_VOXEL_SERVER, 1); QNetworkAccessManager manager; @@ -77,7 +77,7 @@ void Agent::run(QUrl scriptURL) { // allow the scripter's call back to setup visual data emit preSendCallback(); // flush the voxel packet queue - voxelScripter.getVoxelPacketSender()->flushQueue(); + voxelScripter.getVoxelPacketSender()->process(); if (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes)) { NodeList::getInstance()->processNodeData((sockaddr*) &senderAddress, receivedData, receivedBytes); diff --git a/assignment-client/src/VoxelScriptingInterface.cpp b/assignment-client/src/VoxelScriptingInterface.cpp index 9dce6a7c11..343cb01a44 100644 --- a/assignment-client/src/VoxelScriptingInterface.cpp +++ b/assignment-client/src/VoxelScriptingInterface.cpp @@ -11,5 +11,5 @@ void VoxelScriptingInterface::queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue) { // setup a VoxelDetail struct with the data VoxelDetail addVoxelDetail = {x, y, z, scale, red, green, blue}; - _voxelPacketSender.queueVoxelEditMessages(PACKET_TYPE_SET_VOXEL, 1, &addVoxelDetail); + _voxelPacketSender.sendVoxelEditMessage(PACKET_TYPE_SET_VOXEL, addVoxelDetail); } diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 8912c24483..0a935761a3 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -172,21 +172,21 @@ int main(int argc, const char* argv[]) { while (true) { - ::assignmentQueueMutex.lock(); - // check if our audio-mixer or avatar-mixer are dead and we don't have existing assignments in the queue - // so we can add those assignments back to the front of the queue since they are high-priority - if (!nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER) && - std::find(::assignmentQueue.begin(), assignmentQueue.end(), &avatarMixerAssignment) == ::assignmentQueue.end()) { - qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n"); - ::assignmentQueue.push_front(&avatarMixerAssignment); - } - - if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) && - std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &audioMixerAssignment) == ::assignmentQueue.end()) { - qDebug("Missing an audio mixer and assignment not in queue. Adding.\n"); - ::assignmentQueue.push_front(&audioMixerAssignment); - } - ::assignmentQueueMutex.unlock(); +// ::assignmentQueueMutex.lock(); +// // check if our audio-mixer or avatar-mixer are dead and we don't have existing assignments in the queue +// // so we can add those assignments back to the front of the queue since they are high-priority +// if (!nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER) && +// std::find(::assignmentQueue.begin(), assignmentQueue.end(), &avatarMixerAssignment) == ::assignmentQueue.end()) { +// qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n"); +// ::assignmentQueue.push_front(&avatarMixerAssignment); +// } +// +// if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) && +// std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &audioMixerAssignment) == ::assignmentQueue.end()) { +// qDebug("Missing an audio mixer and assignment not in queue. Adding.\n"); +// ::assignmentQueue.push_front(&audioMixerAssignment); +// } +// ::assignmentQueueMutex.unlock(); while (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) && packetVersionMatch(packetData)) { From 75c59c486393901c10cd199a5862e7c5c2a58122 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 10:54:44 -0700 Subject: [PATCH 03/47] add doxygen comments to VoxelScriptingInterface --- assignment-client/src/VoxelScriptingInterface.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/assignment-client/src/VoxelScriptingInterface.h b/assignment-client/src/VoxelScriptingInterface.h index e78dce5ff1..00be3d536f 100644 --- a/assignment-client/src/VoxelScriptingInterface.h +++ b/assignment-client/src/VoxelScriptingInterface.h @@ -13,13 +13,23 @@ #include +/// handles scripting of voxel commands from JS passed to assigned clients class VoxelScriptingInterface : public QObject { Q_OBJECT public: VoxelEditPacketSender* getVoxelPacketSender() { return &_voxelPacketSender; } public slots: + /// queues the creation of a voxel which will be sent by calling process on the PacketSender + /// \param x the x-coordinate of the voxel (in VS space) + /// \param y the y-coordinate of the voxel (in VS space) + /// \param z the z-coordinate of the voxel (in VS space) + /// \param scale the scale of the voxel (in VS space) + /// \param red the R value for RGB color of voxel + /// \param green the G value for RGB color of voxel + /// \param blue the B value for RGB color of voxel void queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue); private: + /// attached VoxelEditPacketSender that handles queuing and sending of packets to VS VoxelEditPacketSender _voxelPacketSender; }; From 17fda717fe85fc7e8fea952a12cc5d2b7fcd1297 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 11:04:46 -0700 Subject: [PATCH 04/47] move audio and avatar classes into assignment-client target --- assignment-client/CMakeLists.txt | 8 +++++++- assignment-client/src/Agent.cpp | 2 +- .../src => assignment-client/src/audio}/AudioMixer.cpp | 0 .../src => assignment-client/src/audio}/AudioMixer.h | 0 .../src/audio}/AvatarAudioRingBuffer.cpp | 0 .../src/audio}/AvatarAudioRingBuffer.h | 0 .../src/avatars}/AvatarMixer.cpp | 0 .../src/avatars}/AvatarMixer.h | 0 assignment-client/src/main.cpp | 4 ++-- .../src/{ => voxels}/VoxelScriptingInterface.cpp | 0 .../src/{ => voxels}/VoxelScriptingInterface.h | 0 cmake/macros/SetupHifiProject.cmake | 10 +++++++++- libraries/audio/CMakeLists.txt | 8 +------- 13 files changed, 20 insertions(+), 12 deletions(-) rename {libraries/audio/src => assignment-client/src/audio}/AudioMixer.cpp (100%) rename {libraries/audio/src => assignment-client/src/audio}/AudioMixer.h (100%) rename {libraries/audio/src => assignment-client/src/audio}/AvatarAudioRingBuffer.cpp (100%) rename {libraries/audio/src => assignment-client/src/audio}/AvatarAudioRingBuffer.h (100%) rename {libraries/avatars/src => assignment-client/src/avatars}/AvatarMixer.cpp (100%) rename {libraries/avatars/src => assignment-client/src/avatars}/AvatarMixer.h (100%) rename assignment-client/src/{ => voxels}/VoxelScriptingInterface.cpp (100%) rename assignment-client/src/{ => voxels}/VoxelScriptingInterface.h (100%) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index f1a8566af3..5d61190286 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -24,4 +24,10 @@ include(${MACRO_DIR}/LinkHifiLibrary.cmake) link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file +link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) + +# link the stk library +set(STK_ROOT_DIR ${ROOT_DIR}/externals/stk) +find_package(STK REQUIRED) +target_link_libraries(${TARGET_NAME} ${STK_LIBRARIES}) +include_directories(${STK_INCLUDE_DIRS}) \ No newline at end of file diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 98f0a0e525..ac6f1eca4f 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -13,7 +13,7 @@ #include #include "Agent.h" -#include "VoxelScriptingInterface.h" +#include "voxels/VoxelScriptingInterface.h" Agent::Agent() : _shouldStop(false) diff --git a/libraries/audio/src/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp similarity index 100% rename from libraries/audio/src/AudioMixer.cpp rename to assignment-client/src/audio/AudioMixer.cpp diff --git a/libraries/audio/src/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h similarity index 100% rename from libraries/audio/src/AudioMixer.h rename to assignment-client/src/audio/AudioMixer.h diff --git a/libraries/audio/src/AvatarAudioRingBuffer.cpp b/assignment-client/src/audio/AvatarAudioRingBuffer.cpp similarity index 100% rename from libraries/audio/src/AvatarAudioRingBuffer.cpp rename to assignment-client/src/audio/AvatarAudioRingBuffer.cpp diff --git a/libraries/audio/src/AvatarAudioRingBuffer.h b/assignment-client/src/audio/AvatarAudioRingBuffer.h similarity index 100% rename from libraries/audio/src/AvatarAudioRingBuffer.h rename to assignment-client/src/audio/AvatarAudioRingBuffer.h diff --git a/libraries/avatars/src/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp similarity index 100% rename from libraries/avatars/src/AvatarMixer.cpp rename to assignment-client/src/avatars/AvatarMixer.cpp diff --git a/libraries/avatars/src/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h similarity index 100% rename from libraries/avatars/src/AvatarMixer.h rename to assignment-client/src/avatars/AvatarMixer.h diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 16522a2d87..2ad8345e53 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -16,8 +16,8 @@ #include "Agent.h" #include -#include -#include +#include "audio/AudioMixer.h" +#include "avatars/AvatarMixer.h" #include #include #include diff --git a/assignment-client/src/VoxelScriptingInterface.cpp b/assignment-client/src/voxels/VoxelScriptingInterface.cpp similarity index 100% rename from assignment-client/src/VoxelScriptingInterface.cpp rename to assignment-client/src/voxels/VoxelScriptingInterface.cpp diff --git a/assignment-client/src/VoxelScriptingInterface.h b/assignment-client/src/voxels/VoxelScriptingInterface.h similarity index 100% rename from assignment-client/src/VoxelScriptingInterface.h rename to assignment-client/src/voxels/VoxelScriptingInterface.h diff --git a/cmake/macros/SetupHifiProject.cmake b/cmake/macros/SetupHifiProject.cmake index 8b2bcb542c..e828e68be2 100644 --- a/cmake/macros/SetupHifiProject.cmake +++ b/cmake/macros/SetupHifiProject.cmake @@ -2,7 +2,15 @@ MACRO(SETUP_HIFI_PROJECT TARGET INCLUDE_QT) project(${TARGET}) # grab the implemenation and header files - file(GLOB TARGET_SRCS src/*.cpp src/*.h src/*.c) + file(GLOB TARGET_SRCS src/*) + + file(GLOB SRC_SUBDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src/*) + foreach(DIR ${SRC_SUBDIRS}) + if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/${DIR}) + FILE(GLOB DIR_CONTENTS src/${DIR}/*) + SET(TARGET_SRCS ${TARGET_SRCS} ${DIR_CONTENTS}) + endif() + endforeach() # add the executable add_executable(${TARGET} ${TARGET_SRCS}) diff --git a/libraries/audio/CMakeLists.txt b/libraries/audio/CMakeLists.txt index 6c458149bc..2d82fff1e1 100644 --- a/libraries/audio/CMakeLists.txt +++ b/libraries/audio/CMakeLists.txt @@ -16,10 +16,4 @@ 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 the stk library -set(STK_ROOT_DIR ${ROOT_DIR}/externals/stk) -find_package(STK REQUIRED) -target_link_libraries(${TARGET_NAME} ${STK_LIBRARIES}) -include_directories(${STK_INCLUDE_DIRS}) \ No newline at end of file +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file From 0e19d9a53ad0e0303750ffc5d49f63cc5175418a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 11:19:13 -0700 Subject: [PATCH 05/47] add handling for number of instances to domain-server --- domain-server/src/main.cpp | 49 ++++++++++++++++++++----------- libraries/shared/src/Assignment.h | 5 ++++ 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 0a935761a3..0d76482808 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -76,9 +76,20 @@ static int mongooseRequestHandler(struct mg_connection *conn) { const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "resources/web/assignment"; static void mongooseUploadHandler(struct mg_connection *conn, const char *path) { + // create an assignment for this saved script, for now make it local only Assignment *scriptAssignment = new Assignment(Assignment::CreateCommand, Assignment::AgentType, Assignment::LocalLocation); + // 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 *requestInstancesHeader = mg_get_header(conn, ASSIGNMENT_INSTANCES_HTTP_HEADER); + + if (requestInstancesHeader) { + // the user has requested a number of instances greater than 1 + // so set that on the created assignment + scriptAssignment->setNumberOfInstances(atoi(requestInstancesHeader)); + } + QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION); newPath += "/"; // append the UUID for this script as the new filename, remove the curly braces @@ -94,7 +105,6 @@ static void mongooseUploadHandler(struct mg_connection *conn, const char *path) ::assignmentQueueMutex.lock(); ::assignmentQueue.push_back(scriptAssignment); ::assignmentQueueMutex.unlock(); - } int main(int argc, const char* argv[]) { @@ -172,21 +182,21 @@ int main(int argc, const char* argv[]) { while (true) { -// ::assignmentQueueMutex.lock(); -// // check if our audio-mixer or avatar-mixer are dead and we don't have existing assignments in the queue -// // so we can add those assignments back to the front of the queue since they are high-priority -// if (!nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER) && -// std::find(::assignmentQueue.begin(), assignmentQueue.end(), &avatarMixerAssignment) == ::assignmentQueue.end()) { -// qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n"); -// ::assignmentQueue.push_front(&avatarMixerAssignment); -// } -// -// if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) && -// std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &audioMixerAssignment) == ::assignmentQueue.end()) { -// qDebug("Missing an audio mixer and assignment not in queue. Adding.\n"); -// ::assignmentQueue.push_front(&audioMixerAssignment); -// } -// ::assignmentQueueMutex.unlock(); + ::assignmentQueueMutex.lock(); + // check if our audio-mixer or avatar-mixer are dead and we don't have existing assignments in the queue + // so we can add those assignments back to the front of the queue since they are high-priority + if (!nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER) && + std::find(::assignmentQueue.begin(), assignmentQueue.end(), &avatarMixerAssignment) == ::assignmentQueue.end()) { + qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n"); + ::assignmentQueue.push_front(&avatarMixerAssignment); + } + + if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) && + std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &audioMixerAssignment) == ::assignmentQueue.end()) { + qDebug("Missing an audio mixer and assignment not in queue. Adding.\n"); + ::assignmentQueue.push_front(&audioMixerAssignment); + } + ::assignmentQueueMutex.unlock(); while (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) && packetVersionMatch(packetData)) { @@ -308,7 +318,12 @@ int main(int argc, const char* argv[]) { if ((*assignment)->getType() == Assignment::AgentType) { // if this is a script assignment we need to delete it to avoid a memory leak - delete *assignment; + // or if there is more than one instance to send out, simpy decrease the number of instances + if ((*assignment)->getNumberOfInstances() > 1) { + (*assignment)->decrementNumberOfInstances(); + } else { + delete *assignment; + } } // stop looping, we've handed out an assignment diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 6985f21535..dc246a9ad6 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -55,6 +55,10 @@ public: Assignment::Location getLocation() const { return _location; } const timeval& getTime() const { return _time; } + int getNumberOfInstances() const { return _numberOfInstances; } + void setNumberOfInstances(int numberOfInstances) { _numberOfInstances = numberOfInstances; } + void decrementNumberOfInstances() { --_numberOfInstances; } + const sockaddr* getAttachedPublicSocket() { return _attachedPublicSocket; } void setAttachedPublicSocket(const sockaddr* attachedPublicSocket); @@ -77,6 +81,7 @@ private: sockaddr* _attachedPublicSocket; /// pointer to a public socket that relates to assignment, depends on direction sockaddr* _attachedLocalSocket; /// pointer to a local socket that relates to assignment, depends on direction timeval _time; /// time the assignment was created (set in constructor) + int _numberOfInstances; /// the number of instances of this assignment }; QDebug operator<<(QDebug debug, const Assignment &assignment); From 76df707e3192ed870ca0ba03ff130cbbebf13b46 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 11:48:08 -0700 Subject: [PATCH 06/47] add the ability to ask for multiple instances from JS page --- .../resources/web/assignment/css/style.css | 13 +++++++++++- .../resources/web/assignment/index.shtml | 3 +++ .../resources/web/assignment/js/assignment.js | 6 ++++++ domain-server/src/main.cpp | 21 ++++++++++++------- libraries/shared/src/Assignment.cpp | 6 ++++-- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/domain-server/resources/web/assignment/css/style.css b/domain-server/resources/web/assignment/css/style.css index 000f2eff67..b6c26ca9fd 100644 --- a/domain-server/resources/web/assignment/css/style.css +++ b/domain-server/resources/web/assignment/css/style.css @@ -36,11 +36,22 @@ body { } #deploy-button { background-color: #0DFFBB; - right: 0px; + right: 85px; } #deploy-button:hover { background-color: #28FF57; } + +#instance-field { + position: absolute; + right: 20px; + top: 40px; +} + +#instance-field input { + width: 80px; +} + #stop-button { background-color: #CC1F00; right: 0px; diff --git a/domain-server/resources/web/assignment/index.shtml b/domain-server/resources/web/assignment/index.shtml index fe47b818ed..0bc0e67eef 100644 --- a/domain-server/resources/web/assignment/index.shtml +++ b/domain-server/resources/web/assignment/index.shtml @@ -14,6 +14,9 @@ Run +
+ +
diff --git a/domain-server/resources/web/assignment/js/assignment.js b/domain-server/resources/web/assignment/js/assignment.js index 630acd4847..a34f539961 100644 --- a/domain-server/resources/web/assignment/js/assignment.js +++ b/domain-server/resources/web/assignment/js/assignment.js @@ -20,6 +20,11 @@ $(document).ready(function(){ // add the script + script + '\r\n' + '--' + boundary + '--'; + + var headers = {}; + if ($('#instance-field input').val()) { + headers['ASSIGNMENT-INSTANCES'] = $('#instance-field input').val(); + } // post form to assignment in order to create an assignment $.ajax({ @@ -27,6 +32,7 @@ $(document).ready(function(){ data: body, type: "POST", url: "/assignment", + headers: headers, success: function (data, status) { console.log(data); console.log(status); diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 0d76482808..b4b5c0ec36 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -313,17 +313,18 @@ int main(int argc, const char* argv[]) { broadcastPacket, numHeaderBytes + numAssignmentBytes); - // remove the assignment from the queue - ::assignmentQueue.erase(assignment); - if ((*assignment)->getType() == Assignment::AgentType) { // if this is a script assignment we need to delete it to avoid a memory leak // or if there is more than one instance to send out, simpy decrease the number of instances if ((*assignment)->getNumberOfInstances() > 1) { (*assignment)->decrementNumberOfInstances(); } else { + ::assignmentQueue.erase(assignment); delete *assignment; } + } else { + // remove the assignment from the queue + ::assignmentQueue.erase(assignment); } // stop looping, we've handed out an assignment @@ -351,12 +352,18 @@ int main(int argc, const char* argv[]) { nodeList->sendAssignment(*(*assignment)); - // remove the assignment from the queue - ::assignmentQueue.erase(assignment); - if ((*assignment)->getType() == Assignment::AgentType) { // if this is a script assignment we need to delete it to avoid a memory leak - delete *assignment; + // or if there is more than one instance to send out, simpy decrease the number of instances + if ((*assignment)->getNumberOfInstances() > 1) { + (*assignment)->decrementNumberOfInstances(); + } else { + ::assignmentQueue.erase(assignment); + delete *assignment; + } + } else { + // remove the assignment from the queue + ::assignmentQueue.erase(assignment); } // stop looping, we've handed out an assignment diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 8f6d20db9e..d794495c29 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -21,7 +21,8 @@ Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assig _type(type), _location(location), _attachedPublicSocket(NULL), - _attachedLocalSocket(NULL) + _attachedLocalSocket(NULL), + _numberOfInstances(1) { // set the create time on this assignment gettimeofday(&_time, NULL); @@ -35,7 +36,8 @@ Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assig Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : _location(GlobalLocation), _attachedPublicSocket(NULL), - _attachedLocalSocket(NULL) + _attachedLocalSocket(NULL), + _numberOfInstances(1) { // set the create time on this assignment gettimeofday(&_time, NULL); From 2cfa45e4f86fe293406a8c8b0fadf9312b4291ab Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 12:09:10 -0700 Subject: [PATCH 07/47] allow the assignment-client to specify the type of assignment it desires --- assignment-client/src/main.cpp | 14 +++++++-- assignment-server/src/main.cpp | 55 ++++++++++++++++++++-------------- domain-server/src/main.cpp | 46 ++++++++++++++++------------ 3 files changed, 71 insertions(+), 44 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index f58828e65f..76fb99839a 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -31,6 +31,7 @@ const char CHILD_TARGET_NAME[] = "assignment-client"; pid_t* childForks = NULL; sockaddr_in customAssignmentSocket = {}; int numForks = 0; +Assignment::Type overiddenAssignmentType = Assignment::AllTypes; void childClient() { // this is one of the child forks or there is a single assignment client, continue assignment-client execution @@ -56,8 +57,8 @@ void childClient() { sockaddr_in senderSocket = {}; - // create a request assignment, accept all assignments, pass the desired pool (if it exists) - Assignment requestAssignment(Assignment::RequestCommand, Assignment::AllTypes); + // create a request assignment, accept assignments defined by the overidden type + Assignment requestAssignment(Assignment::RequestCommand, ::overiddenAssignmentType); while (true) { if (usecTimestampNow() - usecTimestamp(&lastRequest) >= ASSIGNMENT_REQUEST_INTERVAL_USECS) { @@ -211,6 +212,15 @@ int main(int argc, const char* argv[]) { ::customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServerHostname, assignmentServerPort); } + const char ASSIGNMENT_TYPE_OVVERIDE_OPTION[] = "-t"; + const char* assignmentTypeString = getCmdOption(argc, argv, ASSIGNMENT_TYPE_OVVERIDE_OPTION); + + if (assignmentTypeString) { + // the user is asking to only be assigned to a particular type of assignment + // so set that as the ::overridenAssignmentType to be used in requests + ::overiddenAssignmentType = (Assignment::Type) atoi(assignmentTypeString); + } + const char* NUM_FORKS_PARAMETER = "-n"; const char* numForksString = getCmdOption(argc, argv, NUM_FORKS_PARAMETER); diff --git a/assignment-server/src/main.cpp b/assignment-server/src/main.cpp index caec59cd77..db335008a5 100644 --- a/assignment-server/src/main.cpp +++ b/assignment-server/src/main.cpp @@ -62,30 +62,39 @@ int main(int argc, const char* argv[]) { continue; } - // check if the requestor is on the same network as the destination for the assignment - if (senderSocket.sin_addr.s_addr == - ((sockaddr_in*) (*assignment)->getAttachedPublicSocket())->sin_addr.s_addr) { - // if this is the case we remove the public socket on the assignment by setting it to NULL - // this ensures the local IP and port sent to the requestor is the local address of destination - (*assignment)->setAttachedPublicSocket(NULL); + if (requestAssignment.getType() == Assignment::AllTypes || + (*assignment)->getType() == requestAssignment.getType()) { + // give this assignment out, either we have a type match or the requestor has said they will + // take all types + + // check if the requestor is on the same network as the destination for the assignment + if (senderSocket.sin_addr.s_addr == + ((sockaddr_in*) (*assignment)->getAttachedPublicSocket())->sin_addr.s_addr) { + // if this is the case we remove the public socket on the assignment by setting it to NULL + // this ensures the local IP and port sent to the requestor is the local address of destination + (*assignment)->setAttachedPublicSocket(NULL); + } + + + int numAssignmentBytes = (*assignment)->packToBuffer(assignmentPacket + numSendHeaderBytes); + + // send the assignment + serverSocket.send((sockaddr*) &senderSocket, + assignmentPacket, + numSendHeaderBytes + numAssignmentBytes); + + + // delete this assignment now that it has been sent out + delete *assignment; + // remove it from the deque and make the iterator the next assignment + assignmentQueue.erase(assignment); + + // stop looping - we've handed out an assignment + break; + } else { + // push forward the iterator to check the next assignment + assignment++; } - - - int numAssignmentBytes = (*assignment)->packToBuffer(assignmentPacket + numSendHeaderBytes); - - // send the assignment - serverSocket.send((sockaddr*) &senderSocket, - assignmentPacket, - numSendHeaderBytes + numAssignmentBytes); - - - // delete this assignment now that it has been sent out - delete *assignment; - // remove it from the deque and make the iterator the next assignment - assignmentQueue.erase(assignment); - - // stop looping - we've handed out an assignment - break; } } } else if (senderData[0] == PACKET_TYPE_CREATE_ASSIGNMENT && packetVersionMatch(senderData)) { diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 3cb433b933..62d8be42b7 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -330,31 +330,39 @@ int main(int argc, const char* argv[]) { std::deque::iterator assignment = ::assignmentQueue.begin(); while (assignment != ::assignmentQueue.end()) { + // construct the requested assignment from the packet data + Assignment requestAssignment(packetData, receivedBytes); - // give this assignment out, no conditions stop us from giving it to the local assignment client - int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT); - int numAssignmentBytes = (*assignment)->packToBuffer(broadcastPacket + numHeaderBytes); - - nodeList->getNodeSocket()->send((sockaddr*) &nodePublicAddress, - broadcastPacket, - numHeaderBytes + numAssignmentBytes); - - if ((*assignment)->getType() == Assignment::AgentType) { - // if this is a script assignment we need to delete it to avoid a memory leak - // or if there is more than one instance to send out, simpy decrease the number of instances - if ((*assignment)->getNumberOfInstances() > 1) { - (*assignment)->decrementNumberOfInstances(); + if (requestAssignment.getType() == Assignment::AllTypes || + (*assignment)->getType() == requestAssignment.getType()) { + // 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 numAssignmentBytes = (*assignment)->packToBuffer(broadcastPacket + numHeaderBytes); + + nodeList->getNodeSocket()->send((sockaddr*) &nodePublicAddress, + broadcastPacket, + numHeaderBytes + numAssignmentBytes); + + if ((*assignment)->getType() == Assignment::AgentType) { + // if this is a script assignment we need to delete it to avoid a memory leak + // or if there is more than one instance to send out, simpy decrease the number of instances + if ((*assignment)->getNumberOfInstances() > 1) { + (*assignment)->decrementNumberOfInstances(); + } else { + ::assignmentQueue.erase(assignment); + delete *assignment; + } } else { + // remove the assignment from the queue ::assignmentQueue.erase(assignment); - delete *assignment; } + + // stop looping, we've handed out an assignment + break; } else { - // remove the assignment from the queue - ::assignmentQueue.erase(assignment); + // push forward the iterator to check the next assignment + assignment++; } - - // stop looping, we've handed out an assignment - break; } ::assignmentQueueMutex.unlock(); From 48a579ae496a9a969ea0011031f25e0a51c1fc7d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 17 Sep 2013 12:18:46 -0700 Subject: [PATCH 08/47] first cut at domain server config support --- domain-server/src/main.cpp | 41 +++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 044ea0b369..843044b83d 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -27,7 +27,10 @@ #include #include +#include #include +#include +#include #include @@ -45,6 +48,7 @@ const int NODE_COUNT_STAT_INTERVAL_MSECS = 5000; QMutex assignmentQueueMutex; std::deque assignmentQueue; +QMap configMap; unsigned char* addNodeToBroadcastPacket(unsigned char* currentPosition, Node* nodeToAdd) { *currentPosition++ = nodeToAdd->getType(); @@ -58,7 +62,7 @@ unsigned char* addNodeToBroadcastPacket(unsigned char* currentPosition, Node* no } static int mongooseRequestHandler(struct mg_connection *conn) { - const struct mg_request_info *ri = mg_get_request_info(conn); + const struct mg_request_info* ri = mg_get_request_info(conn); if (strcmp(ri->uri, "/assignment") == 0 && strcmp(ri->request_method, "POST") == 0) { // return a 200 @@ -66,6 +70,37 @@ static int mongooseRequestHandler(struct mg_connection *conn) { // upload the file mg_upload(conn, "/tmp"); + return 1; + } else if (strncmp(ri->uri, "/config", strlen("/config")) == 0 && strcmp(ri->request_method, "GET") == 0) { + + // Let's split up the URL into it's pieces so we can service it + QString uri(ri->uri); + QString delimiterPattern("/"); + QStringList uriParts = uri.split(delimiterPattern); + + QString configGuid = uriParts[2]; + + // first part should be empty + // second part should be "config" + // third part should be a guid, and therefore should not be empty + if (!uriParts[0].isEmpty() || uriParts[1] != "config" || configGuid.isEmpty()) { + mg_printf(conn, "%s", "HTTP/1.0 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nInvalid parameters."); + return 1; + } + + // assuming the request format was valid, look up the guid in our configs + if (!::configMap.contains(configGuid)) { + mg_printf(conn, "%s", "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nInvalid config GUID."); + return 1; + } + + const char * configPayload = configMap[configGuid].toLocal8Bit().data(); + + // return a 200 + mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n\r\n"); + // return the configuration "payload" + mg_printf(conn, "%s", configPayload); + return 1; } else { // have mongoose process this request from the document_root @@ -157,13 +192,13 @@ int main(int argc, const char* argv[]) { localSocket.sin_addr.s_addr = serverLocalAddress; // setup the mongoose web server - struct mg_context *ctx; + struct mg_context* ctx; struct mg_callbacks callbacks = {}; QString documentRoot = QString("%1/resources/web").arg(QCoreApplication::applicationDirPath()); // list of options. Last element must be NULL. - const char *options[] = {"listening_ports", "8080", + const char* options[] = {"listening_ports", "8080", "document_root", documentRoot.toStdString().c_str(), NULL}; callbacks.begin_request = mongooseRequestHandler; From 4932c3266fa09b0fede12f09c5498c27aae34baf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 17 Sep 2013 13:22:09 -0700 Subject: [PATCH 09/47] moving to Assignment payload style implementation --- domain-server/src/main.cpp | 48 ++++++++----------------------- libraries/shared/src/Assignment.h | 8 ++++++ 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index ab837a0abe..fb2869c327 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -48,7 +48,6 @@ const int NODE_COUNT_STAT_INTERVAL_MSECS = 5000; QMutex assignmentQueueMutex; std::deque assignmentQueue; -QMap configMap; unsigned char* addNodeToBroadcastPacket(unsigned char* currentPosition, Node* nodeToAdd) { *currentPosition++ = nodeToAdd->getType(); @@ -70,37 +69,6 @@ static int mongooseRequestHandler(struct mg_connection *conn) { // upload the file mg_upload(conn, "/tmp"); - return 1; - } else if (strncmp(ri->uri, "/config", strlen("/config")) == 0 && strcmp(ri->request_method, "GET") == 0) { - - // Let's split up the URL into it's pieces so we can service it - QString uri(ri->uri); - QString delimiterPattern("/"); - QStringList uriParts = uri.split(delimiterPattern); - - QString configGuid = uriParts[2]; - - // first part should be empty - // second part should be "config" - // third part should be a guid, and therefore should not be empty - if (!uriParts[0].isEmpty() || uriParts[1] != "config" || configGuid.isEmpty()) { - mg_printf(conn, "%s", "HTTP/1.0 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nInvalid parameters."); - return 1; - } - - // assuming the request format was valid, look up the guid in our configs - if (!::configMap.contains(configGuid)) { - mg_printf(conn, "%s", "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nInvalid config GUID."); - return 1; - } - - const char * configPayload = configMap[configGuid].toLocal8Bit().data(); - - // return a 200 - mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n\r\n"); - // return the configuration "payload" - mg_printf(conn, "%s", configPayload); - return 1; } else { // have mongoose process this request from the document_root @@ -166,7 +134,7 @@ int main(int argc, const char* argv[]) { in_addr_t serverLocalAddress = getLocalAddress(); nodeList->startSilentNodeRemovalThread(); - + timeval lastStatSendTime = {}; const char ASSIGNMENT_SERVER_OPTION[] = "-a"; @@ -194,6 +162,15 @@ int main(int argc, const char* argv[]) { Assignment voxelServerAssignment(Assignment::CreateCommand, Assignment::VoxelServerType, Assignment::LocalLocation); + + // Handle Domain/Voxel Server configuration command line arguments + const char VOXEL_CONFIG_OPTION[] = "--voxelServerConfig"; + const char* voxelServerConfig = getCmdOption(argc, argv, VOXEL_CONFIG_OPTION); + if (voxelServerConfig) { + qDebug("Reading Voxel Server Configuration.\n"); + qDebug() << " config: " << voxelServerConfig << "\n"; + voxelServerAssignment.setDataPayload((unsigned char*)voxelServerConfig, strlen(voxelServerConfig) + 1); + } // construct a local socket to send with our created assignments to the global AS sockaddr_in localSocket = {}; @@ -249,10 +226,9 @@ int main(int argc, const char* argv[]) { } } const int MIN_VOXEL_SERVER_CHECKS = 10; - if (checkForVoxelServerAttempt > MIN_VOXEL_SERVER_CHECKS && - voxelServerCount == 0 && + if (checkForVoxelServerAttempt > MIN_VOXEL_SERVER_CHECKS && voxelServerCount == 0 && std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &voxelServerAssignment) == ::assignmentQueue.end()) { - qDebug("Missing a Voxel Server and assignment not in queue. Adding.\n"); + qDebug("Missing a voxel server and assignment not in queue. Adding.\n"); ::assignmentQueue.push_front(&voxelServerAssignment); } checkForVoxelServerAttempt++; diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 59e2c45db7..1f0431187a 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -15,6 +15,8 @@ #include "NodeList.h" +const int MAX_PAYLOAD_SIZE = 1024; + /// Holds information used for request, creation, and deployment of assignments class Assignment { public: @@ -65,6 +67,10 @@ public: const sockaddr* getAttachedLocalSocket() { return _attachedLocalSocket; } void setAttachedLocalSocket(const sockaddr* attachedLocalSocket); + + unsigned char* getDataPayload() { return _dataPayload; } + int getDataPayloadSize() { return _dataPayloadSize; } + void setDataPayload(unsigned char* data, int length) { memcpy(_dataPayload, data, length); _dataPayloadSize = length; } /// Packs the assignment to the passed buffer /// \param buffer the buffer in which to pack the assignment @@ -83,6 +89,8 @@ private: sockaddr* _attachedLocalSocket; /// pointer to a local socket that relates to assignment, depends on direction timeval _time; /// time the assignment was created (set in constructor) int _numberOfInstances; /// the number of instances of this assignment + unsigned char _dataPayload[MAX_PAYLOAD_SIZE]; + int _dataPayloadSize; }; QDebug operator<<(QDebug debug, const Assignment &assignment); From 94f04a98064f75c969a090ff6c967d4a31285e26 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 13:24:25 -0700 Subject: [PATCH 10/47] add API to attach payloads to assignments --- libraries/shared/src/Assignment.cpp | 70 ++++++++++++++++++++++------- libraries/shared/src/Assignment.h | 5 +++ 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index d794495c29..55837e4107 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -22,7 +22,9 @@ Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assig _location(location), _attachedPublicSocket(NULL), _attachedLocalSocket(NULL), - _numberOfInstances(1) + _numberOfInstances(1), + _payload(NULL), + _numPayloadBytes(0) { // set the create time on this assignment gettimeofday(&_time, NULL); @@ -37,7 +39,9 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : _location(GlobalLocation), _attachedPublicSocket(NULL), _attachedLocalSocket(NULL), - _numberOfInstances(1) + _numberOfInstances(1), + _payload(NULL), + _numPayloadBytes(0) { // set the create time on this assignment gettimeofday(&_time, NULL); @@ -65,23 +69,31 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : if (numBytes > numBytesRead) { - sockaddr* newSocket = NULL; - - if (dataBuffer[numBytesRead++] == IPv4_ADDRESS_DESIGNATOR) { - // IPv4 address - newSocket = (sockaddr*) new sockaddr_in; - unpackSocket(dataBuffer + numBytesRead, newSocket); - } else { - // IPv6 address, or bad designator - qDebug("Received a socket that cannot be unpacked!\n"); + if (_command != Assignment::RequestCommand) { + sockaddr* newSocket = NULL; + + if (dataBuffer[numBytesRead++] == IPv4_ADDRESS_DESIGNATOR) { + // IPv4 address + newSocket = (sockaddr*) new sockaddr_in; + numBytesRead += unpackSocket(dataBuffer + numBytesRead, newSocket); + + if (_command == Assignment::CreateCommand) { + delete _attachedLocalSocket; + _attachedLocalSocket = newSocket; + } else { + delete _attachedPublicSocket; + _attachedPublicSocket = newSocket; + } + } else { + // IPv6 address, or bad designator + qDebug("Received a socket that cannot be unpacked!\n"); + } } - if (_command == Assignment::CreateCommand) { - delete _attachedLocalSocket; - _attachedLocalSocket = newSocket; - } else { - delete _attachedPublicSocket; - _attachedPublicSocket = newSocket; + _numPayloadBytes = numBytes - numBytesRead; + + if (_numPayloadBytes > 0) { + memcpy(_payload, dataBuffer + numBytesRead, numBytes - numBytesRead); } } } @@ -89,6 +101,25 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : Assignment::~Assignment() { delete _attachedPublicSocket; delete _attachedLocalSocket; + delete _payload; + _numPayloadBytes = 0; +} + +const int MAX_PAYLOAD_BYTES = 1024; + +void Assignment::setPayload(uchar* payload, int numBytes) { + _payload = payload; + + if (numBytes > MAX_PAYLOAD_BYTES) { + qDebug("Set payload called with number of bytes greater than maximum (%d). Will only transfer %d bytes.\n", + MAX_PAYLOAD_BYTES, + MAX_PAYLOAD_BYTES); + + _numPayloadBytes = 1024; + } else { + _numPayloadBytes = numBytes; + } + } QString Assignment::getUUIDStringWithoutCurlyBraces() const { @@ -141,6 +172,11 @@ int Assignment::packToBuffer(unsigned char* buffer) { numPackedBytes += packSocket(buffer + numPackedBytes, socketToPack); } + if (_numPayloadBytes) { + memcpy(buffer + numPackedBytes, _payload, _numPayloadBytes); + numPackedBytes += _numPayloadBytes; + } + return numPackedBytes; } diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 59e2c45db7..4f46ea9e7e 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -56,6 +56,9 @@ public: Assignment::Location getLocation() const { return _location; } const timeval& getTime() const { return _time; } + uchar* getPayload() { return _payload; } + void setPayload(uchar *payload, int numBytes); + int getNumberOfInstances() const { return _numberOfInstances; } void setNumberOfInstances(int numberOfInstances) { _numberOfInstances = numberOfInstances; } void decrementNumberOfInstances() { --_numberOfInstances; } @@ -83,6 +86,8 @@ private: sockaddr* _attachedLocalSocket; /// pointer to a local socket that relates to assignment, depends on direction timeval _time; /// time the assignment was created (set in constructor) int _numberOfInstances; /// the number of instances of this assignment + uchar *_payload; /// an optional payload attached to this assignment, a maximum for 1024 bytes will be packed + int _numPayloadBytes; /// number of bytes in the payload, up to a maximum of 1024 }; QDebug operator<<(QDebug debug, const Assignment &assignment); From 3f2dc7a28de07f3c67033d262ae4c02696bdd55b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 13:27:17 -0700 Subject: [PATCH 11/47] add a getter for the number of bytes in the payload --- libraries/shared/src/Assignment.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 4f46ea9e7e..325cca1c8e 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -57,6 +57,7 @@ public: const timeval& getTime() const { return _time; } uchar* getPayload() { return _payload; } + int getNumPayloadBytes() const { return _numPayloadBytes; } void setPayload(uchar *payload, int numBytes); int getNumberOfInstances() const { return _numberOfInstances; } From fb7927d32677506c70977f10a885a02b6b7c1506 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 13:28:19 -0700 Subject: [PATCH 12/47] cleanup check for attached socket --- libraries/shared/src/Assignment.cpp | 40 +++++++++++++---------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 55837e4107..3a02408a7b 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -67,34 +67,30 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : memcpy(&_type, dataBuffer + numBytesRead, sizeof(Assignment::Type)); numBytesRead += sizeof(Assignment::Type); - if (numBytes > numBytesRead) { + if (_command != Assignment::RequestCommand) { + sockaddr* newSocket = NULL; - if (_command != Assignment::RequestCommand) { - sockaddr* newSocket = NULL; + if (dataBuffer[numBytesRead++] == IPv4_ADDRESS_DESIGNATOR) { + // IPv4 address + newSocket = (sockaddr*) new sockaddr_in; + numBytesRead += unpackSocket(dataBuffer + numBytesRead, newSocket); - if (dataBuffer[numBytesRead++] == IPv4_ADDRESS_DESIGNATOR) { - // IPv4 address - newSocket = (sockaddr*) new sockaddr_in; - numBytesRead += unpackSocket(dataBuffer + numBytesRead, newSocket); - - if (_command == Assignment::CreateCommand) { - delete _attachedLocalSocket; - _attachedLocalSocket = newSocket; - } else { - delete _attachedPublicSocket; - _attachedPublicSocket = newSocket; - } + if (_command == Assignment::CreateCommand) { + delete _attachedLocalSocket; + _attachedLocalSocket = newSocket; } else { - // IPv6 address, or bad designator - qDebug("Received a socket that cannot be unpacked!\n"); + delete _attachedPublicSocket; + _attachedPublicSocket = newSocket; } + } else { + // IPv6 address, or bad designator + qDebug("Received a socket that cannot be unpacked!\n"); } - + } + + if (numBytes > numBytesRead) { _numPayloadBytes = numBytes - numBytesRead; - - if (_numPayloadBytes > 0) { - memcpy(_payload, dataBuffer + numBytesRead, numBytes - numBytesRead); - } + memcpy(_payload, dataBuffer + numBytesRead, numBytes - numBytesRead); } } From 386250cff8fe7ee263436645b5b7da6e62803f15 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 17 Sep 2013 13:41:04 -0700 Subject: [PATCH 13/47] remove hacked payloads --- libraries/shared/src/Assignment.cpp | 2 +- libraries/shared/src/Assignment.h | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index d794495c29..cad644652e 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -140,7 +140,7 @@ int Assignment::packToBuffer(unsigned char* buffer) { numPackedBytes += packSocket(buffer + numPackedBytes, socketToPack); } - + return numPackedBytes; } diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 1f0431187a..adcbf32d2a 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -15,8 +15,6 @@ #include "NodeList.h" -const int MAX_PAYLOAD_SIZE = 1024; - /// Holds information used for request, creation, and deployment of assignments class Assignment { public: @@ -68,10 +66,6 @@ public: const sockaddr* getAttachedLocalSocket() { return _attachedLocalSocket; } void setAttachedLocalSocket(const sockaddr* attachedLocalSocket); - unsigned char* getDataPayload() { return _dataPayload; } - int getDataPayloadSize() { return _dataPayloadSize; } - void setDataPayload(unsigned char* data, int length) { memcpy(_dataPayload, data, length); _dataPayloadSize = length; } - /// Packs the assignment to the passed buffer /// \param buffer the buffer in which to pack the assignment /// \return number of bytes packed into buffer @@ -89,8 +83,6 @@ private: sockaddr* _attachedLocalSocket; /// pointer to a local socket that relates to assignment, depends on direction timeval _time; /// time the assignment was created (set in constructor) int _numberOfInstances; /// the number of instances of this assignment - unsigned char _dataPayload[MAX_PAYLOAD_SIZE]; - int _dataPayloadSize; }; QDebug operator<<(QDebug debug, const Assignment &assignment); From 2388cfc8e07bd7491bdb8da14f613707b4cc5221 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 17 Sep 2013 14:33:31 -0700 Subject: [PATCH 14/47] first cut at making VoxelServer class run with configuration or standalone --- assignment-client/src/main.cpp | 12 +++++++++++- domain-server/src/main.cpp | 2 +- libraries/voxel-server-library/src/VoxelServer.cpp | 14 ++++++++------ libraries/voxel-server-library/src/VoxelServer.h | 14 ++++++++------ voxel-server/src/main.cpp | 10 ++++++---- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 76fb99839a..f287e1066e 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -32,6 +32,7 @@ pid_t* childForks = NULL; sockaddr_in customAssignmentSocket = {}; int numForks = 0; Assignment::Type overiddenAssignmentType = Assignment::AllTypes; +std::vector voxelServers; void childClient() { // this is one of the child forks or there is a single assignment client, continue assignment-client execution @@ -100,7 +101,9 @@ void childClient() { } else if (deployedAssignment.getType() == Assignment::AvatarMixerType) { AvatarMixer::run(); } else if (deployedAssignment.getType() == Assignment::VoxelServerType) { - VoxelServer::run(); + VoxelServer* voxelServer = new VoxelServer(); + ::voxelServers.push_back(voxelServer); + voxelServer->run((const char*)deployedAssignment.getPayload()); } else { // figure out the URL for the script for this agent assignment QString scriptURLString("http://%1:8080/assignment/%2"); @@ -162,6 +165,13 @@ void sigchldHandler(int sig) { } } } + + // cleanup voxelServers + for (int i = 0; i < ::voxelServers.size(); i++) { + VoxelServer* voxelServer = ::voxelServers[i]; + delete voxelServer; + } + } void parentMonitor() { diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index fb2869c327..ec7a4a8897 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -169,7 +169,7 @@ int main(int argc, const char* argv[]) { if (voxelServerConfig) { qDebug("Reading Voxel Server Configuration.\n"); qDebug() << " config: " << voxelServerConfig << "\n"; - voxelServerAssignment.setDataPayload((unsigned char*)voxelServerConfig, strlen(voxelServerConfig) + 1); + voxelServerAssignment.setPayload((uchar*)voxelServerConfig, strlen(voxelServerConfig) + 1); } // construct a local socket to send with our created assignments to the global AS diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index b239a180d9..d2c9613619 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -63,22 +63,24 @@ VoxelPersistThread* voxelPersistThread = NULL; pthread_mutex_t treeLock; NodeWatcher nodeWatcher; // used to cleanup AGENT data when agents are killed -int VoxelServer::_argc = 0; -const char** VoxelServer::_argv = NULL; -bool VoxelServer::_dontKillOnMissingDomain = false; - void attachVoxelNodeDataToNode(Node* newNode) { if (newNode->getLinkedData() == NULL) { newNode->setLinkedData(new VoxelNodeData(newNode)); } } +VoxelServer::VoxelServer() { + _argc = 0; + _argv = NULL; + _dontKillOnMissingDomain = false; +} + void VoxelServer::setArguments(int argc, char** argv) { _argc = argc; _argv = const_cast(argv); } -void VoxelServer::setupDomainAndPort(const char* domain, int port) { +void VoxelServer::setupStandAlone(const char* domain, int port) { NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, port); // Handle Local Domain testing with the --local command line @@ -98,7 +100,7 @@ void VoxelServer::setupDomainAndPort(const char* domain, int port) { } //int main(int argc, const char * argv[]) { -void VoxelServer::run() { +void VoxelServer::run(const char* configuration) { pthread_mutex_init(&::treeLock, NULL); qInstallMessageHandler(sharedMessageHandler); diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index d51870dbb1..6739f4cfeb 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -12,23 +12,25 @@ /// Handles assignments of type VoxelServer - sending voxels to various clients. class VoxelServer { public: + VoxelServer(); + /// runs the voxel server assignment - static void run(); + void run(const char* configuration = NULL); /// allows setting of run arguments - static void setArguments(int argc, char** argv); + void setArguments(int argc, char** argv); /// when VoxelServer class is used by voxel-server stand alone executable it calls this to specify the domain /// and port it is handling. When called by assignment-client, this is not needed because assignment-client /// handles ports and domains automatically. /// \param const char* domain domain name, IP address, or local to specify the domain the voxel server is serving /// \param int port port the voxel server will listen on - static void setupDomainAndPort(const char* domain, int port); + void setupStandAlone(const char* domain, int port); private: - static int _argc; - static const char** _argv; - static bool _dontKillOnMissingDomain; + int _argc; + const char** _argv; + bool _dontKillOnMissingDomain; }; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index f854df84cf..4d82c43343 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -29,17 +29,19 @@ int main(int argc, const char * argv[]) { } printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); } + + VoxelServer ourVoxelServer; if (wantLocalDomain) { - VoxelServer::setupDomainAndPort(local, listenPort); + ourVoxelServer.setupStandAlone(local, listenPort); } else { if (domainIP) { - VoxelServer::setupDomainAndPort(domainIP, listenPort); + ourVoxelServer.setupStandAlone(domainIP, listenPort); } } - VoxelServer::setArguments(argc, const_cast(argv)); - VoxelServer::run(); + ourVoxelServer.setArguments(argc, const_cast(argv)); + ourVoxelServer.run(); } From d830351ed6608478b7b6eb15c1d100a2a4f61a5f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 14:54:58 -0700 Subject: [PATCH 15/47] make the assignment targets subclasses of Assignment for access to UUID --- VoxelScriptingInterface.cpp | 9 ----- assignment-client/src/Agent.cpp | 12 ++++-- assignment-client/src/Agent.h | 10 ++--- assignment-client/src/AssignmentFactory.cpp | 33 +++++++++++++++ assignment-client/src/AssignmentFactory.h | 19 +++++++++ assignment-client/src/audio/AudioMixer.cpp | 4 ++ assignment-client/src/audio/AudioMixer.h | 8 +++- assignment-client/src/avatars/AvatarMixer.cpp | 4 ++ assignment-client/src/avatars/AvatarMixer.h | 8 ++-- assignment-client/src/main.cpp | 40 ++++++++----------- libraries/shared/src/Assignment.cpp | 16 +++++--- libraries/shared/src/Assignment.h | 6 ++- libraries/shared/src/NodeList.h | 1 + .../voxel-server-library/src/VoxelServer.h | 7 +++- 14 files changed, 121 insertions(+), 56 deletions(-) delete mode 100644 VoxelScriptingInterface.cpp create mode 100644 assignment-client/src/AssignmentFactory.cpp create mode 100644 assignment-client/src/AssignmentFactory.h diff --git a/VoxelScriptingInterface.cpp b/VoxelScriptingInterface.cpp deleted file mode 100644 index 901bb06750..0000000000 --- a/VoxelScriptingInterface.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// VoxelScriptingInterface.cpp -// hifi -// -// Created by Stephen Birarda on 9/17/13. -// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. -// - -#include "VoxelScriptingInterface.h" diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index ac6f1eca4f..a2d96c6a1c 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -15,18 +15,22 @@ #include "Agent.h" #include "voxels/VoxelScriptingInterface.h" -Agent::Agent() : - _shouldStop(false) -{ +Agent::Agent(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes) { } -void Agent::run(QUrl scriptURL) { +void Agent::run() { NodeList::getInstance()->setOwnerType(NODE_TYPE_AGENT); NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_VOXEL_SERVER, 1); QNetworkAccessManager manager; + // figure out the URL for the script for this agent assignment + QString scriptURLString("http://%1:8080/assignment/%2"); + scriptURLString = scriptURLString.arg(NodeList::getInstance()->getDomainIP(), + this->getUUIDStringWithoutCurlyBraces()); + QUrl scriptURL(scriptURLString); + qDebug() << "Attemping download of " << scriptURL << "\n"; QNetworkReply* reply = manager.get(QNetworkRequest(scriptURL)); diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 45d0beb650..5e0765fd33 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -9,19 +9,19 @@ #ifndef __hifi__Agent__ #define __hifi__Agent__ -#include "SharedUtil.h" - #include #include -class Agent : public QObject { +#include + +class Agent : public Assignment { Q_OBJECT public: - Agent(); + Agent(const unsigned char* dataBuffer, int numBytes); bool volatile _shouldStop; - void run(QUrl scriptUrl); + void run(); signals: void preSendCallback(); }; diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp new file mode 100644 index 0000000000..01abceea1b --- /dev/null +++ b/assignment-client/src/AssignmentFactory.cpp @@ -0,0 +1,33 @@ +// +// AssignmentFactory.cpp +// hifi +// +// Created by Stephen Birarda on 9/17/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include + +#include "Agent.h" +#include "audio/AudioMixer.h" +#include "avatars/AvatarMixer.h" + +#include "AssignmentFactory.h" + +Assignment* AssignmentFactory::unpackAssignment(const unsigned char* dataBuffer, int numBytes) { + int headerBytes = numBytesForPacketHeader(dataBuffer); + + Assignment::Type type; + memcpy(&type, dataBuffer + headerBytes, sizeof(type)); + + switch (type) { + case Assignment::AudioMixerType: + return new AudioMixer(dataBuffer, numBytes); + case Assignment::AvatarMixerType: + return new AvatarMixer(dataBuffer, numBytes); + case Assignment::AgentType: + return new Agent(dataBuffer, numBytes); + default: + return new Assignment(dataBuffer, numBytes); + } +} \ No newline at end of file diff --git a/assignment-client/src/AssignmentFactory.h b/assignment-client/src/AssignmentFactory.h new file mode 100644 index 0000000000..8adadb07ed --- /dev/null +++ b/assignment-client/src/AssignmentFactory.h @@ -0,0 +1,19 @@ +// +// AssignmentFactory.h +// hifi +// +// Created by Stephen Birarda on 9/17/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__AssignmentFactory__ +#define __hifi__AssignmentFactory__ + +#include "Assignment.h" + +class AssignmentFactory { +public: + static Assignment* unpackAssignment(const unsigned char* dataBuffer, int numBytes); +}; + +#endif /* defined(__hifi__AssignmentFactory__) */ diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index d4b6097134..930b44dbce 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -69,6 +69,10 @@ void attachNewBufferToNode(Node *newNode) { } } +AudioMixer::AudioMixer(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes) { + +} + void AudioMixer::run() { // change the logging target name while this is running Logging::setTargetName(AUDIO_MIXER_LOGGING_TARGET_NAME); diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index fa67d55bca..565bae180a 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -9,11 +9,15 @@ #ifndef __hifi__AudioMixer__ #define __hifi__AudioMixer__ +#include + /// Handles assignments of type AudioMixer - mixing streams of audio and re-distributing to various clients. -class AudioMixer { +class AudioMixer : public Assignment { public: + AudioMixer(const unsigned char* dataBuffer, int numBytes); + /// runs the audio mixer - static void run(); + void run(); }; #endif /* defined(__hifi__AudioMixer__) */ diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index acf77be8da..604301a391 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -83,6 +83,10 @@ void broadcastAvatarData(NodeList* nodeList, sockaddr* nodeAddress) { nodeList->getNodeSocket()->send(nodeAddress, broadcastPacket, currentBufferPosition - broadcastPacket); } +AvatarMixer::AvatarMixer(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes) { + +} + void AvatarMixer::run() { // change the logging target name while AvatarMixer is running Logging::setTargetName(AVATAR_MIXER_LOGGING_NAME); diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 7e58e067ce..41a584a296 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -9,13 +9,15 @@ #ifndef __hifi__AvatarMixer__ #define __hifi__AvatarMixer__ -#include +#include /// Handles assignments of type AvatarMixer - distribution of avatar data to various clients -class AvatarMixer { +class AvatarMixer : public Assignment { public: + AvatarMixer(const unsigned char* dataBuffer, int numBytes); + /// runs the avatar mixer - static void run(); + void run(); }; #endif /* defined(__hifi__AvatarMixer__) */ diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 76fb99839a..3d4f4b6e4c 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -14,16 +14,19 @@ #include -#include "Agent.h" -#include -#include "audio/AudioMixer.h" -#include "avatars/AvatarMixer.h" + #include #include #include #include #include +#include "Agent.h" +#include "Assignment.h" +#include "AssignmentFactory.h" +#include "audio/AudioMixer.h" +#include "avatars/AvatarMixer.h" + const long long ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000; const char PARENT_TARGET_NAME[] = "assignment-client-monitor"; const char CHILD_TARGET_NAME[] = "assignment-client"; @@ -73,13 +76,13 @@ void childClient() { && packetVersionMatch(packetData)) { // construct the deployed assignment from the packet data - Assignment deployedAssignment(packetData, receivedBytes); + Assignment *deployedAssignment = AssignmentFactory::unpackAssignment(packetData, receivedBytes); qDebug() << "Received an assignment -" << deployedAssignment << "\n"; // switch our nodelist DOMAIN_IP if (packetData[0] == PACKET_TYPE_CREATE_ASSIGNMENT || - deployedAssignment.getAttachedPublicSocket()->sa_family == AF_INET) { + deployedAssignment->getAttachedPublicSocket()->sa_family == AF_INET) { in_addr domainSocketAddr = {}; @@ -88,36 +91,25 @@ void childClient() { domainSocketAddr = senderSocket.sin_addr; } else { // grab the domain server IP address from the packet from the AS - domainSocketAddr = ((sockaddr_in*) deployedAssignment.getAttachedPublicSocket())->sin_addr; + domainSocketAddr = ((sockaddr_in*) deployedAssignment->getAttachedPublicSocket())->sin_addr; } nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); qDebug("Destination IP for assignment is %s\n", inet_ntoa(domainSocketAddr)); - if (deployedAssignment.getType() == Assignment::AudioMixerType) { - AudioMixer::run(); - } else if (deployedAssignment.getType() == Assignment::AvatarMixerType) { - AvatarMixer::run(); - } else if (deployedAssignment.getType() == Assignment::VoxelServerType) { - VoxelServer::run(); - } else { - // figure out the URL for the script for this agent assignment - QString scriptURLString("http://%1:8080/assignment/%2"); - scriptURLString = scriptURLString.arg(inet_ntoa(domainSocketAddr), - deployedAssignment.getUUIDStringWithoutCurlyBraces()); - - qDebug() << "Starting an Agent assignment-client with script at" << scriptURLString << "\n"; - - Agent scriptAgent; - scriptAgent.run(QUrl(scriptURLString)); - } + // run the deployed assignment + deployedAssignment->run(); + } else { qDebug("Received a bad destination socket for assignment.\n"); } qDebug("Assignment finished or never started - waiting for new assignment\n"); + // delete the deployedAssignment + delete deployedAssignment; + // reset our NodeList by switching back to unassigned and clearing the list nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); nodeList->clear(); diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 3a02408a7b..1cd30afaf0 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -58,15 +58,15 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : numBytesRead += numBytesForPacketHeader(dataBuffer); + memcpy(&_type, dataBuffer + numBytesRead, sizeof(Assignment::Type)); + numBytesRead += sizeof(Assignment::Type); + if (dataBuffer[0] != PACKET_TYPE_REQUEST_ASSIGNMENT) { // read the GUID for this assignment _uuid = QUuid::fromRfc4122(QByteArray((const char*) dataBuffer + numBytesRead, NUM_BYTES_RFC4122_UUID)); numBytesRead += NUM_BYTES_RFC4122_UUID; } - memcpy(&_type, dataBuffer + numBytesRead, sizeof(Assignment::Type)); - numBytesRead += sizeof(Assignment::Type); - if (_command != Assignment::RequestCommand) { sockaddr* newSocket = NULL; @@ -149,15 +149,15 @@ void Assignment::setAttachedLocalSocket(const sockaddr* attachedLocalSocket) { int Assignment::packToBuffer(unsigned char* buffer) { int numPackedBytes = 0; + memcpy(buffer + numPackedBytes, &_type, sizeof(_type)); + numPackedBytes += sizeof(_type); + // pack the UUID for this assignment, if this is an assignment create or deploy if (_command != Assignment::RequestCommand) { memcpy(buffer, _uuid.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); numPackedBytes += NUM_BYTES_RFC4122_UUID; } - memcpy(buffer + numPackedBytes, &_type, sizeof(_type)); - numPackedBytes += sizeof(_type); - if (_attachedPublicSocket || _attachedLocalSocket) { sockaddr* socketToPack = (_attachedPublicSocket) ? _attachedPublicSocket : _attachedLocalSocket; @@ -176,6 +176,10 @@ int Assignment::packToBuffer(unsigned char* buffer) { return numPackedBytes; } +void Assignment::run() { + // run method ovveridden by subclasses +} + QDebug operator<<(QDebug debug, const Assignment &assignment) { debug << "T:" << assignment.getType(); return debug.nospace(); diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 325cca1c8e..5854ea270d 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -16,7 +16,8 @@ #include "NodeList.h" /// Holds information used for request, creation, and deployment of assignments -class Assignment { +class Assignment : public QObject { + Q_OBJECT public: enum Type { @@ -78,6 +79,9 @@ public: /// Sets _time to the current time given by gettimeofday void setCreateTimeToNow() { gettimeofday(&_time, NULL); } + /// blocking run of the assignment + virtual void run(); + private: QUuid _uuid; /// the 16 byte UUID for this assignment Assignment::Command _command; /// the command for this assignment (Create, Deploy, Request) diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index ea94e8c080..bf64e5bb40 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -72,6 +72,7 @@ public: const char* getDomainHostname() const { return _domainHostname; } void setDomainHostname(const char* domainHostname); + const char* getDomainIP() const { return _domainIP; } void setDomainIP(const char* domainIP); void setDomainIPToLocalhost(); diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index d51870dbb1..d158cdfd5c 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -1,3 +1,4 @@ +// // VoxelServer.h // voxel-server // @@ -9,11 +10,13 @@ #ifndef __voxel_server__VoxelServer__ #define __voxel_server__VoxelServer__ +#include + /// Handles assignments of type VoxelServer - sending voxels to various clients. -class VoxelServer { +class VoxelServer : public Assignment { public: /// runs the voxel server assignment - static void run(); + void run(); /// allows setting of run arguments static void setArguments(int argc, char** argv); From 17a210813be24fa06dd724511903cf0739c31afe Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 15:20:34 -0700 Subject: [PATCH 16/47] repairs to subclasses of assignment --- assignment-client/src/AssignmentFactory.cpp | 9 ++++++--- domain-server/src/main.cpp | 3 +++ libraries/shared/src/Assignment.cpp | 2 +- libraries/voxel-server-library/src/VoxelServer.cpp | 4 ++++ libraries/voxel-server-library/src/VoxelServer.h | 2 ++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp index 01abceea1b..a3aa657943 100644 --- a/assignment-client/src/AssignmentFactory.cpp +++ b/assignment-client/src/AssignmentFactory.cpp @@ -11,22 +11,25 @@ #include "Agent.h" #include "audio/AudioMixer.h" #include "avatars/AvatarMixer.h" +#include #include "AssignmentFactory.h" Assignment* AssignmentFactory::unpackAssignment(const unsigned char* dataBuffer, int numBytes) { int headerBytes = numBytesForPacketHeader(dataBuffer); - Assignment::Type type; - memcpy(&type, dataBuffer + headerBytes, sizeof(type)); + Assignment::Type assignmentType = Assignment::AllTypes; + memcpy(&assignmentType, dataBuffer + headerBytes, sizeof(Assignment::Type)); - switch (type) { + switch (assignmentType) { case Assignment::AudioMixerType: return new AudioMixer(dataBuffer, numBytes); case Assignment::AvatarMixerType: return new AvatarMixer(dataBuffer, numBytes); case Assignment::AgentType: return new Agent(dataBuffer, numBytes); + case Assignment::VoxelServerType: + return new VoxelServer(dataBuffer, numBytes); default: return new Assignment(dataBuffer, numBytes); } diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 62d8be42b7..04072dab49 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -335,6 +335,9 @@ int main(int argc, const char* argv[]) { if (requestAssignment.getType() == Assignment::AllTypes || (*assignment)->getType() == requestAssignment.getType()) { + // attach our local socket to the assignment + (*assignment)->setAttachedLocalSocket((sockaddr*) &localSocket); + // 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 numAssignmentBytes = (*assignment)->packToBuffer(broadcastPacket + numHeaderBytes); diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 1cd30afaf0..f8aabf370f 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -154,7 +154,7 @@ int Assignment::packToBuffer(unsigned char* buffer) { // pack the UUID for this assignment, if this is an assignment create or deploy if (_command != Assignment::RequestCommand) { - memcpy(buffer, _uuid.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); + memcpy(buffer + numPackedBytes, _uuid.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); numPackedBytes += NUM_BYTES_RFC4122_UUID; } diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index b239a180d9..f89b477e6b 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -73,6 +73,10 @@ void attachVoxelNodeDataToNode(Node* newNode) { } } +VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes) { + +} + void VoxelServer::setArguments(int argc, char** argv) { _argc = argc; _argv = const_cast(argv); diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index d158cdfd5c..93baf87fda 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -15,6 +15,8 @@ /// Handles assignments of type VoxelServer - sending voxels to various clients. class VoxelServer : public Assignment { public: + VoxelServer(const unsigned char* dataBuffer, int numBytes); + /// runs the voxel server assignment void run(); From 8bb77ecc9e249cbc8a27b9a4fb49b1da23cb2e58 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 15:23:49 -0700 Subject: [PATCH 17/47] type squish for deployed assignment --- assignment-client/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 3d4f4b6e4c..674550f684 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -76,7 +76,7 @@ void childClient() { && packetVersionMatch(packetData)) { // construct the deployed assignment from the packet data - Assignment *deployedAssignment = AssignmentFactory::unpackAssignment(packetData, receivedBytes); + Assignment* deployedAssignment = AssignmentFactory::unpackAssignment(packetData, receivedBytes); qDebug() << "Received an assignment -" << deployedAssignment << "\n"; From 89546f71406358a5f0415df8630df4967ea9262d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 15:38:54 -0700 Subject: [PATCH 18/47] repairs to temporary standalone voxel-server for assignment subclass --- libraries/voxel-server-library/src/VoxelServer.cpp | 5 +++++ libraries/voxel-server-library/src/VoxelServer.h | 2 ++ voxel-server/src/main.cpp | 4 +++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index f89b477e6b..86a7df5dc6 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -73,6 +73,11 @@ void attachVoxelNodeDataToNode(Node* newNode) { } } +VoxelServer::VoxelServer(Assignment::Command command, Assignment::Location location) : + Assignment(command, Assignment::VoxelServerType, location) { + +} + VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes) { } diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index 93baf87fda..aca3d7c485 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -15,6 +15,8 @@ /// Handles assignments of type VoxelServer - sending voxels to various clients. class VoxelServer : public Assignment { public: + VoxelServer(Assignment::Command command, + Assignment::Location location = Assignment::GlobalLocation); VoxelServer(const unsigned char* dataBuffer, int numBytes); /// runs the voxel server assignment diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index f854df84cf..d38d2e48bc 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -39,7 +39,9 @@ int main(int argc, const char * argv[]) { } VoxelServer::setArguments(argc, const_cast(argv)); - VoxelServer::run(); + + VoxelServer dummyAssignedVoxelServer(Assignment::CreateCommand); + dummyAssignedVoxelServer.run(); } From e86b4f2d8d835e494bd3f2a7aed591516900e7b4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 17 Sep 2013 15:47:29 -0700 Subject: [PATCH 19/47] moving VoxelServer globals to member variables --- .../src/VoxelNodeData.cpp | 13 +- .../voxel-server-library/src/VoxelNodeData.h | 4 + .../src/VoxelSendThread.cpp | 53 ++--- .../src/VoxelSendThread.h | 4 +- .../voxel-server-library/src/VoxelServer.cpp | 203 +++++++++--------- .../voxel-server-library/src/VoxelServer.h | 48 +++++ .../src/VoxelServerPacketProcessor.cpp | 30 +-- .../src/VoxelServerPacketProcessor.h | 9 + .../src/VoxelServerState.h | 53 ----- 9 files changed, 216 insertions(+), 201 deletions(-) delete mode 100644 libraries/voxel-server-library/src/VoxelServerState.h diff --git a/libraries/voxel-server-library/src/VoxelNodeData.cpp b/libraries/voxel-server-library/src/VoxelNodeData.cpp index bdc1de69dc..43d87c2f89 100644 --- a/libraries/voxel-server-library/src/VoxelNodeData.cpp +++ b/libraries/voxel-server-library/src/VoxelNodeData.cpp @@ -28,14 +28,17 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) : _voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE]; _voxelPacketAt = _voxelPacket; resetVoxelPacket(); - +} + +void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) { // Create voxel sending thread... uint16_t nodeID = getOwningNode()->getNodeID(); - _voxelSendThread = new VoxelSendThread(nodeID); + _voxelSendThread = new VoxelSendThread(nodeID, voxelServer); _voxelSendThread->initialize(true); } + void VoxelNodeData::resetVoxelPacket() { // If we're moving, and the client asked for low res, then we force monochrome, otherwise, use // the clients requested color state. @@ -57,8 +60,10 @@ void VoxelNodeData::writeToPacket(unsigned char* buffer, int bytes) { VoxelNodeData::~VoxelNodeData() { delete[] _voxelPacket; - _voxelSendThread->terminate(); - delete _voxelSendThread; + if (_voxelSendThread) { + _voxelSendThread->terminate(); + delete _voxelSendThread; + } } bool VoxelNodeData::updateCurrentViewFrustum() { diff --git a/libraries/voxel-server-library/src/VoxelNodeData.h b/libraries/voxel-server-library/src/VoxelNodeData.h index e3abb7f415..85ebe2ebb7 100644 --- a/libraries/voxel-server-library/src/VoxelNodeData.h +++ b/libraries/voxel-server-library/src/VoxelNodeData.h @@ -19,6 +19,7 @@ #include class VoxelSendThread; +class VoxelServer; class VoxelNodeData : public AvatarData { public: @@ -65,6 +66,9 @@ public: VoxelSceneStats stats; + void initializeVoxelSendThread(VoxelServer* voxelServer); + bool isVoxelSendThreadInitalized() { return _voxelSendThread; } + private: VoxelNodeData(const VoxelNodeData &); VoxelNodeData& operator= (const VoxelNodeData&); diff --git a/libraries/voxel-server-library/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp index b9bb861349..ac2c56d2d3 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.cpp +++ b/libraries/voxel-server-library/src/VoxelSendThread.cpp @@ -16,10 +16,11 @@ extern EnvironmentData environmentData[3]; #include "VoxelSendThread.h" #include "VoxelServer.h" -#include "VoxelServerState.h" +#include "VoxelServerConsts.h" -VoxelSendThread::VoxelSendThread(uint16_t nodeID) : - _nodeID(nodeID) { +VoxelSendThread::VoxelSendThread(uint16_t nodeID, VoxelServer* myServer) : + _nodeID(nodeID), + _myServer(myServer) { } bool VoxelSendThread::process() { @@ -35,7 +36,7 @@ bool VoxelSendThread::process() { // Sometimes the node data has not yet been linked, in which case we can't really do anything if (nodeData) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); - if (::debugVoxelSending) { + if (_myServer->wantsDebugVoxelSending()) { printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged)); } deepestLevelVoxelDistributor(node, nodeData, viewFrustumChanged); @@ -47,7 +48,7 @@ bool VoxelSendThread::process() { if (usecToSleep > 0) { usleep(usecToSleep); } else { - if (::debugVoxelSending) { + if (_myServer->wantsDebugVoxelSending()) { std::cout << "Last send took too much time, not sleeping!\n"; } } @@ -94,7 +95,7 @@ void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& /// Version of voxel distributor that sends the deepest LOD level at once void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged) { - pthread_mutex_lock(&::treeLock); + _myServer->lockTree(); int truePacketsSent = 0; int trueBytesSent = 0; @@ -113,7 +114,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no if (wantColor != nodeData->getCurrentPacketIsColor()) { if (nodeData->isPacketWaiting()) { - if (::debugVoxelSending) { + if (_myServer->wantsDebugVoxelSending()) { printf("wantColor=%s --- SENDING PARTIAL PACKET! nodeData->getCurrentPacketIsColor()=%s\n", debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor())); } @@ -121,7 +122,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent); } else { - if (::debugVoxelSending) { + if (_myServer->wantsDebugVoxelSending()) { printf("wantColor=%s --- FIXING HEADER! nodeData->getCurrentPacketIsColor()=%s\n", debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor())); } @@ -129,7 +130,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no } } - if (::debugVoxelSending) { + if (_myServer->wantsDebugVoxelSending()) { printf("wantColor=%s getCurrentPacketIsColor()=%s, viewFrustumChanged=%s, getWantLowResMoving()=%s\n", debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()), debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->getWantLowResMoving())); @@ -137,7 +138,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no const ViewFrustum* lastViewFrustum = wantDelta ? &nodeData->getLastKnownViewFrustum() : NULL; - if (::debugVoxelSending) { + if (_myServer->wantsDebugVoxelSending()) { printf("deepestLevelVoxelDistributor() viewFrustumChanged=%s, nodeBag.isEmpty=%s, viewSent=%s\n", debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()), debug::valueOf(nodeData->getViewSent()) @@ -148,7 +149,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no // the current view frustum for things to send. if (viewFrustumChanged || nodeData->nodeBag.isEmpty()) { uint64_t now = usecTimestampNow(); - if (::debugVoxelSending) { + if (_myServer->wantsDebugVoxelSending()) { printf("(viewFrustumChanged=%s || nodeData->nodeBag.isEmpty() =%s)...\n", debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty())); if (nodeData->getLastTimeBagEmpty() > 0) { @@ -166,7 +167,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no // if our view has changed, we need to reset these things... if (viewFrustumChanged) { - if (::dumpVoxelsOnMove) { + if (_myServer->wantDumpVoxelsOnMove()) { nodeData->nodeBag.deleteAll(); } nodeData->map.erase(); @@ -180,7 +181,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no nodeData->stats.sceneCompleted(); - if (::displayVoxelStats) { + if (_myServer->wantDisplayVoxelStats()) { nodeData->stats.printDebugDetails(); } @@ -191,10 +192,10 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no if (isFullScene) { nodeData->nodeBag.deleteAll(); } - nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, ::serverTree.rootNode, ::jurisdiction); + nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, _myServer->getServerTree().rootNode, _myServer->getJurisdiction()); // This is the start of "resending" the scene. - nodeData->nodeBag.insert(serverTree.rootNode); + nodeData->nodeBag.insert(_myServer->getServerTree().rootNode); } // If we have something in our nodeBag, then turn them into packets and send them out... @@ -203,8 +204,8 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no int packetsSentThisInterval = 0; uint64_t start = usecTimestampNow(); - bool shouldSendEnvironments = ::sendEnvironments && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS); - while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - (shouldSendEnvironments ? 1 : 0)) { + bool shouldSendEnvironments = _myServer->wantSendEnvironments() && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS); + while (packetsSentThisInterval < _myServer->getPacketsPerClientPerInterval() - (shouldSendEnvironments ? 1 : 0)) { // Check to see if we're taking too long, and if so bail early... uint64_t now = usecTimestampNow(); long elapsedUsec = (now - start); @@ -212,7 +213,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no long usecRemaining = (VOXEL_SEND_INTERVAL_USECS - elapsedUsec); if (elapsedUsecPerPacket + SENDING_TIME_TO_SPARE > usecRemaining) { - if (::debugVoxelSending) { + if (_myServer->wantsDebugVoxelSending()) { printf("packetLoop() usecRemaining=%ld bailing early took %ld usecs to generate %d bytes in %d packets (%ld usec avg), %d nodes still to send\n", usecRemaining, elapsedUsec, trueBytesSent, truePacketsSent, elapsedUsecPerPacket, nodeData->nodeBag.count()); @@ -234,10 +235,10 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum, wantOcclusionCulling, coverageMap, boundaryLevelAdjust, nodeData->getLastTimeBagEmpty(), - isFullScene, &nodeData->stats, ::jurisdiction); + isFullScene, &nodeData->stats, _myServer->getJurisdiction()); nodeData->stats.encodeStarted(); - bytesWritten = serverTree.encodeTreeBitstream(subTree, _tempOutputBuffer, MAX_VOXEL_PACKET_SIZE - 1, + bytesWritten = _myServer->getServerTree().encodeTreeBitstream(subTree, _tempOutputBuffer, MAX_VOXEL_PACKET_SIZE - 1, nodeData->nodeBag, params); nodeData->stats.encodeStopped(); @@ -254,17 +255,17 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent); nodeData->resetVoxelPacket(); } - packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left + packetsSentThisInterval = _myServer->getPacketsPerClientPerInterval(); // done for now, no nodes left } } // send the environment packet if (shouldSendEnvironments) { int numBytesPacketHeader = populateTypeAndVersion(_tempOutputBuffer, PACKET_TYPE_ENVIRONMENT_DATA); int envPacketLength = numBytesPacketHeader; - int environmentsToSend = ::sendMinimalEnvironment ? 1 : sizeof(environmentData) / sizeof(EnvironmentData); + int environmentsToSend = _myServer->getSendMinimalEnvironment() ? 1 : _myServer->getEnvironmentDataCount(); for (int i = 0; i < environmentsToSend; i++) { - envPacketLength += environmentData[i].getBroadcastData(_tempOutputBuffer + envPacketLength); + envPacketLength += _myServer->getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength); } NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(), _tempOutputBuffer, envPacketLength); @@ -283,7 +284,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no printf("WARNING! packetLoop() took %d milliseconds to generate %d bytes in %d packets, %d nodes still to send\n", elapsedmsec, trueBytesSent, truePacketsSent, nodeData->nodeBag.count()); } - } else if (::debugVoxelSending) { + } else if (_myServer->wantsDebugVoxelSending()) { printf("packetLoop() took %d milliseconds to generate %d bytes in %d packets, %d nodes still to send\n", elapsedmsec, trueBytesSent, truePacketsSent, nodeData->nodeBag.count()); } @@ -293,7 +294,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no if (nodeData->nodeBag.isEmpty()) { nodeData->updateLastKnownViewFrustum(); nodeData->setViewSent(true); - if (::debugVoxelSending) { + if (_myServer->wantsDebugVoxelSending()) { nodeData->map.printStats(); } nodeData->map.erase(); // It would be nice if we could save this, and only reset it when the view frustum changes @@ -301,6 +302,6 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no } // end if bag wasn't empty, and so we sent stuff... - pthread_mutex_unlock(&::treeLock); + _myServer->unlockTree(); } diff --git a/libraries/voxel-server-library/src/VoxelSendThread.h b/libraries/voxel-server-library/src/VoxelSendThread.h index fa6c1460c7..37824abedb 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.h +++ b/libraries/voxel-server-library/src/VoxelSendThread.h @@ -16,17 +16,19 @@ #include #include #include "VoxelNodeData.h" +#include "VoxelServer.h" /// Threaded processor for sending voxel packets to a single client class VoxelSendThread : public virtual GenericThread { public: - VoxelSendThread(uint16_t nodeID); + VoxelSendThread(uint16_t nodeID, VoxelServer* myServer); protected: /// Implements generic processing behavior for this thread. virtual bool process(); private: uint16_t _nodeID; + VoxelServer* _myServer; void handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent); void deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged); diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index d2c9613619..9625926ebd 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include "VoxelNodeData.h" #include @@ -23,11 +22,6 @@ #include #include -#include "NodeWatcher.h" -#include "VoxelPersistThread.h" -#include "VoxelSendThread.h" -#include "VoxelServerPacketProcessor.h" - #ifdef _WIN32 #include "Syssocket.h" #include "Systime.h" @@ -38,30 +32,10 @@ #endif #include "VoxelServer.h" -#include "VoxelServerState.h" +#include "VoxelServerConsts.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) { @@ -69,10 +43,29 @@ void attachVoxelNodeDataToNode(Node* newNode) { } } -VoxelServer::VoxelServer() { +VoxelServer::VoxelServer() : + _serverTree(true) +{ _argc = 0; _argv = NULL; _dontKillOnMissingDomain = false; + + _PACKETS_PER_CLIENT_PER_INTERVAL = 10; + _wantVoxelPersist = true; + _wantLocalDomain = false; + _debugVoxelSending = false; + _shouldShowAnimationDebug = false; + _displayVoxelStats = false; + _debugVoxelReceiving = false; + _sendEnvironments = true; + _sendMinimalEnvironment = false; + _dumpVoxelsOnMove = false; + _jurisdiction = NULL; + _jurisdictionSender = NULL; + _voxelServerPacketProcessor = NULL; + _voxelPersistThread = NULL; + + } void VoxelServer::setArguments(int argc, char** argv) { @@ -85,8 +78,8 @@ void VoxelServer::setupStandAlone(const char* domain, int port) { // Handle Local Domain testing with the --local command line const char* local = "--local"; - ::wantLocalDomain = strcmp(domain, local) == 0; - if (::wantLocalDomain) { + _wantLocalDomain = strcmp(domain, local) == 0; + if (_wantLocalDomain) { printf("Local Domain MODE!\n"); NodeList::getInstance()->setDomainIPToLocalhost(); } else { @@ -101,7 +94,7 @@ void VoxelServer::setupStandAlone(const char* domain, int port) { //int main(int argc, const char * argv[]) { void VoxelServer::run(const char* configuration) { - pthread_mutex_init(&::treeLock, NULL); + pthread_mutex_init(&_treeLock, NULL); qInstallMessageHandler(sharedMessageHandler); @@ -111,7 +104,7 @@ void VoxelServer::run(const char* configuration) { printf("jurisdictionFile=%s\n", jurisdictionFile); printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); - jurisdiction = new JurisdictionMap(jurisdictionFile); + _jurisdiction = new JurisdictionMap(jurisdictionFile); printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); } else { const char* JURISDICTION_ROOT = "--jurisdictionRoot"; @@ -127,28 +120,28 @@ void VoxelServer::run(const char* configuration) { } if (jurisdictionRoot || jurisdictionEndNodes) { - ::jurisdiction = new JurisdictionMap(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)); + _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; + _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)); + _sendMinimalEnvironment = getCmdOption(_argc, _argv, MINIMAL_ENVIRONMENT); + printf("Using Minimal Environment=%s\n", debug::valueOf(_sendMinimalEnvironment)); } - printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments)); + printf("Sending environments=%s\n", debug::valueOf(_sendEnvironments)); NodeList* nodeList = NodeList::getInstance(); nodeList->setOwnerType(NODE_TYPE_VOXEL_SERVER); @@ -156,72 +149,72 @@ void VoxelServer::run(const char* configuration) { setvbuf(stdout, NULL, _IOLBF, 0); // tell our NodeList about our desire to get notifications - nodeList->addHook(&nodeWatcher); + nodeList->addHook(&_nodeWatcher); 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)); + _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)); + _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)); + _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)); + _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; + _wantVoxelPersist = false; } - printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist)); + printf("wantVoxelPersist=%s\n", debug::valueOf(_wantVoxelPersist)); // if we want Voxel Persistence, load the local file now... bool persistantFileRead = false; - if (::wantVoxelPersist) { + 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); + strcpy(_voxelPersistFilename, voxelsPersistFilenameParameter); } else { - //strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); - strcpy(voxelPersistFilename, LOCAL_VOXELS_PERSIST_FILE); + //strcpy(voxelPersistFilename, _wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + strcpy(_voxelPersistFilename, LOCAL_VOXELS_PERSIST_FILE); } - printf("loading voxels from file: %s...\n", voxelPersistFilename); + printf("loading voxels from file: %s...\n", _voxelPersistFilename); - persistantFileRead = ::serverTree.readFromSVOFile(::voxelPersistFilename); + persistantFileRead = _serverTree.readFromSVOFile(_voxelPersistFilename); if (persistantFileRead) { - PerformanceWarning warn(::shouldShowAnimationDebug, - "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); + PerformanceWarning warn(_shouldShowAnimationDebug, + "persistVoxelsWhenDirty() - reaverageVoxelColors()", _shouldShowAnimationDebug); // after done inserting all these voxels, then reaverage colors - serverTree.reaverageVoxelColors(serverTree.rootNode); + _serverTree.reaverageVoxelColors(_serverTree.rootNode); printf("Voxels reAveraged\n"); } - ::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it + _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(); + 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); + _voxelPersistThread = new VoxelPersistThread(&_serverTree, _voxelPersistFilename); + if (_voxelPersistThread) { + _voxelPersistThread->initialize(true); } } @@ -230,32 +223,32 @@ void VoxelServer::run(const char* configuration) { const char* INPUT_FILE = "-i"; const char* voxelsFilename = getCmdOption(_argc, _argv, INPUT_FILE); if (voxelsFilename) { - serverTree.readFromSVOFile(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; + _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); + 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 + _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; @@ -265,15 +258,15 @@ void VoxelServer::run(const char* configuration) { timeval lastDomainServerCheckIn = {}; // set up our jurisdiction broadcaster... - ::jurisdictionSender = new JurisdictionSender(::jurisdiction); - if (::jurisdictionSender) { - ::jurisdictionSender->initialize(true); + _jurisdictionSender = new JurisdictionSender(_jurisdiction); + if (_jurisdictionSender) { + _jurisdictionSender->initialize(true); } // set up our VoxelServerPacketProcessor - ::voxelServerPacketProcessor = new VoxelServerPacketProcessor(); - if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->initialize(true); + _voxelServerPacketProcessor = new VoxelServerPacketProcessor(this); + if (_voxelServerPacketProcessor) { + _voxelServerPacketProcessor->initialize(true); } // loop to send to nodes requesting data @@ -312,40 +305,40 @@ void VoxelServer::run(const char* configuration) { } 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); + if (_jurisdictionSender) { + _jurisdictionSender->queueReceivedPacket(senderAddress, packetData, packetLength); } - } else if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->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 (_jurisdiction) { + delete _jurisdiction; } - if (::jurisdictionSender) { - ::jurisdictionSender->terminate(); - delete ::jurisdictionSender; + if (_jurisdictionSender) { + _jurisdictionSender->terminate(); + delete _jurisdictionSender; } - if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->terminate(); - delete ::voxelServerPacketProcessor; + if (_voxelServerPacketProcessor) { + _voxelServerPacketProcessor->terminate(); + delete _voxelServerPacketProcessor; } - if (::voxelPersistThread) { - ::voxelPersistThread->terminate(); - delete ::voxelPersistThread; + if (_voxelPersistThread) { + _voxelPersistThread->terminate(); + delete _voxelPersistThread; } // tell our NodeList we're done with notifications - nodeList->removeHook(&nodeWatcher); + nodeList->removeHook(&_nodeWatcher); - pthread_mutex_destroy(&::treeLock); + pthread_mutex_destroy(&_treeLock); } diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index 6739f4cfeb..923bc5139c 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -9,6 +9,14 @@ #ifndef __voxel_server__VoxelServer__ #define __voxel_server__VoxelServer__ +#include + +#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: @@ -27,10 +35,50 @@ public: /// \param int port port the voxel server will listen on void setupStandAlone(const char* domain, int port); + bool wantsDebugVoxelSending() const { return _debugVoxelSending; } + bool wantsDebugVoxelReceiving() const { return _debugVoxelReceiving; } + 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; } + + void lockTree() { pthread_mutex_lock(&_treeLock); } + void unlockTree() { pthread_mutex_unlock(&_treeLock); } + + int getPacketsPerClientPerInterval() const { return _PACKETS_PER_CLIENT_PER_INTERVAL; } + bool getSendMinimalEnvironment() const { return _sendMinimalEnvironment; } + EnvironmentData* getEnvironmentData(int i) { return &_environmentData[i]; } + int getEnvironmentDataCount() const { return sizeof(_environmentData)/sizeof(EnvironmentData); } + private: int _argc; const char** _argv; bool _dontKillOnMissingDomain; + + char _voxelPersistFilename[MAX_FILENAME_LENGTH]; + int _PACKETS_PER_CLIENT_PER_INTERVAL; + VoxelTree _serverTree; // this IS a reaveraging tree + bool _wantVoxelPersist; + bool _wantLocalDomain; + bool _debugVoxelSending; + bool _shouldShowAnimationDebug; + bool _displayVoxelStats; + bool _debugVoxelReceiving; + bool _sendEnvironments; + bool _sendMinimalEnvironment; + bool _dumpVoxelsOnMove; + JurisdictionMap* _jurisdiction; + JurisdictionSender* _jurisdictionSender; + VoxelServerPacketProcessor* _voxelServerPacketProcessor; + VoxelPersistThread* _voxelPersistThread; + pthread_mutex_t _treeLock; + EnvironmentData _environmentData[3]; + + NodeWatcher _nodeWatcher; // used to cleanup AGENT data when agents are killed + }; diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp index d283296e6f..9b79ae121a 100644 --- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp +++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp @@ -12,33 +12,39 @@ #include #include "VoxelServer.h" -#include "VoxelServerState.h" +#include "VoxelServerConsts.h" #include "VoxelServerPacketProcessor.h" +VoxelServerPacketProcessor::VoxelServerPacketProcessor(VoxelServer* myServer) : + _myServer(myServer), + _receivedPacketCount(0) { +} + + void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength) { int numBytesPacketHeader = numBytesForPacketHeader(packetData); if (packetData[0] == PACKET_TYPE_SET_VOXEL || packetData[0] == PACKET_TYPE_SET_VOXEL_DESTRUCTIVE) { bool destructive = (packetData[0] == PACKET_TYPE_SET_VOXEL_DESTRUCTIVE); - PerformanceWarning warn(::shouldShowAnimationDebug, + PerformanceWarning warn(_myServer->wantShowAnimationDebug(), destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", - ::shouldShowAnimationDebug); + _myServer->wantShowAnimationDebug()); - ::receivedPacketCount++; + _receivedPacketCount++; unsigned short int itemNumber = (*((unsigned short int*)(packetData + numBytesPacketHeader))); - if (::shouldShowAnimationDebug) { + if (_myServer->wantShowAnimationDebug()) { printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n", destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", packetLength, itemNumber); } - if (::debugVoxelReceiving) { + if (_myServer->wantsDebugVoxelReceiving()) { printf("got %s - %d command from client receivedBytes=%ld itemNumber=%d\n", destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", - ::receivedPacketCount, packetLength, itemNumber); + _receivedPacketCount, packetLength, itemNumber); } int atByte = numBytesPacketHeader + sizeof(itemNumber); unsigned char* voxelData = (unsigned char*)&packetData[atByte]; @@ -48,7 +54,7 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned int voxelDataSize = bytesRequiredForCodeLength(octets) + COLOR_SIZE_IN_BYTES; int voxelCodeSize = bytesRequiredForCodeLength(octets); - if (::shouldShowAnimationDebug) { + if (_myServer->wantShowAnimationDebug()) { int red = voxelData[voxelCodeSize + 0]; int green = voxelData[voxelCodeSize + 1]; int blue = voxelData[voxelCodeSize + 2]; @@ -58,7 +64,7 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned delete[] vertices; } - serverTree.readCodeColorBufferToTree(voxelData, destructive); + _myServer->getServerTree().readCodeColorBufferToTree(voxelData, destructive); // skip to next voxelData += voxelDataSize; atByte += voxelDataSize; @@ -73,9 +79,9 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned } else if (packetData[0] == PACKET_TYPE_ERASE_VOXEL) { // Send these bits off to the VoxelTree class to process them - pthread_mutex_lock(&::treeLock); - ::serverTree.processRemoveVoxelBitstream((unsigned char*)packetData, packetLength); - pthread_mutex_unlock(&::treeLock); + _myServer->lockTree(); + _myServer->getServerTree().processRemoveVoxelBitstream((unsigned char*)packetData, packetLength); + _myServer->unlockTree(); // Make sure our Node and NodeList knows we've heard from this node. Node* node = NodeList::getInstance()->nodeWithAddress(&senderAddress); diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h index caad7bf240..8ef316bd23 100644 --- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h +++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h @@ -12,11 +12,20 @@ #define __voxel_server__VoxelServerPacketProcessor__ #include +class VoxelServer; /// Handles processing of incoming network packets for the voxel-server. As with other ReceivedPacketProcessor classes /// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket() class VoxelServerPacketProcessor : public ReceivedPacketProcessor { + +public: + VoxelServerPacketProcessor(VoxelServer* myServer); + protected: virtual void processPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength); + +private: + VoxelServer* _myServer; + int _receivedPacketCount; }; #endif // __voxel_server__VoxelServerPacketProcessor__ diff --git a/libraries/voxel-server-library/src/VoxelServerState.h b/libraries/voxel-server-library/src/VoxelServerState.h deleted file mode 100644 index 2d00d4a046..0000000000 --- a/libraries/voxel-server-library/src/VoxelServerState.h +++ /dev/null @@ -1,53 +0,0 @@ -// VoxelServer.h -// voxel-server -// -// Created by Brad Hefta-Gaub on 8/21/13 -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// -// - -#ifndef __voxel_server__VoxelServerState__ -#define __voxel_server__VoxelServerState__ - -#include -#include // for MAX_PACKET_SIZE -#include -#include - -#include "VoxelServerPacketProcessor.h" - - -const int MAX_FILENAME_LENGTH = 1024; -const int VOXEL_SIZE_BYTES = 3 + (3 * sizeof(float)); -const int VOXELS_PER_PACKET = (MAX_PACKET_SIZE - 1) / VOXEL_SIZE_BYTES; -const int MIN_BRIGHTNESS = 64; -const float DEATH_STAR_RADIUS = 4.0; -const float MAX_CUBE = 0.05f; -const int VOXEL_SEND_INTERVAL_USECS = 17 * 1000; // approximately 60fps -const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels -const int INTERVALS_PER_SECOND = 1000 * 1000 / VOXEL_SEND_INTERVAL_USECS; -const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; -const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000; - -extern const char* LOCAL_VOXELS_PERSIST_FILE; -extern const char* VOXELS_PERSIST_FILE; -extern char voxelPersistFilename[MAX_FILENAME_LENGTH]; -extern int PACKETS_PER_CLIENT_PER_INTERVAL; - -extern VoxelTree serverTree; // this IS a reaveraging tree -extern bool wantVoxelPersist; -extern bool wantLocalDomain; -extern bool debugVoxelSending; -extern bool shouldShowAnimationDebug; -extern bool displayVoxelStats; -extern bool debugVoxelReceiving; -extern bool sendEnvironments; -extern bool sendMinimalEnvironment; -extern bool dumpVoxelsOnMove; -extern int receivedPacketCount; -extern JurisdictionMap* jurisdiction; -extern JurisdictionSender* jurisdictionSender; -extern VoxelServerPacketProcessor* voxelServerPacketProcessor; -extern pthread_mutex_t treeLock; - -#endif // __voxel_server__VoxelServerState__ From 2b9290a9e3fc74853500562d55969233a1119084 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 17 Sep 2013 15:47:39 -0700 Subject: [PATCH 20/47] moving VoxelServer globals to member variables --- .../src/VoxelServerConsts.h | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 libraries/voxel-server-library/src/VoxelServerConsts.h diff --git a/libraries/voxel-server-library/src/VoxelServerConsts.h b/libraries/voxel-server-library/src/VoxelServerConsts.h new file mode 100644 index 0000000000..b70e460a58 --- /dev/null +++ b/libraries/voxel-server-library/src/VoxelServerConsts.h @@ -0,0 +1,31 @@ +// VoxelServerConsts.h +// voxel-server +// +// Created by Brad Hefta-Gaub on 8/21/13 +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// +// + +#ifndef __voxel_server__VoxelServerConsts__ +#define __voxel_server__VoxelServerConsts__ + +#include +#include // for MAX_PACKET_SIZE +#include +#include + +#include "VoxelServerPacketProcessor.h" + + +const int MAX_FILENAME_LENGTH = 1024; +const int VOXEL_SIZE_BYTES = 3 + (3 * sizeof(float)); +const int VOXELS_PER_PACKET = (MAX_PACKET_SIZE - 1) / VOXEL_SIZE_BYTES; +const int VOXEL_SEND_INTERVAL_USECS = 17 * 1000; // approximately 60fps +const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels +const int INTERVALS_PER_SECOND = 1000 * 1000 / VOXEL_SEND_INTERVAL_USECS; +const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000; + +extern const char* LOCAL_VOXELS_PERSIST_FILE; +extern const char* VOXELS_PERSIST_FILE; + +#endif // __voxel_server__VoxelServerConsts__ From 001432ec55cf2c4056fe0c9856f66191bb058fca Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 16:40:30 -0700 Subject: [PATCH 21/47] have domain-server reject audio and avatar mixers with bad UUID --- assignment-client/src/audio/AudioMixer.cpp | 2 +- assignment-client/src/avatars/AvatarMixer.cpp | 2 +- domain-server/src/main.cpp | 149 +++++++++++------- libraries/shared/src/Assignment.cpp | 2 - libraries/shared/src/Assignment.h | 2 + libraries/shared/src/NodeList.cpp | 16 +- libraries/shared/src/NodeList.h | 2 +- libraries/shared/src/PacketHeaders.cpp | 2 +- 8 files changed, 106 insertions(+), 71 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 930b44dbce..135fc341e5 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -129,7 +129,7 @@ void AudioMixer::run() { // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { gettimeofday(&lastDomainServerCheckIn, NULL); - NodeList::getInstance()->sendDomainServerCheckIn(); + NodeList::getInstance()->sendDomainServerCheckIn(this->getUUID().toRfc4122().constData()); if (Logging::shouldSendStats() && numStatCollections > 0) { // if we should be sending stats to Logstash send the appropriate average now diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 604301a391..49c0b02d0c 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -119,7 +119,7 @@ void AvatarMixer::run() { // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { gettimeofday(&lastDomainServerCheckIn, NULL); - NodeList::getInstance()->sendDomainServerCheckIn(); + NodeList::getInstance()->sendDomainServerCheckIn(this->getUUID().toRfc4122().constData()); } if (nodeList->getNodeSocket()->receive(nodeAddress, packetData, &receivedBytes) && diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 04072dab49..28527e27e6 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -247,77 +247,105 @@ int main(int argc, const char* argv[]) { nodePublicAddress.sin_addr.s_addr = 0; } - Node* newNode = nodeList->addOrUpdateNode((sockaddr*) &nodePublicAddress, - (sockaddr*) &nodeLocalAddress, - nodeType, - nodeList->getLastNodeID()); + bool matchedUUID = true; - // if addOrUpdateNode returns NULL this was a solo node we already have, don't talk back to it - if (newNode) { - if (newNode->getNodeID() == nodeList->getLastNodeID()) { - nodeList->increaseNodeID(); + if ((nodeType == NODE_TYPE_AVATAR_MIXER || nodeType == NODE_TYPE_AUDIO_MIXER) && + !nodeList->soloNodeOfType(nodeType)) { + // if this is an audio-mixer or an avatar-mixer and we don't have one yet + // we need to check the GUID of the assignment in the queue + // (if it exists) to make sure there is a match + + // reset matchedUUID to false so there is no match by default + matchedUUID = false; + + // pull the UUID passed with the check in + QUuid checkInUUID = QUuid::fromRfc4122(QByteArray((const char*) packetData + numBytesSenderHeader + + sizeof(NODE_TYPE), + NUM_BYTES_RFC4122_UUID)); + + // lock the assignment queue + ::assignmentQueueMutex.lock(); + + std::deque::iterator assignment = ::assignmentQueue.begin(); + + Assignment::Type matchType = nodeType == NODE_TYPE_AUDIO_MIXER + ? Assignment::AudioMixerType : Assignment::AvatarMixerType; + + // enumerate the assignments and see if there is a type and UUID match + while (assignment != ::assignmentQueue.end()) { + if ((*assignment)->getType() == matchType + && (*assignment)->getUUID() == checkInUUID) { + // type and UUID match + matchedUUID = true; + + // remove this assignment from the queue + ::assignmentQueue.erase(assignment); + + break; + } else { + // no match, keep looking + assignment++; + } } - int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN); + // unlock the assignment queue + ::assignmentQueueMutex.unlock(); + } + + if (matchedUUID) { + Node* newNode = nodeList->addOrUpdateNode((sockaddr*) &nodePublicAddress, + (sockaddr*) &nodeLocalAddress, + nodeType, + nodeList->getLastNodeID()); - currentBufferPos = broadcastPacket + numHeaderBytes; - startPointer = currentBufferPos; - - unsigned char* nodeTypesOfInterest = packetData + numBytesSenderHeader + sizeof(NODE_TYPE) - + numBytesSocket + sizeof(unsigned char); - int numInterestTypes = *(nodeTypesOfInterest - 1); - - if (numInterestTypes > 0) { - // if the node has sent no types of interest, assume they want nothing but their own ID back - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (!node->matches((sockaddr*) &nodePublicAddress, (sockaddr*) &nodeLocalAddress, nodeType) && - memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { - // this is not the node themselves - // and this is an node of a type in the passed node types of interest - // or the node did not pass us any specific types they are interested in - - if (memchr(SOLO_NODE_TYPES, node->getType(), sizeof(SOLO_NODE_TYPES)) == NULL) { - // this is an node of which there can be multiple, just add them to the packet + // if addOrUpdateNode returns NULL this was a solo node we already have, don't talk back to it + if (newNode) { + if (newNode->getNodeID() == nodeList->getLastNodeID()) { + nodeList->increaseNodeID(); + } + + int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN); + + currentBufferPos = broadcastPacket + numHeaderBytes; + startPointer = currentBufferPos; + + int numBytesUUID = (nodeType == NODE_TYPE_AUDIO_MIXER || nodeType == NODE_TYPE_AVATAR_MIXER) + ? NUM_BYTES_RFC4122_UUID + : 0; + + unsigned char* nodeTypesOfInterest = packetData + numBytesSenderHeader + numBytesUUID + + sizeof(NODE_TYPE) + numBytesSocket + sizeof(unsigned char); + int numInterestTypes = *(nodeTypesOfInterest - 1); + + if (numInterestTypes > 0) { + // if the node has sent no types of interest, assume they want nothing but their own ID back + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + if (!node->matches((sockaddr*) &nodePublicAddress, (sockaddr*) &nodeLocalAddress, nodeType) && + memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { + // don't send avatar nodes to other avatars, that will come from avatar mixer if (nodeType != NODE_TYPE_AGENT || node->getType() != NODE_TYPE_AGENT) { currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, &(*node)); } - } else { - // solo node, we need to only send newest - if (newestSoloNodes[node->getType()] == NULL || - newestSoloNodes[node->getType()]->getWakeMicrostamp() < node->getWakeMicrostamp()) { - // we have to set the newer solo node to add it to the broadcast later - newestSoloNodes[node->getType()] = &(*node); - } } } + + } - for (std::map::iterator soloNode = newestSoloNodes.begin(); - soloNode != newestSoloNodes.end(); - soloNode++) { - // this is the newest alive solo node, add them to the packet - currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, soloNode->second); - } + // update last receive to now + uint64_t timeNow = usecTimestampNow(); + newNode->setLastHeardMicrostamp(timeNow); + + // add the node ID to the end of the pointer + currentBufferPos += packNodeId(currentBufferPos, newNode->getNodeID()); + + // send the constructed list back to this node + nodeList->getNodeSocket()->send((sockaddr*)&replyDestinationSocket, + broadcastPacket, + (currentBufferPos - startPointer) + numHeaderBytes); } - - // update last receive to now - uint64_t timeNow = usecTimestampNow(); - newNode->setLastHeardMicrostamp(timeNow); - - if (packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY - && memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES))) { - newNode->setWakeMicrostamp(timeNow); - } - - // add the node ID to the end of the pointer - currentBufferPos += packNodeId(currentBufferPos, newNode->getNodeID()); - - // send the constructed list back to this node - nodeList->getNodeSocket()->send((sockaddr*)&replyDestinationSocket, - broadcastPacket, - (currentBufferPos - startPointer) + numHeaderBytes); } } else if (packetData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) { @@ -355,8 +383,8 @@ int main(int argc, const char* argv[]) { ::assignmentQueue.erase(assignment); delete *assignment; } - } else { - // remove the assignment from the queue + } else if ((*assignment)->getType() == Assignment::VoxelServerType) { + // this is a voxel-server assignment, remove the assignment from the queue ::assignmentQueue.erase(assignment); } @@ -398,7 +426,8 @@ int main(int argc, const char* argv[]) { ::assignmentQueue.erase(assignment); delete *assignment; } - } else { + } else if ((*assignment)->getType() == Assignment::VoxelServerType) { + // this is a voxel server assignment // remove the assignment from the queue ::assignmentQueue.erase(assignment); } diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index f8aabf370f..68e1108334 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -14,8 +14,6 @@ const char IPv4_ADDRESS_DESIGNATOR = 4; const char IPv6_ADDRESS_DESIGNATOR = 6; -const int NUM_BYTES_RFC4122_UUID = 16; - Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assignment::Location location) : _command(command), _type(type), diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 5854ea270d..5370c1a16c 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -15,6 +15,8 @@ #include "NodeList.h" +const int NUM_BYTES_RFC4122_UUID = 16; + /// Holds information used for request, creation, and deployment of assignments class Assignment : public QObject { Q_OBJECT diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index cce0aecf14..d5a8bf99a2 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -268,7 +268,7 @@ void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNo _nodeTypesOfInterest[numNodeTypesOfInterest] = '\0'; } -void NodeList::sendDomainServerCheckIn() { +void NodeList::sendDomainServerCheckIn(const char* assignmentUUID) { static bool printedDomainServerIP = false; // Lookup the IP address of the domain server if we need to @@ -297,9 +297,9 @@ void NodeList::sendDomainServerCheckIn() { const int IP_ADDRESS_BYTES = 4; - // check in packet has header, node type, port, IP, node types of interest, null termination - int numPacketBytes = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) + sizeof(NODE_TYPE) + sizeof(uint16_t) + - IP_ADDRESS_BYTES + numBytesNodesOfInterest + sizeof(unsigned char); + // check in packet has header, optional UUID, node type, port, IP, node types of interest, null termination + int numPacketBytes = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) + sizeof(NODE_TYPE) + + NUM_BYTES_RFC4122_UUID + sizeof(uint16_t) + IP_ADDRESS_BYTES + numBytesNodesOfInterest + sizeof(unsigned char); checkInPacket = new unsigned char[numPacketBytes]; unsigned char* packetPosition = checkInPacket; @@ -313,7 +313,13 @@ void NodeList::sendDomainServerCheckIn() { *(packetPosition++) = _ownerType; - packetPosition += packSocket(checkInPacket + numHeaderBytes + sizeof(NODE_TYPE), + if (assignmentUUID) { + // if we've got an assignment UUID to send add that here + memcpy(packetPosition, assignmentUUID, NUM_BYTES_RFC4122_UUID); + packetPosition += NUM_BYTES_RFC4122_UUID; + } + + packetPosition += packSocket(checkInPacket + (packetPosition - checkInPacket), getLocalAddress(), htons(_nodeSocket.getListeningPort())); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index bf64e5bb40..7233e7af69 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -97,7 +97,7 @@ public: void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest); - void sendDomainServerCheckIn(); + void sendDomainServerCheckIn(const char* assignmentUUID = NULL); int processDomainServerList(unsigned char *packetData, size_t dataBytes); void setAssignmentServerSocket(sockaddr* serverSocket) { _assignmentServerSocket = serverSocket; } diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index fd261e4385..d31d499814 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -26,7 +26,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 1; case PACKET_TYPE_VOXEL_STATS: - return 2; + return 2; default: return 0; } From f75b480b0ec3b7bfef5e82e884f8082fb3b70bbd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 17 Sep 2013 16:40:39 -0700 Subject: [PATCH 22/47] correctly hook up VoxelSendThread in VoxelNodeData --- libraries/voxel-server-library/src/VoxelServer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index fed5bdd869..a6b1f80f49 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -64,7 +64,6 @@ VoxelServer::VoxelServer(Assignment::Command command, Assignment::Location locat _jurisdictionSender = NULL; _voxelServerPacketProcessor = NULL; _voxelPersistThread = NULL; - } VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes) { @@ -301,6 +300,12 @@ void VoxelServer::run() { nodeID); NodeList::getInstance()->updateNodeWithData(node, packetData, packetLength); + + VoxelNodeData* nodeData = (VoxelNodeData*) node->getLinkedData(); + if (nodeData && !nodeData->isVoxelSendThreadInitalized()) { + nodeData->initializeVoxelSendThread(this); + } + } else if (packetData[0] == PACKET_TYPE_PING) { // If the packet is a ping, let processNodeData handle it. NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); From 5f9ac5c28090f1d925d64e0808ff2c5bb176f729 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 17 Sep 2013 17:19:39 -0700 Subject: [PATCH 23/47] second constructor --- .../voxel-server-library/src/VoxelServer.cpp | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index a6b1f80f49..9ff2c44066 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -66,7 +66,26 @@ VoxelServer::VoxelServer(Assignment::Command command, Assignment::Location locat _voxelPersistThread = NULL; } -VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes) { +VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes), + _serverTree(true) { + _argc = 0; + _argv = NULL; + _dontKillOnMissingDomain = false; + + _PACKETS_PER_CLIENT_PER_INTERVAL = 10; + _wantVoxelPersist = true; + _wantLocalDomain = false; + _debugVoxelSending = false; + _shouldShowAnimationDebug = false; + _displayVoxelStats = false; + _debugVoxelReceiving = false; + _sendEnvironments = true; + _sendMinimalEnvironment = false; + _dumpVoxelsOnMove = false; + _jurisdiction = NULL; + _jurisdictionSender = NULL; + _voxelServerPacketProcessor = NULL; + _voxelPersistThread = NULL; } void VoxelServer::setArguments(int argc, char** argv) { @@ -174,7 +193,7 @@ void VoxelServer::run() { // 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)) { + if (getCmdOption(_argc, _argv, NO_VOXEL_PERSIST)) { _wantVoxelPersist = false; } printf("wantVoxelPersist=%s\n", debug::valueOf(_wantVoxelPersist)); @@ -253,7 +272,7 @@ void VoxelServer::run() { sockaddr senderAddress; - unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; + unsigned char* packetData = new unsigned char[MAX_PACKET_SIZE]; ssize_t packetLength; timeval lastDomainServerCheckIn = {}; @@ -269,7 +288,7 @@ void VoxelServer::run() { if (_voxelServerPacketProcessor) { _voxelServerPacketProcessor->initialize(true); } - + // loop to send to nodes requesting data while (true) { From 3f381eeae8fbfed5dd88616f06ba8cb0f29fc2c5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 17:24:22 -0700 Subject: [PATCH 24/47] put unconfirmed AM assignments at the back of the queue --- domain-server/src/main.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 28527e27e6..938b6d35ab 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -155,7 +155,7 @@ int main(int argc, const char* argv[]) { Assignment avatarMixerAssignment(Assignment::CreateCommand, Assignment::AvatarMixerType, Assignment::LocalLocation); - + Assignment voxelServerAssignment(Assignment::CreateCommand, Assignment::VoxelServerType, Assignment::LocalLocation); @@ -271,8 +271,10 @@ int main(int argc, const char* argv[]) { Assignment::Type matchType = nodeType == NODE_TYPE_AUDIO_MIXER ? Assignment::AudioMixerType : Assignment::AvatarMixerType; + // enumerate the assignments and see if there is a type and UUID match while (assignment != ::assignmentQueue.end()) { + if ((*assignment)->getType() == matchType && (*assignment)->getUUID() == checkInUUID) { // type and UUID match @@ -383,9 +385,16 @@ int main(int argc, const char* argv[]) { ::assignmentQueue.erase(assignment); delete *assignment; } - } else if ((*assignment)->getType() == Assignment::VoxelServerType) { - // this is a voxel-server assignment, remove the assignment from the queue + } else { + // remove the assignment from the queue ::assignmentQueue.erase(assignment); + + if ((*assignment)->getType() != Assignment::VoxelServerType) { + // keep audio-mixer and avatar-mixer assignments in the queue + // until we get a check-in from that GUID + // but stick it at the back so the others have a chance to go out + ::assignmentQueue.push_back(*assignment); + } } // stop looping, we've handed out an assignment From 1bfd23e3de9dcae65ec86f558f498d8fe1e5d1d3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 17 Sep 2013 17:27:20 -0700 Subject: [PATCH 25/47] CR feedback --- domain-server/src/main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index a4f7b7d6fb..bfef06ad7e 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -29,8 +29,6 @@ #include #include #include -#include -#include #include From 3145a543d97d0e7cf1725ee68fd66b06a7fcc0c9 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 17 Sep 2013 17:34:47 -0700 Subject: [PATCH 26/47] fixed CR feedback --- .../voxel-server-library/src/VoxelServer.cpp | 16 +++++++--------- libraries/voxel-server-library/src/VoxelServer.h | 4 ++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 9ff2c44066..257f9b2640 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -50,7 +50,7 @@ VoxelServer::VoxelServer(Assignment::Command command, Assignment::Location locat _argv = NULL; _dontKillOnMissingDomain = false; - _PACKETS_PER_CLIENT_PER_INTERVAL = 10; + _packetsPerClientPerInterval = 10; _wantVoxelPersist = true; _wantLocalDomain = false; _debugVoxelSending = false; @@ -72,7 +72,7 @@ VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : Assign _argv = NULL; _dontKillOnMissingDomain = false; - _PACKETS_PER_CLIENT_PER_INTERVAL = 10; + _packetsPerClientPerInterval = 10; _wantVoxelPersist = true; _wantLocalDomain = false; _debugVoxelSending = false; @@ -250,11 +250,11 @@ void VoxelServer::run() { 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; + _packetsPerClientPerInterval = atoi(packetsPerSecond) / INTERVALS_PER_SECOND; + if (_packetsPerClientPerInterval < 1) { + _packetsPerClientPerInterval = 1; } - printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, _PACKETS_PER_CLIENT_PER_INTERVAL); + printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, _packetsPerClientPerInterval); } // for now, initialize the environments with fixed values @@ -342,9 +342,7 @@ void VoxelServer::run() { } } - if (_jurisdiction) { - delete _jurisdiction; - } + delete _jurisdiction; if (_jurisdictionSender) { _jurisdictionSender->terminate(); diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index 3a7d0e5c48..6eb412ea68 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -53,7 +53,7 @@ public: void lockTree() { pthread_mutex_lock(&_treeLock); } void unlockTree() { pthread_mutex_unlock(&_treeLock); } - int getPacketsPerClientPerInterval() const { return _PACKETS_PER_CLIENT_PER_INTERVAL; } + 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); } @@ -64,7 +64,7 @@ private: bool _dontKillOnMissingDomain; char _voxelPersistFilename[MAX_FILENAME_LENGTH]; - int _PACKETS_PER_CLIENT_PER_INTERVAL; + int _packetsPerClientPerInterval; VoxelTree _serverTree; // this IS a reaveraging tree bool _wantVoxelPersist; bool _wantLocalDomain; From 06f739a62390939d78c7cd39493d64ba5be7cc1a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Sep 2013 07:23:37 -0700 Subject: [PATCH 27/47] pass voxelServerConfig from domain-server through Assignment _payload to VoxelServer --- domain-server/src/main.cpp | 5 +- libraries/shared/src/Assignment.cpp | 7 ++- .../voxel-server-library/src/VoxelServer.cpp | 60 ++++++++++++++++++- .../voxel-server-library/src/VoxelServer.h | 4 ++ 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index fa6018b6c6..2ffad2f720 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -167,7 +167,10 @@ int main(int argc, const char* argv[]) { if (voxelServerConfig) { qDebug("Reading Voxel Server Configuration.\n"); qDebug() << " config: " << voxelServerConfig << "\n"; - voxelServerAssignment.setPayload((uchar*)voxelServerConfig, strlen(voxelServerConfig) + 1); + int payloadLength = strlen(voxelServerConfig) + sizeof(char); + uchar* payload = new uchar[payloadLength]; + memcpy(payload, voxelServerConfig, payloadLength); + voxelServerAssignment.setPayload(payload, payloadLength); } // construct a local socket to send with our created assignments to the global AS diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index e2608b230a..2fd5758007 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -85,17 +85,18 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : qDebug("Received a socket that cannot be unpacked!\n"); } } - + if (numBytes > numBytesRead) { _numPayloadBytes = numBytes - numBytesRead; - memcpy(_payload, dataBuffer + numBytesRead, numBytes - numBytesRead); + _payload = new uchar[_numPayloadBytes]; // <<< the code was not allocating _payload + memcpy(_payload, dataBuffer + numBytesRead, _numPayloadBytes); } } Assignment::~Assignment() { delete _attachedPublicSocket; delete _attachedLocalSocket; - delete _payload; + delete _payload; // <<< this probably needs to be delete[]??? _numPayloadBytes = 0; } diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 257f9b2640..9dafeafeee 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -11,6 +11,9 @@ #include #include +#include +#include + #include #include #include @@ -64,6 +67,7 @@ VoxelServer::VoxelServer(Assignment::Command command, Assignment::Location locat _jurisdictionSender = NULL; _voxelServerPacketProcessor = NULL; _voxelPersistThread = NULL; + _parsedArgV = NULL; } VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes), @@ -86,6 +90,16 @@ VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : Assign _jurisdictionSender = NULL; _voxelServerPacketProcessor = NULL; _voxelPersistThread = NULL; + _parsedArgV = NULL; +} + +VoxelServer::~VoxelServer() { + if (_parsedArgV) { + for (int i = 0; i < _argc; i++) { + delete[] _parsedArgV[i]; + } + delete[] _parsedArgV; + } } void VoxelServer::setArguments(int argc, char** argv) { @@ -93,6 +107,44 @@ void VoxelServer::setArguments(int argc, char** argv) { _argv = const_cast(argv); } +void VoxelServer::parsePayload() { + + //uchar* getPayload() { return _payload; } + //int getNumPayloadBytes() const { return _numPayloadBytes; } + + if (getNumPayloadBytes() > 0) { + QString config((const char*)getPayload()); + + QString delimiterPattern(" "); + QStringList configList = config.split(delimiterPattern); + + int argCount = configList.size() + 2; + + printf("VoxelServer::parsePayload()... argCount=%d\n",argCount); + + _parsedArgV = new char*[argCount]; + const char* dummy = "dummy"; + _parsedArgV[0] = new char[strlen(dummy)+1]; + strcpy(_parsedArgV[0], dummy); + + for (int i = 1; i < argCount-1; i++) { + QString configItem = configList.at(i-1); + _parsedArgV[i] = new char[configItem.length() + 1]; + strcpy(_parsedArgV[i], configItem.toLocal8Bit().constData()); + printf("VoxelServer::parsePayload()... _parsedArgV[%d]=%s\n", i, _parsedArgV[i]); + } + _parsedArgV[argCount - 1] = new char[strlen(dummy)+1]; + strcpy(_parsedArgV[argCount - 1], dummy); + + setArguments(argCount, _parsedArgV); + + for (int i = 0; i < argCount; i++) { + printf("_argv[%d]=%s\n", i, _argv[i]); + } + + } +} + void VoxelServer::setupStandAlone(const char* domain, int port) { NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, port); @@ -114,6 +166,12 @@ void VoxelServer::setupStandAlone(const char* domain, int port) { //int main(int argc, const char * argv[]) { void VoxelServer::run() { + + // Now would be a good time to parse our arguments, if we got them as assignment + if (getNumPayloadBytes() > 0) { + parsePayload(); + } + pthread_mutex_init(&_treeLock, NULL); qInstallMessageHandler(sharedMessageHandler); @@ -143,7 +201,7 @@ void VoxelServer::run() { _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); diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index 6eb412ea68..8ab18d8c46 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -27,6 +27,8 @@ public: VoxelServer(const unsigned char* dataBuffer, int numBytes); + ~VoxelServer(); + /// runs the voxel server assignment void run(); @@ -61,6 +63,7 @@ public: private: int _argc; const char** _argv; + char** _parsedArgV; bool _dontKillOnMissingDomain; char _voxelPersistFilename[MAX_FILENAME_LENGTH]; @@ -84,6 +87,7 @@ private: NodeWatcher _nodeWatcher; // used to cleanup AGENT data when agents are killed + void parsePayload(); }; #endif // __voxel_server__VoxelServer__ From 642b446d6f8081d9b6db02a55952dc58081a27e6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Sep 2013 07:30:04 -0700 Subject: [PATCH 28/47] tweak to payload parsing --- .../voxel-server-library/src/VoxelServer.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 9dafeafeee..8e1f19954e 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -105,6 +105,12 @@ VoxelServer::~VoxelServer() { void VoxelServer::setArguments(int argc, char** argv) { _argc = argc; _argv = const_cast(argv); + + printf("VoxelServer::setArguments()\n"); + for (int i = 0; i < _argc; i++) { + printf("_argv[%d]=%s\n", i, _argv[i]); + } + } void VoxelServer::parsePayload() { @@ -118,30 +124,23 @@ void VoxelServer::parsePayload() { QString delimiterPattern(" "); QStringList configList = config.split(delimiterPattern); - int argCount = configList.size() + 2; + int argCount = configList.size() + 1; printf("VoxelServer::parsePayload()... argCount=%d\n",argCount); _parsedArgV = new char*[argCount]; - const char* dummy = "dummy"; + const char* dummy = "config-from-payload"; _parsedArgV[0] = new char[strlen(dummy)+1]; strcpy(_parsedArgV[0], dummy); - for (int i = 1; i < argCount-1; i++) { + for (int i = 1; i < argCount; i++) { QString configItem = configList.at(i-1); _parsedArgV[i] = new char[configItem.length() + 1]; strcpy(_parsedArgV[i], configItem.toLocal8Bit().constData()); printf("VoxelServer::parsePayload()... _parsedArgV[%d]=%s\n", i, _parsedArgV[i]); } - _parsedArgV[argCount - 1] = new char[strlen(dummy)+1]; - strcpy(_parsedArgV[argCount - 1], dummy); setArguments(argCount, _parsedArgV); - - for (int i = 0; i < argCount; i++) { - printf("_argv[%d]=%s\n", i, _argv[i]); - } - } } From 3fde2887a3cc55cf28134bf1e87966f57b8026a9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 10:19:45 -0700 Subject: [PATCH 29/47] fixes to payload in Assignment --- domain-server/src/main.cpp | 2 +- libraries/shared/src/Assignment.cpp | 11 +++++++---- libraries/shared/src/Assignment.h | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index fa6018b6c6..4cb4dcc787 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -167,7 +167,7 @@ int main(int argc, const char* argv[]) { if (voxelServerConfig) { qDebug("Reading Voxel Server Configuration.\n"); qDebug() << " config: " << voxelServerConfig << "\n"; - voxelServerAssignment.setPayload((uchar*)voxelServerConfig, strlen(voxelServerConfig) + 1); + voxelServerAssignment.copyPayload((uchar*)voxelServerConfig, strlen(voxelServerConfig) + 1); } // construct a local socket to send with our created assignments to the global AS diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index e2608b230a..490a067da3 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -88,21 +88,21 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : if (numBytes > numBytesRead) { _numPayloadBytes = numBytes - numBytesRead; - memcpy(_payload, dataBuffer + numBytesRead, numBytes - numBytesRead); + _payload = new uchar[_numPayloadBytes]; + memcpy(_payload, dataBuffer + numBytesRead, _numPayloadBytes); } } Assignment::~Assignment() { delete _attachedPublicSocket; delete _attachedLocalSocket; - delete _payload; + delete[] _payload; _numPayloadBytes = 0; } const int MAX_PAYLOAD_BYTES = 1024; -void Assignment::setPayload(uchar* payload, int numBytes) { - _payload = payload; +void Assignment::copyPayload(uchar* payload, int numBytes) { if (numBytes > MAX_PAYLOAD_BYTES) { qDebug("Set payload called with number of bytes greater than maximum (%d). Will only transfer %d bytes.\n", @@ -114,6 +114,9 @@ void Assignment::setPayload(uchar* payload, int numBytes) { _numPayloadBytes = numBytes; } + delete[] _payload; + _payload = new uchar[_numPayloadBytes]; + memcpy(_payload, payload, _numPayloadBytes); } QString Assignment::getUUIDStringWithoutCurlyBraces() const { diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index d5ac858247..7cd9f0b18e 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -61,7 +61,7 @@ public: uchar* getPayload() { return _payload; } int getNumPayloadBytes() const { return _numPayloadBytes; } - void setPayload(uchar *payload, int numBytes); + void copyPayload(uchar *payload, int numBytes); int getNumberOfInstances() const { return _numberOfInstances; } void setNumberOfInstances(int numberOfInstances) { _numberOfInstances = numberOfInstances; } From 1a82ba230132b498af54664d34640732f6edea05 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 10:58:35 -0700 Subject: [PATCH 30/47] handle create assignment requests in domain-server --- domain-server/src/main.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 4cb4dcc787..402430e632 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -414,6 +414,18 @@ int main(int argc, const char* argv[]) { } } + ::assignmentQueueMutex.unlock(); + } else if (packetData[0] == PACKET_TYPE_CREATE_ASSIGNMENT) { + // this is a create assignment likely recieved from a server needed more clients to help with load + + // unpack it + Assignment* createAssignment = new Assignment(packetData, receivedBytes); + + qDebug() << "Received a create assignment -" << createAssignment << "\n"; + + // add the assignment at the back of the queue + ::assignmentQueueMutex.lock(); + ::assignmentQueue.push_back(createAssignment); ::assignmentQueueMutex.unlock(); } } From f0b834881bcbe9f0662e11cea44be4e96e79d1aa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 10:59:49 -0700 Subject: [PATCH 31/47] de-refs assignments for proper logging --- assignment-client/src/main.cpp | 2 +- domain-server/src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 0b9da7fa70..1d2f7c2bb7 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -78,7 +78,7 @@ void childClient() { // construct the deployed assignment from the packet data Assignment* deployedAssignment = AssignmentFactory::unpackAssignment(packetData, receivedBytes); - qDebug() << "Received an assignment -" << deployedAssignment << "\n"; + qDebug() << "Received an assignment -" << *deployedAssignment << "\n"; // switch our nodelist DOMAIN_IP if (packetData[0] == PACKET_TYPE_CREATE_ASSIGNMENT || diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 402430e632..0845ade33d 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -421,7 +421,7 @@ int main(int argc, const char* argv[]) { // unpack it Assignment* createAssignment = new Assignment(packetData, receivedBytes); - qDebug() << "Received a create assignment -" << createAssignment << "\n"; + qDebug() << "Received a create assignment -" << *createAssignment << "\n"; // add the assignment at the back of the queue ::assignmentQueueMutex.lock(); From 32b507d2ac14620b7541671aaa68eaa72aacf174 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 11:05:31 -0700 Subject: [PATCH 32/47] remove the global assignment-server for now to avoid confusion --- CMakeLists.txt | 1 - assignment-server/CMakeLists.txt | 13 ---- assignment-server/src/main.cpp | 117 ------------------------------- domain-server/src/main.cpp | 55 --------------- 4 files changed, 186 deletions(-) delete mode 100644 assignment-server/CMakeLists.txt delete mode 100644 assignment-server/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 50ac76adc3..0328f9ee1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,6 @@ set(CMAKE_AUTOMOC ON) add_subdirectory(animation-server) add_subdirectory(assignment-client) -add_subdirectory(assignment-server) add_subdirectory(domain-server) add_subdirectory(eve) add_subdirectory(interface) diff --git a/assignment-server/CMakeLists.txt b/assignment-server/CMakeLists.txt deleted file mode 100644 index c551cbf0a5..0000000000 --- a/assignment-server/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(TARGET_NAME assignment-server) - -set(ROOT_DIR ..) -set(MACRO_DIR ${ROOT_DIR}/cmake/macros) - -include(${MACRO_DIR}/SetupHifiProject.cmake) -setup_hifi_project(${TARGET_NAME} TRUE) - -# link in the shared library -include(${MACRO_DIR}/LinkHifiLibrary.cmake) -link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file diff --git a/assignment-server/src/main.cpp b/assignment-server/src/main.cpp deleted file mode 100644 index db335008a5..0000000000 --- a/assignment-server/src/main.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// main.cpp -// assignment-server -// -// Created by Stephen Birarda on 7/1/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -const int MAX_PACKET_SIZE_BYTES = 1400; -const long long NUM_DEFAULT_ASSIGNMENT_STALENESS_USECS = 10 * 1000 * 1000; - -int main(int argc, const char* argv[]) { - - qInstallMessageHandler(Logging::verboseMessageHandler); - - std::deque assignmentQueue; - - sockaddr_in senderSocket; - unsigned char senderData[MAX_PACKET_SIZE_BYTES] = {}; - ssize_t receivedBytes = 0; - - UDPSocket serverSocket(ASSIGNMENT_SERVER_PORT); - - unsigned char assignmentPacket[MAX_PACKET_SIZE_BYTES]; - int numSendHeaderBytes = populateTypeAndVersion(assignmentPacket, PACKET_TYPE_DEPLOY_ASSIGNMENT); - - while (true) { - if (serverSocket.receive((sockaddr*) &senderSocket, &senderData, &receivedBytes)) { - if (senderData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) { - // construct the requested assignment from the packet data - Assignment requestAssignment(senderData, receivedBytes); - - qDebug() << "Received request for assignment:" << requestAssignment << "\n"; - qDebug() << "Current queue size is" << assignmentQueue.size() << "\n"; - - // make sure there are assignments in the queue at all - if (assignmentQueue.size() > 0) { - - std::deque::iterator assignment = assignmentQueue.begin(); - - // enumerate assignments until we find one to give this client (if possible) - while (assignment != assignmentQueue.end()) { - - // if this assignment is stale then get rid of it and check the next one - if (usecTimestampNow() - usecTimestamp(&((*assignment)->getTime())) - >= NUM_DEFAULT_ASSIGNMENT_STALENESS_USECS) { - delete *assignment; - assignment = assignmentQueue.erase(assignment); - - continue; - } - - if (requestAssignment.getType() == Assignment::AllTypes || - (*assignment)->getType() == requestAssignment.getType()) { - // give this assignment out, either we have a type match or the requestor has said they will - // take all types - - // check if the requestor is on the same network as the destination for the assignment - if (senderSocket.sin_addr.s_addr == - ((sockaddr_in*) (*assignment)->getAttachedPublicSocket())->sin_addr.s_addr) { - // if this is the case we remove the public socket on the assignment by setting it to NULL - // this ensures the local IP and port sent to the requestor is the local address of destination - (*assignment)->setAttachedPublicSocket(NULL); - } - - - int numAssignmentBytes = (*assignment)->packToBuffer(assignmentPacket + numSendHeaderBytes); - - // send the assignment - serverSocket.send((sockaddr*) &senderSocket, - assignmentPacket, - numSendHeaderBytes + numAssignmentBytes); - - - // delete this assignment now that it has been sent out - delete *assignment; - // remove it from the deque and make the iterator the next assignment - assignmentQueue.erase(assignment); - - // stop looping - we've handed out an assignment - break; - } else { - // push forward the iterator to check the next assignment - assignment++; - } - } - } - } else if (senderData[0] == PACKET_TYPE_CREATE_ASSIGNMENT && packetVersionMatch(senderData)) { - // construct the create assignment from the packet data - Assignment* createdAssignment = new Assignment(senderData, receivedBytes); - - qDebug() << "Received a created assignment:" << *createdAssignment << "\n"; - qDebug() << "Current queue size is" << assignmentQueue.size() << "\n"; - - // assignment server is likely on a public server - // assume that the address we now have for the sender is the public address/port - // and store that with the assignment so it can be given to the requestor later if necessary - createdAssignment->setAttachedPublicSocket((sockaddr*) &senderSocket); - - // add this assignment to the queue - assignmentQueue.push_back(createdAssignment); - } - } - } -} diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 0845ade33d..188c460562 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -134,18 +134,6 @@ int main(int argc, const char* argv[]) { nodeList->startSilentNodeRemovalThread(); timeval lastStatSendTime = {}; - const char ASSIGNMENT_SERVER_OPTION[] = "-a"; - - // grab the overriden assignment-server hostname from argv, if it exists - const char* customAssignmentServer = getCmdOption(argc, argv, ASSIGNMENT_SERVER_OPTION); - if (customAssignmentServer) { - sockaddr_in customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServer, ASSIGNMENT_SERVER_PORT); - nodeList->setAssignmentServerSocket((sockaddr*) &customAssignmentSocket); - } - - // use a map to keep track of iterations of silence for assignment creation requests - const long long GLOBAL_ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000; - timeval lastGlobalAssignmentRequest = {}; // as a domain-server we will always want an audio mixer and avatar mixer // setup the create assignments for those @@ -430,49 +418,6 @@ int main(int argc, const char* argv[]) { } } - // if ASSIGNMENT_REQUEST_INTERVAL_USECS have passed since last global assignment request then fire off another - if (usecTimestampNow() - usecTimestamp(&lastGlobalAssignmentRequest) >= GLOBAL_ASSIGNMENT_REQUEST_INTERVAL_USECS) { - gettimeofday(&lastGlobalAssignmentRequest, NULL); - - ::assignmentQueueMutex.lock(); - - // go through our queue and see if there are any assignments to send to the global assignment server - std::deque::iterator assignment = ::assignmentQueue.begin(); - - while (assignment != assignmentQueue.end()) { - - if ((*assignment)->getLocation() != Assignment::LocalLocation) { - // attach our local socket to the assignment so the assignment-server can optionally hand it out - (*assignment)->setAttachedLocalSocket((sockaddr*) &localSocket); - - nodeList->sendAssignment(*(*assignment)); - - if ((*assignment)->getType() == Assignment::AgentType) { - // if this is a script assignment we need to delete it to avoid a memory leak - // or if there is more than one instance to send out, simpy decrease the number of instances - if ((*assignment)->getNumberOfInstances() > 1) { - (*assignment)->decrementNumberOfInstances(); - } else { - ::assignmentQueue.erase(assignment); - delete *assignment; - } - } else if ((*assignment)->getType() == Assignment::VoxelServerType) { - // this is a voxel server assignment - // remove the assignment from the queue - ::assignmentQueue.erase(assignment); - } - - // stop looping, we've handed out an assignment - break; - } else { - // push forward the iterator to check the next assignment - assignment++; - } - } - - ::assignmentQueueMutex.unlock(); - } - if (Logging::shouldSendStats()) { if (usecTimestampNow() - usecTimestamp(&lastStatSendTime) >= (NODE_COUNT_STAT_INTERVAL_MSECS * 1000)) { // time to send our count of nodes and servers to logstash From 7220643fe9b72b1df3de72816a1d6f27a9de4082 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 12:04:09 -0700 Subject: [PATCH 33/47] default AC to point to DS on localhost and default port --- assignment-client/src/main.cpp | 2 +- libraries/shared/src/NodeList.cpp | 10 +++++----- libraries/shared/src/NodeList.h | 2 +- libraries/shared/src/PacketHeaders.h | 2 -- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 1d2f7c2bb7..479e12eec7 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -199,7 +199,7 @@ int main(int argc, const char* argv[]) { if (customAssignmentServerHostname) { const char* customAssignmentServerPortString = getCmdOption(argc, argv, CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION); unsigned short assignmentServerPort = customAssignmentServerPortString - ? atoi(customAssignmentServerPortString) : ASSIGNMENT_SERVER_PORT; + ? atoi(customAssignmentServerPortString) : DEFAULT_DOMAINSERVER_PORT; ::customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServerHostname, assignmentServerPort); } diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index d5a8bf99a2..6af17c2dcf 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -33,7 +33,7 @@ const char SOLO_NODE_TYPES[2] = { const char DEFAULT_DOMAIN_HOSTNAME[MAX_HOSTNAME_BYTES] = "root.highfidelity.io"; const char DEFAULT_DOMAIN_IP[INET_ADDRSTRLEN] = ""; // IP Address will be re-set by lookup on startup -const int DEFAULT_DOMAINSERVER_PORT = 40102; +const unsigned short DEFAULT_DOMAINSERVER_PORT = 40102; bool silentNodeThreadStopFlag = false; bool pingUnknownNodeThreadStopFlag = false; @@ -382,9 +382,9 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte return readNodes; } -const char GLOBAL_ASSIGNMENT_SERVER_HOSTNAME[] = "assignment.highfidelity.io"; -const sockaddr_in GLOBAL_ASSIGNMENT_SOCKET = socketForHostnameAndHostOrderPort(GLOBAL_ASSIGNMENT_SERVER_HOSTNAME, - ASSIGNMENT_SERVER_PORT); +const char LOCAL_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost"; +const sockaddr_in DEFAULT_LOCAL_ASSIGNMENT_SOCKET = socketForHostnameAndHostOrderPort(LOCAL_ASSIGNMENT_SERVER_HOSTNAME, + DEFAULT_DOMAINSERVER_PORT); void NodeList::sendAssignment(Assignment& assignment) { unsigned char assignmentPacket[MAX_PACKET_SIZE]; @@ -396,7 +396,7 @@ void NodeList::sendAssignment(Assignment& assignment) { int numAssignmentBytes = assignment.packToBuffer(assignmentPacket + numHeaderBytes); sockaddr* assignmentServerSocket = (_assignmentServerSocket == NULL) - ? (sockaddr*) &GLOBAL_ASSIGNMENT_SOCKET + ? (sockaddr*) &DEFAULT_LOCAL_ASSIGNMENT_SOCKET : _assignmentServerSocket; _nodeSocket.send(assignmentServerSocket, assignmentPacket, numHeaderBytes + numAssignmentBytes); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 7233e7af69..0834a278dc 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -38,7 +38,7 @@ const int MAX_HOSTNAME_BYTES = 256; extern const char DEFAULT_DOMAIN_HOSTNAME[MAX_HOSTNAME_BYTES]; extern const char DEFAULT_DOMAIN_IP[INET_ADDRSTRLEN]; // IP Address will be re-set by lookup on startup -extern const int DEFAULT_DOMAINSERVER_PORT; +extern const unsigned short DEFAULT_DOMAINSERVER_PORT; const int UNKNOWN_NODE_ID = 0; diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 2aaabc4aa8..10ddbf56ad 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -58,6 +58,4 @@ const int MAX_PACKET_HEADER_BYTES = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) #define ADD_SCENE_COMMAND "add scene" #define TEST_COMMAND "a message" -const unsigned short ASSIGNMENT_SERVER_PORT = 7007; - #endif From d6a8a4eb260bf94127212317280bbae15f6acbe4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 12:07:08 -0700 Subject: [PATCH 34/47] allow custom listen port for domain-server --- domain-server/src/main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 188c460562..6d676a2ca0 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -114,7 +114,11 @@ int main(int argc, const char* argv[]) { qInstallMessageHandler(Logging::verboseMessageHandler); - NodeList* nodeList = NodeList::createInstance(NODE_TYPE_DOMAIN, DOMAIN_LISTEN_PORT); + const char CUSTOM_PORT_OPTION[] = "-p"; + const char* customPortString = getCmdOption(argc, argv, CUSTOM_PORT_OPTION); + unsigned short domainServerPort = customPortString ? atoi(customPortString) : DOMAIN_LISTEN_PORT; + + NodeList* nodeList = NodeList::createInstance(NODE_TYPE_DOMAIN, domainServerPort); setvbuf(stdout, NULL, _IOLBF, 0); From 8c9a14cdbeb042a9b9a4422c76df1aec0d98a571 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 13:09:07 -0700 Subject: [PATCH 35/47] CR fix to change back to setPayload with const param --- domain-server/src/main.cpp | 2 +- libraries/shared/src/Assignment.cpp | 2 +- libraries/shared/src/Assignment.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 188c460562..2bb67c6f4c 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -155,7 +155,7 @@ int main(int argc, const char* argv[]) { if (voxelServerConfig) { qDebug("Reading Voxel Server Configuration.\n"); qDebug() << " config: " << voxelServerConfig << "\n"; - voxelServerAssignment.copyPayload((uchar*)voxelServerConfig, strlen(voxelServerConfig) + 1); + voxelServerAssignment.setPayload((uchar*)voxelServerConfig, strlen(voxelServerConfig) + 1); } // construct a local socket to send with our created assignments to the global AS diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 490a067da3..102a5d3c30 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -102,7 +102,7 @@ Assignment::~Assignment() { const int MAX_PAYLOAD_BYTES = 1024; -void Assignment::copyPayload(uchar* payload, int numBytes) { +void Assignment::setPayload(const uchar* payload, int numBytes) { if (numBytes > MAX_PAYLOAD_BYTES) { qDebug("Set payload called with number of bytes greater than maximum (%d). Will only transfer %d bytes.\n", diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 7cd9f0b18e..f1b19938bc 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -61,7 +61,7 @@ public: uchar* getPayload() { return _payload; } int getNumPayloadBytes() const { return _numPayloadBytes; } - void copyPayload(uchar *payload, int numBytes); + void setPayload(const uchar *payload, int numBytes); int getNumberOfInstances() const { return _numberOfInstances; } void setNumberOfInstances(int numberOfInstances) { _numberOfInstances = numberOfInstances; } From 6355f677f7e0349451f953335e75725500f49de5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Sep 2013 13:19:19 -0700 Subject: [PATCH 36/47] have voxel server create assignments for child voxel servers --- .../voxel-server-library/src/VoxelServer.cpp | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 8e1f19954e..8e78597041 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -115,14 +115,37 @@ void VoxelServer::setArguments(int argc, char** argv) { void VoxelServer::parsePayload() { - //uchar* getPayload() { return _payload; } - //int getNumPayloadBytes() const { return _numPayloadBytes; } - if (getNumPayloadBytes() > 0) { - QString config((const char*)getPayload()); + QString multiConfig((const char*)getPayload()); + QStringList multiConfigList = multiConfig.split(";"); + + // There there are multiple configs, then this instance will run the first + // config, and launch Assignment requests for the additional configs. + if (multiConfigList.size() > 1) { + printf("VoxelServer::parsePayload()... multiple Configs... config count=%d\n", multiConfigList.size()); - QString delimiterPattern(" "); - QStringList configList = config.split(delimiterPattern); + + // skip 0 - that's the one we'll run + for (int i = 1; i < multiConfigList.size(); i++) { + QString config = multiConfigList.at(i); + + printf(" config[%d]=%s\n", i, config.toLocal8Bit().constData()); + + Assignment voxelServerAssignment(Assignment::CreateCommand, + Assignment::VoxelServerType, + getLocation()); // use same location as we were created in. + + int payloadLength = config.length() + sizeof(char); + voxelServerAssignment.setPayload((uchar*)config.toLocal8Bit().constData(), payloadLength); + + printf(">>>>> SENDING ASSIGNMENT >>>>>>\n"); + NodeList::getInstance()->sendAssignment(voxelServerAssignment); + } + } + + // Now, parse the first config + QString config = multiConfigList.at(0); + QStringList configList = config.split(" "); int argCount = configList.size() + 1; From 65625c8e76d6b17cd0cb964a726975e832bf1096 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Sep 2013 13:23:34 -0700 Subject: [PATCH 37/47] match setPayload() behavior --- domain-server/src/main.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 698d732059..3e92be4003 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -156,9 +156,7 @@ int main(int argc, const char* argv[]) { qDebug("Reading Voxel Server Configuration.\n"); qDebug() << " config: " << voxelServerConfig << "\n"; int payloadLength = strlen(voxelServerConfig) + sizeof(char); - uchar* payload = new uchar[payloadLength]; - memcpy(payload, voxelServerConfig, payloadLength); - voxelServerAssignment.setPayload(payload, payloadLength); + voxelServerAssignment.setPayload((const uchar*)voxelServerConfig, payloadLength); } // construct a local socket to send with our created assignments to the global AS From ded7a9504ba17be036997f94625a4b0dafa6041c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Sep 2013 13:28:50 -0700 Subject: [PATCH 38/47] moved printf to qDebug --- .../voxel-server-library/src/VoxelServer.cpp | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 8e78597041..6214005b0f 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -106,9 +107,9 @@ void VoxelServer::setArguments(int argc, char** argv) { _argc = argc; _argv = const_cast(argv); - printf("VoxelServer::setArguments()\n"); + qDebug("VoxelServer::setArguments()\n"); for (int i = 0; i < _argc; i++) { - printf("_argv[%d]=%s\n", i, _argv[i]); + qDebug("_argv[%d]=%s\n", i, _argv[i]); } } @@ -122,14 +123,13 @@ void VoxelServer::parsePayload() { // There there are multiple configs, then this instance will run the first // config, and launch Assignment requests for the additional configs. if (multiConfigList.size() > 1) { - printf("VoxelServer::parsePayload()... multiple Configs... config count=%d\n", multiConfigList.size()); - + qDebug("Voxel Server received assignment for multiple Configs... config count=%d\n", multiConfigList.size()); // skip 0 - that's the one we'll run for (int i = 1; i < multiConfigList.size(); i++) { QString config = multiConfigList.at(i); - printf(" config[%d]=%s\n", i, config.toLocal8Bit().constData()); + qDebug(" config[%d]=%s\n", i, config.toLocal8Bit().constData()); Assignment voxelServerAssignment(Assignment::CreateCommand, Assignment::VoxelServerType, @@ -138,7 +138,7 @@ void VoxelServer::parsePayload() { int payloadLength = config.length() + sizeof(char); voxelServerAssignment.setPayload((uchar*)config.toLocal8Bit().constData(), payloadLength); - printf(">>>>> SENDING ASSIGNMENT >>>>>>\n"); + qDebug("Requesting additional Voxel Server assignment to handle config %d\n", i); NodeList::getInstance()->sendAssignment(voxelServerAssignment); } } @@ -149,7 +149,7 @@ void VoxelServer::parsePayload() { int argCount = configList.size() + 1; - printf("VoxelServer::parsePayload()... argCount=%d\n",argCount); + qDebug("VoxelServer::parsePayload()... argCount=%d\n",argCount); _parsedArgV = new char*[argCount]; const char* dummy = "config-from-payload"; @@ -160,7 +160,7 @@ void VoxelServer::parsePayload() { QString configItem = configList.at(i-1); _parsedArgV[i] = new char[configItem.length() + 1]; strcpy(_parsedArgV[i], configItem.toLocal8Bit().constData()); - printf("VoxelServer::parsePayload()... _parsedArgV[%d]=%s\n", i, _parsedArgV[i]); + qDebug("VoxelServer::parsePayload()... _parsedArgV[%d]=%s\n", i, _parsedArgV[i]); } setArguments(argCount, _parsedArgV); @@ -174,7 +174,7 @@ void VoxelServer::setupStandAlone(const char* domain, int port) { const char* local = "--local"; _wantLocalDomain = strcmp(domain, local) == 0; if (_wantLocalDomain) { - printf("Local Domain MODE!\n"); + qDebug("Local Domain MODE!\n"); NodeList::getInstance()->setDomainIPToLocalhost(); } else { if (domain) { @@ -201,22 +201,22 @@ void VoxelServer::run() { const char* JURISDICTION_FILE = "--jurisdictionFile"; const char* jurisdictionFile = getCmdOption(_argc, _argv, JURISDICTION_FILE); if (jurisdictionFile) { - printf("jurisdictionFile=%s\n", jurisdictionFile); + qDebug("jurisdictionFile=%s\n", jurisdictionFile); - printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + qDebug("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); _jurisdiction = new JurisdictionMap(jurisdictionFile); - printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + qDebug("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); + qDebug("jurisdictionRoot=%s\n", jurisdictionRoot); } const char* JURISDICTION_ENDNODES = "--jurisdictionEndNodes"; const char* jurisdictionEndNodes = getCmdOption(_argc, _argv, JURISDICTION_ENDNODES); if (jurisdictionEndNodes) { - printf("jurisdictionEndNodes=%s\n", jurisdictionEndNodes); + qDebug("jurisdictionEndNodes=%s\n", jurisdictionEndNodes); } if (jurisdictionRoot || jurisdictionEndNodes) { @@ -227,21 +227,21 @@ void VoxelServer::run() { // 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)); + qDebug("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"); + qDebug("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)); + qDebug("Using Minimal Environment=%s\n", debug::valueOf(_sendMinimalEnvironment)); } - printf("Sending environments=%s\n", debug::valueOf(_sendEnvironments)); + qDebug("Sending environments=%s\n", debug::valueOf(_sendEnvironments)); NodeList* nodeList = NodeList::getInstance(); nodeList->setOwnerType(NODE_TYPE_VOXEL_SERVER); @@ -257,26 +257,26 @@ void VoxelServer::run() { const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; _displayVoxelStats = getCmdOption(_argc, _argv, DISPLAY_VOXEL_STATS); - printf("displayVoxelStats=%s\n", debug::valueOf(_displayVoxelStats)); + qDebug("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)); + qDebug("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)); + qDebug("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)); + qDebug("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)); + qDebug("wantVoxelPersist=%s\n", debug::valueOf(_wantVoxelPersist)); // if we want Voxel Persistence, load the local file now... bool persistantFileRead = false; @@ -292,7 +292,7 @@ void VoxelServer::run() { strcpy(_voxelPersistFilename, LOCAL_VOXELS_PERSIST_FILE); } - printf("loading voxels from file: %s...\n", _voxelPersistFilename); + qDebug("loading voxels from file: %s...\n", _voxelPersistFilename); persistantFileRead = _serverTree.readFromSVOFile(_voxelPersistFilename); if (persistantFileRead) { @@ -301,15 +301,15 @@ void VoxelServer::run() { // after done inserting all these voxels, then reaverage colors _serverTree.reaverageVoxelColors(_serverTree.rootNode); - printf("Voxels reAveraged\n"); + qDebug("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)); + qDebug("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); + qDebug("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount); // now set up VoxelPersistThread _voxelPersistThread = new VoxelPersistThread(&_serverTree, _voxelPersistFilename); @@ -334,7 +334,7 @@ void VoxelServer::run() { if (_packetsPerClientPerInterval < 1) { _packetsPerClientPerInterval = 1; } - printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, _packetsPerClientPerInterval); + qDebug("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, _packetsPerClientPerInterval); } // for now, initialize the environments with fixed values @@ -417,7 +417,7 @@ void VoxelServer::run() { } else if (_voxelServerPacketProcessor) { _voxelServerPacketProcessor->queueReceivedPacket(senderAddress, packetData, packetLength); } else { - printf("unknown packet ignored... packetData[0]=%c\n", packetData[0]); + qDebug("unknown packet ignored... packetData[0]=%c\n", packetData[0]); } } } From ab85c4109dfb2103fbd991893a762771eaabf5b2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 13:29:53 -0700 Subject: [PATCH 39/47] use QHostInfo and QHostAddress for DS changes in NodeList --- animation-server/src/main.cpp | 6 +-- assignment-client/src/Agent.cpp | 2 +- assignment-client/src/main.cpp | 13 +++--- interface/src/Application.cpp | 6 +-- interface/src/Menu.cpp | 74 +++++++++++------------------- libraries/shared/CMakeLists.txt | 4 ++ libraries/shared/src/NodeList.cpp | 69 ++++++++++++---------------- libraries/shared/src/NodeList.h | 22 ++++----- libraries/shared/src/UDPSocket.cpp | 2 +- libraries/shared/src/UDPSocket.h | 2 +- 10 files changed, 87 insertions(+), 113 deletions(-) diff --git a/animation-server/src/main.cpp b/animation-server/src/main.cpp index eb1e3546dd..50e1da707c 100644 --- a/animation-server/src/main.cpp +++ b/animation-server/src/main.cpp @@ -685,9 +685,9 @@ int main(int argc, const char * argv[]) nodeList->setDomainIPToLocalhost(); } - const char* domainIP = getCmdOption(argc, argv, "--domain"); - if (domainIP) { - NodeList::getInstance()->setDomainIP(domainIP); + const char* domainHostname = getCmdOption(argc, argv, "--domain"); + if (domainHostname) { + NodeList::getInstance()->setDomainHostname(domainHostname); } nodeList->linkedDataCreateCallback = NULL; // do we need a callback? diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index a2d96c6a1c..5ba022d3a6 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -27,7 +27,7 @@ void Agent::run() { // figure out the URL for the script for this agent assignment QString scriptURLString("http://%1:8080/assignment/%2"); - scriptURLString = scriptURLString.arg(NodeList::getInstance()->getDomainIP(), + scriptURLString = scriptURLString.arg(NodeList::getInstance()->getDomainIP().toString(), this->getUUIDStringWithoutCurlyBraces()); QUrl scriptURL(scriptURLString); diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 479e12eec7..83c793736f 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -84,19 +84,20 @@ void childClient() { if (packetData[0] == PACKET_TYPE_CREATE_ASSIGNMENT || deployedAssignment->getAttachedPublicSocket()->sa_family == AF_INET) { - in_addr domainSocketAddr = {}; + + sockaddr* domainSocket = NULL; if (packetData[0] == PACKET_TYPE_CREATE_ASSIGNMENT) { // the domain server IP address is the address we got this packet from - domainSocketAddr = senderSocket.sin_addr; + domainSocket = (sockaddr*) &senderSocket; } else { // grab the domain server IP address from the packet from the AS - domainSocketAddr = ((sockaddr_in*) deployedAssignment->getAttachedPublicSocket())->sin_addr; + domainSocket = (sockaddr*) deployedAssignment->getAttachedPublicSocket(); } - nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); + nodeList->setDomainIP(QHostAddress(domainSocket)); - qDebug("Destination IP for assignment is %s\n", inet_ntoa(domainSocketAddr)); + qDebug("Destination IP for assignment is %s\n", nodeList->getDomainIP().toString().toStdString().c_str()); // run the deployed assignment deployedAssignment->run(); @@ -199,7 +200,7 @@ int main(int argc, const char* argv[]) { if (customAssignmentServerHostname) { const char* customAssignmentServerPortString = getCmdOption(argc, argv, CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION); unsigned short assignmentServerPort = customAssignmentServerPortString - ? atoi(customAssignmentServerPortString) : DEFAULT_DOMAINSERVER_PORT; + ? atoi(customAssignmentServerPortString) : DEFAULT_DOMAIN_SERVER_PORT; ::customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServerHostname, assignmentServerPort); } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c0484bf7fa..06ea59d30a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -183,9 +183,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : // --domain or --local options NodeList::getInstance()->loadData(_settings); - const char* domainIP = getCmdOption(argc, constArgv, "--domain"); - if (domainIP) { - NodeList::getInstance()->setDomainIP(domainIP); + const char* domainHostname = getCmdOption(argc, constArgv, "--domain"); + if (domainHostname) { + NodeList::getInstance()->setDomainHostname(domainHostname); } // Handle Local Domain testing with the --local command line diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8a693582c1..b2e94f993c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -687,6 +687,30 @@ void Menu::aboutApp() { InfoView::forcedShow(); } +void updateDSHostname(const QString& domainServerHostname) { + QString newHostname(DEFAULT_DOMAIN_HOSTNAME); + + if (domainServerHostname.size() > 0) { + // the user input a new hostname, use that + newHostname = domainServerHostname; + } + + // check if the domain server hostname is new + if (NodeList::getInstance()->getDomainHostname() != newHostname) { + + NodeList::getInstance()->clear(); + + // kill the local voxels + Application::getInstance()->getVoxels()->killLocalVoxels(); + + // reset the environment to default + Application::getInstance()->getEnvironment()->resetToDefault(); + + // set the new hostname + NodeList::getInstance()->setDomainHostname(newHostname); + } +} + void Menu::editPreferences() { Application* applicationInstance = Application::getInstance(); QDialog dialog(applicationInstance->getGLWidget()); @@ -738,30 +762,7 @@ void Menu::editPreferences() { return; } - QByteArray newHostname; - - if (domainServerHostname->text().size() > 0) { - // the user input a new hostname, use that - newHostname = domainServerHostname->text().toLocal8Bit(); - } else { - // the user left the field blank, use the default hostname - newHostname = QByteArray(DEFAULT_DOMAIN_HOSTNAME); - } - - // check if the domain server hostname is new - if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname.constData(), newHostname.size()) != 0) { - - NodeList::getInstance()->clear(); - - // kill the local voxels - applicationInstance->getVoxels()->killLocalVoxels(); - - // reset the environment to default - applicationInstance->getEnvironment()->resetToDefault(); - - // set the new hostname - NodeList::getInstance()->setDomainHostname(newHostname.constData()); - } + updateDSHostname(domainServerHostname->text()); QUrl url(avatarURL->text()); applicationInstance->getAvatar()->getVoxels()->setVoxelURL(url); @@ -808,30 +809,7 @@ void Menu::goToDomain() { return; } - QByteArray newHostname; - - if (domainServerHostname->text().size() > 0) { - // the user input a new hostname, use that - newHostname = domainServerHostname->text().toLocal8Bit(); - } else { - // the user left the field blank, use the default hostname - newHostname = QByteArray(DEFAULT_DOMAIN_HOSTNAME); - } - - // check if the domain server hostname is new - if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname.constData(), newHostname.size()) != 0) { - - NodeList::getInstance()->clear(); - - // kill the local voxels - applicationInstance->getVoxels()->killLocalVoxels(); - - // reset the environment to default - applicationInstance->getEnvironment()->resetToDefault(); - - // set the new hostname - NodeList::getInstance()->setDomainHostname(newHostname.constData()); - } + updateDSHostname(domainServerHostname->text()); } void Menu::goToLocation() { diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index 218adb4d5f..d9bfc769d1 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -6,9 +6,13 @@ set(MACRO_DIR ${ROOT_DIR}/cmake/macros) set(TARGET_NAME shared) project(${TARGET_NAME}) +find_package(Qt5Network REQUIRED) + include(${MACRO_DIR}/SetupHifiLibrary.cmake) setup_hifi_library(${TARGET_NAME}) +qt5_use_modules(${TARGET_NAME} Network) + set(EXTERNAL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external) if (WIN32) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 6af17c2dcf..76820d9a40 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -12,6 +12,7 @@ #include #include +#include #include "Assignment.h" #include "Logging.h" @@ -31,9 +32,8 @@ const char SOLO_NODE_TYPES[2] = { NODE_TYPE_AUDIO_MIXER }; -const char DEFAULT_DOMAIN_HOSTNAME[MAX_HOSTNAME_BYTES] = "root.highfidelity.io"; -const char DEFAULT_DOMAIN_IP[INET_ADDRSTRLEN] = ""; // IP Address will be re-set by lookup on startup -const unsigned short DEFAULT_DOMAINSERVER_PORT = 40102; +const QString DEFAULT_DOMAIN_HOSTNAME = "root.highfidelity.io"; +const unsigned short DEFAULT_DOMAIN_SERVER_PORT = 40102; bool silentNodeThreadStopFlag = false; bool pingUnknownNodeThreadStopFlag = false; @@ -59,6 +59,9 @@ NodeList* NodeList::getInstance() { } NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : + _domainHostname(DEFAULT_DOMAIN_HOSTNAME), + _domainIP(), + _domainPort(DEFAULT_DOMAIN_SERVER_PORT), _nodeBuckets(), _numNodes(0), _nodeSocket(newSocketListenPort), @@ -69,8 +72,7 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : _numNoReplyDomainCheckIns(0), _assignmentServerSocket(NULL) { - memcpy(_domainHostname, DEFAULT_DOMAIN_HOSTNAME, sizeof(DEFAULT_DOMAIN_HOSTNAME)); - memcpy(_domainIP, DEFAULT_DOMAIN_IP, sizeof(DEFAULT_DOMAIN_IP)); + } NodeList::~NodeList() { @@ -82,22 +84,11 @@ NodeList::~NodeList() { stopSilentNodeRemovalThread(); } -void NodeList::setDomainHostname(const char* domainHostname) { - memset(_domainHostname, 0, sizeof(_domainHostname)); - memcpy(_domainHostname, domainHostname, strlen(domainHostname)); +void NodeList::setDomainHostname(const QString& domainHostname) { + _domainHostname = domainHostname; - // reset the domain IP so the hostname is checked again - setDomainIP(""); -} - -void NodeList::setDomainIP(const char* domainIP) { - memset(_domainIP, 0, sizeof(_domainIP)); - memcpy(_domainIP, domainIP, strlen(domainIP)); -} - -void NodeList::setDomainIPToLocalhost() { - int ip = getLocalAddress(); - sprintf(_domainIP, "%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); + // reset our _domainIP to the null address so that a lookup happens on next check in + _domainIP = QHostAddress(); } void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) { @@ -117,10 +108,7 @@ void NodeList::processNodeData(sockaddr* senderAddress, unsigned char* packetDat switch (packetData[0]) { case PACKET_TYPE_DOMAIN: { // only process the DS if this is our current domain server - sockaddr_in domainServerSocket = *(sockaddr_in*) senderAddress; - const char* domainSenderIP = inet_ntoa(domainServerSocket.sin_addr); - - if (memcmp(domainSenderIP, _domainIP, strlen(domainSenderIP)) == 0) { + if (_domainIP == QHostAddress(senderAddress)) { processDomainServerList(packetData, dataBytes); } @@ -272,19 +260,23 @@ void NodeList::sendDomainServerCheckIn(const char* assignmentUUID) { static bool printedDomainServerIP = false; // Lookup the IP address of the domain server if we need to - if (atoi(_domainIP) == 0) { - printf("Looking up %s\n", _domainHostname); - struct hostent* pHostInfo; - if ((pHostInfo = gethostbyname(_domainHostname)) != NULL) { - sockaddr_in tempAddress; - memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); - strcpy(_domainIP, inet_ntoa(tempAddress.sin_addr)); - qDebug("Domain Server: %s\n", _domainHostname); + if (_domainIP.isNull()) { + qDebug("Looking up DS hostname %s.\n", _domainHostname.toStdString().c_str()); + + QHostInfo domainServerHostInfo = QHostInfo::fromName(_domainHostname); + + if (!domainServerHostInfo.addresses().isEmpty()) { + // set our domainIP to the first IP address + _domainIP = domainServerHostInfo.addresses().first(); + + qDebug("DS at %s is at %s\n", _domainHostname.toStdString().c_str(), _domainIP.toString().toStdString().c_str()); + + printedDomainServerIP = true; } else { qDebug("Failed domain server lookup\n"); } } else if (!printedDomainServerIP) { - qDebug("Domain Server IP: %s\n", _domainIP); + qDebug("Domain Server IP: %s\n", _domainIP.toString().toStdString().c_str()); printedDomainServerIP = true; } @@ -337,7 +329,7 @@ void NodeList::sendDomainServerCheckIn(const char* assignmentUUID) { checkInPacketSize = packetPosition - checkInPacket; } - _nodeSocket.send(_domainIP, DEFAULT_DOMAINSERVER_PORT, checkInPacket, checkInPacketSize); + _nodeSocket.send(_domainIP.toString().toStdString().c_str(), _domainPort, checkInPacket, checkInPacketSize); // increment the count of un-replied check-ins _numNoReplyDomainCheckIns++; @@ -370,7 +362,7 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte // if the public socket address is 0 then it's reachable at the same IP // as the domain server if (nodePublicSocket.sin_addr.s_addr == 0) { - inet_aton(_domainIP, &nodePublicSocket.sin_addr); + nodePublicSocket.sin_addr.s_addr = _domainIP.toIPv4Address(); } addOrUpdateNode((sockaddr*) &nodePublicSocket, (sockaddr*) &nodeLocalSocket, nodeType, nodeId); @@ -384,7 +376,7 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte const char LOCAL_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost"; const sockaddr_in DEFAULT_LOCAL_ASSIGNMENT_SOCKET = socketForHostnameAndHostOrderPort(LOCAL_ASSIGNMENT_SERVER_HOSTNAME, - DEFAULT_DOMAINSERVER_PORT); + DEFAULT_DOMAIN_SERVER_PORT); void NodeList::sendAssignment(Assignment& assignment) { unsigned char assignmentPacket[MAX_PACKET_SIZE]; @@ -561,8 +553,7 @@ void NodeList::loadData(QSettings *settings) { QString domainServerHostname = settings->value(DOMAIN_SERVER_SETTING_KEY).toString(); if (domainServerHostname.size() > 0) { - memset(_domainHostname, 0, MAX_HOSTNAME_BYTES); - memcpy(_domainHostname, domainServerHostname.toLocal8Bit().constData(), domainServerHostname.size()); + _domainHostname = domainServerHostname; } settings->endGroup(); @@ -571,7 +562,7 @@ void NodeList::loadData(QSettings *settings) { void NodeList::saveData(QSettings* settings) { settings->beginGroup(DOMAIN_SERVER_SETTING_KEY); - if (memcmp(_domainHostname, DEFAULT_DOMAIN_HOSTNAME, strlen(DEFAULT_DOMAIN_HOSTNAME)) != 0) { + if (_domainHostname != DEFAULT_DOMAIN_HOSTNAME) { // the user is using a different hostname, store it settings->setValue(DOMAIN_SERVER_SETTING_KEY, QVariant(_domainHostname)); } else { diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 0834a278dc..32a6d33e1e 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -14,6 +14,7 @@ #include #include +#include #include #include "Node.h" @@ -36,9 +37,8 @@ extern const char SOLO_NODE_TYPES[2]; const int MAX_HOSTNAME_BYTES = 256; -extern const char DEFAULT_DOMAIN_HOSTNAME[MAX_HOSTNAME_BYTES]; -extern const char DEFAULT_DOMAIN_IP[INET_ADDRSTRLEN]; // IP Address will be re-set by lookup on startup -extern const unsigned short DEFAULT_DOMAINSERVER_PORT; +extern const QString DEFAULT_DOMAIN_HOSTNAME; +extern const unsigned short DEFAULT_DOMAIN_SERVER_PORT; const int UNKNOWN_NODE_ID = 0; @@ -65,16 +65,15 @@ public: NodeListIterator begin() const; NodeListIterator end() const; - NODE_TYPE getOwnerType() const { return _ownerType; } void setOwnerType(NODE_TYPE ownerType) { _ownerType = ownerType; } - const char* getDomainHostname() const { return _domainHostname; } - void setDomainHostname(const char* domainHostname); + const QString& getDomainHostname() const { return _domainHostname; } + void setDomainHostname(const QString& domainHostname); - const char* getDomainIP() const { return _domainIP; } - void setDomainIP(const char* domainIP); - void setDomainIPToLocalhost(); + const QHostAddress& getDomainIP() const { return _domainIP; } + void setDomainIP(const QHostAddress& domainIP) { _domainIP = domainIP; } + void setDomainIPToLocalhost() { _domainIP = QHostAddress(INADDR_LOOPBACK); } uint16_t getLastNodeID() const { return _lastNodeID; } void increaseNodeID() { (++_lastNodeID == UNKNOWN_NODE_ID) ? ++_lastNodeID : _lastNodeID; } @@ -141,8 +140,9 @@ private: void addNodeToList(Node* newNode); - char _domainHostname[MAX_HOSTNAME_BYTES]; - char _domainIP[INET_ADDRSTRLEN]; + QString _domainHostname; + QHostAddress _domainIP; + unsigned short _domainPort; Node** _nodeBuckets[MAX_NUM_NODES / NODES_PER_BUCKET]; int _numNodes; UDPSocket _nodeSocket; diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index 11fd218a56..beee5c6879 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -275,7 +275,7 @@ int UDPSocket::send(sockaddr* destAddress, const void* data, size_t byteLength) return sent_bytes; } -int UDPSocket::send(char* destAddress, int destPort, const void* data, size_t byteLength) const { +int UDPSocket::send(const char* destAddress, int destPort, const void* data, size_t byteLength) const { // change address and port on reusable global to passed variables destSockaddr.sin_addr.s_addr = inet_addr(destAddress); diff --git a/libraries/shared/src/UDPSocket.h b/libraries/shared/src/UDPSocket.h index d3f7cfac58..b177fd4e30 100644 --- a/libraries/shared/src/UDPSocket.h +++ b/libraries/shared/src/UDPSocket.h @@ -31,7 +31,7 @@ public: void setBlockingReceiveTimeoutInUsecs(int timeoutUsecs); int send(sockaddr* destAddress, const void* data, size_t byteLength) const; - int send(char* destAddress, int destPort, const void* data, size_t byteLength) const; + int send(const char* destAddress, int destPort, const void* data, size_t byteLength) const; bool receive(void* receivedData, ssize_t* receivedBytes) const; bool receive(sockaddr* recvAddress, void* receivedData, ssize_t* receivedBytes) const; From 9fa695b71cae70f6fe13c2bae4c633a0ff8b5124 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 13:50:14 -0700 Subject: [PATCH 40/47] allow setting of custom port via domainHostname setting --- interface/src/Menu.cpp | 37 +++++++++++++++++++++---------- libraries/shared/src/NodeList.cpp | 20 ++++++++++++++++- libraries/shared/src/NodeList.h | 3 +++ 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index b2e94f993c..ca7e513f67 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -711,6 +711,24 @@ void updateDSHostname(const QString& domainServerHostname) { } } +const int QLINE_MINIMUM_WIDTH = 400; + + +QLineEdit* lineEditForDomainHostname() { + QString currentDomainHostname = NodeList::getInstance()->getDomainHostname(); + + if (NodeList::getInstance()->getDomainPort() != DEFAULT_DOMAIN_SERVER_PORT) { + // add the port to the currentDomainHostname string if it is custom + currentDomainHostname.append(QString(":%1").arg(NodeList::getInstance()->getDomainPort())); + } + + QLineEdit* domainServerLineEdit = new QLineEdit(currentDomainHostname); + domainServerLineEdit->setPlaceholderText(DEFAULT_DOMAIN_HOSTNAME); + domainServerLineEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); + + return domainServerLineEdit; +} + void Menu::editPreferences() { Application* applicationInstance = Application::getInstance(); QDialog dialog(applicationInstance->getGLWidget()); @@ -721,11 +739,8 @@ void Menu::editPreferences() { QFormLayout* form = new QFormLayout(); layout->addLayout(form, 1); - const int QLINE_MINIMUM_WIDTH = 400; - - QLineEdit* domainServerHostname = new QLineEdit(QString(NodeList::getInstance()->getDomainHostname())); - domainServerHostname->setMinimumWidth(QLINE_MINIMUM_WIDTH); - form->addRow("Domain server:", domainServerHostname); + QLineEdit* domainServerLineEdit = lineEditForDomainHostname(); + form->addRow("Domain server:", domainServerLineEdit); QLineEdit* avatarURL = new QLineEdit(applicationInstance->getAvatar()->getVoxels()->getVoxelURL().toString()); avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH); @@ -762,7 +777,7 @@ void Menu::editPreferences() { return; } - updateDSHostname(domainServerHostname->text()); + updateDSHostname(domainServerLineEdit->text()); QUrl url(avatarURL->text()); applicationInstance->getAvatar()->getVoxels()->setVoxelURL(url); @@ -791,12 +806,10 @@ void Menu::goToDomain() { QFormLayout* form = new QFormLayout(); layout->addLayout(form, 1); + - const int QLINE_MINIMUM_WIDTH = 400; - - QLineEdit* domainServerHostname = new QLineEdit(QString(NodeList::getInstance()->getDomainHostname())); - domainServerHostname->setMinimumWidth(QLINE_MINIMUM_WIDTH); - form->addRow("Domain server:", domainServerHostname); + QLineEdit* domainServerLineEdit = lineEditForDomainHostname(); + form->addRow("Domain server:", domainServerLineEdit); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept())); @@ -809,7 +822,7 @@ void Menu::goToDomain() { return; } - updateDSHostname(domainServerHostname->text()); + updateDSHostname(domainServerLineEdit->text()); } void Menu::goToLocation() { diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 76820d9a40..27de44792c 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -85,7 +85,25 @@ NodeList::~NodeList() { } void NodeList::setDomainHostname(const QString& domainHostname) { - _domainHostname = domainHostname; + + int colonIndex = domainHostname.indexOf(':'); + + if (colonIndex > 0) { + // the user has included a custom DS port with the hostname + + // the new hostname is everything up to the colon + _domainHostname = domainHostname.left(colonIndex); + + // grab the port by reading the string after the colon + _domainPort = atoi(domainHostname.mid(colonIndex + 1, domainHostname.size()).toLocal8Bit().constData()); + + qDebug() << "Updated hostname to" << _domainHostname << "and port to" << _domainPort << "\n"; + + } else { + // no port included with the hostname, simply set the member variable and reset the domain server port to default + _domainHostname = domainHostname; + _domainPort = DEFAULT_DOMAIN_SERVER_PORT; + } // reset our _domainIP to the null address so that a lookup happens on next check in _domainIP = QHostAddress(); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 32a6d33e1e..ba01fb49ea 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -74,6 +74,9 @@ public: const QHostAddress& getDomainIP() const { return _domainIP; } void setDomainIP(const QHostAddress& domainIP) { _domainIP = domainIP; } void setDomainIPToLocalhost() { _domainIP = QHostAddress(INADDR_LOOPBACK); } + + unsigned short getDomainPort() const { return _domainPort; } + void setDomainPort(unsigned short domainPort) { _domainPort = domainPort; } uint16_t getLastNodeID() const { return _lastNodeID; } void increaseNodeID() { (++_lastNodeID == UNKNOWN_NODE_ID) ? ++_lastNodeID : _lastNodeID; } From 8a901382a3efbb46575b03305cd9341dd40e5506 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 14:01:32 -0700 Subject: [PATCH 41/47] get rid of local and domain options in interface --- interface/src/Application.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 06ea59d30a..58bb48cae6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -183,18 +183,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : // --domain or --local options NodeList::getInstance()->loadData(_settings); - const char* domainHostname = getCmdOption(argc, constArgv, "--domain"); - if (domainHostname) { - NodeList::getInstance()->setDomainHostname(domainHostname); - } - - // Handle Local Domain testing with the --local command line - if (cmdOptionExists(argc, constArgv, "--local")) { - qDebug("Local Domain MODE!\n"); - - NodeList::getInstance()->setDomainIPToLocalhost(); - } - // Check to see if the user passed in a command line option for loading a local // Voxel File. _voxelsFilename = getCmdOption(argc, constArgv, "-i"); From 80b1b810cefff4123bc7e78406ea108bab1708e7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Sep 2013 16:13:13 -0500 Subject: [PATCH 42/47] spacing fix --- libraries/voxel-server-library/src/VoxelServer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 6214005b0f..f9f61d1a35 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -153,12 +153,12 @@ void VoxelServer::parsePayload() { _parsedArgV = new char*[argCount]; const char* dummy = "config-from-payload"; - _parsedArgV[0] = new char[strlen(dummy)+1]; + _parsedArgV[0] = new char[strlen(dummy) + sizeof(char)]; strcpy(_parsedArgV[0], dummy); for (int i = 1; i < argCount; i++) { QString configItem = configList.at(i-1); - _parsedArgV[i] = new char[configItem.length() + 1]; + _parsedArgV[i] = new char[configItem.length() + sizeof(char)]; strcpy(_parsedArgV[i], configItem.toLocal8Bit().constData()); qDebug("VoxelServer::parsePayload()... _parsedArgV[%d]=%s\n", i, _parsedArgV[i]); } From 5393d7528114d6330c94986c9a64db786ce110b3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 14:39:35 -0700 Subject: [PATCH 43/47] remove call to re-set default setting in InfoView --- interface/src/InfoView.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/src/InfoView.cpp b/interface/src/InfoView.cpp index d5f9b1d881..de1ba88c7a 100644 --- a/interface/src/InfoView.cpp +++ b/interface/src/InfoView.cpp @@ -17,9 +17,8 @@ #define SETTINGS_VERSION_KEY "info-version" #define MAX_DIALOG_HEIGHT_RATIO 0.9 -InfoView::InfoView(bool forced) { - _forced = forced; - settings()->setAttribute(QWebSettings::LocalContentCanAccessFileUrls, true); +InfoView::InfoView(bool forced) : + _forced(forced) { switchToResourcesParentIfRequired(); QString absPath = QFileInfo("resources/html/interface-welcome-allsvg.html").absoluteFilePath(); From 22d2b52ba9c87ff676c24e1eeb7b089fd07a9dea Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 14:48:49 -0700 Subject: [PATCH 44/47] simplifications to README for new assigned stack --- README.md | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index fb1b0c8692..bb93311775 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ I want to run my own virtual world! In order to set up your own virtual world, you need to set up and run your own local "domain". At a minimum, you must run a domain-server, voxel-server, -audio-mixer, and avatar-mixer to have a working virtual world. The audio-mixer and avatar-mixer are assignments given from the domain-server to any assignment-client that reports directly to it. +audio-mixer, and avatar-mixer to have a working virtual world. The audio-mixer, avatar-mixer, and voxel-server are assignments given from the domain-server to any assignment-client that reports directly to it. Complete the steps above to build the system components, using the default Cmake Unix Makefiles generator. Start with an empty build directory. @@ -106,7 +106,7 @@ window, change directory into the build directory, make the needed components, a First we make the targets we'll need. cd build - make domain-server voxel-server assignment-client + make domain-server assignment-client If after this step you're seeing something like the following @@ -114,35 +114,16 @@ If after this step you're seeing something like the following you likely had Cmake generate Xcode project files and have not run `cmake ..` in a clean build directory. -Then, launch the static components - a domain-server and a voxel-server. All of the targets will run in the foreground, so you'll either want to background it yourself or open a seperate terminal window per target. +Then, launch the static domain-server. All of the targets will run in the foreground, so you'll either want to background it yourself or open a seperate terminal window per target. cd domain-server && ./domain-server - ./voxel-server/voxel-server --local > /tmp/voxel-server.log 2>&1 & -Then, run an assignment-client with 2 forks to fulfill the avatar-mixer and audio-mixer assignments. It uses localhost as its assignment-server and talks to it on port 40102 (the default domain-server port). +Then, run an assignment-client with 3 forks to fulfill the avatar-mixer, audio-mixer, and voxel-server assignments. It uses localhost as its assignment-server and talks to it on port 40102 (the default domain-server port). - ./assignment-client/assignment-client -n 2 -a localhost -p 40102 + ./assignment-client/assignment-client -n 3 Any target can be terminated with CTRL-C (SIGINT) in the associated terminal window. -Determine the IP address of the machine you're running these servers on. Here's -a handy resource that explains how to do this for different operating systems. -http://kb.iu.edu/data/aapa.html - -On Mac OS X, and many Unix systems you can use the ifconfig command. Typically, -the following command will give you the IP address you need to use. - - ifconfig | grep inet | grep broadcast - -You should get something like this: - - inet 192.168.1.104 netmask 0xffffff00 broadcast 192.168.1.255 - -Your IP address is the first set of numbers. In this case "192.168.1.104". You -may now use this IP address to access your domain. If you are running a local -DNS or other name service you should be able to access this IP address by name -as well. - To test things out you'll want to run the Interface client. You can make that target with the following command: make interface @@ -150,9 +131,8 @@ To test things out you'll want to run the Interface client. You can make that ta Then run the executable it builds, or open interface.app if you're on OS X. To access your local domain in Interface, open the Preferences dialog box, from -the Interface menu on OS X or the File menu on Linux, and enter the IP address of the local DNS name for the -server computer in the "Domain" edit control. +the Interface menu on OS X or the File menu on Linux, and enter "localhost" for the +server hostname in the "Domain" edit control. In the voxel-server/src directory you will find a README that explains in -further detail how to setup and administer a voxel-server. - +further detail how to setup and administer a voxel-server. \ No newline at end of file From a9efa169be8c080c8050dd53a390429a317f37cb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 14:58:44 -0700 Subject: [PATCH 45/47] fix ordering of QHostAdress to s_addr --- libraries/shared/src/NodeList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 27de44792c..d330065405 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -380,7 +380,7 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte // if the public socket address is 0 then it's reachable at the same IP // as the domain server if (nodePublicSocket.sin_addr.s_addr == 0) { - nodePublicSocket.sin_addr.s_addr = _domainIP.toIPv4Address(); + nodePublicSocket.sin_addr.s_addr = htonl(_domainIP.toIPv4Address()); } addOrUpdateNode((sockaddr*) &nodePublicSocket, (sockaddr*) &nodeLocalSocket, nodeType, nodeId); From b4f9e393a47c095b13bda241f7ff70fc20acf587 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 15:05:23 -0700 Subject: [PATCH 46/47] prefer IPv4 address when looking up for domain IP --- libraries/shared/src/NodeList.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index d330065405..b6db77875a 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -106,7 +106,7 @@ void NodeList::setDomainHostname(const QString& domainHostname) { } // reset our _domainIP to the null address so that a lookup happens on next check in - _domainIP = QHostAddress(); + _domainIP.clear(); } void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) { @@ -283,15 +283,21 @@ void NodeList::sendDomainServerCheckIn(const char* assignmentUUID) { QHostInfo domainServerHostInfo = QHostInfo::fromName(_domainHostname); - if (!domainServerHostInfo.addresses().isEmpty()) { - // set our domainIP to the first IP address - _domainIP = domainServerHostInfo.addresses().first(); + for (int i = 0; i < domainServerHostInfo.addresses().size(); i++) { + if (domainServerHostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) { + _domainIP = domainServerHostInfo.addresses()[i]; + + qDebug("DS at %s is at %s\n", _domainHostname.toStdString().c_str(), _domainIP.toString().toStdString().c_str()); + + printedDomainServerIP = true; + + break; + } - qDebug("DS at %s is at %s\n", _domainHostname.toStdString().c_str(), _domainIP.toString().toStdString().c_str()); - - printedDomainServerIP = true; - } else { - qDebug("Failed domain server lookup\n"); + // if we got here without a break out of the for loop then we failed to lookup the address + if (i == domainServerHostInfo.addresses().size() - 1) { + qDebug("Failed domain server lookup\n"); + } } } else if (!printedDomainServerIP) { qDebug("Domain Server IP: %s\n", _domainIP.toString().toStdString().c_str()); From 5479c5b40fc2714b9508144e1fabdcaee9ea1b21 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Sep 2013 15:20:55 -0700 Subject: [PATCH 47/47] use qDebug for too much time message in AudioMixer --- assignment-client/src/audio/AudioMixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 135fc341e5..98e4036533 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -425,7 +425,7 @@ void AudioMixer::run() { if (usecToSleep > 0) { usleep(usecToSleep); } else { - std::cout << "Took too much time, not sleeping!\n"; + qDebug("Took too much time, not sleeping!\n"); } } } \ No newline at end of file