bool JurisdictionListener::queueJurisdictionRequest() {
    //qDebug() << "JurisdictionListener::queueJurisdictionRequest()\n";

    static unsigned char buffer[MAX_PACKET_SIZE];
    unsigned char* bufferOut = &buffer[0];
    ssize_t sizeOut = populateTypeAndVersion(bufferOut, PACKET_TYPE_JURISDICTION_REQUEST);
    int nodeCount = 0;

    NodeList* nodeList = NodeList::getInstance();
    for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
        if (nodeList->getNodeActiveSocketOrPing(&(*node)) &&
                node->getType() == getNodeType()) {
            const HifiSockAddr* nodeAddress = node->getActiveSocket();
            PacketSender::queuePacketForSending(*nodeAddress, bufferOut, sizeOut);
            nodeCount++;
        }
    }

    if (nodeCount > 0) {
        setPacketsPerSecond(nodeCount);
    } else {
        setPacketsPerSecond(NO_SERVER_CHECK_RATE);
    }

    // keep going if still running
    return isStillRunning();
}
bool VoxelEditPacketSender::voxelServersExist() const {
    bool hasVoxelServers = false;
    bool atLeastOnJurisdictionMissing = false; // assume the best
    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->getType() == NODE_TYPE_VOXEL_SERVER) {
            if (nodeList->getNodeActiveSocketOrPing(&(*node))) {
                QUuid nodeUUID = node->getUUID();
                // If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server
                if (_voxelServerJurisdictions) {
                    // lookup our nodeUUID in the jurisdiction map, if it's missing then we're 
                    // missing at least one jurisdiction
                    if ((*_voxelServerJurisdictions).find(nodeUUID) == (*_voxelServerJurisdictions).end()) {
                        atLeastOnJurisdictionMissing = true;
                    }
                }
                hasVoxelServers = true;
            }
        }
        if (atLeastOnJurisdictionMissing) {
            break; // no point in looking further...
        }
    }
    return (hasVoxelServers && !atLeastOnJurisdictionMissing);
}
// This method is called when the edit packet layer has determined that it has a fully formed packet destined for
// a known nodeID. However, we also want to handle the case where the 
void VoxelEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, ssize_t length) {
    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->getType() == NODE_TYPE_VOXEL_SERVER &&
            ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) {
            if (nodeList->getNodeActiveSocketOrPing(&(*node))) {
                sockaddr* nodeAddress = node->getActiveSocket();
                queuePacketForSending(*nodeAddress, buffer, length);
                
                // debugging output...
                bool wantDebugging = false;
                if (wantDebugging) {
                    int numBytesPacketHeader = numBytesForPacketHeader(buffer);
                    unsigned short int sequence = (*((unsigned short int*)(buffer + numBytesPacketHeader)));
                    uint64_t createdAt = (*((uint64_t*)(buffer + numBytesPacketHeader + sizeof(sequence))));
                    uint64_t queuedAt = usecTimestampNow();
                    uint64_t transitTime = queuedAt - createdAt;

                    const char* messageName;
                    switch (buffer[0]) {
                        case PACKET_TYPE_SET_VOXEL: 
                            messageName = "PACKET_TYPE_SET_VOXEL"; 
                            break;
                        case PACKET_TYPE_SET_VOXEL_DESTRUCTIVE: 
                            messageName = "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE"; 
                            break;
                        case PACKET_TYPE_ERASE_VOXEL: 
                            messageName = "PACKET_TYPE_ERASE_VOXEL"; 
                            break;
                    }
                    printf("VoxelEditPacketSender::queuePacketToNode() queued %s - command to node bytes=%ld sequence=%d transitTimeSoFar=%llu usecs\n",
                        messageName, length, sequence, transitTime);
                }                
            }
        }
    }
}
Exemple #4
0
void AudioInjector::injectAudio() {

    QByteArray soundByteArray = _sound->getByteArray();

    // make sure we actually have samples downloaded to inject
    if (soundByteArray.size()) {
        // give our sample byte array to the local audio interface, if we have it, so it can be handled locally
        if (_options.getLoopbackAudioInterface()) {
            // assume that localAudioInterface could be on a separate thread, use Qt::AutoConnection to handle properly
            QMetaObject::invokeMethod(_options.getLoopbackAudioInterface(), "handleAudioByteArray",
                                      Qt::AutoConnection,
                                      Q_ARG(QByteArray, soundByteArray));

        }

        NodeList* nodeList = NodeList::getInstance();

        // setup the packet for injected audio
        QByteArray injectAudioPacket = byteArrayWithPopluatedHeader(PacketTypeInjectAudio);
        QDataStream packetStream(&injectAudioPacket, QIODevice::Append);

        packetStream << QUuid::createUuid();

        // pack the flag for loopback
        uchar loopbackFlag = (uchar) (_options.getLoopbackAudioInterface() == NULL);
        packetStream << loopbackFlag;

        // pack the position for injected audio
        packetStream.writeRawData(reinterpret_cast<const char*>(&_options.getPosition()), sizeof(_options.getPosition()));

        // pack our orientation for injected audio
        packetStream.writeRawData(reinterpret_cast<const char*>(&_options.getOrientation()), sizeof(_options.getOrientation()));

        // pack zero for radius
        float radius = 0;
        packetStream << radius;

        // pack 255 for attenuation byte
        quint8 volume = MAX_INJECTOR_VOLUME * _options.getVolume();
        packetStream << volume;

        timeval startTime = {};
        gettimeofday(&startTime, NULL);
        int nextFrame = 0;

        int currentSendPosition = 0;

        int numPreAudioDataBytes = injectAudioPacket.size();

        // loop to send off our audio in NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL byte chunks
        while (currentSendPosition < soundByteArray.size()) {

            int bytesToCopy = std::min(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL,
                                       soundByteArray.size() - currentSendPosition);

            // resize the QByteArray to the right size
            injectAudioPacket.resize(numPreAudioDataBytes + bytesToCopy);

            // copy the next NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL bytes to the packet
            memcpy(injectAudioPacket.data() + numPreAudioDataBytes, soundByteArray.data() + currentSendPosition, bytesToCopy);

            // grab our audio mixer from the NodeList, if it exists
            SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);

            if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer.data())) {
                // send off this audio packet
                nodeList->getNodeSocket().writeDatagram(injectAudioPacket,
                                                        audioMixer->getActiveSocket()->getAddress(),
                                                        audioMixer->getActiveSocket()->getPort());
            }

            currentSendPosition += bytesToCopy;

            // send two packets before the first sleep so the mixer can start playback right away

            if (currentSendPosition != bytesToCopy && currentSendPosition < soundByteArray.size()) {
                // not the first packet and not done
                // sleep for the appropriate time
                int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow();

                if (usecToSleep > 0) {
                    usleep(usecToSleep);
                }
            }
        }
    }

    emit finished();
}