This commit is contained in:
stojce 2013-09-19 19:51:40 +02:00
commit eb7c122991
23 changed files with 317 additions and 493 deletions

View file

@ -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)

View file

@ -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.

View file

@ -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?

View file

@ -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);

View file

@ -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");
}
}
}

View file

@ -78,25 +78,15 @@ 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 ||
deployedAssignment->getAttachedPublicSocket()->sa_family == AF_INET) {
// switch our nodelist domain IP and port to whoever sent us the assignment
if (packetData[0] == PACKET_TYPE_CREATE_ASSIGNMENT) {
in_addr domainSocketAddr = {};
nodeList->setDomainIP(QHostAddress((sockaddr*) &senderSocket));
nodeList->setDomainPort(ntohs(senderSocket.sin_port));
if (packetData[0] == PACKET_TYPE_CREATE_ASSIGNMENT) {
// the domain server IP address is the address we got this packet from
domainSocketAddr = senderSocket.sin_addr;
} else {
// grab the domain server IP address from the packet from the AS
domainSocketAddr = ((sockaddr_in*) deployedAssignment->getAttachedPublicSocket())->sin_addr;
}
nodeList->setDomainIP(inet_ntoa(domainSocketAddr));
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();
@ -195,11 +185,18 @@ int main(int argc, const char* argv[]) {
// grab the overriden assignment-server hostname from argv, if it exists
const char* customAssignmentServerHostname = getCmdOption(argc, argv, CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION);
const char* customAssignmentServerPortString = getCmdOption(argc, argv, CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION);
if (customAssignmentServerHostname) {
const char* customAssignmentServerPortString = getCmdOption(argc, argv, CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION);
if (customAssignmentServerHostname || customAssignmentServerPortString) {
// set the custom port or default if it wasn't passed
unsigned short assignmentServerPort = customAssignmentServerPortString
? atoi(customAssignmentServerPortString) : ASSIGNMENT_SERVER_PORT;
? atoi(customAssignmentServerPortString) : DEFAULT_DOMAIN_SERVER_PORT;
// set the custom hostname or default if it wasn't passed
if (!customAssignmentServerHostname) {
customAssignmentServerHostname = LOCAL_ASSIGNMENT_SERVER_HOSTNAME;
}
::customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServerHostname, assignmentServerPort);
}

View file

@ -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})

View file

@ -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 <arpa/inet.h>
#include <fstream>
#include <deque>
#include <QtCore/QString>
#include <Assignment.h>
#include <Logging.h>
#include <PacketHeaders.h>
#include <SharedUtil.h>
#include <UDPSocket.h>
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<Assignment*> 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<Assignment*>::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);
}
}
}
}

View file

