Пример #1
0
int numBytesArithmeticCodingFromBuffer(const char* checkValue) {
    if (((uchar) *checkValue) < 255) {
        return 1;
    } else {
        return 1 + numBytesArithmeticCodingFromBuffer(checkValue + 1);
    }
}
Пример #2
0
bool LimitedNodeList::packetVersionAndHashMatch(const QByteArray& packet) {
    PacketType checkType = packetTypeForPacket(packet);
    int numPacketTypeBytes = numBytesArithmeticCodingFromBuffer(packet.data());

    if (packet[numPacketTypeBytes] != versionForPacketType(checkType)
            && checkType != PacketTypeStunResponse) {
        PacketType mismatchType = packetTypeForPacket(packet);

        static QMultiMap<QUuid, PacketType> versionDebugSuppressMap;

        QUuid senderUUID = uuidFromPacketHeader(packet);
        if (!versionDebugSuppressMap.contains(senderUUID, checkType)) {
            qCDebug(networking) << "Packet version mismatch on" << packetTypeForPacket(packet) << "- Sender"
                                << uuidFromPacketHeader(packet) << "sent" << qPrintable(QString::number(packet[numPacketTypeBytes])) << "but"
                                << qPrintable(QString::number(versionForPacketType(mismatchType))) << "expected.";

            emit packetVersionMismatch();

            versionDebugSuppressMap.insert(senderUUID, checkType);
        }

        return false;
    }

    if (!NON_VERIFIED_PACKETS.contains(checkType)) {
        // figure out which node this is from
        SharedNodePointer sendingNode = sendingNodeForPacket(packet);
        if (sendingNode) {
            // check if the md5 hash in the header matches the hash we would expect
            if (hashFromPacketHeader(packet) == hashForPacketAndConnectionUUID(packet, sendingNode->getConnectionSecret())) {
                return true;
            } else {
                static QMultiMap<QUuid, PacketType> hashDebugSuppressMap;

                QUuid senderUUID = uuidFromPacketHeader(packet);
                if (!hashDebugSuppressMap.contains(senderUUID, checkType)) {
                    qCDebug(networking) << "Packet hash mismatch on" << checkType << "- Sender"
                                        << uuidFromPacketHeader(packet);

                    hashDebugSuppressMap.insert(senderUUID, checkType);
                }
            }
        } else {
            static QString repeatedMessage
                = LogHandler::getInstance().addRepeatedMessageRegex("Packet of type \\d+ received from unknown node with UUID");

            qCDebug(networking) << "Packet of type" << checkType << "received from unknown node with UUID"
                                << qPrintable(uuidStringWithoutCurlyBraces(uuidFromPacketHeader(packet)));
        }
    } else {
        return true;
    }

    return false;
}
Пример #3
0
void DataServer::readPendingDatagrams() {
    QByteArray receivedPacket;
    HifiSockAddr senderSockAddr;
    
    while (_socket.hasPendingDatagrams()) {
        receivedPacket.resize(_socket.pendingDatagramSize());
        _socket.readDatagram(receivedPacket.data(), _socket.pendingDatagramSize(),
                             senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
        
        PacketType requestType = packetTypeForPacket(receivedPacket);
        
        if ((requestType == PacketTypeDataServerPut || requestType == PacketTypeDataServerGet) &&
            receivedPacket[numBytesArithmeticCodingFromBuffer(receivedPacket.data())] == versionForPacketType(requestType)) {
            
            QDataStream packetStream(receivedPacket);
            int numReceivedHeaderBytes = numBytesForPacketHeader(receivedPacket);
            packetStream.skipRawData(numReceivedHeaderBytes);
            
            // pull the sequence number used for this packet
            quint8 sequenceNumber = 0;
            
            packetStream >> sequenceNumber;
            
            // pull the UUID that we will need as part of the key
            QString userString;
            packetStream >> userString;
            QUuid parsedUUID(userString);
            
            if (parsedUUID.isNull()) {
                // we failed to parse a UUID, this means the user has sent us a username
                
                // ask redis for the UUID for this user
                redisReply* reply = (redisReply*) redisCommand(_redis, "GET user:%s", qPrintable(userString));
                
                if (reply->type == REDIS_REPLY_STRING) {
                    parsedUUID = QUuid(QString(reply->str));
                }
                
                if (!parsedUUID.isNull()) {
                    qDebug() << "Found UUID" << parsedUUID << "for username" << userString;
                } else {
                    qDebug() << "Failed UUID lookup for username" << userString;
                }
                
                freeReplyObject(reply);
                reply = NULL;
            }
            
            if (!parsedUUID.isNull()) {
                if (requestType == PacketTypeDataServerPut) {
                    
                    // pull the key and value that specifies the data the user is putting/getting
                    QString dataKey, dataValue;
                    
                    packetStream >> dataKey >> dataValue;
                    
                    qDebug("Sending command to redis: SET uuid:%s:%s %s",
                           qPrintable(uuidStringWithoutCurlyBraces(parsedUUID)),
                           qPrintable(dataKey), qPrintable(dataValue));
                    
                    redisReply* reply = (redisReply*) redisCommand(_redis, "SET uuid:%s:%s %s",
                                                                   qPrintable(uuidStringWithoutCurlyBraces(parsedUUID)),
                                                                   qPrintable(dataKey), qPrintable(dataValue));
                    
                    if (reply->type == REDIS_REPLY_STATUS && strcmp("OK", reply->str) == 0) {
                        // if redis stored the value successfully reply back with a confirm
                        // which is a reply packet with the sequence number
                        QByteArray replyPacket = byteArrayWithPopluatedHeader(PacketTypeDataServerConfirm, _uuid);
                        
                        replyPacket.append(sequenceNumber);
                        
                        _socket.writeDatagram(replyPacket, senderSockAddr.getAddress(), senderSockAddr.getPort());
                    }
                    
                    freeReplyObject(reply);
                } else {
                    // setup a send packet with the returned data
                    // leverage the packetData sent by overwriting and appending
                    QByteArray sendPacket = byteArrayWithPopluatedHeader(PacketTypeDataServerSend, _uuid);
                    QDataStream sendPacketStream(&sendPacket, QIODevice::Append);
                    
                    sendPacketStream << sequenceNumber;
                    
                    // pull the key list that specifies the data the user is putting/getting
                    QString keyListString;
                    packetStream >> keyListString;
                    
                    if (keyListString != "uuid") {
                        
                        // copy the parsed UUID
                        sendPacketStream << uuidStringWithoutCurlyBraces(parsedUUID);
                        
                        const char MULTI_KEY_VALUE_SEPARATOR = '|';
                        
                        // append the keyListString back to the sendPacket
                        sendPacketStream << keyListString;
                        
                        QStringList keyList = keyListString.split(MULTI_KEY_VALUE_SEPARATOR);
                        QStringList valueList;
                        
                        foreach (const QString& dataKey, keyList) {
                            qDebug("Sending command to redis: GET uuid:%s:%s",
                                   qPrintable(uuidStringWithoutCurlyBraces(parsedUUID)),
                                   qPrintable(dataKey));
                            redisReply* reply = (redisReply*) redisCommand(_redis, "GET uuid:%s:%s",
                                                                           qPrintable(uuidStringWithoutCurlyBraces(parsedUUID)),
                                                                           qPrintable(dataKey));
                            
                            if (reply->len) {
                                // copy the value that redis returned
                                valueList << QString(reply->str);
                            } else {
                                // didn't find a value - insert a space
                                valueList << QChar(' ');
                            }
                            
                            freeReplyObject(reply);
                        }
                        
                        // append the value QStringList using the right separator
                        sendPacketStream << valueList.join(MULTI_KEY_VALUE_SEPARATOR);
                    } else {
Пример #4
0
QUuid uuidFromPacketHeader(const QByteArray& packet) {
    return QUuid::fromRfc4122(packet.mid(numBytesArithmeticCodingFromBuffer(packet.data()) + sizeof(PacketVersion),
                                         NUM_BYTES_RFC4122_UUID));
}
Пример #5
0
int numBytesForPacketHeader(const char* packet) {
    // returns the number of bytes used for the type, version, and UUID
    return numBytesArithmeticCodingFromBuffer(packet) + NUM_STATIC_HEADER_BYTES;
}
Пример #6
0
int numBytesForPacketHeader(const QByteArray& packet) {
    // returns the number of bytes used for the type, version, and UUID
    return numBytesArithmeticCodingFromBuffer(packet.data())
    + numHashBytesInPacketHeaderGivenPacketType(packetTypeForPacket(packet))
    + NUM_STATIC_HEADER_BYTES;
}
Пример #7
0
int numBytesForPacketHeader(const QByteArray& packet) {
    // returns the number of bytes used for the type, version, and UUID
    return numBytesArithmeticCodingFromBuffer(packet.data()) + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;
}
Пример #8
0
void deconstructPacketHeader(const QByteArray& packet, QUuid& senderUUID) {
    senderUUID = QUuid::fromRfc4122(packet.mid(numBytesArithmeticCodingFromBuffer(packet.data()) + sizeof(PacketVersion),
                                               NUM_BYTES_RFC4122_UUID));
}