<commit_before>#include "client.h"
#include "discovery.h"
#include "requests.h"
#include "networkhelper.h"

#include <QUdpSocket>
#include <QBuffer>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QTimer>
#include <QHostInfo>
#include <QDataStream>

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#else
#ifdef Q_OS_WIN
#include <QJson/Parser>
#else
#include <qjson/parser.h>
#endif
#endif

#include <QDebug>

const QUrl masterUrl = QUrl("http://mplane.informatik.hs-augsburg.de:16001");

class Client::Private : public QObject
{
    Q_OBJECT

public:
    Private(Client* q)
    : q(q)
    , status(Client::Unregistered)
    , networkAccessManager(new QNetworkAccessManager(q))
    {
        connect(&discovery, SIGNAL(finished()), this, SLOT(onDiscoveryFinished()));
        connect(&managerSocket, SIGNAL(readyRead()), this, SLOT(onDatagramReady()));
        connect(&aliveTimer, SIGNAL(timeout()), this, SLOT(onAliveTimer()));

        scheduler.setManagerSocket(&managerSocket);

        aliveTimer.setInterval(20 * 1000);
        aliveTimer.start();
    }

    Client* q;

    // Properties
    Client::Status status;
    QNetworkAccessManager* networkAccessManager;
    Discovery discovery;
    QUdpSocket managerSocket;
    QTimer aliveTimer;
    QHostInfo aliveInfo;

    TestScheduler scheduler;
    Settings settings;

    QHostAddress lastLocalIp;

    // Functions
    void setStatus(Client::Status status);

    void processDatagram(const QByteArray &datagram, const QHostAddress& host, quint16 port);
    void processClientInfoRequest();
    void processPeerRequest();

    void sendClientInfo();
    void sendPeerResponse(const QHostAddress &host, quint16 port);
    void sendPeerRequest(bool manual = false);

public slots:
    void onDatagramReady();
    void onLookupFinished(const QHostInfo &host);
    void onAliveTimer();
    void onDiscoveryFinished();

    void onRegisterFinished();
    void onRegisterError(QNetworkReply::NetworkError error);

    void onPeerRequestFinished();
    void onPeerRequestError(QNetworkReply::NetworkError error);
};

void Client::Private::setStatus(Client::Status status)
{
    if ( this->status == status )
        return;

    this->status = status;
    emit q->statusChanged();
}

void Client::Private::processDatagram(const QByteArray& datagram, const QHostAddress &host, quint16 port)
{
    // Master server
    if ( aliveInfo.addresses().contains(host) ) {
        const RequestType* type = (const RequestType*)datagram.constData();

        qDebug() << Q_FUNC_INFO << *type;

        switch(*type) {
        case ClientInfoRequest:
            processClientInfoRequest();
            break;

        case PeerRequest:
            sendPeerRequest();
            break;

        case RegisteredClientResponse:
            setStatus(Client::Registered);
            break;

        default:
            qDebug() << "Received unknown request from master" << host.toString() << port;
        }
    } else {
        AbstractTest* currentTest = scheduler.currentTest();
        if ( currentTest ) {
            currentTest->processDatagram(datagram, host, port);
        } else {
            const RequestType* type = (const RequestType*)datagram.constData();

            switch(*type) {
            case PeerResponse:
                qDebug() << "Received peer response from" << host.toString() << port;
                break;

            default:
                qDebug() << "Received invalid datagram from" << host.toString() << port;
            }
        }
    }
}

void Client::Private::processClientInfoRequest()
{
    qDebug() << Q_FUNC_INFO;

    setStatus(Client::Unregistered);

    // Get some information
    discovery.discover();
}

void Client::Private::processPeerRequest()
{
    qDebug() << Q_FUNC_INFO;
}