@ -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);
@ -134,18 +138,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
@ -167,7 +159,8 @@ 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);
voxelServerAssignment.setPayload((const uchar*)voxelServerConfig, payloadLength);
}
// construct a local socket to send with our created assignments to the global AS
@ -374,8 +367,6 @@ 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);
@ -395,14 +386,15 @@ int main(int argc, const char* argv[]) {
delete *assignment;
}
} else {
Assignment *sentAssignment = *assignment;
// remove the assignment from the queue
::assignmentQueue.erase(assignment);
if ((*assignment)->getType() != Assignment::VoxelServerType) {
if (sentAssignment->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);
::assignmentQueue.push_back(sentAssignment);
}
}
@ -415,50 +407,19 @@ int main(int argc, const char* argv[]) {
}
::assignmentQueueMutex.unlock();
}
}
// 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<Assignment*>::iterator assignment = ::assignmentQueue.begin();
while (assignment != assignmentQueue.end()) {
} 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
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++;
}
// 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();
}
::assignmentQueueMutex.unlock();
}
if (Logging::shouldSendStats()) {

View file

@ -183,18 +183,6 @@ 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);
}
// 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");
@ -333,7 +321,7 @@ void Application::initializeGL() {
Menu::getInstance()->checkForUpdates();
#endif
InfoView::showFirstTime();
InfoView::showFirstTime(Menu::getInstance());
}
void Application::paintGL() {

View file

@ -17,9 +17,9 @@
#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, QWidget* parent) :
QWebView(parent),
_forced(forced) {
switchToResourcesParentIfRequired();
QString absPath = QFileInfo("resources/html/interface-welcome-allsvg.html").absoluteFilePath();
@ -29,12 +29,12 @@ InfoView::InfoView(bool forced) {
connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loaded(bool)));
}
void InfoView::showFirstTime() {
new InfoView(false);
void InfoView::showFirstTime(QWidget* parent) {
new InfoView(false, parent);
}
void InfoView::forcedShow() {
new InfoView(true);
void InfoView::forcedShow(QWidget* parent) {
new InfoView(true, parent);
}
bool InfoView::shouldShow() {
@ -46,18 +46,15 @@ bool InfoView::shouldShow() {
QString lastVersion = settings->value(SETTINGS_VERSION_KEY).toString();
QWebFrame* mainFrame = page()->mainFrame();
QWebElement versionTag = mainFrame->findFirstElement("#version");
QWebElement versionTag = page()->mainFrame()->findFirstElement("#version");
QString version = versionTag.attribute("value");
if (lastVersion == QString::null || version == QString::null || lastVersion != version) {
if (version != QString::null) {
settings->setValue(SETTINGS_VERSION_KEY, version);
}
if (version != QString::null && (lastVersion == QString::null || lastVersion != version)) {
settings->setValue(SETTINGS_VERSION_KEY, version);
return true;
}
return false;
} else {
return false;
}
}
void InfoView::loaded(bool ok) {

View file

@ -14,11 +14,11 @@
class InfoView : public QWebView {
Q_OBJECT
public:
static void showFirstTime();
static void forcedShow();
static void showFirstTime(QWidget* parent);
static void forcedShow(QWidget* parent);
private:
InfoView(bool forced);
InfoView(bool forced, QWidget* parent);
bool _forced;
bool shouldShow();

View file

@ -684,7 +684,49 @@ bool Menu::isVoxelModeActionChecked() {
}
void Menu::aboutApp() {
InfoView::forcedShow();
InfoView::forcedShow(this);
}
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);
}
}
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() {
@ -697,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);
@ -738,30 +777,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(domainServerLineEdit->text());
QUrl url(avatarURL->text());
applicationInstance->getAvatar()->getVoxels()->setVoxelURL(url);
@ -790,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()));
@ -808,30 +822,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(domainServerLineEdit->text());
}
void Menu::goToLocation() {

View file

@ -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)

View file

