Esempio n. 1
0
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;
}
Esempio n. 2
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);
}
Esempio n. 3
0
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);
        }
    }
}
Esempio n. 4
0
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);
    }
}
Esempio n. 5
0
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);
            }
        }
    }
}
Esempio n. 6
0
// 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";
                }
            }
        }
    }
}
Esempio n. 7
0
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();
    }
}
Esempio n. 8
0
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);
            }
        }
    }
}
Esempio n. 9
0
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();
}
Esempio n. 10
0
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;
    }
}
Esempio n. 11
0
// 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;
}
Esempio n. 13
0
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);
    }
}
Esempio n. 14
0
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);
    }
}
Esempio n. 15
0
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);
        }
    }
}
Esempio n. 16
0
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;
        }
    }
}
Esempio n. 17
0
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;
        }
    }
}
Esempio n. 18
0
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;
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
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);
    }
}
Esempio n. 21
0
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;
}
Esempio n. 22
0
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());
    }
}
Esempio n. 23
0
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();
    }
}
Esempio n. 24
0
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);
    }
}
Esempio n. 25
0
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;
}
Esempio n. 26
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;
}
Esempio n. 27
0
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;
}
Esempio n. 28
0
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;
}
Esempio n. 29
0
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));
    }
Esempio n. 30
0
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;
    }
}