void AvatarMixer::run() { // change the logging target name while AvatarMixer is running Logging::setTargetName(AVATAR_MIXER_LOGGING_NAME); NodeList* nodeList = NodeList::getInstance(); nodeList->setOwnerType(NODE_TYPE_AVATAR_MIXER); nodeList->setNodeTypesOfInterest(&NODE_TYPE_AGENT, 1); nodeList->linkedDataCreateCallback = attachAvatarDataToNode; nodeList->startSilentNodeRemovalThread(); sockaddr nodeAddress = {}; ssize_t receivedBytes = 0; unsigned char packetData[MAX_PACKET_SIZE]; QUuid nodeUUID; Node* avatarNode = NULL; timeval lastDomainServerCheckIn = {}; while (true) { if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) { break; } // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { gettimeofday(&lastDomainServerCheckIn, NULL); NodeList::getInstance()->sendDomainServerCheckIn(); } nodeList->possiblyPingInactiveNodes(); if (nodeList->getNodeSocket()->receive(&nodeAddress, packetData, &receivedBytes) && packetVersionMatch(packetData)) { switch (packetData[0]) { case PACKET_TYPE_HEAD_DATA: nodeUUID = QUuid::fromRfc4122(QByteArray((char*) packetData + numBytesForPacketHeader(packetData), NUM_BYTES_RFC4122_UUID)); // add or update the node in our list avatarNode = nodeList->nodeWithUUID(nodeUUID); if (avatarNode) { // parse positional data from an node nodeList->updateNodeWithData(avatarNode, &nodeAddress, packetData, receivedBytes); } else { break; } case PACKET_TYPE_INJECT_AUDIO: broadcastAvatarData(nodeList, nodeUUID, &nodeAddress); break; case PACKET_TYPE_AVATAR_URLS: case PACKET_TYPE_AVATAR_FACE_VIDEO: nodeUUID = QUuid::fromRfc4122(QByteArray((char*) packetData + numBytesForPacketHeader(packetData), NUM_BYTES_RFC4122_UUID)); // let everyone else know about the update for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { if (node->getActiveSocket() && node->getUUID() != nodeUUID) { nodeList->getNodeSocket()->send(node->getActiveSocket(), packetData, receivedBytes); } } break; default: // hand this off to the NodeList nodeList->processNodeData(&nodeAddress, packetData, receivedBytes); break; } } } nodeList->stopSilentNodeRemovalThread(); }
int main(int argc, const char* argv[]) { NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT); setvbuf(stdout, NULL, _IOLBF, 0); // Handle Local Domain testing with the --local command line const char* local = "--local"; if (cmdOptionExists(argc, argv, local)) { printf("Local Domain MODE!\n"); nodeList->setDomainIPToLocalhost(); } nodeList->linkedDataCreateCallback = attachAvatarDataToNode; nodeList->startSilentNodeRemovalThread(); sockaddr* nodeAddress = new sockaddr; ssize_t receivedBytes = 0; unsigned char* packetData = new unsigned char[MAX_PACKET_SIZE]; uint16_t nodeID = 0; Node* avatarNode = NULL; timeval lastDomainServerCheckIn = {}; // we only need to hear back about avatar nodes from the DS NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_AGENT, 1); while (true) { // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { gettimeofday(&lastDomainServerCheckIn, NULL); NodeList::getInstance()->sendDomainServerCheckIn(); } if (nodeList->getNodeSocket()->receive(nodeAddress, packetData, &receivedBytes) && packetVersionMatch(packetData)) { switch (packetData[0]) { case PACKET_TYPE_HEAD_DATA: // grab the node ID from the packet unpackNodeId(packetData + numBytesForPacketHeader(packetData), &nodeID); // add or update the node in our list avatarNode = nodeList->addOrUpdateNode(nodeAddress, nodeAddress, NODE_TYPE_AGENT, nodeID); // parse positional data from an node nodeList->updateNodeWithData(avatarNode, packetData, receivedBytes); case PACKET_TYPE_INJECT_AUDIO: broadcastAvatarData(nodeList, nodeAddress); break; case PACKET_TYPE_AVATAR_VOXEL_URL: case PACKET_TYPE_AVATAR_FACE_VIDEO: // grab the node ID from the packet unpackNodeId(packetData + numBytesForPacketHeader(packetData), &nodeID); // let everyone else know about the update for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { if (node->getActiveSocket() && node->getNodeID() != nodeID) { nodeList->getNodeSocket()->send(node->getActiveSocket(), packetData, receivedBytes); } } break; case PACKET_TYPE_DOMAIN: // ignore the DS packet, for now nodes are added only when they communicate directly with us break; default: // hand this off to the NodeList nodeList->processNodeData(nodeAddress, packetData, receivedBytes); break; } } } nodeList->stopSilentNodeRemovalThread(); return 0; }
void AvatarMixer::run() { // change the logging target name while AvatarMixer is running Logging::setTargetName(AVATAR_MIXER_LOGGING_NAME); NodeList* nodeList = NodeList::getInstance(); nodeList->setOwnerType(NODE_TYPE_AVATAR_MIXER); nodeList->linkedDataCreateCallback = attachAvatarDataToNode; nodeList->startSilentNodeRemovalThread(); sockaddr* nodeAddress = new sockaddr; ssize_t receivedBytes = 0; unsigned char* packetData = new unsigned char[MAX_PACKET_SIZE]; uint16_t nodeID = 0; Node* avatarNode = NULL; timeval lastDomainServerCheckIn = {}; // we only need to hear back about avatar nodes from the DS nodeList->setNodeTypesOfInterest(&NODE_TYPE_AGENT, 1); while (true) { if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) { break; } // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { gettimeofday(&lastDomainServerCheckIn, NULL); NodeList::getInstance()->sendDomainServerCheckIn(); } if (nodeList->getNodeSocket()->receive(nodeAddress, packetData, &receivedBytes) && packetVersionMatch(packetData)) { switch (packetData[0]) { case PACKET_TYPE_HEAD_DATA: // grab the node ID from the packet unpackNodeId(packetData + numBytesForPacketHeader(packetData), &nodeID); // add or update the node in our list avatarNode = nodeList->addOrUpdateNode(nodeAddress, nodeAddress, NODE_TYPE_AGENT, nodeID); // parse positional data from an node nodeList->updateNodeWithData(avatarNode, packetData, receivedBytes); case PACKET_TYPE_INJECT_AUDIO: broadcastAvatarData(nodeList, nodeAddress); break; case PACKET_TYPE_AVATAR_VOXEL_URL: case PACKET_TYPE_AVATAR_FACE_VIDEO: // grab the node ID from the packet unpackNodeId(packetData + numBytesForPacketHeader(packetData), &nodeID); // let everyone else know about the update for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { if (node->getActiveSocket() && node->getNodeID() != nodeID) { nodeList->getNodeSocket()->send(node->getActiveSocket(), packetData, receivedBytes); } } break; default: // hand this off to the NodeList nodeList->processNodeData(nodeAddress, packetData, receivedBytes); break; } } } nodeList->stopSilentNodeRemovalThread(); }