diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 958995daae..2d29bd3f33 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -125,7 +125,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _lookingAwayFromOrigin(true), _lookatTargetAvatar(NULL), _lookatIndicatorScale(1.0f), - _perfStatsOn(false), _chatEntryOn(false), _audio(&_audioScope, STARTUP_JITTER_SAMPLES), _stopNetworkReceiveThread(false), @@ -207,7 +206,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : #endif // tell the NodeList instance who to tell the domain server we care about - const char nodeTypesOfInterest[] = {NODE_TYPE_AUDIO_MIXER, NODE_TYPE_AVATAR_MIXER, NODE_TYPE_VOXEL_SERVER, + const char nodeTypesOfInterest[] = {NODE_TYPE_AUDIO_MIXER, NODE_TYPE_AVATAR_MIXER, NODE_TYPE_VOXEL_SERVER, NODE_TYPE_PARTICLE_SERVER, NODE_TYPE_METAVOXEL_SERVER}; nodeList->setNodeTypesOfInterest(nodeTypesOfInterest, sizeof(nodeTypesOfInterest)); @@ -3655,20 +3654,6 @@ void Application::displayStats() { } statsVerticalOffset += PELS_PER_LINE; drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str()); - - if (_perfStatsOn) { - // Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups - char** perfStatLinesArray = new char*[PerfStat::getGroupCount()+1]; - int lines = PerfStat::DumpStats(perfStatLinesArray); - - for (int line=0; line < lines; line++) { - statsVerticalOffset += PELS_PER_LINE; - drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, perfStatLinesArray[line]); - delete perfStatLinesArray[line]; // we're responsible for cleanup - perfStatLinesArray[line]=NULL; - } - delete []perfStatLinesArray; // we're responsible for cleanup - } } void Application::renderThrustAtVoxel(const glm::vec3& thrust) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 92831ff9ce..67ec3d229c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -452,8 +452,6 @@ private: glm::vec3 _transmitterPickStart; glm::vec3 _transmitterPickEnd; - bool _perfStatsOn; // Do we want to display perfStats? - ChatEntry _chatEntry; // chat entry field bool _chatEntryOn; // Whether to show the chat entry diff --git a/libraries/octree-server/CMakeLists.txt b/libraries/octree-server/CMakeLists.txt index d9ee7b0e2f..930c91018c 100644 --- a/libraries/octree-server/CMakeLists.txt +++ b/libraries/octree-server/CMakeLists.txt @@ -12,7 +12,7 @@ find_package(Qt5Widgets REQUIRED) include(${MACRO_DIR}/SetupHifiLibrary.cmake) -# grab cJSON and civetweb sources to pass as OPTIONAL_SRCS +# grab cJSON and civetweb sources to pass as OPTIONAL_SRCS FILE(GLOB OPTIONAL_SRCS ${ROOT_DIR}/externals/civetweb/src/*) setup_hifi_library(${TARGET_NAME} ${OPTIONAL_SRCS}) diff --git a/libraries/shared/src/Logging.h b/libraries/shared/src/Logging.h index d64c39992b..175ed063d1 100644 --- a/libraries/shared/src/Logging.h +++ b/libraries/shared/src/Logging.h @@ -9,7 +9,11 @@ #ifndef __hifi__Logging__ #define __hifi__Logging__ +#ifdef _WIN32 +#include "Syssocket.h" +#else #include +#endif #include @@ -27,21 +31,21 @@ class Logging { public: /// \return the socket used to send stats to logstash static const HifiSockAddr& socket(); - + /// checks if this target should send stats to logstash, given its current environment /// \return true if the caller should send stats to logstash static bool shouldSendStats(); - + /// stashes a float value to Logstash instance /// \param statType a stat type from the constants in this file /// \param key the key at which to store the stat /// \param value the value to store static void stashValue(char statType, const char* key, float value); - + /// sets the target name to output via the verboseMessageHandler, called once before logging begins /// \param targetName the desired target name to output in logs static void setTargetName(const char* targetName); - + /// a qtMessageHandler that can be hooked up to a target that links to Qt /// prints various process, message type, and time information static void verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message); diff --git a/libraries/shared/src/NetworkPacket.h b/libraries/shared/src/NetworkPacket.h index f3c8fd08e6..139c69bd35 100644 --- a/libraries/shared/src/NetworkPacket.h +++ b/libraries/shared/src/NetworkPacket.h @@ -13,7 +13,7 @@ #include //#include // not available on windows, apparently not needed on mac -#include +//#include #include "HifiSockAddr.h" diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 0a50a659b2..d8e5f675c9 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -39,7 +39,7 @@ NodeList* NodeList::createInstance(char ownerType, unsigned short int socketList } else { qDebug("NodeList createInstance called with existing instance."); } - + return _sharedInstance; } @@ -47,7 +47,7 @@ NodeList* NodeList::getInstance() { if (!_sharedInstance) { qDebug("NodeList getInstance called before call to createInstance. Returning NULL pointer."); } - + return _sharedInstance; } @@ -72,35 +72,35 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : NodeList::~NodeList() { delete _nodeTypesOfInterest; - + clear(); } void NodeList::setDomainHostname(const QString& domainHostname) { - + if (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 _domainSockAddr.setPort(atoi(domainHostname.mid(colonIndex + 1, domainHostname.size()).toLocal8Bit().constData())); - + qDebug() << "Updated hostname to" << _domainHostname << "and port to" << _domainSockAddr.getPort() << "\n"; - + } else { // no port included with the hostname, simply set the member variable and reset the domain server port to default _domainHostname = domainHostname; _domainSockAddr.setPort(DEFAULT_DOMAIN_SERVER_PORT); } - + // clear the NodeList so nodes from this domain are killed clear(); - + // reset our _domainIP to the null address so that a lookup happens on next check in _domainSockAddr.setAddress(QHostAddress::Null); notifyDomainChanged(); @@ -119,17 +119,17 @@ void NodeList::timePingReply(const HifiSockAddr& nodeAddress, unsigned char *pac uint64_t now = usecTimestampNow(); int pingTime = now - ourOriginalTime; int oneWayFlightTime = pingTime / 2; // half of the ping is our one way flight - + // The other node's expected time should be our original time plus the one way flight time // anything other than that is clock skew uint64_t othersExprectedReply = ourOriginalTime + oneWayFlightTime; int clockSkew = othersReplyTime - othersExprectedReply; - + node->setPingMs(pingTime / 1000); node->setClockSkewUsec(clockSkew); - + const bool wantDebug = false; - if (wantDebug) { + if (wantDebug) { qDebug() << "PING_REPLY from node " << *node << "\n" << " now: " << now << "\n" << " ourTime: " << ourOriginalTime << "\n" << @@ -151,21 +151,21 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, unsigned char if (_domainSockAddr == senderSockAddr) { processDomainServerList(packetData, dataBytes); } - + break; } case PACKET_TYPE_PING: { // send back a reply unsigned char replyPacket[MAX_PACKET_SIZE]; int replyPacketLength = fillPingReplyPacket(packetData, replyPacket); - _nodeSocket.writeDatagram((char*)replyPacket, replyPacketLength, + _nodeSocket.writeDatagram((char*)replyPacket, replyPacketLength, senderSockAddr.getAddress(), senderSockAddr.getPort()); break; } case PACKET_TYPE_PING_REPLY: { // activate the appropriate socket for this node, if not yet updated activateSocketFromNodeCommunication(senderSockAddr); - + // set the ping time for this node for stat collection timePingReply(senderSockAddr, packetData); break; @@ -184,67 +184,69 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, unsigned char } void NodeList::processBulkNodeData(const HifiSockAddr& senderAddress, unsigned char *packetData, int numTotalBytes) { - + // find the avatar mixer in our node list and update the lastRecvTime from it Node* bulkSendNode = nodeWithAddress(senderAddress); 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]; - + unsigned char* packetHolder = new unsigned char[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); - + while ((currentPosition - startPosition) < numTotalBytes) { - + memcpy(packetHolder + numBytesPacketHeader, currentPosition, numTotalBytes - (currentPosition - startPosition)); - + QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*)currentPosition, NUM_BYTES_RFC4122_UUID)); Node* matchingNode = nodeWithUUID(nodeUUID); - + if (!matchingNode) { // we're missing this node, we need to add it to the list matchingNode = addOrUpdateNode(nodeUUID, NODE_TYPE_AGENT, HifiSockAddr(), HifiSockAddr()); } - + currentPosition += updateNodeWithData(matchingNode, HifiSockAddr(), packetHolder, numTotalBytes - (currentPosition - startPosition)); - + } - } + + delete[] packetHolder; + } } int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, unsigned char *packetData, int dataBytes) { node->lock(); - + node->setLastHeardMicrostamp(usecTimestampNow()); - + if (!senderSockAddr.isNull()) { activateSocketFromNodeCommunication(senderSockAddr); } - + if (node->getActiveSocket() || senderSockAddr.isNull()) { node->recordBytesReceived(dataBytes); - + if (!node->getLinkedData() && linkedDataCreateCallback) { linkedDataCreateCallback(node); } - + int numParsedBytes = node->getLinkedData()->parseData(packetData, dataBytes); - + node->unlock(); - + return numParsedBytes; } else { // we weren't able to match the sender address to the address we have for this node, unlock and don't parse @@ -259,7 +261,7 @@ Node* NodeList::nodeWithAddress(const HifiSockAddr &senderSockAddr) { return &(*node); } } - + return NULL; } @@ -275,47 +277,47 @@ Node* NodeList::nodeWithUUID(const QUuid& nodeUUID) { int NodeList::getNumAliveNodes() const { int numAliveNodes = 0; - + for (NodeList::iterator node = begin(); node != end(); node++) { if (node->isAlive()) { ++numAliveNodes; } } - + return numAliveNodes; } void NodeList::clear() { qDebug() << "Clearing the NodeList. Deleting all nodes in list.\n"; - + // 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]; - + node->lock(); notifyHooksOfKilledNode(&*node); - + delete node; } - + _numNodes = 0; } void NodeList::reset() { clear(); _numNoReplyDomainCheckIns = 0; - + delete _nodeTypesOfInterest; _nodeTypesOfInterest = NULL; - + // refresh the owner UUID _ownerUUID = QUuid::createUuid(); } void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest) { delete _nodeTypesOfInterest; - + _nodeTypesOfInterest = new char[numNodeTypesOfInterest + sizeof(char)]; memcpy(_nodeTypesOfInterest, nodeTypesOfInterest, numNodeTypesOfInterest); _nodeTypesOfInterest[numNodeTypesOfInterest] = '\0'; @@ -328,54 +330,54 @@ const int NUM_STUN_REQUESTS_BEFORE_FALLBACK = 5; void NodeList::sendSTUNRequest() { const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const unsigned short STUN_SERVER_PORT = 3478; - + unsigned char stunRequestPacket[NUM_BYTES_STUN_HEADER]; - + int packetIndex = 0; - + const uint32_t RFC_5389_MAGIC_COOKIE_NETWORK_ORDER = htonl(RFC_5389_MAGIC_COOKIE); - + // leading zeros + message type const uint16_t REQUEST_MESSAGE_TYPE = htons(0x0001); memcpy(stunRequestPacket + packetIndex, &REQUEST_MESSAGE_TYPE, sizeof(REQUEST_MESSAGE_TYPE)); packetIndex += sizeof(REQUEST_MESSAGE_TYPE); - + // message length (no additional attributes are included) uint16_t messageLength = 0; memcpy(stunRequestPacket + packetIndex, &messageLength, sizeof(messageLength)); packetIndex += sizeof(messageLength); - + memcpy(stunRequestPacket + packetIndex, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)); packetIndex += sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER); - + // transaction ID (random 12-byte unsigned integer) const uint NUM_TRANSACTION_ID_BYTES = 12; unsigned char transactionID[NUM_TRANSACTION_ID_BYTES]; loadRandomIdentifier(transactionID, NUM_TRANSACTION_ID_BYTES); memcpy(stunRequestPacket + packetIndex, &transactionID, sizeof(transactionID)); - + // lookup the IP for the STUN server static HifiSockAddr stunSockAddr(STUN_SERVER_HOSTNAME, STUN_SERVER_PORT); - + if (!_hasCompletedInitialSTUNFailure) { qDebug("Sending intial stun request to %s\n", stunSockAddr.getAddress().toString().toLocal8Bit().constData()); } - + _nodeSocket.writeDatagram((char*) stunRequestPacket, sizeof(stunRequestPacket), stunSockAddr.getAddress(), stunSockAddr.getPort()); - + _stunRequestsSinceSuccess++; - + if (_stunRequestsSinceSuccess >= NUM_STUN_REQUESTS_BEFORE_FALLBACK) { if (!_hasCompletedInitialSTUNFailure) { // if we're here this was the last failed STUN request // use our DS as our stun server qDebug("Failed to lookup public address via STUN server at %s:%hu. Using DS for STUN.\n", STUN_SERVER_HOSTNAME, STUN_SERVER_PORT); - + _hasCompletedInitialSTUNFailure = true; } - + // reset the public address and port // use 0 so the DS knows to act as out STUN server _publicSockAddr = HifiSockAddr(QHostAddress(), _nodeSocket.localPort()); @@ -387,70 +389,70 @@ void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes) // and read the first attribute and make sure it is a XOR_MAPPED_ADDRESS const int NUM_BYTES_MESSAGE_TYPE_AND_LENGTH = 4; const uint16_t XOR_MAPPED_ADDRESS_TYPE = htons(0x0020); - + const uint32_t RFC_5389_MAGIC_COOKIE_NETWORK_ORDER = htonl(RFC_5389_MAGIC_COOKIE); - + int attributeStartIndex = NUM_BYTES_STUN_HEADER; - + if (memcmp(packetData + NUM_BYTES_MESSAGE_TYPE_AND_LENGTH, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)) == 0) { - + // enumerate the attributes to find XOR_MAPPED_ADDRESS_TYPE while (attributeStartIndex < dataBytes) { if (memcmp(packetData + attributeStartIndex, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0) { const int NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH = 4; const int NUM_BYTES_FAMILY_ALIGN = 1; const uint8_t IPV4_FAMILY_NETWORK_ORDER = htons(0x01) >> 8; - + // reset the number of failed STUN requests since last success _stunRequestsSinceSuccess = 0; - + int byteIndex = attributeStartIndex + NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH + NUM_BYTES_FAMILY_ALIGN; - + uint8_t addressFamily = 0; memcpy(&addressFamily, packetData + byteIndex, sizeof(addressFamily)); - + byteIndex += sizeof(addressFamily); - + if (addressFamily == IPV4_FAMILY_NETWORK_ORDER) { // grab the X-Port uint16_t xorMappedPort = 0; memcpy(&xorMappedPort, packetData + byteIndex, sizeof(xorMappedPort)); - + uint16_t newPublicPort = ntohs(xorMappedPort) ^ (ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER) >> 16); - + byteIndex += sizeof(xorMappedPort); - + // grab the X-Address uint32_t xorMappedAddress = 0; memcpy(&xorMappedAddress, packetData + byteIndex, sizeof(xorMappedAddress)); - + uint32_t stunAddress = ntohl(xorMappedAddress) ^ ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER); - + QHostAddress newPublicAddress = QHostAddress(stunAddress); - + if (newPublicAddress != _publicSockAddr.getAddress() || newPublicPort != _publicSockAddr.getPort()) { _publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort); - + qDebug("New public socket received from STUN server is %s:%hu\n", _publicSockAddr.getAddress().toString().toLocal8Bit().constData(), _publicSockAddr.getPort()); - + } - + _hasCompletedInitialSTUNFailure = true; - + break; } } else { // push forward attributeStartIndex by the length of this attribute const int NUM_BYTES_ATTRIBUTE_TYPE = 2; - + uint16_t attributeLength = 0; memcpy(&attributeLength, packetData + attributeStartIndex + NUM_BYTES_ATTRIBUTE_TYPE, sizeof(attributeLength)); attributeLength = ntohs(attributeLength); - + attributeStartIndex += NUM_BYTES_MESSAGE_TYPE_AND_LENGTH + attributeLength; } } @@ -460,13 +462,13 @@ void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes) void NodeList::sendKillNode(const char* nodeTypes, int numNodeTypes) { unsigned char packet[MAX_PACKET_SIZE]; unsigned char* packetPosition = packet; - + packetPosition += populateTypeAndVersion(packetPosition, PACKET_TYPE_KILL_NODE); - + QByteArray rfcUUID = _ownerUUID.toRfc4122(); memcpy(packetPosition, rfcUUID.constData(), rfcUUID.size()); packetPosition += rfcUUID.size(); - + broadcastToNodes(packet, packetPosition - packet, nodeTypes, numNodeTypes); } @@ -475,13 +477,13 @@ void NodeList::processKillNode(unsigned char* packetData, size_t dataBytes) { int numBytesPacketHeader = numBytesForPacketHeader(packetData); packetData += numBytesPacketHeader; dataBytes -= numBytesPacketHeader; - + // read the node id QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*)packetData, NUM_BYTES_RFC4122_UUID)); - + packetData += NUM_BYTES_RFC4122_UUID; dataBytes -= NUM_BYTES_RFC4122_UUID; - + // make sure the node exists Node* node = nodeWithUUID(nodeUUID); if (node) { @@ -491,25 +493,25 @@ void NodeList::processKillNode(unsigned char* packetData, size_t dataBytes) { void NodeList::sendDomainServerCheckIn() { static bool printedDomainServerIP = false; - + // Lookup the IP address of the domain server if we need to if (_domainSockAddr.getAddress().isNull()) { qDebug("Looking up DS hostname %s.\n", _domainHostname.toLocal8Bit().constData()); - + QHostInfo domainServerHostInfo = QHostInfo::fromName(_domainHostname); - + for (int i = 0; i < domainServerHostInfo.addresses().size(); i++) { if (domainServerHostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) { _domainSockAddr.setAddress(domainServerHostInfo.addresses()[i]); - + qDebug("DS at %s is at %s\n", _domainHostname.toLocal8Bit().constData(), _domainSockAddr.getAddress().toString().toLocal8Bit().constData()); - + 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"); @@ -519,7 +521,7 @@ void NodeList::sendDomainServerCheckIn() { qDebug("Domain Server IP: %s\n", _domainSockAddr.getAddress().toString().toLocal8Bit().constData()); printedDomainServerIP = true; } - + if (_publicSockAddr.isNull() && !_hasCompletedInitialSTUNFailure) { // we don't know our public socket and we need to send it to the domain server // send a STUN request to figure it out @@ -527,41 +529,41 @@ void NodeList::sendDomainServerCheckIn() { } else { // construct the DS check in packet if we need to int numBytesNodesOfInterest = _nodeTypesOfInterest ? strlen((char*) _nodeTypesOfInterest) : 0; - + const int IP_ADDRESS_BYTES = 4; - + // 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 + (2 * (sizeof(uint16_t) + IP_ADDRESS_BYTES)) + numBytesNodesOfInterest + sizeof(unsigned char); - + unsigned char checkInPacket[numPacketBytes]; unsigned char* packetPosition = checkInPacket; - + PACKET_TYPE nodePacketType = (memchr(SOLO_NODE_TYPES, _ownerType, sizeof(SOLO_NODE_TYPES))) ? PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY : PACKET_TYPE_DOMAIN_LIST_REQUEST; - + packetPosition += populateTypeAndVersion(packetPosition, nodePacketType); - + *(packetPosition++) = _ownerType; - + // send our owner UUID or the null one QByteArray rfcOwnerUUID = _ownerUUID.toRfc4122(); memcpy(packetPosition, rfcOwnerUUID.constData(), rfcOwnerUUID.size()); packetPosition += rfcOwnerUUID.size(); - + // pack our public address to send to domain-server packetPosition += HifiSockAddr::packSockAddr(checkInPacket + (packetPosition - checkInPacket), _publicSockAddr); - + // pack our local address to send to domain-server packetPosition += HifiSockAddr::packSockAddr(checkInPacket + (packetPosition - checkInPacket), HifiSockAddr(QHostAddress(getHostOrderLocalAddress()), _nodeSocket.localPort())); - + // add the number of bytes for node types of interest *(packetPosition++) = numBytesNodesOfInterest; - + // copy over the bytes for node types of interest, if required if (numBytesNodesOfInterest > 0) { memcpy(packetPosition, @@ -569,17 +571,17 @@ void NodeList::sendDomainServerCheckIn() { numBytesNodesOfInterest); packetPosition += numBytesNodesOfInterest; } - + _nodeSocket.writeDatagram((char*) checkInPacket, packetPosition - checkInPacket, _domainSockAddr.getAddress(), _domainSockAddr.getPort()); const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5; static unsigned int numDomainCheckins = 0; - + // send a STUN request every Nth domain server check in so we update our public socket, if required if (numDomainCheckins++ % NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST == 0) { sendSTUNRequest(); } - + // increment the count of un-replied check-ins _numNoReplyDomainCheckIns++; } @@ -588,55 +590,55 @@ void NodeList::sendDomainServerCheckIn() { int NodeList::processDomainServerList(unsigned char* packetData, size_t dataBytes) { // this is a packet from the domain server, reset the count of un-replied check-ins _numNoReplyDomainCheckIns = 0; - + int readNodes = 0; char nodeType; - + // assumes only IPv4 addresses HifiSockAddr nodePublicSocket; HifiSockAddr nodeLocalSocket; - + unsigned char* readPtr = packetData + numBytesForPacketHeader(packetData); unsigned char* startPtr = packetData; - + while((readPtr - startPtr) < dataBytes - sizeof(uint16_t)) { nodeType = *readPtr++; QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*) readPtr, NUM_BYTES_RFC4122_UUID)); readPtr += NUM_BYTES_RFC4122_UUID; - + readPtr += HifiSockAddr::unpackSockAddr(readPtr, nodePublicSocket); readPtr += HifiSockAddr::unpackSockAddr(readPtr, nodeLocalSocket); - + // if the public socket address is 0 then it's reachable at the same IP // as the domain server if (nodePublicSocket.getAddress().isNull()) { nodePublicSocket.setAddress(_domainSockAddr.getAddress()); } - + addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket); } - + return readNodes; } void NodeList::sendAssignment(Assignment& assignment) { unsigned char assignmentPacket[MAX_PACKET_SIZE]; - + PACKET_TYPE assignmentPacketType = assignment.getCommand() == Assignment::CreateCommand ? PACKET_TYPE_CREATE_ASSIGNMENT : PACKET_TYPE_REQUEST_ASSIGNMENT; - + int numHeaderBytes = populateTypeAndVersion(assignmentPacket, assignmentPacketType); int numAssignmentBytes = assignment.packToBuffer(assignmentPacket + numHeaderBytes); - + static HifiSockAddr DEFAULT_ASSIGNMENT_SOCKET(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME, DEFAULT_DOMAIN_SERVER_PORT); - + const HifiSockAddr* assignmentServerSocket = _assignmentServerSocket.isNull() ? &DEFAULT_ASSIGNMENT_SOCKET : &_assignmentServerSocket; - + _nodeSocket.writeDatagram((char*) assignmentPacket, numHeaderBytes + numAssignmentBytes, assignmentServerSocket->getAddress(), assignmentServerSocket->getPort()); @@ -665,7 +667,7 @@ int NodeList::fillPingReplyPacket(unsigned char* pingBuffer, unsigned char* repl memcpy(dataAt, &ourReplyTime, sizeof(ourReplyTime)); dataAt += sizeof(ourReplyTime); length += sizeof(ourReplyTime); - + return length; } @@ -673,7 +675,7 @@ int NodeList::fillPingReplyPacket(unsigned char* pingBuffer, unsigned char* repl void NodeList::pingPublicAndLocalSocketsForInactiveNode(Node* node) { unsigned char pingPacket[MAX_PACKET_SIZE]; int pingPacketLength = fillPingPacket(pingPacket); - + // send the ping packet to the local and public sockets for this node _nodeSocket.writeDatagram((char*) pingPacket, pingPacketLength, node->getLocalSocket().getAddress(), node->getLocalSocket().getPort()); @@ -684,24 +686,24 @@ void NodeList::pingPublicAndLocalSocketsForInactiveNode(Node* node) { Node* NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { NodeList::iterator node = end(); - + for (node = begin(); node != end(); node++) { if (node->getUUID() == uuid) { // we already have this node, stop checking break; } } - + if (node == end()) { // we didn't have this node, so add them Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); - + addNodeToList(newNode); - + return newNode; } else { node->lock(); - + if (node->getType() == NODE_TYPE_AUDIO_MIXER || node->getType() == NODE_TYPE_VOXEL_SERVER || node->getType() == NODE_TYPE_METAVOXEL_SERVER) { @@ -709,39 +711,39 @@ Node* NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, // the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously node->setLastHeardMicrostamp(usecTimestampNow()); } - + // check if we need to change this node's public or local sockets if (publicSocket != node->getPublicSocket()) { node->setPublicSocket(publicSocket); qDebug() << "Public socket change for node" << *node << "\n"; } - + if (localSocket != node->getLocalSocket()) { node->setLocalSocket(localSocket); qDebug() << "Local socket change for node" << *node << "\n"; } - + node->unlock(); - + // we had this node already, do nothing for now return &*node; - } + } } void NodeList::addNodeToList(Node* newNode) { // find the correct array to add this node to int bucketIndex = _numNodes / NODES_PER_BUCKET; - + if (!_nodeBuckets[bucketIndex]) { _nodeBuckets[bucketIndex] = new Node*[NODES_PER_BUCKET](); } - + _nodeBuckets[bucketIndex][_numNodes % NODES_PER_BUCKET] = newNode; - + ++_numNodes; - + qDebug() << "Added" << *newNode << "\n"; - + notifyHooksOfAddedNode(newNode); } @@ -803,7 +805,7 @@ Node* NodeList::soloNodeOfType(char nodeType) { } } } - + return NULL; } @@ -811,13 +813,13 @@ void NodeList::killNode(Node* node, bool mustLockNode) { if (mustLockNode) { node->lock(); } - + qDebug() << "Killed " << *node << "\n"; - + notifyHooksOfKilledNode(&*node); - + node->setAlive(false); - + if (mustLockNode) { node->unlock(); } @@ -825,15 +827,15 @@ void NodeList::killNode(Node* node, bool mustLockNode) { void NodeList::removeSilentNodes() { NodeList* nodeList = NodeList::getInstance(); - + for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); ++node) { node->lock(); - + if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { // kill this node, don't lock - we already did it nodeList->killNode(&(*node), false); } - + node->unlock(); } } @@ -843,20 +845,20 @@ const QString DOMAIN_SERVER_SETTING_KEY = "domainServerHostname"; void NodeList::loadData(QSettings *settings) { settings->beginGroup(DOMAIN_SERVER_SETTING_KEY); - + QString domainServerHostname = settings->value(DOMAIN_SERVER_SETTING_KEY).toString(); - + if (domainServerHostname.size() > 0) { _domainHostname = domainServerHostname; notifyDomainChanged(); } - + settings->endGroup(); } void NodeList::saveData(QSettings* settings) { settings->beginGroup(DOMAIN_SERVER_SETTING_KEY); - + if (_domainHostname != DEFAULT_DOMAIN_HOSTNAME) { // the user is using a different hostname, store it settings->setValue(DOMAIN_SERVER_SETTING_KEY, QVariant(_domainHostname)); @@ -864,23 +866,23 @@ void NodeList::saveData(QSettings* settings) { // the user has switched back to default, remove the current setting settings->remove(DOMAIN_SERVER_SETTING_KEY); } - + settings->endGroup(); } NodeList::iterator NodeList::begin() const { Node** nodeBucket = NULL; - + for (int i = 0; i < _numNodes; i++) { if (i % NODES_PER_BUCKET == 0) { nodeBucket = _nodeBuckets[i / NODES_PER_BUCKET]; } - + if (nodeBucket[i % NODES_PER_BUCKET]->isAlive()) { return NodeListIterator(this, i); } } - + // there's no alive node to start from - return the end return end(); } @@ -932,7 +934,7 @@ NodeList::iterator NodeListIterator::operator++(int) { void NodeListIterator::skipDeadAndStopIncrement() { while (_nodeIndex != _nodeList->_numNodes) { ++_nodeIndex; - + if (_nodeIndex == _nodeList->_numNodes) { break; } else if ((*(*this)).isAlive()) { diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 8c1972f2e9..28241f1cb0 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -9,7 +9,11 @@ #ifndef __hifi__NodeList__ #define __hifi__NodeList__ +#ifdef _WIN32 +#include "Syssocket.h" +#else #include +#endif #include #include diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index cbec4806e5..24fb15d88e 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -19,90 +19,6 @@ #include "PerfStat.h" // Static class members initialization here! -std::map > PerfStat::groupHistoryMap; -bool PerfStat::wantDebugOut = false; -timeval PerfStat::firstDumpTime; -bool PerfStat::firstDumpTimeSet = false; - -// Constructor handles starting the timer -PerfStat::PerfStat(std::string groupName) { - this->group = groupName; - gettimeofday(&this->start,NULL); - - // If this is our first ever PerfStat object, we'll also initialize this - if (!firstDumpTimeSet) { - gettimeofday(&firstDumpTime,NULL); - firstDumpTimeSet=true; - } -} - -// Destructor handles recording all of our stats -PerfStat::~PerfStat() { - timeval end; - gettimeofday(&end,NULL); - double elapsed = ((end.tv_usec-start.tv_usec)/1000000.0)+(end.tv_sec-start.tv_sec); - - double average = elapsed; - double totalTime = elapsed; - long int count = 1; - - // check to see if this group exists in the history... - if (groupHistoryMap.find(group) == groupHistoryMap.end()) { - groupHistoryMap[group]=PerfStatHistory(group,elapsed,1); - } else { - PerfStatHistory history = groupHistoryMap[group]; - history.recordTime(elapsed); - groupHistoryMap[group] = history; - average = history.getAverage(); - count = history.getCount(); - totalTime = history.getTotalTime(); - } - - if (wantDebugOut) { - qDebug("PerfStats: %s elapsed:%f average:%lf count:%ld total:%lf ut:%ld us:%ld ue:%ld t:%ld s:%ld e:%ld\n", - this->group.c_str(),elapsed,average,count,totalTime, - (long)(end.tv_usec-start.tv_usec), (long)start.tv_usec, (long)end.tv_usec, - (long)(end.tv_sec-start.tv_sec), (long)start.tv_sec, (long)end.tv_sec - ); - } -}; - -// How many groups have we added? -int PerfStat::getGroupCount() { - return groupHistoryMap.size(); -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Method: DumpStats() -// Description: Generates some lines of debug stats for all the groups of PerfStats you've created. -// Note: Caller is responsible for allocating an array of char*'s that is large enough to hold -// groupCount + 1. Caller is also responsible for deleting all this memory. -int PerfStat::DumpStats(char** array) { - // If we haven't yet set a dump time, we'll also initialize this now, but this is unlikely - if (!firstDumpTimeSet) { - gettimeofday(&firstDumpTime,NULL); - firstDumpTimeSet=true; - } - - timeval now; - gettimeofday(&now,NULL); - double elapsed = ((now.tv_usec-firstDumpTime.tv_usec)/1000000.0)+(now.tv_sec-firstDumpTime.tv_sec); - - array[0] = new char[MAX_PERFSTAT_DEBUG_LINE_LEN]; - snprintf(array[0],MAX_PERFSTAT_DEBUG_LINE_LEN,"PerfStats:"); - int lineCount=1; - // For each active performance group - for (PerfStatMapItr i = groupHistoryMap.begin(); i != groupHistoryMap.end(); i++) { - float percent = (i->second.getTotalTime()/elapsed) * 100.0; - - array[lineCount] = new char[MAX_PERFSTAT_DEBUG_LINE_LEN]; - snprintf(array[lineCount],MAX_PERFSTAT_DEBUG_LINE_LEN,"%s Avg: %lf Num: %ld TTime: %lf (%.2f%%)", - i->second.group.c_str(),i->second.getAverage(),i->second.getCount(),i->second.getTotalTime(),percent); - lineCount++; - } - return lineCount; -} - bool PerformanceWarning::_suppressShortTimings = false; // Destructor handles recording all of our stats diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 81e2818fc5..311ab5ed91 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -27,62 +27,6 @@ #include #include -class PerfStatHistory { - -private: - long int count; - double totalTime; -public: - std::string group; - - PerfStatHistory(): count(0), totalTime(0.0) {} - PerfStatHistory(std::string myGroup, double initialTime, long int initialCount) : - count(initialCount), totalTime(initialTime), group(myGroup) {} - - void recordTime(double thisTime) { - totalTime+=thisTime; - count++; - }; - double getAverage() { - return totalTime/count; - }; - double getTotalTime() { - return totalTime; - }; - long int getCount() { - return count; - }; - - // needed for map template? Maybe not. - bool operator<( const PerfStatHistory& other) const { - return group < other.group; - } -}; - -#define MAX_PERFSTAT_DEBUG_LINE_LEN 200 - -class PerfStat { -private: - static std::map > groupHistoryMap; - - static timeval firstDumpTime; - static bool firstDumpTimeSet; - - std::string group; - timeval start; - -public: - PerfStat(std::string groupName); - ~PerfStat(); - - // Format debug stats into buffer, returns number of "lines" of stats - static int DumpStats(char** array); - static int getGroupCount(); - static bool wantDebugOut; -}; - -typedef std::map >::iterator PerfStatMapItr; - class PerformanceWarning { private: uint64_t _start; @@ -94,7 +38,7 @@ private: static bool _suppressShortTimings; public: - PerformanceWarning(bool renderWarnings, const char* message, bool alwaysDisplay = false, + PerformanceWarning(bool renderWarnings, const char* message, bool alwaysDisplay = false, uint64_t* runningTotal = NULL, uint64_t* totalCalls = NULL) : _start(usecTimestampNow()), _message(message), @@ -104,7 +48,7 @@ public: _totalCalls(totalCalls) { } ~PerformanceWarning(); - + static void setSuppressShortTimings(bool suppressShortTimings) { _suppressShortTimings = suppressShortTimings; } };