From 12697c6b141475d491ff2a314d7e58f79f192778 Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 14:30:13 -0700
Subject: [PATCH 01/11] add method to clear the NodeList

---
 libraries/shared/src/NodeList.cpp | 15 +++++++++++++++
 libraries/shared/src/NodeList.h   |  2 ++
 2 files changed, 17 insertions(+)

diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp
index 391e22a915..b4e3112768 100644
--- a/libraries/shared/src/NodeList.cpp
+++ b/libraries/shared/src/NodeList.cpp
@@ -70,6 +70,8 @@ NodeList::NodeList(char newOwnerType, unsigned int newSocketListenPort) :
 NodeList::~NodeList() {
     delete _nodeTypesOfInterest;
     
+    clear();
+    
     // stop the spawned threads, if they were started
     stopSilentNodeRemovalThread();
     
@@ -209,6 +211,19 @@ int NodeList::getNumAliveNodes() const {
     return numAliveNodes;
 }
 
+void NodeList::clear() {
+    // delete all of the nodes in the list, set the pointers back to NULL and the number of nodes to 0
+    for (int i = 0; i < _numNodes; i++) {
+        Node** nodeBucket = _nodeBuckets[i / NODES_PER_BUCKET];
+        Node* node = nodeBucket[i % NODES_PER_BUCKET];
+        
+        delete node;
+        node = NULL;
+    }
+    
+    _numNodes = 0;
+}
+
 void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest) {
     delete _nodeTypesOfInterest;
     
diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h
index da9c4a556a..57f8083113 100644
--- a/libraries/shared/src/NodeList.h
+++ b/libraries/shared/src/NodeList.h
@@ -65,6 +65,8 @@ public:
     int size() { return _numNodes; }
     int getNumAliveNodes() const;
     
+    void clear();
+    
     void lock() { pthread_mutex_lock(&mutex); }
     void unlock() { pthread_mutex_unlock(&mutex); }
     

From d389dc6e3ad73ece5fa78f6835a0a41d07713a83 Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 15:17:10 -0700
Subject: [PATCH 02/11] add method to NodeList to set domain IP to local, move
 mutex lock to node

---
 animation-server/src/main.cpp     |  3 +-
 audio-mixer/src/main.cpp          |  9 +++---
 avatar-mixer/src/main.cpp         |  3 +-
 interface/src/Application.cpp     | 27 +++++++++++-----
 interface/src/Audio.cpp           |  4 +--
 libraries/shared/src/Node.cpp     |  4 +++
 libraries/shared/src/Node.h       |  4 +++
 libraries/shared/src/NodeList.cpp | 51 ++++++++++++++++++++-----------
 libraries/shared/src/NodeList.h   | 22 ++++++++-----
 voxel-server/src/main.cpp         |  3 +-
 10 files changed, 85 insertions(+), 45 deletions(-)

diff --git a/animation-server/src/main.cpp b/animation-server/src/main.cpp
index 126216ea9b..c6c38d8748 100644
--- a/animation-server/src/main.cpp
+++ b/animation-server/src/main.cpp
@@ -697,8 +697,7 @@ int main(int argc, const char * argv[])
     ::wantLocalDomain = cmdOptionExists(argc, argv,local);
     if (::wantLocalDomain) {
         printf("Local Domain MODE!\n");
-        int ip = getLocalAddress();
-        sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
+        nodeList->setDomainIPToLocalhost();
     }
 
     nodeList->linkedDataCreateCallback = NULL; // do we need a callback?
diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp
index b900c48479..239eb7a32d 100644
--- a/audio-mixer/src/main.cpp
+++ b/audio-mixer/src/main.cpp
@@ -70,16 +70,15 @@ bool wantLocalDomain = false;
 int main(int argc, const char* argv[]) {
     setvbuf(stdout, NULL, _IOLBF, 0);
     
+    NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT);
+    
     // Handle Local Domain testing with the --local command line
     const char* local = "--local";
     ::wantLocalDomain = cmdOptionExists(argc, argv,local);
     if (::wantLocalDomain) {
         printf("Local Domain MODE!\n");
-        int ip = getLocalAddress();
-        sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
-    }
-    
-    NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT);
+        nodeList->setDomainIPToLocalhost();
+    }    
     
     ssize_t receivedBytes = 0;
     
