void AudioMixer::readPendingDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) { NodeList* nodeList = NodeList::getInstance(); if (nodeList->packetVersionAndHashMatch(receivedPacket)) { // pull any new audio data from nodes off of the network stack PacketType mixerPacketType = packetTypeForPacket(receivedPacket); if (mixerPacketType == PacketTypeMicrophoneAudioNoEcho || mixerPacketType == PacketTypeMicrophoneAudioWithEcho || mixerPacketType == PacketTypeInjectAudio || mixerPacketType == PacketTypeSilentAudioFrame || mixerPacketType == PacketTypeAudioStreamStats) { nodeList->findNodeAndUpdateWithDataFromPacket(receivedPacket); } else if (mixerPacketType == PacketTypeMuteEnvironment) { QByteArray packet = receivedPacket; populatePacketHeader(packet, PacketTypeMuteEnvironment); foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getType() == NodeType::Agent && node->getActiveSocket() && node->getLinkedData() && node != nodeList->sendingNodeForPacket(receivedPacket)) { nodeList->writeDatagram(packet, packet.size(), node); } } } else {
void Agent::readPendingDatagrams() { QByteArray receivedPacket; HifiSockAddr senderSockAddr; NodeList* nodeList = NodeList::getInstance(); while (readAvailableDatagram(receivedPacket, senderSockAddr)) { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { PacketType datagramPacketType = packetTypeForPacket(receivedPacket); if (datagramPacketType == PacketTypeJurisdiction) { int headerBytes = numBytesForPacketHeader(receivedPacket); SharedNodePointer matchedNode = nodeList->sendingNodeForPacket(receivedPacket); if (matchedNode) { // PacketType_JURISDICTION, first byte is the node type... switch (receivedPacket[headerBytes]) { case NodeType::VoxelServer: _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()-> queueReceivedPacket(matchedNode,receivedPacket); break; case NodeType::ParticleServer: _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()-> queueReceivedPacket(matchedNode, receivedPacket); break; case NodeType::ModelServer: _scriptEngine.getModelsScriptingInterface()->getJurisdictionListener()-> queueReceivedPacket(matchedNode, receivedPacket); break; } } } else if (datagramPacketType == PacketTypeParticleAddResponse) { // this will keep creatorTokenIDs to IDs mapped correctly Particle::handleAddParticleResponse(receivedPacket); // also give our local particle tree a chance to remap any internal locally created particles _particleViewer.getTree()->handleAddParticleResponse(receivedPacket); // Make sure our Node and NodeList knows we've heard from this node. SharedNodePointer sourceNode = nodeList->sendingNodeForPacket(receivedPacket); sourceNode->setLastHeardMicrostamp(usecTimestampNow()); } else if (datagramPacketType == PacketTypeModelAddResponse) { // this will keep creatorTokenIDs to IDs mapped correctly ModelItem::handleAddModelResponse(receivedPacket); // also give our local particle tree a chance to remap any internal locally created particles _modelViewer.getTree()->handleAddModelResponse(receivedPacket); // Make sure our Node and NodeList knows we've heard from this node. SharedNodePointer sourceNode = nodeList->sendingNodeForPacket(receivedPacket); sourceNode->setLastHeardMicrostamp(usecTimestampNow()); } else if (datagramPacketType == PacketTypeParticleData || datagramPacketType == PacketTypeParticleErase || datagramPacketType == PacketTypeOctreeStats || datagramPacketType == PacketTypeVoxelData || datagramPacketType == PacketTypeModelData || datagramPacketType == PacketTypeModelErase ) { // Make sure our Node and NodeList knows we've heard from this node. SharedNodePointer sourceNode = nodeList->sendingNodeForPacket(receivedPacket); sourceNode->setLastHeardMicrostamp(usecTimestampNow()); QByteArray mutablePacket = receivedPacket; int messageLength = mutablePacket.size(); if (datagramPacketType == PacketTypeOctreeStats) { int statsMessageLength = OctreeHeadlessViewer::parseOctreeStats(mutablePacket, sourceNode); if (messageLength > statsMessageLength) { mutablePacket = mutablePacket.mid(statsMessageLength); // TODO: this needs to be fixed, the goal is to test the packet version for the piggyback, but // this is testing the version and hash of the original packet // need to use numBytesArithmeticCodingFromBuffer()... if (!NodeList::getInstance()->packetVersionAndHashMatch(receivedPacket)) { return; // bail since piggyback data doesn't match our versioning } } else { return; // bail since no piggyback data } datagramPacketType = packetTypeForPacket(mutablePacket); } // fall through to piggyback message if (datagramPacketType == PacketTypeParticleData || datagramPacketType == PacketTypeParticleErase) { _particleViewer.processDatagram(mutablePacket, sourceNode); } if (datagramPacketType == PacketTypeModelData || datagramPacketType == PacketTypeModelErase) { _modelViewer.processDatagram(mutablePacket, sourceNode); } if (datagramPacketType == PacketTypeVoxelData) { _voxelViewer.processDatagram(mutablePacket, sourceNode); } } else if (datagramPacketType == PacketTypeMixedAudio || datagramPacketType == PacketTypeSilentAudioFrame) { _receivedAudioStream.parseData(receivedPacket); _lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness(); _receivedAudioStream.clearBuffer(); // let this continue through to the NodeList so it updates last heard timestamp // for the sending audio mixer NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); } else if (datagramPacketType == PacketTypeBulkAvatarData || datagramPacketType == PacketTypeAvatarIdentity || datagramPacketType == PacketTypeAvatarBillboard || datagramPacketType == PacketTypeKillAvatar) { // let the avatar hash map process it _avatarHashMap.processAvatarMixerDatagram(receivedPacket, nodeList->sendingNodeForPacket(receivedPacket)); // let this continue through to the NodeList so it updates last heard timestamp // for the sending avatar-mixer NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); } else { NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); } } } }
void DatagramProcessor::processDatagrams() { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "DatagramProcessor::processDatagrams()"); HifiSockAddr senderSockAddr; static QByteArray incomingPacket; Application* application = Application::getInstance(); NodeList* nodeList = NodeList::getInstance(); while (NodeList::getInstance()->getNodeSocket().hasPendingDatagrams()) { incomingPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); nodeList->getNodeSocket().readDatagram(incomingPacket.data(), incomingPacket.size(), senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); _packetCount++; _byteCount += incomingPacket.size(); if (nodeList->packetVersionAndHashMatch(incomingPacket)) { // only process this packet if we have a match on the packet version switch (packetTypeForPacket(incomingPacket)) { case PacketTypeTransmitterData: // V2 = IOS transmitter app application->getAvatar()->getTransmitter().processIncomingData(reinterpret_cast<unsigned char*>(incomingPacket.data()), incomingPacket.size()); break; case PacketTypeMixedAudio: QMetaObject::invokeMethod(&application->_audio, "addReceivedAudioToBuffer", Qt::QueuedConnection, Q_ARG(QByteArray, incomingPacket)); break; case PacketTypeParticleAddResponse: // this will keep creatorTokenIDs to IDs mapped correctly Particle::handleAddParticleResponse(incomingPacket); application->getParticles()->getTree()->handleAddParticleResponse(incomingPacket); break; case PacketTypeParticleData: case PacketTypeParticleErase: case PacketTypeVoxelData: case PacketTypeVoxelErase: case PacketTypeOctreeStats: case PacketTypeEnvironmentData: { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::networkReceive()... _voxelProcessor.queueReceivedPacket()"); bool wantExtraDebugging = application->getLogger()->extraDebugging(); if (wantExtraDebugging && packetTypeForPacket(incomingPacket) == PacketTypeVoxelData) { int numBytesPacketHeader = numBytesForPacketHeader(incomingPacket); unsigned char* dataAt = reinterpret_cast<unsigned char*>(incomingPacket.data()) + numBytesPacketHeader; 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); OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); int flightTime = arrivedAt - sentAt; printf("got PacketType_VOXEL_DATA, sequence:%d flightTime:%d\n", sequence, flightTime); } SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(incomingPacket); if (matchedNode) { // add this packet to our list of voxel packets and process them on the voxel processing application->_voxelProcessor.queueReceivedPacket(matchedNode, incomingPacket); } break; } case PacketTypeMetavoxelData: nodeList->findNodeAndUpdateWithDataFromPacket(incomingPacket); break; case PacketTypeBulkAvatarData: case PacketTypeKillAvatar: case PacketTypeAvatarIdentity: case PacketTypeAvatarBillboard: { // update having heard from the avatar-mixer and record the bytes received SharedNodePointer avatarMixer = nodeList->sendingNodeForPacket(incomingPacket); if (avatarMixer) { avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); avatarMixer->recordBytesReceived(incomingPacket.size()); QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram", Q_ARG(const QByteArray&, incomingPacket), Q_ARG(const QWeakPointer<Node>&, avatarMixer)); } application->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(incomingPacket.size()); break; } case PacketTypeDataServerGet: case PacketTypeDataServerPut: case PacketTypeDataServerSend: case PacketTypeDataServerConfirm: DataServerClient::processMessageFromDataServer(incomingPacket); break; default: nodeList->processNodeData(senderSockAddr, incomingPacket); break; } } } }
void DatagramProcessor::processDatagrams() { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "DatagramProcessor::processDatagrams()"); HifiSockAddr senderSockAddr; static QByteArray incomingPacket; Application* application = Application::getInstance(); NodeList* nodeList = NodeList::getInstance(); while (NodeList::getInstance()->getNodeSocket().hasPendingDatagrams()) { incomingPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); nodeList->getNodeSocket().readDatagram(incomingPacket.data(), incomingPacket.size(), senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); _packetCount++; _byteCount += incomingPacket.size(); if (nodeList->packetVersionAndHashMatch(incomingPacket)) { PacketType incomingType = packetTypeForPacket(incomingPacket); // only process this packet if we have a match on the packet version switch (incomingType) { case PacketTypeAudioEnvironment: case PacketTypeAudioStreamStats: case PacketTypeMixedAudio: case PacketTypeSilentAudioFrame: { if (incomingType == PacketTypeAudioStreamStats) { QMetaObject::invokeMethod(&application->_audio, "parseAudioStreamStatsPacket", Qt::QueuedConnection, Q_ARG(QByteArray, incomingPacket)); } else if (incomingType == PacketTypeAudioEnvironment) { QMetaObject::invokeMethod(&application->_audio, "parseAudioEnvironmentData", Qt::QueuedConnection, Q_ARG(QByteArray, incomingPacket)); } else { QMetaObject::invokeMethod(&application->_audio, "addReceivedAudioToStream", Qt::QueuedConnection, Q_ARG(QByteArray, incomingPacket)); } // update having heard from the audio-mixer and record the bytes received SharedNodePointer audioMixer = nodeList->sendingNodeForPacket(incomingPacket); if (audioMixer) { audioMixer->setLastHeardMicrostamp(usecTimestampNow()); audioMixer->recordBytesReceived(incomingPacket.size()); } break; } case PacketTypeEntityAddResponse: // this will keep creatorTokenIDs to IDs mapped correctly EntityItemID::handleAddEntityResponse(incomingPacket); application->getEntities()->getTree()->handleAddEntityResponse(incomingPacket); break; case PacketTypeEntityData: case PacketTypeEntityErase: case PacketTypeVoxelData: case PacketTypeVoxelErase: case PacketTypeOctreeStats: case PacketTypeEnvironmentData: { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::networkReceive()... _octreeProcessor.queueReceivedPacket()"); bool wantExtraDebugging = application->getLogger()->extraDebugging(); if (wantExtraDebugging && packetTypeForPacket(incomingPacket) == PacketTypeVoxelData) { int numBytesPacketHeader = numBytesForPacketHeader(incomingPacket); unsigned char* dataAt = reinterpret_cast<unsigned char*>(incomingPacket.data()) + numBytesPacketHeader; 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); OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); int flightTime = arrivedAt - sentAt; qDebug("got an Octree data or erase message, sequence:%d flightTime:%d", sequence, flightTime); } SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(incomingPacket); if (matchedNode) { // add this packet to our list of voxel packets and process them on the voxel processing application->_octreeProcessor.queueReceivedPacket(matchedNode, incomingPacket); } break; } case PacketTypeMetavoxelData: nodeList->findNodeAndUpdateWithDataFromPacket(incomingPacket); break; case PacketTypeBulkAvatarData: case PacketTypeKillAvatar: case PacketTypeAvatarIdentity: case PacketTypeAvatarBillboard: { // update having heard from the avatar-mixer and record the bytes received SharedNodePointer avatarMixer = nodeList->sendingNodeForPacket(incomingPacket); if (avatarMixer) { avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); avatarMixer->recordBytesReceived(incomingPacket.size()); QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram", Q_ARG(const QByteArray&, incomingPacket), Q_ARG(const QWeakPointer<Node>&, avatarMixer)); } application->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(incomingPacket.size()); break; } case PacketTypeDomainConnectionDenied: { // output to the log so the user knows they got a denied connection request // and check and signal for an access token so that we can make sure they are logged in qDebug() << "The domain-server denied a connection request."; qDebug() << "You may need to re-log to generate a keypair so you can provide a username signature."; AccountManager::getInstance().checkAndSignalForAccessToken(); break; } case PacketTypeNoisyMute: case PacketTypeMuteEnvironment: { bool mute = !Application::getInstance()->getAudio()->getMuted(); if (incomingType == PacketTypeMuteEnvironment) { glm::vec3 position; float radius, distance; int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment); memcpy(&position, incomingPacket.constData() + headerSize, sizeof(glm::vec3)); memcpy(&radius, incomingPacket.constData() + headerSize + sizeof(glm::vec3), sizeof(float)); distance = glm::distance(Application::getInstance()->getAvatar()->getPosition(), position); mute = mute && (distance < radius); } if (mute) { Application::getInstance()->getAudio()->toggleMute(); if (incomingType == PacketTypeMuteEnvironment) { AudioScriptingInterface::getInstance().environmentMuted(); } else { AudioScriptingInterface::getInstance().mutedByMixer(); } } break; } case PacketTypeVoxelEditNack: if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) { application->_voxelEditSender.processNackPacket(incomingPacket); } break; case PacketTypeEntityEditNack: if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) { application->_entityEditSender.processNackPacket(incomingPacket); } break; default: nodeList->processNodeData(senderSockAddr, incomingPacket); break; } } }
void DatagramProcessor::processDatagrams() { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "DatagramProcessor::processDatagrams()"); HifiSockAddr senderSockAddr; static QByteArray incomingPacket; Application* application = Application::getInstance(); NodeList* nodeList = NodeList::getInstance(); while (NodeList::getInstance()->getNodeSocket().hasPendingDatagrams()) { incomingPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); nodeList->getNodeSocket().readDatagram(incomingPacket.data(), incomingPacket.size(), senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); _packetCount++; _byteCount += incomingPacket.size(); if (nodeList->packetVersionAndHashMatch(incomingPacket)) { // only process this packet if we have a match on the packet version switch (packetTypeForPacket(incomingPacket)) { case PacketTypeMixedAudio: case PacketTypeSilentAudioFrame: QMetaObject::invokeMethod(&application->_audio, "addReceivedAudioToStream", Qt::QueuedConnection, Q_ARG(QByteArray, incomingPacket)); break; case PacketTypeAudioStreamStats: QMetaObject::invokeMethod(&application->_audio, "parseAudioStreamStatsPacket", Qt::QueuedConnection, Q_ARG(QByteArray, incomingPacket)); break; case PacketTypeParticleAddResponse: // this will keep creatorTokenIDs to IDs mapped correctly Particle::handleAddParticleResponse(incomingPacket); application->getParticles()->getTree()->handleAddParticleResponse(incomingPacket); break; case PacketTypeModelAddResponse: // this will keep creatorTokenIDs to IDs mapped correctly ModelItem::handleAddModelResponse(incomingPacket); application->getModels()->getTree()->handleAddModelResponse(incomingPacket); break; case PacketTypeParticleData: case PacketTypeParticleErase: case PacketTypeModelData: case PacketTypeModelErase: case PacketTypeVoxelData: case PacketTypeVoxelErase: case PacketTypeOctreeStats: case PacketTypeEnvironmentData: { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::networkReceive()... _octreeProcessor.queueReceivedPacket()"); bool wantExtraDebugging = application->getLogger()->extraDebugging(); if (wantExtraDebugging && packetTypeForPacket(incomingPacket) == PacketTypeVoxelData) { int numBytesPacketHeader = numBytesForPacketHeader(incomingPacket); unsigned char* dataAt = reinterpret_cast<unsigned char*>(incomingPacket.data()) + numBytesPacketHeader; 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); OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); int flightTime = arrivedAt - sentAt; qDebug("got PacketType_VOXEL_DATA, sequence:%d flightTime:%d", sequence, flightTime); } SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(incomingPacket); if (matchedNode) { // add this packet to our list of voxel packets and process them on the voxel processing application->_octreeProcessor.queueReceivedPacket(matchedNode, incomingPacket); } break; } case PacketTypeMetavoxelData: nodeList->findNodeAndUpdateWithDataFromPacket(incomingPacket); break; case PacketTypeBulkAvatarData: case PacketTypeKillAvatar: case PacketTypeAvatarIdentity: case PacketTypeAvatarBillboard: { // update having heard from the avatar-mixer and record the bytes received SharedNodePointer avatarMixer = nodeList->sendingNodeForPacket(incomingPacket); if (avatarMixer) { avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); avatarMixer->recordBytesReceived(incomingPacket.size()); QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram", Q_ARG(const QByteArray&, incomingPacket), Q_ARG(const QWeakPointer<Node>&, avatarMixer)); } application->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(incomingPacket.size()); break; } case PacketTypeDomainOAuthRequest: { QDataStream readStream(incomingPacket); readStream.skipRawData(numBytesForPacketHeader(incomingPacket)); QUrl authorizationURL; readStream >> authorizationURL; QMetaObject::invokeMethod(&OAuthWebViewHandler::getInstance(), "displayWebviewForAuthorizationURL", Q_ARG(const QUrl&, authorizationURL)); break; } case PacketTypeMuteEnvironment: { glm::vec3 position; float radius; int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment); memcpy(&position, incomingPacket.constData() + headerSize, sizeof(glm::vec3)); memcpy(&radius, incomingPacket.constData() + headerSize + sizeof(glm::vec3), sizeof(float)); if (glm::distance(Application::getInstance()->getAvatar()->getPosition(), position) < radius && !Application::getInstance()->getAudio()->getMuted()) { Application::getInstance()->getAudio()->toggleMute(); } break; } case PacketTypeVoxelEditNack: if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) { application->_voxelEditSender.processNackPacket(incomingPacket); } break; case PacketTypeParticleEditNack: if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) { application->_particleEditSender.processNackPacket(incomingPacket); } break; case PacketTypeModelEditNack: if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) { application->_modelEditSender.processNackPacket(incomingPacket); } break; default: nodeList->processNodeData(senderSockAddr, incomingPacket); break; } } } }