void Client::Private::sendClientInfo()
{
    QHostAddress myIp = NetworkHelper::localIpAddress();
    QString localIp = QString("%1:%2").arg(myIp.toString()).arg(1337);

    ClientInfo info;
    info.setDeviceId(settings.deviceId());
    info.setLocalIp(localIp);
    QByteArray data = QJsonDocument::fromVariant(info.toVariant()).toJson();

    QUrl url = masterUrl;
    url.setPath("/info");

    QNetworkRequest request(url);<commit_msg>Take the local ip address from upnp if available. Otherwise we try to find it ourself.<commit_after>#include "client.h"
#include "discovery.h"
#include "requests.h"
#include "networkhelper.h"

#include <QUdpSocket>
#include <QBuffer>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QTimer>
#include <QHostInfo>
#include <QDataStream>

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#else
#ifdef Q_OS_WIN
#include <QJson/Parser>
#else
#include <qjson/parser.h>
#endif
#endif

#include <QDebug>

const QUrl masterUrl = QUrl("http://mplane.informatik.hs-augsburg.de:16001");

class Client::Private : public QObject
{
    Q_OBJECT

public:
    Private(Client* q)
    : q(q)
    , status(Client::Unregistered)
    , networkAccessManager(new QNetworkAccessManager(q))
    {
        connect(&discovery, SIGNAL(finished()), this, SLOT(onDiscoveryFinished()));
        connect(&managerSocket, SIGNAL(readyRead()), this, SLOT(onDatagramReady()));
        connect(&aliveTimer, SIGNAL(timeout()), this, SLOT(onAliveTimer()));

        scheduler.setManagerSocket(&managerSocket);

        aliveTimer.setInterval(20 * 1000);
        aliveTimer.start();
    }

    Client* q;

    // Properties
    Client::Status status;
    QNetworkAccessManager* networkAccessManager;
    Discovery discovery;
    QUdpSocket managerSocket;
    QTimer aliveTimer;
    QHostInfo aliveInfo;

    TestScheduler scheduler;
    Settings settings;

    QHostAddress lastLocalIp;

    // Functions
    void setStatus(Client::Status status);

    void processDatagram(const QByteArray &datagram, const QHostAddress& host, quint16 port);
    void processClientInfoRequest();
    void processPeerRequest();

    void sendClientInfo();
    void sendPeerResponse(const QHostAddress &host, quint16 port);
    void sendPeerRequest(bool manual = false);

public slots:
    void onDatagramReady();
    void onLookupFinished(const QHostInfo &host);
    void onAliveTimer();
    void onDiscoveryFinished();

    void onRegisterFinished();
    void onRegisterError(QNetworkReply::NetworkError error);

    void onPeerRequestFinished();
    void onPeerRequestError(QNetworkReply::NetworkError error);
};

void Client::Private::setStatus(Client::Status status)
{
    if ( this->status == status )
        return;

    this->status = status;
    emit q->statusChanged();
}

void Client::Private::processDatagram(const QByteArray& datagram, const QHostAddress &host, quint16 port)
{
    // Master server
    if ( aliveInfo.addresses().contains(host) ) {
        const RequestType* type = (const RequestType*)datagram.constData();

        qDebug() << Q_FUNC_INFO << *type;

        switch(*type) {
        case ClientInfoRequest:
            processClientInfoRequest();
            break;

        case PeerRequest:
            sendPeerRequest();
            break;

        case RegisteredClientResponse:
            setStatus(Client::Registered);
            break;

        default:
            qDebug() << "Received unknown request from master" << host.toString() << port;
        }
    } else {
        AbstractTest* currentTest = scheduler.currentTest();
        if ( currentTest ) {
            currentTest->processDatagram(datagram, host, port);
        } else {
            const RequestType* type = (const RequestType*)datagram.constData();

            switch(*type) {
            case PeerResponse:
                qDebug() << "Received peer response from" << host.toString() << port;
                break;

            default:
                qDebug() << "Received invalid datagram from" << host.toString() << port;
            }
        }
    }
}

void Client::Private::processClientInfoRequest()
{
    qDebug() << Q_FUNC_INFO;

    setStatus(Client::Unregistered);

    // Get some information
    discovery.discover();
}

void Client::Private::processPeerRequest()
{
    qDebug() << Q_FUNC_INFO;
}

void Client::Private::sendClientInfo()
{
    Discovery::DiscoveryHash upnpData = discovery.data();

    QHostAddress myIp = upnpData.contains(Discovery::LanIpAddress) ? QHostAddress(upnpData.value(Discovery::LanIpAddress).toString())
                                                                   : NetworkHelper::localIpAddress();
    QString localIp = QString("%1:%2").arg(myIp.toString()).arg(1337);

    ClientInfo info;
    info.setDeviceId(settings.deviceId());
    info.setLocalIp(localIp);
    QByteArray data = QJsonDocument::fromVariant(info.toVariant()).toJson();

    QUrl url = masterUrl;
    url.setPath("/info");

    QNetworkRequest request(url);
{'fraction_non_alphanumeric': 0.12071452346610452, 'fraction_numerical': 0.005769444136247642, 'mean_word_length': 3.296472831267874, 'pattern_counts': {'":': 0, '<': 85, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6167477', 'n_tokens_mistral': 2677, 'n_tokens_neox': 2563, 'n_words': 569}