diff --git a/avatar-mixer/src/main.cpp b/avatar-mixer/src/main.cpp
index f2fd031526..b24fb7dcbc 100644
--- a/avatar-mixer/src/main.cpp
+++ b/avatar-mixer/src/main.cpp
@@ -60,8 +60,7 @@ int main(int argc, const char* argv[]) {
     const char* local = "--local";
     if (cmdOptionExists(argc, argv, local)) {
         printf("Local Domain MODE!\n");
-        int ip = getLocalAddress();
-        sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
+        nodeList->setDomainIPToLocalhost();
     }
     
     nodeList->linkedDataCreateCallback = attachAvatarDataToNode;
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 75f45e8d91..6504c2d87f 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -227,14 +227,14 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
     
     const char* domainIP = getCmdOption(argc, constArgv, "--domain");
     if (domainIP) {
-        strcpy(DOMAIN_IP, domainIP);
+        NodeList::getInstance()->setDomainIP(domainIP);
     }
     
     // Handle Local Domain testing with the --local command line
     if (cmdOptionExists(argc, constArgv, "--local")) {
         printLog("Local Domain MODE!\n");
-        int ip = getLocalAddress();
-        sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
+        
+        NodeList::getInstance()->setDomainIPToLocalhost();
     }
     
     // Check to see if the user passed in a command line option for loading a local
@@ -1101,8 +1101,14 @@ void Application::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* avatarURL = new QLineEdit(_myAvatar.getVoxels()->getVoxelURL().toString());
-    avatarURL->setMinimumWidth(400);
+    avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH);
     form->addRow("Avatar URL:", avatarURL);
     
     QSpinBox* horizontalFieldOfView = new QSpinBox();
@@ -1133,9 +1139,11 @@ void Application::editPreferences() {
     if (dialog.exec() != QDialog::Accepted) {
         return;
     }
+    
     QUrl url(avatarURL->text());
     _myAvatar.getVoxels()->setVoxelURL(url);
     sendAvatarVoxelURLMessage(url);
+    
     _headCameraPitchYawScale = headCameraPitchYawScale->value();
     _myAvatar.setLeanScale(leanScale->value());
     _audioJitterBufferSamples = audioJitterBufferSamples->value();
@@ -1956,8 +1964,8 @@ void Application::update(float deltaTime) {
     
     //loop through all the other avatars and simulate them...
     NodeList* nodeList = NodeList::getInstance();
-    nodeList->lock();
     for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
+        node->lock();
         if (node->getLinkedData() != NULL) {
             Avatar *avatar = (Avatar *)node->getLinkedData();
             if (!avatar->isInitialized()) {
@@ -1966,8 +1974,8 @@ void Application::update(float deltaTime) {
             avatar->simulate(deltaTime, NULL);
             avatar->setMouseRay(mouseRayOrigin, mouseRayDirection);
         }
+        node->unlock();
     }
-    nodeList->unlock();
 
     //  Simulate myself
     if (_gravityUse->isChecked()) {
@@ -2456,8 +2464,10 @@ void Application::displaySide(Camera& whichCamera) {
     if (_renderAvatarsOn->isChecked()) {
         //  Render avatars of other nodes
         NodeList* nodeList = NodeList::getInstance();
-        nodeList->lock();
+        
         for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
+            node->lock();
+            
             if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
                 Avatar *avatar = (Avatar *)node->getLinkedData();
                 if (!avatar->isInitialized()) {
@@ -2466,8 +2476,9 @@ void Application::displaySide(Camera& whichCamera) {
                 avatar->render(false, _renderAvatarBalls->isChecked());
                 avatar->setDisplayingLookatVectors(_renderLookatOn->isChecked());
             }
+            
+            node->unlock();
         }
-        nodeList->unlock();
         
         // Render my own Avatar
         if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp
index 73f971b7da..0e07f50693 100644
--- a/interface/src/Audio.cpp
+++ b/interface/src/Audio.cpp
@@ -126,8 +126,8 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
                                               dataPacket,
                                               BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes);
 
-            interface->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO)
-                    .updateValue(BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes);
+            interface->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO).updateValue(BUFFER_LENGTH_BYTES_PER_CHANNEL
+                                                                                            + leadingBytes);
         }
         
     }
diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp
index 3fddc71ad1..a023a70326 100644
--- a/libraries/shared/src/Node.cpp
+++ b/libraries/shared/src/Node.cpp
@@ -53,6 +53,8 @@ Node::Node(sockaddr* publicSocket, sockaddr* localSocket, char type, uint16_t no
     } else {
         _localSocket = NULL;
     }
+    
+    pthread_mutex_init(&mutex, 0);
 }
 
 Node::~Node() {
@@ -60,6 +62,8 @@ Node::~Node() {
     delete _localSocket;
     delete _linkedData;
     delete _bytesReceivedMovingAverage;
+    
+    pthread_mutex_destroy(&mutex);
 }
 
 // Names of Node Types
diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h
index de43558b7a..d61657d730 100644
--- a/libraries/shared/src/Node.h
+++ b/libraries/shared/src/Node.h
@@ -65,6 +65,9 @@ public:
 
     int getPingMs() const { return _pingMs; };
     void setPingMs(int pingMs) { _pingMs = pingMs; };
+    
+    void lock() { pthread_mutex_lock(&mutex); }
+    void unlock() { pthread_mutex_unlock(&mutex); }
 
     static void printLog(Node const&);
 private:
@@ -83,6 +86,7 @@ private:
     NodeData* _linkedData;
     bool _isAlive;
     int _pingMs;
+    pthread_mutex_t mutex;
 };
 
 
diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp
index b4e3112768..7e34f37535 100644
--- a/libraries/shared/src/NodeList.cpp
+++ b/libraries/shared/src/NodeList.cpp
@@ -29,9 +29,9 @@ const char SOLO_NODE_TYPES[3] = {
     NODE_TYPE_VOXEL_SERVER
 };
 
-char DOMAIN_HOSTNAME[] = "highfidelity.below92.com";
-char DOMAIN_IP[100] = "";    //  IP Address will be re-set by lookup on startup
-const int DOMAINSERVER_PORT = 40102;
+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;
 
 bool silentNodeThreadStopFlag = false;
 bool pingUnknownNodeThreadStopFlag = false;
@@ -63,8 +63,10 @@ NodeList::NodeList(char newOwnerType, unsigned int newSocketListenPort) :
     _ownerType(newOwnerType),
     _nodeTypesOfInterest(NULL),
     _ownerID(UNKNOWN_NODE_ID),
-    _lastNodeID(0) {
-    pthread_mutex_init(&mutex, 0);
+    _lastNodeID(0)
+{
+    memcpy(_domainHostname, DEFAULT_DOMAIN_HOSTNAME, sizeof(DEFAULT_DOMAIN_HOSTNAME));
+    memcpy(_domainIP, DEFAULT_DOMAIN_IP, sizeof(DEFAULT_DOMAIN_IP));
 }
 
 NodeList::~NodeList() {
@@ -74,8 +76,19 @@ NodeList::~NodeList() {
     
     // stop the spawned threads, if they were started
     stopSilentNodeRemovalThread();
-    
-    pthread_mutex_destroy(&mutex);
+}
+
+void NodeList::setDomainHostname(const char* domainHostname) {
+    memcpy(_domainHostname, domainHostname, sizeof(&domainHostname));
+}
+
+void NodeList::setDomainIP(const char* domainIP) {
+    memcpy(_domainIP, domainIP, sizeof(&domainIP));
+}
+
+void NodeList::setDomainIPToLocalhost() {
+    int ip = getLocalAddress();
+    sprintf(_domainIP, "%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
 }
 
 void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) {
@@ -112,7 +125,6 @@ void NodeList::processNodeData(sockaddr* senderAddress, unsigned char* packetDat
 }
 
 void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) {
-    lock();
     
     // find the avatar mixer in our node list and update the lastRecvTime from it
     Node* bulkSendNode = nodeWithAddress(senderAddress);
@@ -149,9 +161,8 @@ void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packe
         currentPosition += updateNodeWithData(matchingNode,
                                               packetHolder,
                                               numTotalBytes - (currentPosition - startPosition));
+        
     }
-    
-    unlock();
 }
 
 int NodeList::updateNodeWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {
@@ -166,6 +177,8 @@ int NodeList::updateNodeWithData(sockaddr *senderAddress, unsigned char *packetD
 }
 
 int NodeList::updateNodeWithData(Node *node, unsigned char *packetData, int dataBytes) {
+    node->lock();
+    
     node->setLastHeardMicrostamp(usecTimestampNow());
     
     if (node->getActiveSocket()) {
@@ -176,7 +189,11 @@ int NodeList::updateNodeWithData(Node *node, unsigned char *packetData, int data
         linkedDataCreateCallback(node);
     }
     
-    return node->getLinkedData()->parseData(packetData, dataBytes);
+    int numParsedBytes = node->getLinkedData()->parseData(packetData, dataBytes);
+    
+    node->unlock();
+    
+    return numParsedBytes;
 }
 
 Node* NodeList::nodeWithAddress(sockaddr *senderAddress) {
@@ -236,18 +253,18 @@ void NodeList::sendDomainServerCheckIn() {
     static bool printedDomainServerIP = false;
     
     //  Lookup the IP address of the domain server if we need to
-    if (atoi(DOMAIN_IP) == 0) {
+    if (atoi(_domainIP) == 0) {
         struct hostent* pHostInfo;
-        if ((pHostInfo = gethostbyname(DOMAIN_HOSTNAME)) != NULL) {
+        if ((pHostInfo = gethostbyname(_domainHostname)) != NULL) {
             sockaddr_in tempAddress;
             memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
-            strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr));
-            printLog("Domain Server: %s \n", DOMAIN_HOSTNAME);
+            strcpy(_domainIP, inet_ntoa(tempAddress.sin_addr));
+            printLog("Domain Server: %s \n", _domainHostname);
         } else {
             printLog("Failed domain server lookup\n");
         }
     } else if (!printedDomainServerIP) {
-        printLog("Domain Server IP: %s\n", DOMAIN_IP);
+        printLog("Domain Server IP: %s\n", _domainIP);
         printedDomainServerIP = true;
     }
     
@@ -294,7 +311,7 @@ void NodeList::sendDomainServerCheckIn() {
         checkInPacketSize = packetPosition - checkInPacket;
     }
     
-    _nodeSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, checkInPacket, checkInPacketSize);
+    _nodeSocket.send(_domainIP, DEFAULT_DOMAINSERVER_PORT, checkInPacket, checkInPacketSize);
 }
 
 int NodeList::processDomainServerList(unsigned char* packetData, size_t dataBytes) {
diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h
index 57f8083113..20eaddc738 100644
--- a/libraries/shared/src/NodeList.h
+++ b/libraries/shared/src/NodeList.h
@@ -9,8 +9,10 @@
 #ifndef __hifi__NodeList__
 #define __hifi__NodeList__
 
+#include <netinet/in.h>
 #include <stdint.h>
 #include <iterator>
+#include <unistd.h>
 
 #include "Node.h"
 #include "UDPSocket.h"
@@ -30,9 +32,11 @@ const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
 
 extern const char SOLO_NODE_TYPES[3];
 
-extern char DOMAIN_HOSTNAME[];
-extern char DOMAIN_IP[100];    //  IP Address will be re-set by lookup on startup
-extern const int DOMAINSERVER_PORT;
+const int MAX_HOSTNAME_BYTES = 255;
+
+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;
 
 const int UNKNOWN_NODE_ID = -1;
 
@@ -48,6 +52,12 @@ public:
     NodeListIterator begin() const;
     NodeListIterator end() const;
     
+    const char* getDomainHostname() const { return _domainHostname; };
+    void setDomainHostname(const char* domainHostname);
+    
+    void setDomainIP(const char* domainIP);
+    void setDomainIPToLocalhost();
+    
     char getOwnerType() const { return _ownerType; }
     
     uint16_t getLastNodeID() const { return _lastNodeID; }
@@ -67,9 +77,6 @@ public:
     
     void clear();
     
-    void lock() { pthread_mutex_lock(&mutex); }
-    void unlock() { pthread_mutex_unlock(&mutex); }
-    
     void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest);
     void sendDomainServerCheckIn();
     int processDomainServerList(unsigned char *packetData, size_t dataBytes);
@@ -103,6 +110,8 @@ private:
     
     void addNodeToList(Node* newNode);
     
+    char _domainHostname[MAX_HOSTNAME_BYTES];
+    char _domainIP[INET_ADDRSTRLEN];
     Node** _nodeBuckets[MAX_NUM_NODES / NODES_PER_BUCKET];
     int _numNodes;
     UDPSocket _nodeSocket;
@@ -113,7 +122,6 @@ private:
     uint16_t _lastNodeID;
     pthread_t removeSilentNodesThread;
     pthread_t checkInWithDomainServerThread;
-    pthread_mutex_t mutex;
     
     void handlePingReply(sockaddr *nodeAddress);
     void timePingReply(sockaddr *nodeAddress, unsigned char *packetData);
diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp
index 254b1d2d96..4529d34bd8 100644
--- a/voxel-server/src/main.cpp
+++ b/voxel-server/src/main.cpp
@@ -383,8 +383,7 @@ int main(int argc, const char * argv[]) {
     ::wantLocalDomain = cmdOptionExists(argc, argv,local);
     if (::wantLocalDomain) {
         printf("Local Domain MODE!\n");
-        int ip = getLocalAddress();
-        sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
+        nodeList->setDomainIPToLocalhost();
     }
 
     nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode;

From 94b6bfccf64f09fb7351bf919aeb42fb61b47dbb Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 15:17:53 -0700
Subject: [PATCH 03/11] update the private mutex node variable to standard

---
 libraries/shared/src/Node.cpp | 4 ++--
 libraries/shared/src/Node.h   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp
index a023a70326..f7c9758fd0 100644
--- a/libraries/shared/src/Node.cpp
+++ b/libraries/shared/src/Node.cpp
@@ -54,7 +54,7 @@ Node::Node(sockaddr* publicSocket, sockaddr* localSocket, char type, uint16_t no
         _localSocket = NULL;
     }
     
-    pthread_mutex_init(&mutex, 0);
+    pthread_mutex_init(&_mutex, 0);
 }
 
 Node::~Node() {
@@ -63,7 +63,7 @@ Node::~Node() {
     delete _linkedData;
     delete _bytesReceivedMovingAverage;
     
-    pthread_mutex_destroy(&mutex);
+    pthread_mutex_destroy(&_mutex);
 }
 
 // Names of Node Types
diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h
index d61657d730..e5396a5b25 100644
--- a/libraries/shared/src/Node.h
+++ b/libraries/shared/src/Node.h
@@ -86,7 +86,7 @@ private:
     NodeData* _linkedData;
     bool _isAlive;
     int _pingMs;
-    pthread_mutex_t mutex;
+    pthread_mutex_t _mutex;
 };
 
 

From e3d1e5db5d3eda5254c3123f1e608c5560f5adcc Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 15:45:27 -0700
Subject: [PATCH 04/11] correct reference to mutex to lock in Node

---
 libraries/shared/src/Node.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h
index e5396a5b25..aa88cb158c 100644
--- a/libraries/shared/src/Node.h
+++ b/libraries/shared/src/Node.h
@@ -66,8 +66,8 @@ public:
     int getPingMs() const { return _pingMs; };
     void setPingMs(int pingMs) { _pingMs = pingMs; };
     
-    void lock() { pthread_mutex_lock(&mutex); }
-    void unlock() { pthread_mutex_unlock(&mutex); }
+    void lock() { pthread_mutex_lock(&_mutex); }
+    void unlock() { pthread_mutex_unlock(&_mutex); }
 
     static void printLog(Node const&);
 private:

From 6b83f95f9e433a3007e136fca575f439b617fbfd Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 15:46:04 -0700
Subject: [PATCH 05/11] conditionally set a new hostname on preferences save

---
 interface/src/Application.cpp     |  8 ++++
 libraries/shared/src/NodeList.cpp | 70 +++++++++++++++++--------------
 2 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 6504c2d87f..998d2c9126 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -1140,6 +1140,14 @@ void Application::editPreferences() {
         return;
     }
     
+    // check if the domain server hostname is new - if so we need to clear the nodelist and delete the local voxels
+    const char* newHostname = domainServerHostname->text().toLocal8Bit().data();
+    
+    if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname, sizeof(&newHostname)) != 0) {
+        NodeList::getInstance()->clear();
+        NodeList::getInstance()->setDomainHostname(newHostname);
+    }
+    
     QUrl url(avatarURL->text());
     _myAvatar.getVoxels()->setVoxelURL(url);
     sendAvatarVoxelURLMessage(url);
diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp
index 7e34f37535..2e12e8ab71 100644
--- a/libraries/shared/src/NodeList.cpp
+++ b/libraries/shared/src/NodeList.cpp
@@ -78,12 +78,17 @@ NodeList::~NodeList() {
     stopSilentNodeRemovalThread();
 }
 
-void NodeList::setDomainHostname(const char* domainHostname) {
-    memcpy(_domainHostname, domainHostname, sizeof(&domainHostname));
+void NodeList::setDomainHostname(const char* domainHostname) {    
+    memset(_domainHostname, 0, sizeof(_domainHostname));
+    memcpy(_domainHostname, domainHostname, strlen(domainHostname));
+    
+    // reset the domain IP so the hostname is checked again
+    setDomainIP("");
 }
 
 void NodeList::setDomainIP(const char* domainIP) {
-    memcpy(_domainIP, domainIP, sizeof(&domainIP));
+    memset(_domainIP, 0, sizeof(_domainIP));
+    memcpy(_domainIP, domainIP, strlen(domainIP));
 }
 
 void NodeList::setDomainIPToLocalhost() {
@@ -132,37 +137,37 @@ void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packe
     if (bulkSendNode) {
         bulkSendNode->setLastHeardMicrostamp(usecTimestampNow());
         bulkSendNode->recordBytesReceived(numTotalBytes);
-    }
-    
-    int numBytesPacketHeader = numBytesForPacketHeader(packetData);
-    
-    unsigned char *startPosition = packetData;
-    unsigned char *currentPosition = startPosition + numBytesPacketHeader;
-    unsigned char packetHolder[numTotalBytes];
-    
-    // we've already verified packet version for the bulk packet, so all head data in the packet is also up to date
-    populateTypeAndVersion(packetHolder, PACKET_TYPE_HEAD_DATA);
-    
-    uint16_t nodeID = -1;
-    
-    while ((currentPosition - startPosition) < numTotalBytes) {
-        unpackNodeId(currentPosition, &nodeID);
-        memcpy(packetHolder + numBytesPacketHeader,
-               currentPosition,
-               numTotalBytes - (currentPosition - startPosition));
         
-        Node* matchingNode = nodeWithID(nodeID);
+        int numBytesPacketHeader = numBytesForPacketHeader(packetData);
         
-        if (!matchingNode) {
-            // we're missing this node, we need to add it to the list
-            matchingNode = addOrUpdateNode(NULL, NULL, NODE_TYPE_AGENT, nodeID);
+        unsigned char *startPosition = packetData;
+        unsigned char *currentPosition = startPosition + numBytesPacketHeader;
+        unsigned char packetHolder[numTotalBytes];
+        
+        // we've already verified packet version for the bulk packet, so all head data in the packet is also up to date
+        populateTypeAndVersion(packetHolder, PACKET_TYPE_HEAD_DATA);
+        
+        uint16_t nodeID = -1;
+        
+        while ((currentPosition - startPosition) < numTotalBytes) {
+            unpackNodeId(currentPosition, &nodeID);
+            memcpy(packetHolder + numBytesPacketHeader,
+                   currentPosition,
+                   numTotalBytes - (currentPosition - startPosition));
+            
+            Node* matchingNode = nodeWithID(nodeID);
+            
+            if (!matchingNode) {
+                // we're missing this node, we need to add it to the list
+                matchingNode = addOrUpdateNode(NULL, NULL, NODE_TYPE_AGENT, nodeID);
+            }
+            
+            currentPosition += updateNodeWithData(matchingNode,
+                                                  packetHolder,
+                                                  numTotalBytes - (currentPosition - startPosition));
+            
         }
-        
-        currentPosition += updateNodeWithData(matchingNode,
-                                              packetHolder,
-                                              numTotalBytes - (currentPosition - startPosition));
-        
-    }
+    }    
 }
 
 int NodeList::updateNodeWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {
@@ -234,7 +239,9 @@ void NodeList::clear() {
         Node** nodeBucket = _nodeBuckets[i / NODES_PER_BUCKET];
         Node* node = nodeBucket[i % NODES_PER_BUCKET];
         
+        node->lock();
         delete node;
+        
         node = NULL;
     }
     
@@ -254,6 +261,7 @@ void NodeList::sendDomainServerCheckIn() {
     
     //  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;

From 6c2682833ec0c05d3e9010e4c71f61a0d73d5bac Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 15:53:25 -0700
Subject: [PATCH 06/11] lock on the solo voxelServer before deleting local
 voxels

---
 interface/src/Application.cpp | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 998d2c9126..cbccb5135f 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -1140,10 +1140,24 @@ void Application::editPreferences() {
         return;
     }
     
-    // check if the domain server hostname is new - if so we need to clear the nodelist and delete the local voxels
+    
     const char* newHostname = domainServerHostname->text().toLocal8Bit().data();
     
+    // check if the domain server hostname is new 
     if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname, sizeof(&newHostname)) != 0) {
+        // if so we need to clear the nodelist and delete the local voxels
+        Node *voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
+        
+        if (voxelServer) {
+            voxelServer->lock();
+        }
+        
+        _voxels.killLocalVoxels();
+        
+        if (voxelServer) {
+            voxelServer->unlock();
+        }
+        
         NodeList::getInstance()->clear();
         NodeList::getInstance()->setDomainHostname(newHostname);
     }

From 9fe1c7c63daddb204879745fa4c1e2a063625337 Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 15:59:31 -0700
Subject: [PATCH 07/11] lock the voxel server when receiving data to avoid race
 crash

---
 interface/src/Application.cpp | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index cbccb5135f..82851355b7 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -3270,11 +3270,21 @@ void* Application::networkReceive(void* args) {
                     case PACKET_TYPE_VOXEL_DATA_MONOCHROME:
                     case PACKET_TYPE_Z_COMMAND:
                     case PACKET_TYPE_ERASE_VOXEL:
-                        app->_voxels.parseData(app->_incomingPacket, bytesReceived);
-                        break;
-                    case PACKET_TYPE_ENVIRONMENT_DATA:
-                        app->_environment.parseData(&senderAddress, app->_incomingPacket, bytesReceived);
+                    case PACKET_TYPE_ENVIRONMENT_DATA: {
+                        Node *voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
+                        if (voxelServer) {
+                            voxelServer->lock();
+                            
+                            if (app->_incomingPacket[0] == PACKET_TYPE_ENVIRONMENT_DATA) {
+                                app->_environment.parseData(&senderAddress, app->_incomingPacket, bytesReceived);
+                            } else {
+                                app->_voxels.parseData(app->_incomingPacket, bytesReceived);
+                            }
+                            
+                            voxelServer->unlock();
+                        }
                         break;
+                    }
                     case PACKET_TYPE_BULK_AVATAR_DATA:
                         NodeList::getInstance()->processBulkNodeData(&senderAddress,
                                                                      app->_incomingPacket,

From a204a8b87238a9628f551ef40623b4e5c5f4d782 Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 16:01:05 -0700
Subject: [PATCH 08/11] lock the audioMixer to avoid crash when grabbing socket

---
 interface/src/Audio.cpp | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp
index 0e07f50693..0307a2df3b 100644
--- a/interface/src/Audio.cpp
+++ b/interface/src/Audio.cpp
@@ -96,6 +96,10 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
         Node* audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
         
         if (audioMixer) {
+            audioMixer->lock();
+            sockaddr_in audioSocket = *audioMixer->getActiveSocket();
+            audioMixer->unlock();
+            
             glm::vec3 headPosition = interfaceAvatar->getHeadJointPosition();
             glm::quat headOrientation = interfaceAvatar->getHead().getOrientation();
             
@@ -122,12 +126,13 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
             
             // copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet
             memcpy(currentPacketPtr, inputLeft, BUFFER_LENGTH_BYTES_PER_CHANNEL);
-            nodeList->getNodeSocket()->send(audioMixer->getActiveSocket(),
-                                              dataPacket,
-                                              BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes);
+            nodeList->getNodeSocket()->send(audioSocket,
+                                            dataPacket,
+                                            BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes);
 
             interface->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO).updateValue(BUFFER_LENGTH_BYTES_PER_CHANNEL
                                                                                             + leadingBytes);
+            
         }
         
     }

From 33ddda25586e0411cf77fbbb2d5b96dd3a757771 Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 16:02:36 -0700
Subject: [PATCH 09/11] correct reference to audio mixer sockaddr_in

---
 interface/src/Audio.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp
index 0307a2df3b..63fc24f56d 100644
--- a/interface/src/Audio.cpp
+++ b/interface/src/Audio.cpp
@@ -97,7 +97,7 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
         
         if (audioMixer) {
             audioMixer->lock();
-            sockaddr_in audioSocket = *audioMixer->getActiveSocket();
+            sockaddr_in audioSocket = *(sockaddr_in*) audioMixer->getActiveSocket();
             audioMixer->unlock();
             
             glm::vec3 headPosition = interfaceAvatar->getHeadJointPosition();
@@ -126,7 +126,7 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
             
             // copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet
             memcpy(currentPacketPtr, inputLeft, BUFFER_LENGTH_BYTES_PER_CHANNEL);
-            nodeList->getNodeSocket()->send(audioSocket,
+            nodeList->getNodeSocket()->send((sockaddr*) &audioSocket,
                                             dataPacket,
                                             BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes);
 

From 081a44dbff05d390473b280f60776b1b7b5203c1 Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 16:05:23 -0700
Subject: [PATCH 10/11] only process new domain list if it comes from current
 DS

---
 libraries/shared/src/NodeList.cpp | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp
index 2e12e8ab71..6d79b9471a 100644
--- a/libraries/shared/src/NodeList.cpp
+++ b/libraries/shared/src/NodeList.cpp
@@ -112,7 +112,14 @@ void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) {
 void NodeList::processNodeData(sockaddr* senderAddress, unsigned char* packetData, size_t dataBytes) {
     switch (packetData[0]) {
         case PACKET_TYPE_DOMAIN: {
-            processDomainServerList(packetData, dataBytes);
+            // 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) {
+                processDomainServerList(packetData, dataBytes);
+            }
+            
             break;
         }
         case PACKET_TYPE_PING: {

From c27cd7ae426a49de46a45738d3e8b7f70b6c281a Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 15 Jul 2013 16:49:36 -0700
Subject: [PATCH 11/11] couple of type squishes in NodeList

---
 interface/src/Application.cpp     | 2 +-
 libraries/shared/src/NodeList.cpp | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 82851355b7..a9313e7549 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -3271,7 +3271,7 @@ void* Application::networkReceive(void* args) {
                     case PACKET_TYPE_Z_COMMAND:
                     case PACKET_TYPE_ERASE_VOXEL:
                     case PACKET_TYPE_ENVIRONMENT_DATA: {
-                        Node *voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
+                        Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
                         if (voxelServer) {
                             voxelServer->lock();
                             
diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp
index 6d79b9471a..004568584d 100644
--- a/libraries/shared/src/NodeList.cpp
+++ b/libraries/shared/src/NodeList.cpp
@@ -147,8 +147,8 @@ void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packe
         
         int numBytesPacketHeader = numBytesForPacketHeader(packetData);
         
-        unsigned char *startPosition = packetData;
-        unsigned char *currentPosition = startPosition + numBytesPacketHeader;
+        unsigned char* startPosition = packetData;
+        unsigned char* currentPosition = startPosition + numBytesPacketHeader;
         unsigned char packetHolder[numTotalBytes];
         
         // we've already verified packet version for the bulk packet, so all head data in the packet is also up to date