@ -18,8 +18,6 @@ Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assig
_command(command),
_type(type),
_location(location),
_attachedPublicSocket(NULL),
_attachedLocalSocket(NULL),
_numberOfInstances(1),
_payload(NULL),
_numPayloadBytes(0)
@ -35,8 +33,6 @@ Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assig
Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) :
_location(GlobalLocation),
_attachedPublicSocket(NULL),
_attachedLocalSocket(NULL),
_numberOfInstances(1),
_payload(NULL),
_numPayloadBytes(0)
@ -59,50 +55,27 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) :
memcpy(&_type, dataBuffer + numBytesRead, sizeof(Assignment::Type));
numBytesRead += sizeof(Assignment::Type);
if (dataBuffer[0] != PACKET_TYPE_REQUEST_ASSIGNMENT) {
if (_command != Assignment::RequestCommand) {
// read the GUID for this assignment
_uuid = QUuid::fromRfc4122(QByteArray((const char*) dataBuffer + numBytesRead, NUM_BYTES_RFC4122_UUID));
numBytesRead += NUM_BYTES_RFC4122_UUID;
}
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 (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::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",
@ -114,36 +87,15 @@ void Assignment::setPayload(uchar* payload, int numBytes) {
_numPayloadBytes = numBytes;
}
delete[] _payload;
_payload = new uchar[_numPayloadBytes];
memcpy(_payload, payload, _numPayloadBytes);
}
QString Assignment::getUUIDStringWithoutCurlyBraces() const {
return _uuid.toString().mid(1, _uuid.toString().length() - 2);
}
void Assignment::setAttachedPublicSocket(const sockaddr* attachedPublicSocket) {
if (_attachedPublicSocket) {
// delete the old socket if it exists
delete _attachedPublicSocket;
_attachedPublicSocket = NULL;
}
if (attachedPublicSocket) {
copySocketToEmptySocketPointer(&_attachedPublicSocket, attachedPublicSocket);
}
}
void Assignment::setAttachedLocalSocket(const sockaddr* attachedLocalSocket) {
if (_attachedLocalSocket) {
// delete the old socket if it exists
delete _attachedLocalSocket;
_attachedLocalSocket = NULL;
}
if (attachedLocalSocket) {
copySocketToEmptySocketPointer(&_attachedLocalSocket, attachedLocalSocket);
}
}
int Assignment::packToBuffer(unsigned char* buffer) {
int numPackedBytes = 0;
@ -156,19 +108,11 @@ int Assignment::packToBuffer(unsigned char* buffer) {
numPackedBytes += NUM_BYTES_RFC4122_UUID;
}
if (_attachedPublicSocket || _attachedLocalSocket) {
sockaddr* socketToPack = (_attachedPublicSocket) ? _attachedPublicSocket : _attachedLocalSocket;
// we have a socket to pack, add the designator
buffer[numPackedBytes++] = (socketToPack->sa_family == AF_INET)
? IPv4_ADDRESS_DESIGNATOR : IPv6_ADDRESS_DESIGNATOR;
numPackedBytes += packSocket(buffer + numPackedBytes, socketToPack);
}
if (_numPayloadBytes) {
memcpy(buffer + numPackedBytes, _payload, _numPayloadBytes);
numPackedBytes += _numPayloadBytes;
}
return numPackedBytes;
}

View file

@ -43,7 +43,7 @@ public:
Assignment(Assignment::Command command,
Assignment::Type type,
Assignment::Location location = Assignment::GlobalLocation);
Assignment::Location location = Assignment::LocalLocation);
/// Constructs an Assignment from the data in the buffer
/// \param dataBuffer the source buffer to un-pack the assignment from
@ -61,17 +61,11 @@ public:
uchar* getPayload() { return _payload; }
int getNumPayloadBytes() const { return _numPayloadBytes; }
void setPayload(uchar *payload, int numBytes);
void setPayload(const uchar *payload, int numBytes);
int getNumberOfInstances() const { return _numberOfInstances; }
void setNumberOfInstances(int numberOfInstances) { _numberOfInstances = numberOfInstances; }
void decrementNumberOfInstances() { --_numberOfInstances; }
const sockaddr* getAttachedPublicSocket() { return _attachedPublicSocket; }
void setAttachedPublicSocket(const sockaddr* attachedPublicSocket);
const sockaddr* getAttachedLocalSocket() { return _attachedLocalSocket; }
void setAttachedLocalSocket(const sockaddr* attachedLocalSocket);
/// Packs the assignment to the passed buffer
/// \param buffer the buffer in which to pack the assignment
@ -89,8 +83,6 @@ private:
Assignment::Command _command; /// the command for this assignment (Create, Deploy, Request)
Assignment::Type _type; /// the type of the assignment, defines what the assignee will do
Assignment::Location _location; /// the location of the assignment, allows a domain to preferentially use local ACs
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
uchar *_payload; /// an optional payload attached to this assignment, a maximum for 1024 bytes will be packed

View file

