168 lines · 6.8 KB · C++
RawDownload
////  DataServerClient.cpp//  hifi////  Created by Stephen Birarda on 10/7/13.//  Copyright (c) 2013 HighFidelity, Inc. All rights reserved.// #include <QtCore/QUrl> #include <NodeList.h>#include <PacketHeaders.h>#include <UDPSocket.h>#include <UUID.h> #include "Application.h"#include "DataServerClient.h" QString DataServerClient::_clientUsername;std::map<unsigned char*, int> DataServerClient::_unmatchedPackets; const char DATA_SERVER_HOSTNAME[] = "127.0.0.1";const unsigned short DATA_SERVER_PORT = 3282;const sockaddr_in DATA_SERVER_SOCKET = socketForHostnameAndHostOrderPort(DATA_SERVER_HOSTNAME, DATA_SERVER_PORT); void DataServerClient::putValueForKey(const char* key, const char* value) {    if (!_clientUsername.isEmpty()) {        unsigned char* putPacket = new unsigned char[MAX_PACKET_SIZE];                // setup the header for this packet        int numPacketBytes = populateTypeAndVersion(putPacket, PACKET_TYPE_DATA_SERVER_PUT);                // pack the client UUID, null terminated        memcpy(putPacket + numPacketBytes, _clientUsername.toLocal8Bit().constData(), _clientUsername.toLocal8Bit().size());        numPacketBytes += _clientUsername.toLocal8Bit().size();        putPacket[numPacketBytes++] = '\0';                // pack the key, null terminated        strcpy((char*) putPacket + numPacketBytes, key);        numPacketBytes += strlen(key);        putPacket[numPacketBytes++] = '\0';                // pack the value, null terminated        strcpy((char*) putPacket + numPacketBytes, value);        numPacketBytes += strlen(value);        putPacket[numPacketBytes++] = '\0';                // add the putPacket to our vector of unconfirmed packets, will be deleted once put is confirmed        _unmatchedPackets.insert(std::pair<unsigned char*, int>(putPacket, numPacketBytes));                // send this put request to the data server        NodeList::getInstance()->getNodeSocket()->send((sockaddr*) &DATA_SERVER_SOCKET, putPacket, numPacketBytes);    }} void DataServerClient::getValueForKeyAndUUID(const char* key, QUuid &uuid) {    if (!uuid.isNull()) {        QString uuidString = uuidStringWithoutCurlyBraces(uuid);        getValueForKeyAndUserString(key, uuidString);    }} void DataServerClient::getValueForKeyAndUserString(const char* key, QString& userString) {    unsigned char getPacket[MAX_PACKET_SIZE];        // setup the header for this packet    int numPacketBytes = populateTypeAndVersion(getPacket, PACKET_TYPE_DATA_SERVER_GET);        // pack the user string (could be username or UUID string), null-terminate    memcpy(getPacket + numPacketBytes, userString.toLocal8Bit().constData(), userString.toLocal8Bit().size());    numPacketBytes += userString.toLocal8Bit().size();    getPacket[numPacketBytes++] = '\0';        // pack the key, null terminated    strcpy((char*) getPacket + numPacketBytes, key);    numPacketBytes += strlen(key);    getPacket[numPacketBytes++] = '\0';        // add the getPacket to our vector of uncofirmed packets, will be deleted once we get a response from the nameserver    _unmatchedPackets.insert(std::pair<unsigned char*, int>(getPacket, numPacketBytes));        // send the get to the data server    NodeList::getInstance()->getNodeSocket()->send((sockaddr*) &DATA_SERVER_SOCKET, getPacket, numPacketBytes);}   void DataServerClient::processConfirmFromDataServer(unsigned char* packetData, int numPacketBytes) {    removeMatchedPacketFromMap(packetData, numPacketBytes);} void DataServerClient::processSendFromDataServer(unsigned char* packetData, int numPacketBytes) {    // pull the user string from the packet so we know who to associate this with    int numHeaderBytes = numBytesForPacketHeader(packetData);            QString userString(QByteArray((char*) packetData + numHeaderBytes, strlen((char*) packetData + numHeaderBytes)));        QUuid userUUID(userString);        if (userUUID.isNull()) {        // the user string was a username        // for now assume this means that it is for our avatar                char* dataKeyPosition = (char*) packetData + numHeaderBytes + sizeof(userString);                if (strcmp(dataKeyPosition, DataServerKey::FaceMeshURL) == 0) {            // pull the user's face mesh and set it on the Avatar instance            char* faceMeshPosition = dataKeyPosition + strlen(dataKeyPosition) + sizeof(char);                QUrl faceMeshURL(QByteArray(faceMeshPosition,                                        numPacketBytes - ((unsigned char*) faceMeshPosition - packetData)));                        qDebug("Changing user's face model URL to %s\n", faceMeshURL.toString().toLocal8Bit().constData());            QMetaObject::invokeMethod(&Application::getInstance()->getAvatar()->getHead().getBlendFace(),                                      "setModelURL",                                      Q_ARG(QUrl, faceMeshURL));        }    } else {        // user string was UUID, find matching avatar and associate data            }        // remove the matched packet from  our map so it isn't re-sent to the data-server    removeMatchedPacketFromMap(packetData, numPacketBytes);} void DataServerClient::processMessageFromDataServer(unsigned char* packetData, int numPacketBytes) {    switch (packetData[0]) {        case PACKET_TYPE_DATA_SERVER_SEND:            processSendFromDataServer(packetData, numPacketBytes);            break;        case PACKET_TYPE_DATA_SERVER_CONFIRM:            processConfirmFromDataServer(packetData, numPacketBytes);            break;        default:            break;    }} void DataServerClient::removeMatchedPacketFromMap(unsigned char* packetData, int numPacketBytes) {    for  (std::map<unsigned char*, int>::iterator mapIterator = _unmatchedPackets.begin();          mapIterator != _unmatchedPackets.end();          ++mapIterator) {        if (memcmp(mapIterator->first + sizeof(PACKET_TYPE),                   packetData + sizeof(PACKET_TYPE),                   numPacketBytes - sizeof(PACKET_TYPE)) == 0) {                        // this is a match - remove the confirmed packet from the vector and delete associated member            // so it isn't sent back out            delete[] mapIterator->first;            _unmatchedPackets.erase(mapIterator);                        // we've matched the packet - bail out            break;        }    }} void DataServerClient::resendUnmatchedPackets() {    for  (std::map<unsigned char*, int>::iterator mapIterator = _unmatchedPackets.begin();          mapIterator != _unmatchedPackets.end();          ++mapIterator) {        // send the unmatched packet to the data server        NodeList::getInstance()->getNodeSocket()->send((sockaddr*) &DATA_SERVER_SOCKET,                                                       mapIterator->first,                                                       mapIterator->second);    }}