int AudioMixerClientData::parseData(const QByteArray& packet) { PacketType packetType = packetTypeForPacket(packet); if (packetType == PacketTypeMicrophoneAudioWithEcho || packetType == PacketTypeMicrophoneAudioNoEcho || packetType == PacketTypeSilentAudioFrame) { // grab the AvatarAudioRingBuffer from the vector (or create it if it doesn't exist) AvatarAudioRingBuffer* avatarRingBuffer = getAvatarAudioRingBuffer(); // read the first byte after the header to see if this is a stereo or mono buffer quint8 channelFlag = packet.at(numBytesForPacketHeader(packet)); bool isStereo = channelFlag == 1; if (avatarRingBuffer && avatarRingBuffer->isStereo() != isStereo) { // there's a mismatch in the buffer channels for the incoming and current buffer // so delete our current buffer and create a new one _ringBuffers.removeOne(avatarRingBuffer); avatarRingBuffer->deleteLater(); avatarRingBuffer = NULL; } if (!avatarRingBuffer) { // we don't have an AvatarAudioRingBuffer yet, so add it avatarRingBuffer = new AvatarAudioRingBuffer(isStereo); _ringBuffers.push_back(avatarRingBuffer); } // ask the AvatarAudioRingBuffer instance to parse the data avatarRingBuffer->parseData(packet); } else { // this is injected audio // grab the stream identifier for this injected audio QUuid streamIdentifier = QUuid::fromRfc4122(packet.mid(numBytesForPacketHeader(packet), NUM_BYTES_RFC4122_UUID)); InjectedAudioRingBuffer* matchingInjectedRingBuffer = NULL; for (unsigned int i = 0; i < _ringBuffers.size(); i++) { if (_ringBuffers[i]->getType() == PositionalAudioRingBuffer::Injector && ((InjectedAudioRingBuffer*) _ringBuffers[i])->getStreamIdentifier() == streamIdentifier) { matchingInjectedRingBuffer = (InjectedAudioRingBuffer*) _ringBuffers[i]; } } if (!matchingInjectedRingBuffer) { // we don't have a matching injected audio ring buffer, so add it matchingInjectedRingBuffer = new InjectedAudioRingBuffer(streamIdentifier); _ringBuffers.push_back(matchingInjectedRingBuffer); } matchingInjectedRingBuffer->parseData(packet); } return 0; }
void LimitedNodeList::processKillNode(const QByteArray& dataByteArray) { // read the node id QUuid nodeUUID = QUuid::fromRfc4122(dataByteArray.mid(numBytesForPacketHeader(dataByteArray), NUM_BYTES_RFC4122_UUID)); // kill the node with this UUID, if it exists killNodeWithUUID(nodeUUID); }
void OctreeEditPacketSender::processNackPacket(const QByteArray& packet) { // parse sending node from packet, retrieve packet history for that node QUuid sendingNodeUUID = uuidFromPacketHeader(packet); // if packet history doesn't exist for the sender node (somehow), bail if (!_sentPacketHistories.contains(sendingNodeUUID)) { return; } const SentPacketHistory& sentPacketHistory = _sentPacketHistories.value(sendingNodeUUID); int numBytesPacketHeader = numBytesForPacketHeader(packet); const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(packet.data()) + numBytesPacketHeader; // read number of sequence numbers uint16_t numSequenceNumbers = (*(uint16_t*)dataAt); dataAt += sizeof(uint16_t); // read sequence numbers and queue packets for resend for (int i = 0; i < numSequenceNumbers; i++) { unsigned short int sequenceNumber = (*(unsigned short int*)dataAt); dataAt += sizeof(unsigned short int); // retrieve packet from history const QByteArray* packet = sentPacketHistory.getPacket(sequenceNumber); if (packet) { const SharedNodePointer& node = DependencyManager::get<NodeList>()->nodeWithUUID(sendingNodeUUID); queuePacketForSending(node, *packet); } } }
void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { PacketType datagramPacketType = packetTypeForPacket(dataByteArray); if (datagramPacketType == PacketTypeJurisdiction) { int headerBytes = numBytesForPacketHeader(dataByteArray); // PacketType_JURISDICTION, first byte is the node type... switch (dataByteArray[headerBytes]) { case NodeType::VoxelServer: _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr, dataByteArray); break; case NodeType::ParticleServer: _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr, dataByteArray); break; } } else if (datagramPacketType == PacketTypeParticleAddResponse) { // this will keep creatorTokenIDs to IDs mapped correctly Particle::handleAddParticleResponse(dataByteArray); // also give our local particle tree a chance to remap any internal locally created particles _particleTree.handleAddParticleResponse(dataByteArray); } else { NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray); } }
void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t length) { if (!_shouldSend) { return; // bail early } assert(serversExist()); // we must have jurisdictions to be here!! int headerBytes = numBytesForPacketHeader(reinterpret_cast<char*>(buffer)) + sizeof(short) + sizeof(quint64); unsigned char* octCode = buffer + headerBytes; // skip the packet header to get to the octcode // We want to filter out edit messages for servers based on the server's Jurisdiction // But we can't really do that with a packed message, since each edit message could be destined // for a different server... So we need to actually manage multiple queued packets... one // for each server foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); bool isMyJurisdiction = true; // we need to get the jurisdiction for this // here we need to get the "pending packet" for this server const JurisdictionMap& map = (*_serverJurisdictions)[nodeUUID]; isMyJurisdiction = (map.isMyJurisdiction(octCode, CHECK_NODE_ONLY) == JurisdictionMap::WITHIN); if (isMyJurisdiction) { queuePacketToNode(nodeUUID, buffer, length); } } } }
// This method is called when the edit packet layer has determined that it has a fully formed packet destined for // a known nodeID. void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, ssize_t length) { NodeList* nodeList = NodeList::getInstance(); foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { if (node->getActiveSocket()) { queuePacketForSending(node, QByteArray(reinterpret_cast<char*>(buffer), length)); // debugging output... bool wantDebugging = false; if (wantDebugging) { int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast<char*>(buffer)); unsigned short int sequence = (*((unsigned short int*)(buffer + numBytesPacketHeader))); quint64 createdAt = (*((quint64*)(buffer + numBytesPacketHeader + sizeof(sequence)))); quint64 queuedAt = usecTimestampNow(); quint64 transitTime = queuedAt - createdAt; qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] << " - command to node bytes=" << length << " sequence=" << sequence << " transitTimeSoFar=" << transitTime << " usecs"; } } } } }
void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) { QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); quint8 pingType; quint64 ourOriginalTime, othersReplyTime; packetStream >> pingType >> ourOriginalTime >> othersReplyTime; quint64 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 quint64 othersExprectedReply = ourOriginalTime + oneWayFlightTime; int clockSkew = othersReplyTime - othersExprectedReply; sendingNode->setPingMs(pingTime / 1000); sendingNode->updateClockSkewUsec(clockSkew); const bool wantDebug = false; if (wantDebug) { qDebug() << "PING_REPLY from node " << *sendingNode << "\n" << " now: " << now << "\n" << " ourTime: " << ourOriginalTime << "\n" << " pingTime: " << pingTime << "\n" << " oneWayFlightTime: " << oneWayFlightTime << "\n" << " othersReplyTime: " << othersReplyTime << "\n" << " othersExprectedReply: " << othersExprectedReply << "\n" << " clockSkew: " << clockSkew << "\n" << " average clockSkew: " << sendingNode->getClockSkewUsec(); } }
void VoxelEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t length) { if (!_shouldSend) { return; // bail early } assert(voxelServersExist()); // we must have jurisdictions to be here!! int headerBytes = numBytesForPacketHeader(buffer) + sizeof(short) + sizeof(uint64_t); unsigned char* octCode = buffer + headerBytes; // skip the packet header to get to the octcode // We want to filter out edit messages for voxel servers based on the server's Jurisdiction // But we can't really do that with a packed message, since each edit message could be destined // for a different voxel server... So we need to actually manage multiple queued packets... one // for each voxel server NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { // only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER if (node->getActiveSocket() != NULL && node->getType() == NODE_TYPE_VOXEL_SERVER) { QUuid nodeUUID = node->getUUID(); bool isMyJurisdiction = true; // we need to get the jurisdiction for this // here we need to get the "pending packet" for this server const JurisdictionMap& map = (*_voxelServerJurisdictions)[nodeUUID]; isMyJurisdiction = (map.isMyJurisdiction(octCode, CHECK_NODE_ONLY) == JurisdictionMap::WITHIN); if (isMyJurisdiction) { queuePacketToNode(nodeUUID, buffer, length); } } } }
int InjectedAudioRingBuffer::parseData(const QByteArray& packet) { // setup a data stream to read from this packet QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); // push past the stream identifier packetStream.skipRawData(NUM_BYTES_RFC4122_UUID); // pull the loopback flag and set our boolean uchar shouldLoopback; packetStream >> shouldLoopback; _shouldLoopbackForNode = (shouldLoopback == 1); // use parsePositionalData in parent PostionalAudioRingBuffer class to pull common positional data packetStream.skipRawData(parsePositionalData(packet.mid(packetStream.device()->pos()))); // pull out the radius for this injected source - if it's zero this is a point source packetStream >> _radius; quint8 attenuationByte = 0; packetStream >> attenuationByte; _attenuationRatio = attenuationByte / (float) MAX_INJECTOR_VOLUME; packetStream.skipRawData(writeData(packet.data() + packetStream.device()->pos(), packet.size() - packetStream.device()->pos())); return packetStream.device()->pos(); }
ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet) { QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); quint8 packedType; packetStream >> packedType; Assignment::Type unpackedType = (Assignment::Type) packedType; switch (unpackedType) { case Assignment::AudioMixerType: return new AudioMixer(packet); case Assignment::AvatarMixerType: return new AvatarMixer(packet); case Assignment::AgentType: return new Agent(packet); case Assignment::VoxelServerType: return new VoxelServer(packet); case Assignment::ParticleServerType: return new ParticleServer(packet); case Assignment::MetavoxelServerType: return new MetavoxelServer(packet); default: return NULL; } }
// This method is called when the edit packet layer has determined that it has a fully formed packet destined for // a known nodeID. void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, size_t length, qint64 satoshiCost) { bool wantDebug = false; DependencyManager::get<NodeList>()->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull())) && node->getActiveSocket()) { // pack sequence number int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast<char*>(buffer)); unsigned char* sequenceAt = buffer + numBytesPacketHeader; quint16 sequence = _outgoingSequenceNumbers[nodeUUID]++; memcpy(sequenceAt, &sequence, sizeof(quint16)); // send packet QByteArray packet(reinterpret_cast<const char*>(buffer), length); queuePacketForSending(node, packet); if (hasDestinationWalletUUID() && satoshiCost > 0) { // if we have a destination wallet UUID and a cost associated with this packet, signal that it // needs to be sent emit octreePaymentRequired(satoshiCost, nodeUUID, _destinationWalletUUID); } // add packet to history _sentPacketHistories[nodeUUID].packetSent(sequence, packet); // debugging output... if (wantDebug) { int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast<const char*>(buffer)); unsigned short int sequence = (*((unsigned short int*)(buffer + numBytesPacketHeader))); quint64 createdAt = (*((quint64*)(buffer + numBytesPacketHeader + sizeof(sequence)))); quint64 queuedAt = usecTimestampNow(); quint64 transitTime = queuedAt - createdAt; qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] << " - command to node bytes=" << length << " satoshiCost=" << satoshiCost << " sequence=" << sequence << " transitTimeSoFar=" << transitTime << " usecs"; } } }); }
int PositionalAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char* currentBuffer = sourceBuffer + numBytesForPacketHeader(sourceBuffer); currentBuffer += sizeof(uint16_t); // the source ID currentBuffer += parseListenModeData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); currentBuffer += parsePositionalData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); currentBuffer += parseAudioSamples(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); return currentBuffer - sourceBuffer; }
void AvatarHashMap::processKillAvatar(const QByteArray& datagram) { // read the node id QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(numBytesForPacketHeader(datagram), NUM_BYTES_RFC4122_UUID)); // remove the avatar with that UUID from our hash, if it exists AvatarHash::iterator matchedAvatar = _avatarHash.find(sessionUUID); if (matchedAvatar != _avatarHash.end()) { erase(matchedAvatar); } }
void Transmitter::processIncomingData(unsigned char* packetData, int numBytes) { // Packet's first byte is 'T' int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast<const char*>(packetData)); const int ROTATION_MARKER_SIZE = 1; // 'R' = Rotation (clockwise about x,y,z) const int ACCELERATION_MARKER_SIZE = 1; // 'A' = Acceleration (x,y,z) if (!_lastReceivedPacket) { _lastReceivedPacket = new timeval; } gettimeofday(_lastReceivedPacket, NULL); if (numBytes == numBytesPacketHeader + ROTATION_MARKER_SIZE + ACCELERATION_MARKER_SIZE + sizeof(_lastRotationRate) + sizeof(_lastAcceleration) + sizeof(_touchState.x) + sizeof(_touchState.y) + sizeof(_touchState.state)) { unsigned char* packetDataPosition = packetData + numBytesPacketHeader + ROTATION_MARKER_SIZE; memcpy(&_lastRotationRate, packetDataPosition, sizeof(_lastRotationRate)); packetDataPosition += sizeof(_lastRotationRate) + ACCELERATION_MARKER_SIZE; memcpy(&_lastAcceleration, packetDataPosition, sizeof(_lastAcceleration)); packetDataPosition += sizeof(_lastAcceleration); memcpy(&_touchState.state, packetDataPosition, sizeof(_touchState.state)); packetDataPosition += sizeof(_touchState.state); memcpy(&_touchState.x, packetDataPosition, sizeof(_touchState.x)); packetDataPosition += sizeof(_touchState.x); memcpy(&_touchState.y, packetDataPosition, sizeof(_touchState.y)); packetDataPosition += sizeof(_touchState.y); // Update estimated absolute position from rotation rates _estimatedRotation += _lastRotationRate * DELTA_TIME; // Sensor Fusion! Slowly adjust estimated rotation to be relative to gravity (average acceleration) const float GRAVITY_FOLLOW_RATE = 1.f; float rollAngle = angleBetween(glm::vec3(_lastAcceleration.x, _lastAcceleration.y, 0.f), glm::vec3(0,-1,0)) * ((_lastAcceleration.x < 0.f) ? -1.f : 1.f); float pitchAngle = angleBetween(glm::vec3(0.f, _lastAcceleration.y, _lastAcceleration.z), glm::vec3(0,-1,0)) * ((_lastAcceleration.z < 0.f) ? 1.f : -1.f); _estimatedRotation.x = (1.f - GRAVITY_FOLLOW_RATE * DELTA_TIME) * _estimatedRotation.x + GRAVITY_FOLLOW_RATE * DELTA_TIME * pitchAngle; _estimatedRotation.z = (1.f - GRAVITY_FOLLOW_RATE * DELTA_TIME) * _estimatedRotation.z + GRAVITY_FOLLOW_RATE * DELTA_TIME * rollAngle; // Can't apply gravity fusion to Yaw, so decay estimated yaw to zero, // presuming that the average yaw direction is toward screen _estimatedRotation.y *= (1.f - DECAY_RATE * DELTA_TIME); if (!_isConnected) { qDebug("Transmitter Connected."); _isConnected = true; _estimatedRotation *= 0.0; } } else { qDebug("Transmitter packet read error, %d bytes.", numBytes); } }
void AvatarHashMap::processAvatarBillboardPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer) { int headerSize = numBytesForPacketHeader(packet); QUuid sessionUUID = QUuid::fromRfc4122(QByteArray::fromRawData(packet.constData() + headerSize, NUM_BYTES_RFC4122_UUID)); AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer); if (matchingAvatar) { QByteArray billboard = packet.mid(headerSize + NUM_BYTES_RFC4122_UUID); if (matchingAvatar->getBillboard() != billboard) { matchingAvatar->setBillboard(billboard); } } }
void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) { for(NodeList::iterator node = begin(); node != end(); node++) { if (socketMatch(node->getPublicSocket(), nodeAddress) || socketMatch(node->getLocalSocket(), nodeAddress)) { int pingTime = usecTimestampNow() - *(uint64_t*)(packetData + numBytesForPacketHeader(packetData)); node->setPingMs(pingTime / 1000); break; } } }
Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : _location(GlobalLocation), _attachedPublicSocket(NULL), _attachedLocalSocket(NULL) { // set the create time on this assignment gettimeofday(&_time, NULL); int numBytesRead = 0; if (dataBuffer[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) { _command = Assignment::RequestCommand; } else if (dataBuffer[0] == PACKET_TYPE_CREATE_ASSIGNMENT) { _command = Assignment::CreateCommand; } else if (dataBuffer[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT) { _command = Assignment::DeployCommand; } numBytesRead += numBytesForPacketHeader(dataBuffer); if (dataBuffer[0] != PACKET_TYPE_REQUEST_ASSIGNMENT) { // read the GUID for this assignment _uuid = QUuid::fromRfc4122(QByteArray((const char*) dataBuffer + numBytesRead, NUM_BYTES_RFC4122_UUID)); numBytesRead += NUM_BYTES_RFC4122_UUID; } memcpy(&_type, dataBuffer + numBytesRead, sizeof(Assignment::Type)); numBytesRead += sizeof(Assignment::Type); if (numBytes > numBytesRead) { sockaddr* newSocket = NULL; if (dataBuffer[numBytesRead++] == IPv4_ADDRESS_DESIGNATOR) { // IPv4 address newSocket = (sockaddr*) new sockaddr_in; unpackSocket(dataBuffer + numBytesRead, newSocket); } else { // IPv6 address, or bad designator qDebug("Received a socket that cannot be unpacked!\n"); } if (_command == Assignment::CreateCommand) { delete _attachedLocalSocket; _attachedLocalSocket = newSocket; } else { delete _attachedPublicSocket; _attachedPublicSocket = newSocket; } } }
int NodeList::processDomainServerList(const QByteArray& packet) { // this is a packet from the domain server, reset the count of un-replied check-ins _numNoReplyDomainCheckIns = 0; // if this was the first domain-server list from this domain, we've now connected if (!_domainHandler.isConnected()) { _domainHandler.setUUID(uuidFromPacketHeader(packet)); _domainHandler.setIsConnected(true); } int readNodes = 0; // setup variables to read into from QDataStream qint8 nodeType; QUuid nodeUUID, connectionUUID; HifiSockAddr nodePublicSocket; HifiSockAddr nodeLocalSocket; QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); // pull our owner UUID from the packet, it's always the first thing QUuid newUUID; packetStream >> newUUID; setSessionUUID(newUUID); // pull each node in the packet while(packetStream.device()->pos() < packet.size()) { packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> 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(_domainHandler.getIP()); } SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket); packetStream >> connectionUUID; node->setConnectionSecret(connectionUUID); } // ping inactive nodes in conjunction with receipt of list from domain-server // this makes it happen every second and also pings any newly added nodes pingInactiveNodes(); return readNodes; }
void ModelItem::handleAddModelResponse(const QByteArray& packet) { const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(packet.data()); int numBytesPacketHeader = numBytesForPacketHeader(packet); dataAt += numBytesPacketHeader; uint32_t creatorTokenID; memcpy(&creatorTokenID, dataAt, sizeof(creatorTokenID)); dataAt += sizeof(creatorTokenID); uint32_t modelItemID; memcpy(&modelItemID, dataAt, sizeof(modelItemID)); dataAt += sizeof(modelItemID); // add our token to id mapping _tokenIDsToIDs[creatorTokenID] = modelItemID; }
void OctreeQueryNode::parseNackPacket(QByteArray& packet) { int numBytesPacketHeader = numBytesForPacketHeader(packet); const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(packet.data()) + numBytesPacketHeader; // read number of sequence numbers uint16_t numSequenceNumbers = (*(uint16_t*)dataAt); dataAt += sizeof(uint16_t); // read sequence numbers for (int i = 0; i < numSequenceNumbers; i++) { OCTREE_PACKET_SEQUENCE sequenceNumber = (*(OCTREE_PACKET_SEQUENCE*)dataAt); _nackedSequenceNumbers.enqueue(sequenceNumber); dataAt += sizeof(OCTREE_PACKET_SEQUENCE); } }
void EntityItemID::handleAddEntityResponse(const QByteArray& packet) { const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(packet.data()); int numBytesPacketHeader = numBytesForPacketHeader(packet); int bytesRead = numBytesPacketHeader; dataAt += numBytesPacketHeader; uint32_t creatorTokenID; memcpy(&creatorTokenID, dataAt, sizeof(creatorTokenID)); dataAt += sizeof(creatorTokenID); bytesRead += sizeof(creatorTokenID); QUuid entityID = QUuid::fromRfc4122(packet.mid(bytesRead, NUM_BYTES_RFC4122_UUID)); dataAt += NUM_BYTES_RFC4122_UUID; // add our token to id mapping _tokenIDsToIDs[creatorTokenID] = entityID; }
void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { NodeList* nodeList = NodeList::getInstance(); PACKET_TYPE packetType = dataByteArray[0]; if (packetType == getMyQueryMessageType()) { bool debug = false; if (debug) { qDebug("Got PACKET_TYPE_VOXEL_QUERY at %llu.\n", usecTimestampNow()); } int numBytesPacketHeader = numBytesForPacketHeader((unsigned char*) dataByteArray.data()); // If we got a PACKET_TYPE_VOXEL_QUERY, then we're talking to an NODE_TYPE_AVATAR, and we // need to make sure we have it in our nodeList. QUuid nodeUUID = QUuid::fromRfc4122(dataByteArray.mid(numBytesPacketHeader, NUM_BYTES_RFC4122_UUID)); Node* node = nodeList->nodeWithUUID(nodeUUID); if (node) { nodeList->updateNodeWithData(node, senderSockAddr, (unsigned char *) dataByteArray.data(), dataByteArray.size()); if (!node->getActiveSocket()) { // we don't have an active socket for this node, but they're talking to us // this means they've heard from us and can reply, let's assume public is active node->activatePublicSocket(); } OctreeQueryNode* nodeData = (OctreeQueryNode*) node->getLinkedData(); if (nodeData && !nodeData->isOctreeSendThreadInitalized()) { nodeData->initializeOctreeSendThread(this); } } } else if (packetType == PACKET_TYPE_JURISDICTION_REQUEST) { _jurisdictionSender->queueReceivedPacket(senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size()); } else if (_octreeInboundPacketProcessor && getOctree()->handlesEditPacketType(packetType)) { _octreeInboundPacketProcessor->queueReceivedPacket(senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size()); } else { // let processNodeData handle it. NodeList::getInstance()->processNodeData(senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size()); } }
void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode) { // deconstruct this ping packet to see if it is a public or local reply QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); quint8 pingType; packetStream >> pingType; // if this is a local or public ping then we can activate a socket // we do nothing with agnostic pings, those are simply for timing if (pingType == PingType::Local && sendingNode->getActiveSocket() != &sendingNode->getLocalSocket()) { sendingNode->activateLocalSocket(); } else if (pingType == PingType::Public && !sendingNode->getActiveSocket()) { sendingNode->activatePublicSocket(); } else if (pingType == PingType::Symmetric && !sendingNode->getActiveSocket()) { sendingNode->activateSymmetricSocket(); } }
Assignment* AssignmentFactory::unpackAssignment(const unsigned char* dataBuffer, int numBytes) { int headerBytes = numBytesForPacketHeader(dataBuffer); Assignment::Type assignmentType = Assignment::AllTypes; memcpy(&assignmentType, dataBuffer + headerBytes, sizeof(Assignment::Type)); switch (assignmentType) { case Assignment::AudioMixerType: return new AudioMixer(dataBuffer, numBytes); case Assignment::AvatarMixerType: return new AvatarMixer(dataBuffer, numBytes); case Assignment::AgentType: return new Agent(dataBuffer, numBytes); case Assignment::VoxelServerType: return new VoxelServer(dataBuffer, numBytes); default: return new Assignment(dataBuffer, numBytes); } }
int AudioMixerClientData::parseData(const QByteArray& packet) { PacketType packetType = packetTypeForPacket(packet); if (packetType == PacketTypeMicrophoneAudioWithEcho || packetType == PacketTypeMicrophoneAudioNoEcho || packetType == PacketTypeSilentAudioFrame) { // grab the AvatarAudioRingBuffer from the vector (or create it if it doesn't exist) AvatarAudioRingBuffer* avatarRingBuffer = getAvatarAudioRingBuffer(); if (!avatarRingBuffer) { // we don't have an AvatarAudioRingBuffer yet, so add it avatarRingBuffer = new AvatarAudioRingBuffer(); _ringBuffers.push_back(avatarRingBuffer); } // ask the AvatarAudioRingBuffer instance to parse the data avatarRingBuffer->parseData(packet); } else { // this is injected audio // grab the stream identifier for this injected audio QUuid streamIdentifier = QUuid::fromRfc4122(packet.mid(numBytesForPacketHeader(packet), NUM_BYTES_RFC4122_UUID)); InjectedAudioRingBuffer* matchingInjectedRingBuffer = NULL; for (unsigned int i = 0; i < _ringBuffers.size(); i++) { if (_ringBuffers[i]->getType() == PositionalAudioRingBuffer::Injector && ((InjectedAudioRingBuffer*) _ringBuffers[i])->getStreamIdentifier() == streamIdentifier) { matchingInjectedRingBuffer = (InjectedAudioRingBuffer*) _ringBuffers[i]; } } if (!matchingInjectedRingBuffer) { // we don't have a matching injected audio ring buffer, so add it matchingInjectedRingBuffer = new InjectedAudioRingBuffer(streamIdentifier); _ringBuffers.push_back(matchingInjectedRingBuffer); } matchingInjectedRingBuffer->parseData(packet); } return 0; }
// called on the other nodes - assigns it to my views of the others int OctreeQuery::parseData(const QByteArray& packet) { // increment to push past the packet header int numBytesPacketHeader = numBytesForPacketHeader(packet); const unsigned char* startPosition = reinterpret_cast<const unsigned char*>(packet.data()); const unsigned char* sourceBuffer = startPosition + numBytesPacketHeader; // camera details memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition)); sourceBuffer += sizeof(_cameraPosition); sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _cameraOrientation); sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_cameraFov); sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer,_cameraAspectRatio); sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraNearClip); sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip); memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition)); sourceBuffer += sizeof(_cameraEyeOffsetPosition); // voxel sending features... unsigned char bitItems = 0; bitItems = (unsigned char)*sourceBuffer++; _wantLowResMoving = oneAtBit(bitItems, WANT_LOW_RES_MOVING_BIT); _wantColor = oneAtBit(bitItems, WANT_COLOR_AT_BIT); _wantDelta = oneAtBit(bitItems, WANT_DELTA_AT_BIT); _wantOcclusionCulling = oneAtBit(bitItems, WANT_OCCLUSION_CULLING_BIT); _wantCompression = oneAtBit(bitItems, WANT_COMPRESSION); // desired Max Octree PPS memcpy(&_maxOctreePPS, sourceBuffer, sizeof(_maxOctreePPS)); sourceBuffer += sizeof(_maxOctreePPS); // desired _octreeElementSizeScale memcpy(&_octreeElementSizeScale, sourceBuffer, sizeof(_octreeElementSizeScale)); sourceBuffer += sizeof(_octreeElementSizeScale); // desired boundaryLevelAdjust memcpy(&_boundaryLevelAdjust, sourceBuffer, sizeof(_boundaryLevelAdjust)); sourceBuffer += sizeof(_boundaryLevelAdjust); return sourceBuffer - startPosition; }
void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec) { _incomingPacket++; _incomingBytes += packet.size(); if (!wasStatsPacket) { _incomingWastedBytes += (MAX_PACKET_SIZE - packet.size()); } int numBytesPacketHeader = numBytesForPacketHeader(packet); const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(packet.data()) + numBytesPacketHeader; //VOXEL_PACKET_FLAGS flags = (*(VOXEL_PACKET_FLAGS*)(dataAt)); dataAt += sizeof(OCTREE_PACKET_FLAGS); OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt); dataAt += sizeof(OCTREE_PACKET_SEQUENCE); OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt); dataAt += sizeof(OCTREE_PACKET_SENT_TIME); //bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT); //bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT); OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); int flightTime = arrivedAt - sentAt + nodeClockSkewUsec; const int USECS_PER_MSEC = 1000; float flightTimeMsecs = flightTime / USECS_PER_MSEC; _incomingFlightTimeAverage.updateAverage(flightTimeMsecs); // detect out of order packets if (sequence < _incomingLastSequence) { _incomingOutOfOrder++; } // detect likely lost packets OCTREE_PACKET_SEQUENCE expected = _incomingLastSequence+1; if (sequence > expected) { _incomingLikelyLost++; } _incomingLastSequence = sequence; }
QByteArray LimitedNodeList::constructPingReplyPacket(const QByteArray& pingPacket, const QUuid& packetHeaderID) { QDataStream pingPacketStream(pingPacket); pingPacketStream.skipRawData(numBytesForPacketHeader(pingPacket)); PingType_t typeFromOriginalPing; pingPacketStream >> typeFromOriginalPing; quint64 timeFromOriginalPing; pingPacketStream >> timeFromOriginalPing; PacketType replyType = (packetTypeForPacket(pingPacket) == PacketTypePing) ? PacketTypePingReply : PacketTypeUnverifiedPingReply; QByteArray replyPacket = byteArrayWithPopulatedHeader(replyType, packetHeaderID); QDataStream packetStream(&replyPacket, QIODevice::Append); packetStream << typeFromOriginalPing << timeFromOriginalPing << usecTimestampNow(); return replyPacket; }
void DataServerClient::processSendFromDataServer(const QByteArray& packet) { // pull the user string from the packet so we know who to associate this with QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); quint8 sequenceNumber = 0; packetStream >> sequenceNumber; if (_callbackObjects.find(sequenceNumber) != _callbackObjects.end()) { // remove the packet from our two maps, it's matched DataServerCallbackObject* callbackObject = _callbackObjects.take(sequenceNumber); _unmatchedPackets.remove(sequenceNumber); QString userString, keyListString, valueListString; packetStream >> userString >> keyListString >> valueListString; callbackObject->processDataServerResponse(userString, keyListString.split(MULTI_KEY_VALUE_SEPARATOR), valueListString.split(MULTI_KEY_VALUE_SEPARATOR)); }
void ParticleEditHandle::handleAddResponse(unsigned char* packetData , int packetLength) { unsigned char* dataAt = packetData; int numBytesPacketHeader = numBytesForPacketHeader(packetData); dataAt += numBytesPacketHeader; uint32_t creatorTokenID; memcpy(&creatorTokenID, dataAt, sizeof(creatorTokenID)); dataAt += sizeof(creatorTokenID); uint32_t particleID; memcpy(&particleID, dataAt, sizeof(particleID)); dataAt += sizeof(particleID); // find this particle in the _allHandles map if (_allHandles.find(creatorTokenID) != _allHandles.end()) { ParticleEditHandle* theHandle = _allHandles[creatorTokenID]; theHandle->_id = particleID; theHandle->_isKnownID = true; } }