@ -12,6 +12,7 @@
#include <cstdio>
#include <QtCore/QDebug>
#include <QtNetwork/QHostInfo>
#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 int 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,29 @@ 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) {
// 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));
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.clear();
}
void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) {
@ -117,10 +126,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,24 +278,34 @@ 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);
} else {
qDebug("Failed domain server lookup\n");
if (_domainIP.isNull()) {
qDebug("Looking up DS hostname %s.\n", _domainHostname.toStdString().c_str());
QHostInfo domainServerHostInfo = QHostInfo::fromName(_domainHostname);
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;
}
// 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);
qDebug("Domain Server IP: %s\n", _domainIP.toString().toStdString().c_str());
printedDomainServerIP = true;
}
static unsigned char* checkInPacket = NULL;
static int checkInPacketSize = 0;
unsigned char* checkInPacket = NULL;
int checkInPacketSize = 0;
// construct the DS check in packet if we need to
if (!checkInPacket) {
@ -337,7 +353,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 +386,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 = htonl(_domainIP.toIPv4Address());
}
addOrUpdateNode((sockaddr*) &nodePublicSocket, (sockaddr*) &nodeLocalSocket, nodeType, nodeId);
@ -382,9 +398,8 @@ 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 sockaddr_in DEFAULT_LOCAL_ASSIGNMENT_SOCKET = socketForHostnameAndHostOrderPort(LOCAL_ASSIGNMENT_SERVER_HOSTNAME,
DEFAULT_DOMAIN_SERVER_PORT);
void NodeList::sendAssignment(Assignment& assignment) {
unsigned char assignmentPacket[MAX_PACKET_SIZE];
@ -396,7 +411,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);
@ -561,8 +576,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 +585,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 {

View file

@ -14,6 +14,7 @@
#include <iterator>
#include <unistd.h>
#include <QtNetwork/QHostAddress>
#include <QtCore/QSettings>
#include "Node.h"
@ -36,9 +37,10 @@ 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 int DEFAULT_DOMAINSERVER_PORT;
extern const QString DEFAULT_DOMAIN_HOSTNAME;
extern const unsigned short DEFAULT_DOMAIN_SERVER_PORT;
const char LOCAL_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost";
const int UNKNOWN_NODE_ID = 0;
@ -65,16 +67,18 @@ 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); }
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; }
@ -141,8 +145,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;

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -11,6 +11,10 @@
#include <cstring>
#include <cstdio>
#include <QDebug>
#include <QString>
#include <QStringList>
#include <OctalCode.h>
#include <NodeList.h>
#include <NodeTypes.h>
@ -64,6 +68,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,11 +91,80 @@ 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) {
_argc = argc;
_argv = const_cast<const char**>(argv);
qDebug("VoxelServer::setArguments()\n");
for (int i = 0; i < _argc; i++) {
qDebug("_argv[%d]=%s\n", i, _argv[i]);
}
}
void VoxelServer::parsePayload() {
if (getNumPayloadBytes() > 0) {
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) {
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);
qDebug(" 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);
qDebug("Requesting additional Voxel Server assignment to handle config %d\n", i);
NodeList::getInstance()->sendAssignment(voxelServerAssignment);
}
}
// Now, parse the first config
QString config = multiConfigList.at(0);
QStringList configList = config.split(" ");
int argCount = configList.size() + 1;
qDebug("VoxelServer::parsePayload()... argCount=%d\n",argCount);
_parsedArgV = new char*[argCount];
const char* dummy = "config-from-payload";
_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() + sizeof(char)];
strcpy(_parsedArgV[i], configItem.toLocal8Bit().constData());
qDebug("VoxelServer::parsePayload()... _parsedArgV[%d]=%s\n", i, _parsedArgV[i]);
}
setArguments(argCount, _parsedArgV);
}
}
void VoxelServer::setupStandAlone(const char* domain, int port) {
@ -100,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) {
@ -114,6 +188,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);
@ -121,47 +201,47 @@ 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) {
_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));
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);
@ -177,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;
@ -212,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) {
@ -221,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);
@ -254,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
@ -337,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]);
}
}
}

View file

@ -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__