示例#1
0
void LimitedNodeList::fillPacketHeader(const NLPacket& packet, const QUuid& connectionSecret) {
    if (!NON_SOURCED_PACKETS.contains(packet.getType())) {
        packet.writeSourceID(getSessionUUID());
    }
    
    if (!connectionSecret.isNull()
        && !NON_SOURCED_PACKETS.contains(packet.getType())
        && !NON_VERIFIED_PACKETS.contains(packet.getType())) {
        packet.writeVerificationHashGivenSecret(connectionSecret);
    }
}
示例#2
0
qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const HifiSockAddr& sockAddr,
                                             const QUuid& connectionSecret) {
    Q_ASSERT(!packet.isPartOfMessage());
    Q_ASSERT_X(!packet.isReliable(), "LimitedNodeList::sendUnreliablePacket",
               "Trying to send a reliable packet unreliably.");
    
    collectPacketStats(packet);
    fillPacketHeader(packet, connectionSecret);
    
    return _nodeSocket.writePacket(packet, sockAddr);
}
示例#3
0
qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const Node& destinationNode) {
    Q_ASSERT(!packet.isPartOfMessage());
    
    if (!destinationNode.getActiveSocket()) {
        return 0;
    }
    
    emit dataSent(destinationNode.getType(), packet.getDataSize());
    destinationNode.recordBytesSent(packet.getDataSize());
    
    return sendUnreliablePacket(packet, *destinationNode.getActiveSocket(), destinationNode.getConnectionSecret());
}
示例#4
0
qint64 LimitedNodeList::writePacket(const NLPacket& packet, const Node& destinationNode) {
    if (!destinationNode.getActiveSocket()) {
        return 0;
    }
    
    // TODO Move to transport layer when ready
    if (SEQUENCE_NUMBERED_PACKETS.contains(packet.getType())) {
        PacketSequenceNumber sequenceNumber = getNextSequenceNumberForPacket(destinationNode.getUUID(), packet.getType());
        const_cast<NLPacket&>(packet).writeSequenceNumber(sequenceNumber);
    }

    emit dataSent(destinationNode.getType(), packet.getDataSize());
    
    return writePacket(packet, *destinationNode.getActiveSocket(), destinationNode.getConnectionSecret());
}
示例#5
0
Assignment::Assignment(NLPacket& packet) :
    _pool(),
    _location(GlobalLocation),
    _payload(),
    _walletUUID(),
    _nodeVersion()
{
    if (packet.getType() == PacketType::RequestAssignment) {
        _command = Assignment::RequestCommand;
    } else if (packet.getType() == PacketType::CreateAssignment) {
        _command = Assignment::CreateCommand;
    }
    
    QDataStream packetStream(&packet);
    
    packetStream >> *this;
}
示例#6
0
void ReceivedMessage::appendPacket(NLPacket& packet) {
    Q_ASSERT_X(!_isComplete, "ReceivedMessage::appendPacket", 
               "We should not be appending to a complete message");

    // Limit progress signal to every X packets
    const int EMIT_PROGRESS_EVERY_X_PACKETS = 50;

    ++_numPackets;

    _data.append(packet.getPayload(), packet.getPayloadSize());

    if (_numPackets % EMIT_PROGRESS_EVERY_X_PACKETS == 0) {
        emit progress(getSize());
    }

    if (packet.getPacketPosition() == NLPacket::PacketPosition::LAST) {
        _isComplete = true;
        emit completed();
    }
}
示例#7
0
bool LimitedNodeList::packetSourceAndHashMatch(const NLPacket& packet, SharedNodePointer& matchingNode) {
    
    if (NON_SOURCED_PACKETS.contains(packet.getType())) {
        return true;
    } else {
        
        // figure out which node this is from
        matchingNode = nodeWithUUID(packet.getSourceID());
        
        if (matchingNode) {
            if (!NON_VERIFIED_PACKETS.contains(packet.getType())) {
                // check if the md5 hash in the header matches the hash we would expect
                if (packet.getVerificationHash() != packet.payloadHashWithConnectionUUID(matchingNode->getConnectionSecret())) {
                    static QMultiMap<QUuid, PacketType::Value> hashDebugSuppressMap;
                    
                    const QUuid& senderID = packet.getSourceID();

                    if (!hashDebugSuppressMap.contains(senderID, packet.getType())) {
                        qCDebug(networking) << "Packet hash mismatch on" << packet.getType() << "- Sender" << senderID;

                        hashDebugSuppressMap.insert(senderID, packet.getType());
                    }

                    return false;
                }
            }
            
            return true;
            
        } else {
            static QString repeatedMessage
                = LogHandler::getInstance().addRepeatedMessageRegex("Packet of type \\d+ \\([\\sa-zA-Z]+\\) received from unknown node with UUID");

            qCDebug(networking) << "Packet of type" << packet.getType() << "(" << qPrintable(nameForPacketType(packet.getType())) << ")"
                << "received from unknown node with UUID" << qPrintable(uuidStringWithoutCurlyBraces(packet.getSourceID()));
        }
    }

    return false;
}
示例#8
0
ReceivedMessage::ReceivedMessage(NLPacket& packet)
    : _data(packet.readAll()),
      _headData(_data.mid(0, HEAD_DATA_SIZE)),
      _numPackets(1),
      _sourceID(packet.getSourceID()),
      _packetType(packet.getType()),
      _packetVersion(packet.getVersion()),
      _senderSockAddr(packet.getSenderSockAddr()),
      _isComplete(packet.getPacketPosition() == NLPacket::ONLY)
{
}
示例#9
0
qint64 LimitedNodeList::writePacket(const NLPacket& packet, const HifiSockAddr& destinationSockAddr,
                                    const QUuid& connectionSecret) {
    if (!NON_SOURCED_PACKETS.contains(packet.getType())) {
        const_cast<NLPacket&>(packet).writeSourceID(getSessionUUID());
    }
    
    if (!connectionSecret.isNull()
        && !NON_SOURCED_PACKETS.contains(packet.getType())
        && !NON_VERIFIED_PACKETS.contains(packet.getType())) {
        const_cast<NLPacket&>(packet).writeVerificationHash(packet.payloadHashWithConnectionUUID(connectionSecret));
    }

    emit dataSent(NodeType::Unassigned, packet.getDataSize());
    
    return writeDatagram(QByteArray::fromRawData(packet.getData(), packet.getDataSize()), destinationSockAddr);
}
示例#10
0
void LimitedNodeList::collectPacketStats(const NLPacket& packet) {
    // stat collection for packets
    ++_numCollectedPackets;
    _numCollectedBytes += packet.getDataSize();
}
示例#11
0
int InboundAudioStream::parseData(NLPacket& packet) {

    // parse sequence number and track it
    quint16 sequence;
    packet.readPrimitive(&sequence);
    SequenceNumberStats::ArrivalInfo arrivalInfo = _incomingSequenceNumberStats.sequenceNumberReceived(sequence,
            packet.getSourceID());

    packetReceivedUpdateTimingStats();

    int networkSamples;

    // parse the info after the seq number and before the audio data (the stream properties)
    int prePropertyPosition = packet.pos();
    int propertyBytes = parseStreamProperties(packet.getType(), packet.read(packet.bytesLeftToRead()), networkSamples);
    packet.seek(prePropertyPosition + propertyBytes);

    // handle this packet based on its arrival status.
    switch (arrivalInfo._status) {
    case SequenceNumberStats::Early: {
        // Packet is early; write droppable silent samples for each of the skipped packets.
        // NOTE: we assume that each dropped packet contains the same number of samples
        // as the packet we just received.
        int packetsDropped = arrivalInfo._seqDiffFromExpected;
        writeSamplesForDroppedPackets(packetsDropped * networkSamples);

        // fall through to OnTime case
    }
    case SequenceNumberStats::OnTime: {
        // Packet is on time; parse its data to the ringbuffer
        if (packet.getType() == PacketType::SilentAudioFrame) {
            writeDroppableSilentSamples(networkSamples);
        } else {
            parseAudioData(packet.getType(), packet.read(packet.bytesLeftToRead()), networkSamples);
        }
        break;
    }
    default: {
        // For now, late packets are ignored.  It may be good in the future to insert the late audio packet data
        // into the ring buffer to fill in the missing frame if it hasn't been mixed yet.
        break;
    }
    }

    int framesAvailable = _ringBuffer.framesAvailable();
    // if this stream was starved, check if we're still starved.
    if (_isStarved && framesAvailable >= _desiredJitterBufferFrames) {
        _isStarved = false;
    }
    // if the ringbuffer exceeds the desired size by more than the threshold specified,
    // drop the oldest frames so the ringbuffer is down to the desired size.
    if (framesAvailable > _desiredJitterBufferFrames + _maxFramesOverDesired) {
        int framesToDrop = framesAvailable - (_desiredJitterBufferFrames + DESIRED_JITTER_BUFFER_FRAMES_PADDING);
        _ringBuffer.shiftReadPosition(framesToDrop * _ringBuffer.getNumFrameSamples());

        _framesAvailableStat.reset();
        _currentJitterBufferFrames = 0;

        _oldFramesDropped += framesToDrop;
    }

    framesAvailableChanged();

    return packet.pos();
}
int AudioMixerClientData::parseData(NLPacket& packet) {
    PacketType packetType = packet.getType();
    
    if (packetType == PacketType::AudioStreamStats) {

        // skip over header, appendFlag, and num stats packed
        packet.seek(sizeof(quint8) + sizeof(quint16));

        // read the downstream audio stream stats
        packet.readPrimitive(&_downstreamAudioStreamStats);

        return packet.pos();

    } else {
        PositionalAudioStream* matchingStream = NULL;

        if (packetType == PacketType::MicrophoneAudioWithEcho
            || packetType == PacketType::MicrophoneAudioNoEcho
            || packetType == PacketType::SilentAudioFrame) {

            QUuid nullUUID = QUuid();
            if (!_audioStreams.contains(nullUUID)) {
                // we don't have a mic stream yet, so add it

                // read the channel flag to see if our stream is stereo or not
                packet.seek(sizeof(quint16));

                quint8 channelFlag;
                packet.readPrimitive(&channelFlag);

                bool isStereo = channelFlag == 1;

                _audioStreams.insert(nullUUID, matchingStream = new AvatarAudioStream(isStereo, AudioMixer::getStreamSettings()));
            } else {
                matchingStream = _audioStreams.value(nullUUID);
            }
        } else if (packetType == PacketType::InjectAudio) {
            // this is injected audio

            // grab the stream identifier for this injected audio
            packet.seek(sizeof(quint16));
            QUuid streamIdentifier = QUuid::fromRfc4122(packet.readWithoutCopy(NUM_BYTES_RFC4122_UUID));

            bool isStereo;
            packet.readPrimitive(&isStereo);

            if (!_audioStreams.contains(streamIdentifier)) {
                // we don't have this injected stream yet, so add it
                _audioStreams.insert(streamIdentifier,
                        matchingStream = new InjectedAudioStream(streamIdentifier, isStereo, AudioMixer::getStreamSettings()));
            } else {
                matchingStream = _audioStreams.value(streamIdentifier);
            }
        }

        // seek to the beginning of the packet so that the next reader is in the right spot
        packet.seek(0);

        return matchingStream->parseData(packet);
    }
    return 0;
}