<commit_before>#include "networkmanager.h"
#include "../networkhelper.h"
#include "../log/logger.h"
#include "../scheduler/scheduler.h"
#include "../task/taskexecutor.h"
#include "../settings.h"
#include "../timing/immediatetiming.h"
#include "../timing/periodictiming.h"

#include "tcpsocket.h"
#include "udpsocket.h"

#include <QDataStream>
#include <QJsonDocument>
#include <QPointer>
#include <QTcpServer>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QStringList>
#include <QHash>
#include <QMutex>
#include <QReadWriteLock>
#include <QTimer>
#include <QDebug>
#include <QNetworkConfigurationManager>

LOGGER(NetworkManager);

class PeerRequest
{
public:
    QVariant toVariant()
    {
        QVariantMap map;
        map.insert("type", "peer_request");
        map.insert("connectionId", connectionId);
        map.insert("definition", measurementDefinition);
        map.insert("measurement", measurement);
        map.insert("peer", peer);
        map.insert("port", port);
        map.insert("protocol", protocol);
        return map;
    }

    static PeerRequest fromVariant(const QVariant& variant)
    {
        QVariantMap map = variant.toMap();

        PeerRequest request;
        request.connectionId = map.value("connectionId").toUuid();
        request.measurementDefinition = map.value("definition");
        request.measurement = map.value("measurement").toString();
        request.peer = map.value("peer").toString();
        request.port = map.value("port").toUInt();
        request.protocol = (NetworkManager::SocketType)map.value("protocol").toInt();
        return request;
    }

    QUuid connectionId;
    QVariant measurementDefinition;
    QString measurement;
    QString peer;
    quint16 port;
    NetworkManager::SocketType protocol;
};

class NetworkManager::Private : public QObject
{
    Q_OBJECT

public:
    Private(NetworkManager* q)
        : q(q)
    {
        connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
    }

    NetworkManager* q;

    // Properties
    QMutex mutex;
    QHash<QString, QObject*> objectHash;
    QHash<QString, QAbstractSocket*> socketHash;

    QTimer timer;
    QPointer<QUdpSocket> socket;
    QPointer<Scheduler> scheduler;
    QPointer<Settings> settings;

    QSet<QUuid> handledConnectionIds;

    quint16 localPort;

    QNetworkConfigurationManager ncm;

    // Functions
    QAbstractSocket* createSocket(NetworkManager::SocketType socketType);

    void updateSocket();
    void updateTimer();
    void processDatagram(const QByteArray& datagram, const QHostAddress& host, quint16 port);

public slots:
    void socketDestroyed(QObject* obj);
    void responseChanged();
    void timeout();
    void onDatagramReady();
};

QAbstractSocket *NetworkManager::Private::createSocket(NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = NULL;

    switch (socketType)
    {
    case TcpSocket:
        socket = new ::TcpSocket;
        break;

    case UdpSocket:
        socket = new ::UdpSocket;
        break;

    case UtpSocket:
        //socket = new UtpSocket;
        break;

    default:
        break;
    }

    if (socket)
    {
        connect(socket, SIGNAL(destroyed(QObject*)), this, SLOT(socketDestroyed(QObject*)));
    }

    return socket;
}

void NetworkManager::Private::socketDestroyed(QObject *obj)
{
    QString hostname = objectHash.key(obj);
    if (hostname.isEmpty())
    {
        return;
    }

    objectHash.remove(hostname);
    socketHash.remove(hostname);
}

void NetworkManager::Private::updateSocket()
{
    if (!socket.isNull())
    {
        delete socket.data();
        socket.clear();
    }

    QString keepaliveAddress = settings->config()->keepaliveAddress();
    RemoteHost remote = NetworkHelper::remoteHost(keepaliveAddress);
    if (!remote.isValid())
    {
        return;
    }

    localPort = remote.port;

    socket = qobject_cast<QUdpSocket*>( q->createConnection(NetworkManager::UdpSocket) );
    socket->setParent(this);
    connect(socket.data(), SIGNAL(readyRead()), this, SLOT(onDatagramReady()));
    if (!socket->bind(remote.port))
    {
        LOG_ERROR(QString("Unable to bind port %1: %2").arg(remote.port).arg(socket->errorString()));
    }
}

void NetworkManager::Private::updateTimer()
{
    TimingPtr timing = settings->config()->keepaliveSchedule();
    if (!timing)
    {
        return;
    }

    QSharedPointer<PeriodicTiming> periodicTiming = timing.dynamicCast<PeriodicTiming>();
    Q_ASSERT(periodicTiming);

    int interval = periodicTiming->period();
    if (interval < 1000)
    {
        LOG_INFO("Keepalive interval < 1 sec will not be accepted.");
        return;
    }
    else
    {
        LOG_INFO(QString("Keepalive set to %1 sec.").arg(interval/1000));
    }

    timer.setInterval(interval);
    timer.start();
}

class NetworkManagerMeasurementObserver : public MeasurementObserver
{
public:
    NetworkManager* networkManager;
    NetworkManager::SocketType socketType;
    quint16 localPort;

    QHostAddress host;
    quint16 port;

    // MeasurementObserver interface
    void created(const MeasurementPtr &measurement)
    {
        QAbstractSocket* socket = networkManager->createConnection(socketType);

        QUdpSocket* udpSocket = qobject_cast<QUdpSocket*>(socket);
        if (!udpSocket->bind(localPort))
        {
            LOG_ERROR("Cannot bind socket");
            return;
        }

        // ACK the connection
        udpSocket->writeDatagram(QByteArray(), host, port);
        measurement->setPeerSocket(udpSocket);
    }
};

void NetworkManager::Private::processDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)
{
    QString hostAndPort = QString("%1:%2").arg(host.toString()).arg(port);
    if (datagram.isEmpty())
    {
        LOG_DEBUG(QString("Received empty datagram from %1").arg(hostAndPort));
        return;
    }

    LOG_DEBUG(QString("Received datagram from %1: %2").arg(hostAndPort).arg(QString::fromUtf8(datagram)));
//    if (settings->config()->keepaliveAddress() == hostAndPort) {
    // Master server
    QJsonParseError error;
    QJsonDocument document = QJsonDocument::fromJson(datagram, &error);

    if (error.error == QJsonParseError::NoError)
    {
        PeerRequest request = PeerRequest::fromVariant(document.toVariant());

        if (handledConnectionIds.contains(request.connectionId))
        {
            LOG_DEBUG("Connection id is already handled, skipping second try");
            return;
        }

        handledConnectionIds.insert(request.connectionId);

        MeasurementObserver* observer = NULL;
        if (request.protocol == NetworkManager::UdpSocket)
        {
            NetworkManagerMeasurementObserver* tempObs = new NetworkManagerMeasurementObserver;
            tempObs->networkManager = q;
            tempObs->socketType = request.protocol;
            tempObs->localPort = 5106; // FIXME: Don't hardcode this here
            tempObs->host = host; //request.peer;
            tempObs->port = port;

            observer = tempObs;
        }

        // FIXME: We can't assign the Peer socket to Measurement since this is created in a separate thread
        //        and we can't access.

        TimingPtr timing(new ImmediateTiming);
        TestDefinitionPtr testDefinition(new TestDefinition(request.connectionId, request.measurement, timing, request.measurementDefinition));

        // Bypass scheduler and run directly on the executor
        scheduler->executor()->execute(testDefinition, observer);
    }
    else
    {
        LOG_ERROR(QString("Invalid JSon: %1").arg(error.errorString()));
    }
//    } else {
    // TODO: Process incoming data
//    }
}

void NetworkManager::Private::responseChanged()
{
    updateSocket();
    updateTimer();

    // Send the first timeout now
    timeout();
}

void NetworkManager::Private::timeout()
{
    RemoteHost remote = NetworkHelper::remoteHost(settings->config()->keepaliveAddress());
    if (!remote.isValid())
    {
        LOG_INFO("Invalid keepalive host");
        return;
    }

    QString sessionId = settings->sessionId();
    if (sessionId.isEmpty())
    {
        LOG_INFO("Empty session id");
        return;
    }

    QStringList srcIp;
    srcIp.append( NetworkHelper::localIpAddress().toString() );

    QVariantMap map;
    map.insert("type", "keepalive");
    map.insert("session_id", sessionId);
    map.insert("src_ip", srcIp);
    map.insert("src_port", localPort);

    QByteArray data = QJsonDocument::fromVariant(map).toJson();
    socket->writeDatagram(data, QHostAddress(remote.host), remote.port);

    LOG_INFO("Alive packet sent");
}

void NetworkManager::Private::onDatagramReady()
{
    while (socket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(socket->pendingDatagramSize());

        QHostAddress host;
        quint16 port;
        socket->readDatagram(datagram.data(), datagram.size(), &host, &port);

        // Process the datagram
        processDatagram(datagram, host, port);
    }
}

NetworkManager::NetworkManager(QObject *parent)
: QObject(parent)
, d(new Private(this))
{
}

NetworkManager::~NetworkManager()
{
    delete d;
}

bool NetworkManager::init(Scheduler* scheduler, Settings *settings)
{
    connect(settings->config(), SIGNAL(responseChanged()), d, SLOT(responseChanged()));

    d->scheduler = scheduler;
    d->settings = settings;
    d->responseChanged();

    emit d->ncm.updateConfigurations();

    return true;
}

void NetworkManager::setRunning(bool running)
{
    if (isRunning() == running)
    {
        return;
    }

    if ( !running )
    {
        d->timer.stop();
    }
    else
    {
        d->updateTimer();
    }
}

bool NetworkManager::isRunning() const
{
    return d->timer.isActive();
}

bool NetworkManager::onMobileConnection() const
{
    QList<QNetworkConfiguration> confList = d->ncm.allConfigurations(QNetworkConfiguration::Active);

    foreach(QNetworkConfiguration conf, confList)
    {
        QNetworkConfiguration::BearerType type = conf.bearerType();
        if (type != QNetworkConfiguration::BearerEthernet && type != QNetworkConfiguration::BearerWLAN)
        {
            return true;
        }
    }

    return false;
}

QAbstractSocket *NetworkManager::connection(const QString &hostname, NetworkManager::SocketType socketType) const
{
    return d->socketHash.value(hostname);
}

QAbstractSocket *NetworkManager::createConnection(NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = d->createSocket(socketType);
    if ( !socket )
    {
        qDebug() << "Unknown socket type requested";
        return NULL;
    }

    //d->socketHash.insert(hostname, socket);
    //d->objectHash.insert(hostname, socket);

    return socket;
}

QAbstractSocket *NetworkManager::establishConnection(const QString &hostname, const QString &measurement, const QVariant &definition, NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = d->createSocket(socketType);
    if ( !socket )
    {
        qDebug() << "Unknown socket type requested";
        return NULL;
    }

    RemoteHost remote = NetworkHelper::remoteHost(hostname);
    RemoteHost aliveRemote = NetworkHelper::remoteHost(d->settings->config()->keepaliveAddress());

    if (!aliveRemote.isValid())
    {
        LOG_ERROR(QString("Invalid alive remote: '%1' can't talk to alive server").arg(d->settings->config()->keepaliveAddress()));
        delete socket;
        return NULL;
    }

    PeerRequest request;
    request.connectionId = QUuid::createUuid();
    request.measurement = measurement;
    request.measurementDefinition = definition;
    request.peer = remote.host;
    request.port = aliveRemote.port;
    request.protocol = socketType;

    // If for some reason our packet gets routed back to us, don't handle it
    d->handledConnectionIds.insert(request.connectionId);

    QUdpSocket* testSocket = d->socket.data();
    if ( socketType != TcpSocket )
    {
        if (!socket->bind(remote.port))
        {
            LOG_ERROR(QString("Unable to bind source port to %1").arg(remote.port));
            delete socket;
            return NULL;
        }

        QUdpSocket* udpSocket = qobject_cast<QUdpSocket*>(socket);
        udpSocket->writeDatagram(QByteArray(), QHostAddress(remote.host), remote.port);

        testSocket = udpSocket;
    }

    QByteArray data = QJsonDocument::fromVariant(request.toVariant()).toJson();

    // Step one: Send test offer to peer directly
    testSocket->writeDatagram(data, QHostAddress(remote.host), d->localPort);

    // Step two: Send test offer to peer via alive-server
    testSocket->writeDatagram(data, QHostAddress(aliveRemote.host), aliveRemote.port);

    LOG_TRACE("Sent test offer to peer and alive-server");

    if ( socketType != UdpSocket )
    {
        // Final step: Connect to remote host
        //if (socket->waitForReadyRead(5000))
        //    return socket;

        const int tries = 20;
        for (int i=0; i < tries; ++i)
        {
            socket->connectToHost(remote.host, remote.port);
            if (socket->waitForConnected(5000/tries))
            {
                return socket;
            }
        }

        LOG_ERROR(QString("Unable to connect tcp socket in %3 tries to %1: %2").arg(hostname).arg(socket->errorString()).arg(tries));
    }
    else
    {
        if (!testSocket->waitForReadyRead(5000))
        {
            LOG_ERROR("Remote did not answer for 5 sec, aborting connection.");
        }
        else
        {
            // TODO: Read the first (empty) datagram
            QHostAddress packetHost;
            testSocket->readDatagram(0, 0, &packetHost);

            if (packetHost != QHostAddress(remote.host))
            {
                LOG_ERROR("Received connection packet from wrong host!");
            }
            else
            {
                return socket;
            }
        }
    }

    delete socket;
    return NULL;
}

QTcpServer *NetworkManager::createServerSocket()
{
    // TODO: Connect to traffic counter
    QTcpServer* server = new QTcpServer;
    return server;
}

#include "networkmanager.moc"
<commit_msg>Show error message if something with the keepalive server goes wrong<commit_after>#include "networkmanager.h"
#include "../networkhelper.h"
#include "../log/logger.h"
#include "../scheduler/scheduler.h"
#include "../task/taskexecutor.h"
#include "../settings.h"
#include "../timing/immediatetiming.h"
#include "../timing/periodictiming.h"

#include "tcpsocket.h"
#include "udpsocket.h"

#include <QDataStream>
#include <QJsonDocument>
#include <QJsonObject>
#include <QPointer>
#include <QTcpServer>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QStringList>
#include <QHash>
#include <QMutex>
#include <QReadWriteLock>
#include <QTimer>
#include <QDebug>
#include <QNetworkConfigurationManager>

LOGGER(NetworkManager);

class PeerRequest
{
public:
    QVariant toVariant()
    {
        QVariantMap map;
        map.insert("type", "peer_request");
        map.insert("connectionId", connectionId);
        map.insert("definition", measurementDefinition);
        map.insert("measurement", measurement);
        map.insert("peer", peer);
        map.insert("port", port);
        map.insert("protocol", protocol);
        return map;
    }

    static PeerRequest fromVariant(const QVariant& variant)
    {
        QVariantMap map = variant.toMap();

        PeerRequest request;
        request.connectionId = map.value("connectionId").toUuid();
        request.measurementDefinition = map.value("definition");
        request.measurement = map.value("measurement").toString();
        request.peer = map.value("peer").toString();
        request.port = map.value("port").toUInt();
        request.protocol = (NetworkManager::SocketType)map.value("protocol").toInt();
        return request;
    }

    QUuid connectionId;
    QVariant measurementDefinition;
    QString measurement;
    QString peer;
    quint16 port;
    NetworkManager::SocketType protocol;
};

class NetworkManager::Private : public QObject
{
    Q_OBJECT

public:
    Private(NetworkManager* q)
        : q(q)
    {
        connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
    }

    NetworkManager* q;

    // Properties
    QMutex mutex;
    QHash<QString, QObject*> objectHash;
    QHash<QString, QAbstractSocket*> socketHash;

    QTimer timer;
    QPointer<QUdpSocket> socket;
    QPointer<Scheduler> scheduler;
    QPointer<Settings> settings;

    QSet<QUuid> handledConnectionIds;

    quint16 localPort;

    QNetworkConfigurationManager ncm;

    // Functions
    QAbstractSocket* createSocket(NetworkManager::SocketType socketType);

    void updateSocket();
    void updateTimer();
    void processDatagram(const QByteArray& datagram, const QHostAddress& host, quint16 port);

public slots:
    void socketDestroyed(QObject* obj);
    void responseChanged();
    void timeout();
    void onDatagramReady();
};

QAbstractSocket *NetworkManager::Private::createSocket(NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = NULL;

    switch (socketType)
    {
    case TcpSocket:
        socket = new ::TcpSocket;
        break;

    case UdpSocket:
        socket = new ::UdpSocket;
        break;

    case UtpSocket:
        //socket = new UtpSocket;
        break;

    default:
        break;
    }

    if (socket)
    {
        connect(socket, SIGNAL(destroyed(QObject*)), this, SLOT(socketDestroyed(QObject*)));
    }

    return socket;
}

void NetworkManager::Private::socketDestroyed(QObject *obj)
{
    QString hostname = objectHash.key(obj);
    if (hostname.isEmpty())
    {
        return;
    }

    objectHash.remove(hostname);
    socketHash.remove(hostname);
}

void NetworkManager::Private::updateSocket()
{
    if (!socket.isNull())
    {
        delete socket.data();
        socket.clear();
    }

    QString keepaliveAddress = settings->config()->keepaliveAddress();
    RemoteHost remote = NetworkHelper::remoteHost(keepaliveAddress);
    if (!remote.isValid())
    {
        return;
    }

    localPort = remote.port;

    socket = qobject_cast<QUdpSocket*>( q->createConnection(NetworkManager::UdpSocket) );
    socket->setParent(this);
    connect(socket.data(), SIGNAL(readyRead()), this, SLOT(onDatagramReady()));
    if (!socket->bind(remote.port))
    {
        LOG_ERROR(QString("Unable to bind port %1: %2").arg(remote.port).arg(socket->errorString()));
    }
}

void NetworkManager::Private::updateTimer()
{
    TimingPtr timing = settings->config()->keepaliveSchedule();
    if (!timing)
    {
        return;
    }

    QSharedPointer<PeriodicTiming> periodicTiming = timing.dynamicCast<PeriodicTiming>();
    Q_ASSERT(periodicTiming);

    int interval = periodicTiming->period();
    if (interval < 1000)
    {
        LOG_INFO("Keepalive interval < 1 sec will not be accepted.");
        return;
    }
    else
    {
        LOG_INFO(QString("Keepalive set to %1 sec.").arg(interval/1000));
    }

    timer.setInterval(interval);
    timer.start();
}

class NetworkManagerMeasurementObserver : public MeasurementObserver
{
public:
    NetworkManager* networkManager;
    NetworkManager::SocketType socketType;
    quint16 localPort;

    QHostAddress host;
    quint16 port;

    // MeasurementObserver interface
    void created(const MeasurementPtr &measurement)
    {
        QAbstractSocket* socket = networkManager->createConnection(socketType);

        QUdpSocket* udpSocket = qobject_cast<QUdpSocket*>(socket);
        if (!udpSocket->bind(localPort))
        {
            LOG_ERROR("Cannot bind socket");
            return;
        }

        // ACK the connection
        udpSocket->writeDatagram(QByteArray(), host, port);
        measurement->setPeerSocket(udpSocket);
    }
};

void NetworkManager::Private::processDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)
{
    QString hostAndPort = QString("%1:%2").arg(host.toString()).arg(port);
    if (datagram.isEmpty())
    {
        LOG_DEBUG(QString("Received empty datagram from %1").arg(hostAndPort));
        return;
    }

    LOG_DEBUG(QString("Received datagram from %1: %2").arg(hostAndPort).arg(QString::fromUtf8(datagram)));
//    if (settings->config()->keepaliveAddress() == hostAndPort) {
    // Master server
    QJsonParseError error;
    QJsonDocument document = QJsonDocument::fromJson(datagram, &error);

    if (error.error == QJsonParseError::NoError)
    {
        QJsonObject root = document.object();

        QString replyError = root.value("error").toString();
        if ( !replyError.isEmpty() )
        {
            LOG_ERROR(QString("Error from server: %1").arg(root.value("error").toString()));
            return;
        }

        PeerRequest request = PeerRequest::fromVariant(document.toVariant());

        if (handledConnectionIds.contains(request.connectionId))
        {
            LOG_DEBUG("Connection id is already handled, skipping second try");
            return;
        }

        handledConnectionIds.insert(request.connectionId);

        MeasurementObserver* observer = NULL;
        if (request.protocol == NetworkManager::UdpSocket)
        {
            NetworkManagerMeasurementObserver* tempObs = new NetworkManagerMeasurementObserver;
            tempObs->networkManager = q;
            tempObs->socketType = request.protocol;
            tempObs->localPort = 5106; // FIXME: Don't hardcode this here
            tempObs->host = host; //request.peer;
            tempObs->port = port;

            observer = tempObs;
        }

        // FIXME: We can't assign the Peer socket to Measurement since this is created in a separate thread
        //        and we can't access.

        TimingPtr timing(new ImmediateTiming);
        TestDefinitionPtr testDefinition(new TestDefinition(request.connectionId, request.measurement, timing, request.measurementDefinition));

        // Bypass scheduler and run directly on the executor
        scheduler->executor()->execute(testDefinition, observer);
    }
    else
    {
        LOG_ERROR(QString("Invalid JSon: %1").arg(error.errorString()));
    }
//    } else {
    // TODO: Process incoming data
//    }
}

void NetworkManager::Private::responseChanged()
{
    updateSocket();
    updateTimer();

    // Send the first timeout now
    timeout();
}

void NetworkManager::Private::timeout()
{
    RemoteHost remote = NetworkHelper::remoteHost(settings->config()->keepaliveAddress());
    if (!remote.isValid())
    {
        LOG_INFO("Invalid keepalive host");
        return;
    }

    QString sessionId = settings->sessionId();
    if (sessionId.isEmpty())
    {
        LOG_INFO("Empty session id");
        return;
    }

    QStringList srcIp;
    srcIp.append( NetworkHelper::localIpAddress().toString() );

    QVariantMap map;
    map.insert("type", "keepalive");
    map.insert("session_id", sessionId);
    map.insert("src_ip", srcIp);
    map.insert("src_port", localPort);

    QByteArray data = QJsonDocument::fromVariant(map).toJson();
    socket->writeDatagram(data, QHostAddress(remote.host), remote.port);

    LOG_INFO("Alive packet sent");
}

void NetworkManager::Private::onDatagramReady()
{
    while (socket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(socket->pendingDatagramSize());

        QHostAddress host;
        quint16 port;
        socket->readDatagram(datagram.data(), datagram.size(), &host, &port);

        // Process the datagram
        processDatagram(datagram, host, port);
    }
}

NetworkManager::NetworkManager(QObject *parent)
: QObject(parent)
, d(new Private(this))
{
}

NetworkManager::~NetworkManager()
{
    delete d;
}

bool NetworkManager::init(Scheduler* scheduler, Settings *settings)
{
    connect(settings->config(), SIGNAL(responseChanged()), d, SLOT(responseChanged()));

    d->scheduler = scheduler;
    d->settings = settings;
    d->responseChanged();

    emit d->ncm.updateConfigurations();

    return true;
}

void NetworkManager::setRunning(bool running)
{
    if (isRunning() == running)
    {
        return;
    }

    if ( !running )
    {
        d->timer.stop();
    }
    else
    {
        d->updateTimer();
    }
}

bool NetworkManager::isRunning() const
{
    return d->timer.isActive();
}

bool NetworkManager::onMobileConnection() const
{
    QList<QNetworkConfiguration> confList = d->ncm.allConfigurations(QNetworkConfiguration::Active);

    foreach(QNetworkConfiguration conf, confList)
    {
        QNetworkConfiguration::BearerType type = conf.bearerType();
        if (type != QNetworkConfiguration::BearerEthernet && type != QNetworkConfiguration::BearerWLAN)
        {
            return true;
        }
    }

    return false;
}

QAbstractSocket *NetworkManager::connection(const QString &hostname, NetworkManager::SocketType socketType) const
{
    return d->socketHash.value(hostname);
}

QAbstractSocket *NetworkManager::createConnection(NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = d->createSocket(socketType);
    if ( !socket )
    {
        qDebug() << "Unknown socket type requested";
        return NULL;
    }

    //d->socketHash.insert(hostname, socket);
    //d->objectHash.insert(hostname, socket);

    return socket;
}

QAbstractSocket *NetworkManager::establishConnection(const QString &hostname, const QString &measurement, const QVariant &definition, NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = d->createSocket(socketType);
    if ( !socket )
    {
        qDebug() << "Unknown socket type requested";
        return NULL;
    }

    RemoteHost remote = NetworkHelper::remoteHost(hostname);
    RemoteHost aliveRemote = NetworkHelper::remoteHost(d->settings->config()->keepaliveAddress());

    if (!aliveRemote.isValid())
    {
        LOG_ERROR(QString("Invalid alive remote: '%1' can't talk to alive server").arg(d->settings->config()->keepaliveAddress()));
        delete socket;
        return NULL;
    }

    PeerRequest request;
    request.connectionId = QUuid::createUuid();
    request.measurement = measurement;
    request.measurementDefinition = definition;
    request.peer = remote.host;
    request.port = aliveRemote.port;
    request.protocol = socketType;

    // If for some reason our packet gets routed back to us, don't handle it
    d->handledConnectionIds.insert(request.connectionId);

    QUdpSocket* testSocket = d->socket.data();
    if ( socketType != TcpSocket )
    {
        if (!socket->bind(remote.port))
        {
            LOG_ERROR(QString("Unable to bind source port to %1").arg(remote.port));
            delete socket;
            return NULL;
        }

        QUdpSocket* udpSocket = qobject_cast<QUdpSocket*>(socket);
        udpSocket->writeDatagram(QByteArray(), QHostAddress(remote.host), remote.port);

        testSocket = udpSocket;
    }

    QByteArray data = QJsonDocument::fromVariant(request.toVariant()).toJson();

    // Step one: Send test offer to peer directly
    testSocket->writeDatagram(data, QHostAddress(remote.host), d->localPort);

    // Step two: Send test offer to peer via alive-server
    testSocket->writeDatagram(data, QHostAddress(aliveRemote.host), aliveRemote.port);

    LOG_TRACE("Sent test offer to peer and alive-server");

    if ( socketType != UdpSocket )
    {
        // Final step: Connect to remote host
        //if (socket->waitForReadyRead(5000))
        //    return socket;

        const int tries = 20;
        for (int i=0; i < tries; ++i)
        {
            socket->connectToHost(remote.host, remote.port);
            if (socket->waitForConnected(5000/tries))
            {
                return socket;
            }
        }

        LOG_ERROR(QString("Unable to connect tcp socket in %3 tries to %1: %2").arg(hostname).arg(socket->errorString()).arg(tries));
    }
    else
    {
        if (!testSocket->waitForReadyRead(5000))
        {
            LOG_ERROR("Remote did not answer for 5 sec, aborting connection.");
        }
        else
        {
            // TODO: Read the first (empty) datagram
            QHostAddress packetHost;
            testSocket->readDatagram(0, 0, &packetHost);

            if (packetHost != QHostAddress(remote.host))
            {
                LOG_ERROR("Received connection packet from wrong host!");
            }
            else
            {
                return socket;
            }
        }
    }

    delete socket;
    return NULL;
}

QTcpServer *NetworkManager::createServerSocket()
{
    // TODO: Connect to traffic counter
    QTcpServer* server = new QTcpServer;
    return server;
}

#include "networkmanager.moc"
<|endoftext|>


<commit_before>struct B { int i; };
struct D : public B {};
int D::*dp = &D::i;

<commit_msg>Make test more interesting<commit_after>struct B { int i, j; };
struct D : public B {};
int D::*di = &D::i;
int D::*dj = &D::j;

<|endoftext|>


<commit_before>#include <node.h>
#include <node_object_wrap.h>
#include <nan.h>

namespace CustomRunInThisContext {
  using v8::FunctionCallbackInfo;
  using v8::Local;
  using v8::Object;
  using v8::Script;
  using v8::ScriptCompiler;
  using v8::ScriptOrigin;
  using v8::String;
  using v8::TryCatch;
  using v8::UnboundScript;
  using v8::Value;
  using v8::MaybeLocal;

  static void RunInThisContextCached(const FunctionCallbackInfo<Value>& args) {
    if (!args[0]->IsString() || !args[1]->IsString()) {
      Nan::ThrowTypeError("Filename and script must be strings");
      return;
    }

    Local<String> code = args[0]->ToString(args.GetIsolate());
    Local<String> filename = args[1]->ToString(args.GetIsolate());

    uint8_t *bufferData = nullptr;
    size_t bufferLength = 0;
    if (args[2]->IsObject()) {
      Local<Object> bufferObj = args[2]->ToObject();
      bufferData = reinterpret_cast<uint8_t*>(node::Buffer::Data(bufferObj));
      bufferLength = node::Buffer::Length(bufferObj);
    }

    auto cachedData = new ScriptCompiler::CachedData(bufferData, bufferLength);
    ScriptOrigin origin(filename);
    ScriptCompiler::Source source(code, origin, cachedData);
    MaybeLocal<UnboundScript> maybe_unbound_script = ScriptCompiler::CompileUnboundScript(
      args.GetIsolate(),
      &source,
      ScriptCompiler::CompileOptions::kConsumeCodeCache
    );

    Local<UnboundScript> unbound_script;
    if (!maybe_unbound_script.ToLocal(&unbound_script)) return;

    Nan::TryCatch try_catch;
    Local<Script> script = unbound_script->BindToCurrentContext();
    Local<Value> result = script->Run();
    if (result.IsEmpty()) {
      try_catch.ReThrow();
      return;
    }

    Local<Object> returnValue = Nan::New<v8::Object>();
    Nan::Set(returnValue, Nan::New("result").ToLocalChecked(), result);
    Nan::Set(returnValue, Nan::New("wasRejected").ToLocalChecked(), Nan::New(source.GetCachedData()->rejected));
    args.GetReturnValue().Set(returnValue);
  }

  static void RunInThisContext(const FunctionCallbackInfo<Value>& args) {
    if (!args[0]->IsString() || !args[1]->IsString()) {
      Nan::ThrowTypeError("Filename and script must be strings");
      return;
    }

    Local<String> code = args[0]->ToString(args.GetIsolate());
    Local<String> filename = args[1]->ToString(args.GetIsolate());
    ScriptOrigin origin(filename);
    ScriptCompiler::Source source(code, origin);
    MaybeLocal<UnboundScript> maybe_unbound_script = ScriptCompiler::CompileUnboundScript(
      args.GetIsolate(),
      &source,
      ScriptCompiler::CompileOptions::kProduceCodeCache
    );

    Local<UnboundScript> unbound_script;
    if (!maybe_unbound_script.ToLocal(&unbound_script)) return;
    if (unbound_script.IsEmpty()) return;

    Nan::TryCatch try_catch;
    Local<Script> script = unbound_script->BindToCurrentContext();
    Local<Value> result = script->Run();
    if (result.IsEmpty()) {
      try_catch.ReThrow();
      return;
    }

    Local<Value> cacheBuffer = Nan::Null();
    if (source.GetCachedData() && source.GetCachedData()->data) {
      cacheBuffer = Nan::CopyBuffer(reinterpret_cast<const char*>(source.GetCachedData()->data), source.GetCachedData()->length).ToLocalChecked();
    }

    Local<Object> returnValue = Nan::New<v8::Object>();
    Nan::Set(returnValue, Nan::New("cacheBuffer").ToLocalChecked(), cacheBuffer);
    Nan::Set(returnValue, Nan::New("result").ToLocalChecked(), result);
    args.GetReturnValue().Set(returnValue);
  }

  void Init(Local<Object> exports) {
    NODE_SET_METHOD(exports, "runInThisContext", RunInThisContext);
    NODE_SET_METHOD(exports, "runInThisContextCached", RunInThisContextCached);
  }

  NODE_MODULE(cached_run_in_this_context, Init)
}
<commit_msg>Use new CreateCodeCache API on node 10<commit_after>#include <node.h>
#include <node_object_wrap.h>
#include <nan.h>

namespace CustomRunInThisContext {
  using v8::FunctionCallbackInfo;
  using v8::Local;
  using v8::Object;
  using v8::Script;
  using v8::ScriptCompiler;
  using v8::ScriptOrigin;
  using v8::String;
  using v8::TryCatch;
  using v8::UnboundScript;
  using v8::Value;
  using v8::MaybeLocal;

  static void RunInThisContextCached(const FunctionCallbackInfo<Value>& args) {
    if (!args[0]->IsString() || !args[1]->IsString()) {
      Nan::ThrowTypeError("Filename and script must be strings");
      return;
    }

    Local<String> code = args[0]->ToString(args.GetIsolate());
    Local<String> filename = args[1]->ToString(args.GetIsolate());

    uint8_t *bufferData = nullptr;
    size_t bufferLength = 0;
    if (args[2]->IsObject()) {
      Local<Object> bufferObj = args[2]->ToObject();
      bufferData = reinterpret_cast<uint8_t*>(node::Buffer::Data(bufferObj));
      bufferLength = node::Buffer::Length(bufferObj);
    }

    auto cachedData = new ScriptCompiler::CachedData(bufferData, bufferLength);
    ScriptOrigin origin(filename);
    ScriptCompiler::Source source(code, origin, cachedData);
    MaybeLocal<UnboundScript> maybe_unbound_script = ScriptCompiler::CompileUnboundScript(
      args.GetIsolate(),
      &source,
      ScriptCompiler::CompileOptions::kConsumeCodeCache
    );

    Local<UnboundScript> unbound_script;
    if (!maybe_unbound_script.ToLocal(&unbound_script)) return;

    Nan::TryCatch try_catch;
    Local<Script> script = unbound_script->BindToCurrentContext();
    Local<Value> result = script->Run();
    if (result.IsEmpty()) {
      try_catch.ReThrow();
      return;
    }

    Local<Object> returnValue = Nan::New<v8::Object>();
    Nan::Set(returnValue, Nan::New("result").ToLocalChecked(), result);
    Nan::Set(returnValue, Nan::New("wasRejected").ToLocalChecked(), Nan::New(source.GetCachedData()->rejected));
    args.GetReturnValue().Set(returnValue);
  }

  static void RunInThisContext(const FunctionCallbackInfo<Value>& args) {
    if (!args[0]->IsString() || !args[1]->IsString()) {
      Nan::ThrowTypeError("Filename and script must be strings");
      return;
    }

    Local<String> code = args[0]->ToString(args.GetIsolate());
    Local<String> filename = args[1]->ToString(args.GetIsolate());
    ScriptOrigin origin(filename);
    ScriptCompiler::Source source(code, origin);
    MaybeLocal<UnboundScript> maybe_unbound_script = ScriptCompiler::CompileUnboundScript(
      args.GetIsolate(),
      &source,
      ScriptCompiler::CompileOptions::kProduceCodeCache
    );

    Local<UnboundScript> unbound_script;
    if (!maybe_unbound_script.ToLocal(&unbound_script)) return;
    if (unbound_script.IsEmpty()) return;

    Nan::TryCatch try_catch;
    Local<Script> script = unbound_script->BindToCurrentContext();
    Local<Value> result = script->Run();
    if (result.IsEmpty()) {
      try_catch.ReThrow();
      return;
    }

    Local<Value> cacheBuffer = Nan::Null();

    #if V8_MAJOR_VERSION == 6 && V8_MINOR_VERSION >= 7
      const ScriptCompiler::CachedData *data = ScriptCompiler::CreateCodeCache(unbound_script);
      if (data) {
        cacheBuffer = Nan::CopyBuffer(reinterpret_cast<const char*>(data->data), data->length).ToLocalChecked();
        delete data;
      }
    #else
      const ScriptCompiler::CachedData *data = source.GetCachedData();
      if (data) {
        cacheBuffer = Nan::CopyBuffer(reinterpret_cast<const char*>(data->data), data->length).ToLocalChecked();
      }
    #endif

    Local<Object> returnValue = Nan::New<v8::Object>();
    Nan::Set(returnValue, Nan::New("cacheBuffer").ToLocalChecked(), cacheBuffer);
    Nan::Set(returnValue, Nan::New("result").ToLocalChecked(), result);
    args.GetReturnValue().Set(returnValue);
  }

  void Init(Local<Object> exports) {
    NODE_SET_METHOD(exports, "runInThisContext", RunInThisContext);
    NODE_SET_METHOD(exports, "runInThisContextCached", RunInThisContextCached);
  }

  NODE_MODULE(cached_run_in_this_context, Init)
}
<|endoftext|>


<commit_before>#include <aruco/aruco.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>

void Autobalance(cv::Mat* im);
void DetectArucoMarkers(cv::Mat* im, std::vector<aruco::Marker>* markers);

struct camera {
  cv::Matx33d K;
  cv::Matx<double, 5, 1> distorsion;
  cv::Size size;
};

aruco::MarkerDetector aruco_detector;
aruco::BoardConfiguration aruco_board_config;
std::vector<int> aruco_marker_map;
std::vector<cv::Point3f> aruco_board_pts;

std::vector<std::vector<int> > num_detected_markers;
std::vector<std::vector<std::vector<cv::Point2f> > > marker_pnts_;
std::vector<std::vector<std::vector<cv::Point3f> > > marker_pnts_map_;
std::vector<std::vector<cv::Mat> > rvecs_;
std::vector<std::vector<cv::Mat> > tvecs_;

bool AUTOBALANCE = true;
bool DRAWMARKERS = true;

int main(int argc, char *argv[]) {

  if (argc < 2) {
    std::cerr << "Usage: ./fisheye_calibration <first device #> "
              << "<OPTIONAL: # cameras>\n";
    return -1;
  }

  int num_cameras = 1;
  if (argc == 3) {
    num_cameras = atoi(argv[2]);
  }

  std::vector<int> video_num(num_cameras);
  std::vector<cv::VideoCapture> video_stream(num_cameras);
  std::string window_name = "Video stream";
  video_num[0] = atoi(argv[1]);

  for (int i = 0; i < num_cameras; ++i) {
    video_num[i] = video_num[0] + i;
    video_stream[i].open(CV_CAP_FIREWIRE + video_num[i]);
    if (!video_stream[i].isOpened()) {
      std::cerr << "Cannot open firewire video stream: "
                << video_num[i] << std::endl;
      return -1;
    } else {
      std::cout << "Video stream /dev/fw" << video_num[i] << " opened.\n";
    }
  }

  aruco_marker_map.resize(1024, -1); // in place of hashtable
  aruco_board_config.readFromFile("../data/aruco20x10_meters.yml");
  for (int i = 0; i < aruco_board_config.size(); ++i) {
    aruco_marker_map[aruco_board_config[i].id] = i;
  }

  std::vector<camera> cameras(num_cameras);
  cv::namedWindow(window_name, CV_WINDOW_AUTOSIZE);
  std::vector<cv::Mat> frame(num_cameras);
  cv::Mat frames;
  //  cv::Mat frame_edit;

  for (int i = 0; i < num_cameras; ++i) {
    video_stream[i].set(CV_CAP_PROP_RECTIFICATION, 1);
    video_stream[i].read(frame[i]);
    cameras[i].size = frame[i].size();
    cameras[i].K = cv::Matx33d::eye();
    cameras[i].distorsion = cv::Matx<double, 5, 1>::zeros();
    if (i == 0)
      frames = frame[i];
    else
      cv::hconcat(frames, frame[i], frames);
  }

  std::vector<aruco::Marker> aruco_markers_detected; ////
  cv::imshow(window_name, frames);
  int keypress = cv::waitKey(30);

  while(video_stream[0].read(frame[0])) {
    frames = frame[0];

    DetectArucoMarkers(&(frame[0]), &aruco_markers_detected);

    for (int i = 1; i < num_cameras; ++i) {
      video_stream[i].read(frame[i]);
      DetectArucoMarkers(&(frame[i]), &aruco_markers_detected);
      cv::hconcat(frames, frame[i], frames);
    }
    cv::imshow(window_name, frames);
    keypress = cv::waitKey(30);
    if (keypress == 27) break;
  }

  for (int i = 0; i < num_cameras; ++i)
    video_stream[i].release();

  return 0;
}

void DetectArucoMarkers(cv::Mat* im, std::vector<aruco::Marker>* markers) {
  cv::Mat im_copy;
  cv::cvtColor(*im, im_copy, CV_BGR2GRAY);
  if (AUTOBALANCE) Autobalance(&im_copy);
  markers->clear();
  aruco_detector.detect(im_copy, *markers);
  if (DRAWMARKERS) {
    for (int i = 0; i < markers->size(); ++i) {
      (*markers)[i].draw(*im, cv::Scalar(0, 0, 255), 2);
    }
  }
}

void Autobalance(cv::Mat* im) {
  if (!(im == NULL)) {
    double min_px, max_px;
    cv::minMaxLoc(*im, &min_px, &max_px);
    double d = 255.0f/(max_px - min_px);
    int n = im->rows * im->cols;
    for (int i = 0; i < n; ++i) {
      im->data[i] = static_cast<unsigned char>((static_cast<double>(im->data[i]) - min_px) * d);
    }
  }
}
<commit_msg>add some UI<commit_after>#include <aruco/aruco.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstdio>

void Autobalance(cv::Mat* im);
void DetectArucoMarkers(cv::Mat* im, std::vector<aruco::Marker>* markers);

struct camera {
  cv::Matx33d K;
  cv::Matx<double, 5, 1> distorsion;
  cv::Size size;
};

aruco::MarkerDetector aruco_detector;
aruco::BoardConfiguration aruco_board_config;
std::vector<int> aruco_marker_map;
std::vector<cv::Point3f> aruco_board_pts;

std::vector<std::vector<int> > num_detected_markers;
std::vector<std::vector<std::vector<cv::Point2f> > > marker_pnts_;
std::vector<std::vector<std::vector<cv::Point3f> > > marker_pnts_map_;
std::vector<std::vector<cv::Mat> > rvecs_;
std::vector<std::vector<cv::Mat> > tvecs_;

//std::vector<cv::Rect> ROIs;

bool AUTOBALANCE = true;
bool DRAWMARKERS = true;

int main(int argc, char *argv[]) {

  if (argc < 2) {
    std::cerr << "Usage: ./fisheye_calibration <first device #> "
              << "<OPTIONAL: # cameras>\n";
    return -1;
  }

  int num_cameras = 1;
  if (argc == 3) {
    num_cameras = atoi(argv[2]);
  }

  std::vector<int> video_num(num_cameras);
  std::vector<cv::VideoCapture> video_stream(num_cameras);
  //  ROIs.resize(num_cameras);
  std::string window_name = "Video stream";
  video_num[0] = atoi(argv[1]);

  for (int i = 0; i < num_cameras; ++i) {
    video_num[i] = video_num[0] + i;
    video_stream[i].open(CV_CAP_FIREWIRE + video_num[i]);
    video_stream[i].set(CV_CAP_PROP_FPS, 10);
    if (!video_stream[i].isOpened()) {
      std::cerr << "Cannot open firewire video stream: "
                << video_num[i] << std::endl;
      return -1;
    } else {
      std::cout << "Video stream /dev/fw" << video_num[i] << " opened.\n";
    }
  }

  aruco_marker_map.resize(1024, -1); // in place of hashtable
  aruco_board_config.readFromFile("../data/aruco20x10_meters.yml");
  for (int i = 0; i < aruco_board_config.size(); ++i) {
    aruco_marker_map[aruco_board_config[i].id] = i;
  }

  std::vector<camera> cameras(num_cameras);
  cv::namedWindow(window_name, CV_WINDOW_AUTOSIZE);
  std::vector<cv::Mat> frame(num_cameras);
  cv::Mat frames;
  int num_calib = 0;
  char num_calib_buffer[10];

  for (int i = 0; i < num_cameras; ++i) {
    video_stream[i].set(CV_CAP_PROP_RECTIFICATION, 1);
    video_stream[i].read(frame[i]);
    cameras[i].size = frame[i].size();
    cameras[i].K = cv::Matx33d::eye();
    cameras[i].distorsion = cv::Matx<double, 5, 1>::zeros();
    //    ROIs[i] = cv::Rect(0, 0, frame[i].cols, frame[i].rows);
    if (i == 0)
      frames = frame[i];
    else
      cv::hconcat(frames, frame[i], frames);
  }

  std::vector<aruco::Marker> aruco_markers_detected; ////
  cv::imshow(window_name, frames);
  char keypress = cv::waitKey(30);

  std::vector<std::vector<std::vector<aruco::Marker> > >
      all_aruco_markers_detected;
  std::vector<std::vector<aruco::Marker> >
      single_time_aruco_markers_detected(num_cameras);
  while(video_stream[0].read(frame[0])) {
    frames = frame[0];
    DetectArucoMarkers(&(frame[0]), &aruco_markers_detected);
    single_time_aruco_markers_detected[0] = aruco_markers_detected;

    for (int i = 1; i < num_cameras; ++i) {
      video_stream[i].read(frame[i]);
      DetectArucoMarkers(&(frame[i]), &aruco_markers_detected);
      single_time_aruco_markers_detected[i] = aruco_markers_detected;
      cv::hconcat(frames, frame[i], frames);
    }

    sprintf(num_calib_buffer, "%d", num_calib);
    std::string str(num_calib_buffer);
    cv::putText(frames, "# calibration captures = " + str, cv::Point(50, 50),
                cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 255, 255), 8);
    cv::putText(frames, "# calibration captures = " + str, cv::Point(50, 50),
                cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 0), 3);
    cv::imshow(window_name, frames);

    keypress = cv::waitKey(30);

    // Esc key press -- EXIT
    if (keypress == 27) break;
    // SPACEBAR key press -- Collect data
    if (keypress == 32) {
      all_aruco_markers_detected.push_back(single_time_aruco_markers_detected);
      num_calib++;
    }
    // Carriage return key press -- calibrate
    if (keypress == 10) {
      if (all_aruco_markers_detected.size() == 0) {
        std::cout << "Cannot calibrate!  No data collected.\n";
      } else {
        std::cout << "Calibrating from " << num_calib
                  << " captured collections.";
        num_calib = 0;
      }
    }
  }

  for (int i = 0; i < num_cameras; ++i)
    video_stream[i].release();

  return 0;
}

void DetectArucoMarkers(cv::Mat* im, std::vector<aruco::Marker>* markers) {
  cv::Mat im_copy;
  if (!(im == NULL)) {
    cv::cvtColor(*im, im_copy, CV_BGR2GRAY);

    if (AUTOBALANCE) Autobalance(&im_copy);
    markers->clear();
    aruco_detector.detect(im_copy, *markers);
    //    if (markers->size() == 0) {}
    if (DRAWMARKERS) {
      for (int i = 0; i < markers->size(); ++i) {
        (*markers)[i].draw(*im, cv::Scalar(0, 0, 255), 2);
        //        for (int j = 0; j < 4; ++j) {}
      }
    }
  }
}

void Autobalance(cv::Mat* im) {
  if (!(im == NULL)) {
    double min_px, max_px;
    cv::minMaxLoc(*im, &min_px, &max_px);
    double d = 255.0f/(max_px - min_px);
    int n = im->rows * im->cols;
    for (int i = 0; i < n; ++i) {
      im->data[i] = static_cast<unsigned char>((static_cast<double>(im->data[i]) - min_px) * d);
    }
  }
}
<|endoftext|>


<commit_before>#include "networkmanager.h"
#include "../networkhelper.h"
#include "../log/logger.h"
#include "../scheduler/scheduler.h"
#include "../task/taskexecutor.h"
#include "../settings.h"
#include "../timing/immediatetiming.h"
#include "../timing/periodictiming.h"

#include "tcpsocket.h"
#include "udpsocket.h"

#include <QDataStream>
#include <QJsonDocument>
#include <QPointer>
#include <QTcpServer>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QStringList>
#include <QHash>
#include <QMutex>
#include <QReadWriteLock>
#include <QTimer>
#include <QDebug>
#include <QNetworkConfigurationManager>

LOGGER(NetworkManager);

class PeerRequest
{
public:
    QVariant toVariant()
    {
        QVariantMap map;
        map.insert("type", "peer_request");
        map.insert("connectionId", connectionId);
        map.insert("definition", measurementDefinition);
        map.insert("measurement", measurement);
        map.insert("peer", peer);
        map.insert("port", port);
        map.insert("protocol", protocol);
        return map;
    }

    static PeerRequest fromVariant(const QVariant& variant)
    {
        QVariantMap map = variant.toMap();

        PeerRequest request;
        request.connectionId = map.value("connectionId").toUuid();
        request.measurementDefinition = map.value("definition");
        request.measurement = map.value("measurement").toString();
        request.peer = map.value("peer").toString();
        request.port = map.value("port").toUInt();
        request.protocol = (NetworkManager::SocketType)map.value("protocol").toInt();
        return request;
    }

    QUuid connectionId;
    QVariant measurementDefinition;
    QString measurement;
    QString peer;
    quint16 port;
    NetworkManager::SocketType protocol;
};

class NetworkManager::Private : public QObject
{
    Q_OBJECT

public:
    Private(NetworkManager* q)
        : q(q)
    {
        connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
    }

    NetworkManager* q;

    // Properties
    QMutex mutex;
    QHash<QString, QObject*> objectHash;
    QHash<QString, QAbstractSocket*> socketHash;

    QTimer timer;
    QPointer<QUdpSocket> socket;
    QPointer<Scheduler> scheduler;
    QPointer<Settings> settings;

    QSet<QUuid> handledConnectionIds;

    quint16 localPort;

    QNetworkConfigurationManager ncm;

    // Functions
    QAbstractSocket* createSocket(NetworkManager::SocketType socketType);

    void updateSocket();
    void updateTimer();
    void processDatagram(const QByteArray& datagram, const QHostAddress& host, quint16 port);

public slots:
    void socketDestroyed(QObject* obj);
    void responseChanged();
    void timeout();
    void onDatagramReady();
};

QAbstractSocket *NetworkManager::Private::createSocket(NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = NULL;

    switch (socketType)
    {
    case TcpSocket:
        socket = new ::TcpSocket;
        break;

    case UdpSocket:
        socket = new ::UdpSocket;
        break;

    case UtpSocket:
        //socket = new UtpSocket;
        break;

    default:
        break;
    }

    if (socket)
    {
        connect(socket, SIGNAL(destroyed(QObject*)), this, SLOT(socketDestroyed(QObject*)));
    }

    return socket;
}

void NetworkManager::Private::socketDestroyed(QObject *obj)
{
    QString hostname = objectHash.key(obj);
    if (hostname.isEmpty())
    {
        return;
    }

    objectHash.remove(hostname);
    socketHash.remove(hostname);
}

void NetworkManager::Private::updateSocket()
{
    if (!socket.isNull())
    {
        delete socket.data();
        socket.clear();
    }

    QString keepaliveAddress = settings->config()->keepaliveAddress();
    RemoteHost remote = NetworkHelper::remoteHost(keepaliveAddress);
    if (!remote.isValid())
    {
        return;
    }

    localPort = remote.port;

    socket = qobject_cast<QUdpSocket*>( q->createConnection(NetworkManager::UdpSocket) );
    socket->setParent(this);
    connect(socket.data(), SIGNAL(readyRead()), this, SLOT(onDatagramReady()));
    if (!socket->bind(remote.port))
    {
        LOG_ERROR(QString("Unable to bind port %1: %2").arg(remote.port).arg(socket->errorString()));
    }
}

void NetworkManager::Private::updateTimer()
{
    TimingPtr timing = settings->config()->keepaliveSchedule();
    if (!timing)
    {
        return;
    }

    QSharedPointer<PeriodicTiming> periodicTiming = timing.dynamicCast<PeriodicTiming>();
    Q_ASSERT(periodicTiming);

    int interval = periodicTiming->period();
    if (interval < 1000)
    {
        LOG_INFO("Keepalive interval < 1 sec will not be accepted.");
        return;
    }
    else
    {
        LOG_INFO(QString("Keepalive set to %1 sec.").arg(interval/1000));
    }

    timer.setInterval(interval);
    timer.start();
}

class NetworkManagerMeasurementObserver : public MeasurementObserver
{
public:
    NetworkManager* networkManager;
    NetworkManager::SocketType socketType;
    quint16 localPort;

    QHostAddress host;
    quint16 port;

    // MeasurementObserver interface
    void created(const MeasurementPtr &measurement)
    {
        QAbstractSocket* socket = networkManager->createConnection(socketType);

        QUdpSocket* udpSocket = qobject_cast<QUdpSocket*>(socket);
        if (!udpSocket->bind(localPort))
        {
            LOG_ERROR("Cannot bind socket");
            return;
        }

        // ACK the connection
        udpSocket->writeDatagram(QByteArray(), host, port);
        measurement->setPeerSocket(udpSocket);
    }
};

void NetworkManager::Private::processDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)
{
    QString hostAndPort = QString("%1:%2").arg(host.toString()).arg(port);
    if (datagram.isEmpty())
    {
        LOG_DEBUG(QString("Received empty datagram from %1").arg(hostAndPort));
        return;
    }

    LOG_DEBUG(QString("Received datagram from %1: %2").arg(hostAndPort).arg(QString::fromUtf8(datagram)));
//    if (settings->config()->keepaliveAddress() == hostAndPort) {
    // Master server
    QJsonParseError error;
    QJsonDocument document = QJsonDocument::fromJson(datagram, &error);

    if (error.error == QJsonParseError::NoError)
    {
        PeerRequest request = PeerRequest::fromVariant(document.toVariant());

        if (handledConnectionIds.contains(request.connectionId))
        {
            LOG_DEBUG("Connection id is already handled, skipping second try");
            return;
        }

        handledConnectionIds.insert(request.connectionId);

        MeasurementObserver* observer = NULL;
        if (request.protocol == NetworkManager::UdpSocket)
        {
            NetworkManagerMeasurementObserver* tempObs = new NetworkManagerMeasurementObserver;
            tempObs->networkManager = q;
            tempObs->socketType = request.protocol;
            tempObs->localPort = 5106; // FIXME: Don't hardcode this here
            tempObs->host = host; //request.peer;
            tempObs->port = port;

            observer = tempObs;
        }

        // FIXME: We can't assign the Peer socket to Measurement since this is created in a separate thread
        //        and we can't access.

        TimingPtr timing(new ImmediateTiming);
        TestDefinitionPtr testDefinition(new TestDefinition(request.connectionId, request.measurement, timing, request.measurementDefinition));

        // Bypass scheduler and run directly on the executor
        scheduler->executor()->execute(testDefinition, observer);
    }
    else
    {
        LOG_ERROR(QString("Invalid JSon: %1").arg(error.errorString()));
    }
//    } else {
    // TODO: Process incoming data
//    }
}

void NetworkManager::Private::responseChanged()
{
    updateSocket();
    updateTimer();

    // Send the first timeout now
    timeout();
}

void NetworkManager::Private::timeout()
{
    RemoteHost remote = NetworkHelper::remoteHost(settings->config()->keepaliveAddress());
    if (!remote.isValid())
    {
        LOG_INFO("Invalid keepalive host");
        return;
    }

    QString sessionId = settings->sessionId();
    if (sessionId.isEmpty())
    {
        LOG_INFO("Empty session id");
        return;
    }

    QStringList srcIp;
    srcIp.append( NetworkHelper::localIpAddress().toString() );

    QVariantMap map;
    map.insert("type", "keepalive");
    map.insert("session_id", sessionId);
    map.insert("src_ip", srcIp);
    map.insert("src_port", localPort);

    QByteArray data = QJsonDocument::fromVariant(map).toJson();
    socket->writeDatagram(data, QHostAddress(remote.host), remote.port);

    LOG_INFO("Alive packet sent");
}

void NetworkManager::Private::onDatagramReady()
{
    while (socket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(socket->pendingDatagramSize());

        QHostAddress host;
        quint16 port;
        socket->readDatagram(datagram.data(), datagram.size(), &host, &port);

        // Process the datagram
        processDatagram(datagram, host, port);
    }
}

NetworkManager::NetworkManager(QObject *parent)
: QObject(parent)
, d(new Private(this))
{
}

NetworkManager::~NetworkManager()
{
    delete d;
}

bool NetworkManager::init(Scheduler* scheduler, Settings *settings)
{
    connect(settings->config(), SIGNAL(responseChanged()), d, SLOT(responseChanged()));

    d->scheduler = scheduler;
    d->settings = settings;
    d->responseChanged();

    emit d->ncm.updateConfigurations();

    return true;
}

void NetworkManager::setRunning(bool running)
{
    if (isRunning() == running)
    {
        return;
    }

    if ( !running )
    {
        d->timer.stop();
    }
    else
    {
        d->updateTimer();
    }
}

bool NetworkManager::isRunning() const
{
    return d->timer.isActive();
}

bool NetworkManager::onMobileConnection() const
{
    QList<QNetworkConfiguration> confList = d->ncm.allConfigurations(QNetworkConfiguration::Active);

    foreach(QNetworkConfiguration conf, confList)
    {
        LOG_INFO(QString("%1").arg(conf.name()));
        QNetworkConfiguration::BearerType type = conf.bearerType();
        LOG_INFO(QString("%1").arg(type));
        if (type != QNetworkConfiguration::BearerEthernet && type != QNetworkConfiguration::BearerWLAN)
        {
            return true;
        }
    }

    return false;
}

QAbstractSocket *NetworkManager::connection(const QString &hostname, NetworkManager::SocketType socketType) const
{
    return d->socketHash.value(hostname);
}

QAbstractSocket *NetworkManager::createConnection(NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = d->createSocket(socketType);
    if ( !socket )
    {
        qDebug() << "Unknown socket type requested";
        return NULL;
    }

    //d->socketHash.insert(hostname, socket);
    //d->objectHash.insert(hostname, socket);

    return socket;
}

QAbstractSocket *NetworkManager::establishConnection(const QString &hostname, const QString &measurement, const QVariant &definition, NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = d->createSocket(socketType);
    if ( !socket )
    {
        qDebug() << "Unknown socket type requested";
        return NULL;
    }

    RemoteHost remote = NetworkHelper::remoteHost(hostname);
    RemoteHost aliveRemote = NetworkHelper::remoteHost(d->settings->config()->keepaliveAddress());

    if (!aliveRemote.isValid())
    {
        LOG_ERROR(QString("Invalid alive remote: '%1' can't talk to alive server").arg(d->settings->config()->keepaliveAddress()));
        delete socket;
        return NULL;
    }

    PeerRequest request;
    request.connectionId = QUuid::createUuid();
    request.measurement = measurement;
    request.measurementDefinition = definition;
    request.peer = remote.host;
    request.port = aliveRemote.port;
    request.protocol = socketType;

    // If for some reason our packet gets routed back to us, don't handle it
    d->handledConnectionIds.insert(request.connectionId);

    QUdpSocket* testSocket = d->socket.data();
    if ( socketType != TcpSocket )
    {
        if (!socket->bind(remote.port))
        {
            LOG_ERROR(QString("Unable to bind source port to %1").arg(remote.port));
            delete socket;
            return NULL;
        }

        QUdpSocket* udpSocket = qobject_cast<QUdpSocket*>(socket);
        udpSocket->writeDatagram(QByteArray(), QHostAddress(remote.host), remote.port);

        testSocket = udpSocket;
    }

    QByteArray data = QJsonDocument::fromVariant(request.toVariant()).toJson();

    // Step one: Send test offer to peer directly
    testSocket->writeDatagram(data, QHostAddress(remote.host), d->localPort);

    // Step two: Send test offer to peer via alive-server
    testSocket->writeDatagram(data, QHostAddress(aliveRemote.host), aliveRemote.port);

    LOG_TRACE("Sent test offer to peer and alive-server");

    if ( socketType != UdpSocket )
    {
        // Final step: Connect to remote host
        //if (socket->waitForReadyRead(5000))
        //    return socket;

        const int tries = 20;
        for (int i=0; i < tries; ++i)
        {
            socket->connectToHost(remote.host, remote.port);
            if (socket->waitForConnected(5000/tries))
            {
                return socket;
            }
        }

        LOG_ERROR(QString("Unable to connect tcp socket in %3 tries to %1: %2").arg(hostname).arg(socket->errorString()).arg(tries));
    }
    else
    {
        if (!testSocket->waitForReadyRead(5000))
        {
            LOG_ERROR("Remote did not answer for 5 sec, aborting connection.");
        }
        else
        {
            // TODO: Read the first (empty) datagram
            QHostAddress packetHost;
            testSocket->readDatagram(0, 0, &packetHost);

            if (packetHost != QHostAddress(remote.host))
            {
                LOG_ERROR("Received connection packet from wrong host!");
            }
            else
            {
                return socket;
            }
        }
    }

    delete socket;
    return NULL;
}

QTcpServer *NetworkManager::createServerSocket()
{
    // TODO: Connect to traffic counter
    QTcpServer* server = new QTcpServer;
    return server;
}

#include "networkmanager.moc"
<commit_msg>Removed old logging output<commit_after>#include "networkmanager.h"
#include "../networkhelper.h"
#include "../log/logger.h"
#include "../scheduler/scheduler.h"
#include "../task/taskexecutor.h"
#include "../settings.h"
#include "../timing/immediatetiming.h"
#include "../timing/periodictiming.h"

#include "tcpsocket.h"
#include "udpsocket.h"

#include <QDataStream>
#include <QJsonDocument>
#include <QPointer>
#include <QTcpServer>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QStringList>
#include <QHash>
#include <QMutex>
#include <QReadWriteLock>
#include <QTimer>
#include <QDebug>
#include <QNetworkConfigurationManager>

LOGGER(NetworkManager);

class PeerRequest
{
public:
    QVariant toVariant()
    {
        QVariantMap map;
        map.insert("type", "peer_request");
        map.insert("connectionId", connectionId);
        map.insert("definition", measurementDefinition);
        map.insert("measurement", measurement);
        map.insert("peer", peer);
        map.insert("port", port);
        map.insert("protocol", protocol);
        return map;
    }

    static PeerRequest fromVariant(const QVariant& variant)
    {
        QVariantMap map = variant.toMap();

        PeerRequest request;
        request.connectionId = map.value("connectionId").toUuid();
        request.measurementDefinition = map.value("definition");
        request.measurement = map.value("measurement").toString();
        request.peer = map.value("peer").toString();
        request.port = map.value("port").toUInt();
        request.protocol = (NetworkManager::SocketType)map.value("protocol").toInt();
        return request;
    }

    QUuid connectionId;
    QVariant measurementDefinition;
    QString measurement;
    QString peer;
    quint16 port;
    NetworkManager::SocketType protocol;
};

class NetworkManager::Private : public QObject
{
    Q_OBJECT

public:
    Private(NetworkManager* q)
        : q(q)
    {
        connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
    }

    NetworkManager* q;

    // Properties
    QMutex mutex;
    QHash<QString, QObject*> objectHash;
    QHash<QString, QAbstractSocket*> socketHash;

    QTimer timer;
    QPointer<QUdpSocket> socket;
    QPointer<Scheduler> scheduler;
    QPointer<Settings> settings;

    QSet<QUuid> handledConnectionIds;

    quint16 localPort;

    QNetworkConfigurationManager ncm;

    // Functions
    QAbstractSocket* createSocket(NetworkManager::SocketType socketType);

    void updateSocket();
    void updateTimer();
    void processDatagram(const QByteArray& datagram, const QHostAddress& host, quint16 port);

public slots:
    void socketDestroyed(QObject* obj);
    void responseChanged();
    void timeout();
    void onDatagramReady();
};

QAbstractSocket *NetworkManager::Private::createSocket(NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = NULL;

    switch (socketType)
    {
    case TcpSocket:
        socket = new ::TcpSocket;
        break;

    case UdpSocket:
        socket = new ::UdpSocket;
        break;

    case UtpSocket:
        //socket = new UtpSocket;
        break;

    default:
        break;
    }

    if (socket)
    {
        connect(socket, SIGNAL(destroyed(QObject*)), this, SLOT(socketDestroyed(QObject*)));
    }

    return socket;
}

void NetworkManager::Private::socketDestroyed(QObject *obj)
{
    QString hostname = objectHash.key(obj);
    if (hostname.isEmpty())
    {
        return;
    }

    objectHash.remove(hostname);
    socketHash.remove(hostname);
}

void NetworkManager::Private::updateSocket()
{
    if (!socket.isNull())
    {
        delete socket.data();
        socket.clear();
    }

    QString keepaliveAddress = settings->config()->keepaliveAddress();
    RemoteHost remote = NetworkHelper::remoteHost(keepaliveAddress);
    if (!remote.isValid())
    {
        return;
    }

    localPort = remote.port;

    socket = qobject_cast<QUdpSocket*>( q->createConnection(NetworkManager::UdpSocket) );
    socket->setParent(this);
    connect(socket.data(), SIGNAL(readyRead()), this, SLOT(onDatagramReady()));
    if (!socket->bind(remote.port))
    {
        LOG_ERROR(QString("Unable to bind port %1: %2").arg(remote.port).arg(socket->errorString()));
    }
}

void NetworkManager::Private::updateTimer()
{
    TimingPtr timing = settings->config()->keepaliveSchedule();
    if (!timing)
    {
        return;
    }

    QSharedPointer<PeriodicTiming> periodicTiming = timing.dynamicCast<PeriodicTiming>();
    Q_ASSERT(periodicTiming);

    int interval = periodicTiming->period();
    if (interval < 1000)
    {
        LOG_INFO("Keepalive interval < 1 sec will not be accepted.");
        return;
    }
    else
    {
        LOG_INFO(QString("Keepalive set to %1 sec.").arg(interval/1000));
    }

    timer.setInterval(interval);
    timer.start();
}

class NetworkManagerMeasurementObserver : public MeasurementObserver
{
public:
    NetworkManager* networkManager;
    NetworkManager::SocketType socketType;
    quint16 localPort;

    QHostAddress host;
    quint16 port;

    // MeasurementObserver interface
    void created(const MeasurementPtr &measurement)
    {
        QAbstractSocket* socket = networkManager->createConnection(socketType);

        QUdpSocket* udpSocket = qobject_cast<QUdpSocket*>(socket);
        if (!udpSocket->bind(localPort))
        {
            LOG_ERROR("Cannot bind socket");
            return;
        }

        // ACK the connection
        udpSocket->writeDatagram(QByteArray(), host, port);
        measurement->setPeerSocket(udpSocket);
    }
};

void NetworkManager::Private::processDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)
{
    QString hostAndPort = QString("%1:%2").arg(host.toString()).arg(port);
    if (datagram.isEmpty())
    {
        LOG_DEBUG(QString("Received empty datagram from %1").arg(hostAndPort));
        return;
    }

    LOG_DEBUG(QString("Received datagram from %1: %2").arg(hostAndPort).arg(QString::fromUtf8(datagram)));
//    if (settings->config()->keepaliveAddress() == hostAndPort) {
    // Master server
    QJsonParseError error;
    QJsonDocument document = QJsonDocument::fromJson(datagram, &error);

    if (error.error == QJsonParseError::NoError)
    {
        PeerRequest request = PeerRequest::fromVariant(document.toVariant());

        if (handledConnectionIds.contains(request.connectionId))
        {
            LOG_DEBUG("Connection id is already handled, skipping second try");
            return;
        }

        handledConnectionIds.insert(request.connectionId);

        MeasurementObserver* observer = NULL;
        if (request.protocol == NetworkManager::UdpSocket)
        {
            NetworkManagerMeasurementObserver* tempObs = new NetworkManagerMeasurementObserver;
            tempObs->networkManager = q;
            tempObs->socketType = request.protocol;
            tempObs->localPort = 5106; // FIXME: Don't hardcode this here
            tempObs->host = host; //request.peer;
            tempObs->port = port;

            observer = tempObs;
        }

        // FIXME: We can't assign the Peer socket to Measurement since this is created in a separate thread
        //        and we can't access.

        TimingPtr timing(new ImmediateTiming);
        TestDefinitionPtr testDefinition(new TestDefinition(request.connectionId, request.measurement, timing, request.measurementDefinition));

        // Bypass scheduler and run directly on the executor
        scheduler->executor()->execute(testDefinition, observer);
    }
    else
    {
        LOG_ERROR(QString("Invalid JSon: %1").arg(error.errorString()));
    }
//    } else {
    // TODO: Process incoming data
//    }
}

void NetworkManager::Private::responseChanged()
{
    updateSocket();
    updateTimer();

    // Send the first timeout now
    timeout();
}

void NetworkManager::Private::timeout()
{
    RemoteHost remote = NetworkHelper::remoteHost(settings->config()->keepaliveAddress());
    if (!remote.isValid())
    {
        LOG_INFO("Invalid keepalive host");
        return;
    }

    QString sessionId = settings->sessionId();
    if (sessionId.isEmpty())
    {
        LOG_INFO("Empty session id");
        return;
    }

    QStringList srcIp;
    srcIp.append( NetworkHelper::localIpAddress().toString() );

    QVariantMap map;
    map.insert("type", "keepalive");
    map.insert("session_id", sessionId);
    map.insert("src_ip", srcIp);
    map.insert("src_port", localPort);

    QByteArray data = QJsonDocument::fromVariant(map).toJson();
    socket->writeDatagram(data, QHostAddress(remote.host), remote.port);

    LOG_INFO("Alive packet sent");
}

void NetworkManager::Private::onDatagramReady()
{
    while (socket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(socket->pendingDatagramSize());

        QHostAddress host;
        quint16 port;
        socket->readDatagram(datagram.data(), datagram.size(), &host, &port);

        // Process the datagram
        processDatagram(datagram, host, port);
    }
}

NetworkManager::NetworkManager(QObject *parent)
: QObject(parent)
, d(new Private(this))
{
}

NetworkManager::~NetworkManager()
{
    delete d;
}

bool NetworkManager::init(Scheduler* scheduler, Settings *settings)
{
    connect(settings->config(), SIGNAL(responseChanged()), d, SLOT(responseChanged()));

    d->scheduler = scheduler;
    d->settings = settings;
    d->responseChanged();

    emit d->ncm.updateConfigurations();

    return true;
}

void NetworkManager::setRunning(bool running)
{
    if (isRunning() == running)
    {
        return;
    }

    if ( !running )
    {
        d->timer.stop();
    }
    else
    {
        d->updateTimer();
    }
}

bool NetworkManager::isRunning() const
{
    return d->timer.isActive();
}

bool NetworkManager::onMobileConnection() const
{
    QList<QNetworkConfiguration> confList = d->ncm.allConfigurations(QNetworkConfiguration::Active);

    foreach(QNetworkConfiguration conf, confList)
    {
        QNetworkConfiguration::BearerType type = conf.bearerType();
        if (type != QNetworkConfiguration::BearerEthernet && type != QNetworkConfiguration::BearerWLAN)
        {
            return true;
        }
    }

    return false;
}

QAbstractSocket *NetworkManager::connection(const QString &hostname, NetworkManager::SocketType socketType) const
{
    return d->socketHash.value(hostname);
}

QAbstractSocket *NetworkManager::createConnection(NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = d->createSocket(socketType);
    if ( !socket )
    {
        qDebug() << "Unknown socket type requested";
        return NULL;
    }

    //d->socketHash.insert(hostname, socket);
    //d->objectHash.insert(hostname, socket);

    return socket;
}

QAbstractSocket *NetworkManager::establishConnection(const QString &hostname, const QString &measurement, const QVariant &definition, NetworkManager::SocketType socketType)
{
    QAbstractSocket* socket = d->createSocket(socketType);
    if ( !socket )
    {
        qDebug() << "Unknown socket type requested";
        return NULL;
    }

    RemoteHost remote = NetworkHelper::remoteHost(hostname);
    RemoteHost aliveRemote = NetworkHelper::remoteHost(d->settings->config()->keepaliveAddress());

    if (!aliveRemote.isValid())
    {
        LOG_ERROR(QString("Invalid alive remote: '%1' can't talk to alive server").arg(d->settings->config()->keepaliveAddress()));
        delete socket;
        return NULL;
    }

    PeerRequest request;
    request.connectionId = QUuid::createUuid();
    request.measurement = measurement;
    request.measurementDefinition = definition;
    request.peer = remote.host;
    request.port = aliveRemote.port;
    request.protocol = socketType;

    // If for some reason our packet gets routed back to us, don't handle it
    d->handledConnectionIds.insert(request.connectionId);

    QUdpSocket* testSocket = d->socket.data();
    if ( socketType != TcpSocket )
    {
        if (!socket->bind(remote.port))
        {
            LOG_ERROR(QString("Unable to bind source port to %1").arg(remote.port));
            delete socket;
            return NULL;
        }

        QUdpSocket* udpSocket = qobject_cast<QUdpSocket*>(socket);
        udpSocket->writeDatagram(QByteArray(), QHostAddress(remote.host), remote.port);

        testSocket = udpSocket;
    }

    QByteArray data = QJsonDocument::fromVariant(request.toVariant()).toJson();

    // Step one: Send test offer to peer directly
    testSocket->writeDatagram(data, QHostAddress(remote.host), d->localPort);

    // Step two: Send test offer to peer via alive-server
    testSocket->writeDatagram(data, QHostAddress(aliveRemote.host), aliveRemote.port);

    LOG_TRACE("Sent test offer to peer and alive-server");

    if ( socketType != UdpSocket )
    {
        // Final step: Connect to remote host
        //if (socket->waitForReadyRead(5000))
        //    return socket;

        const int tries = 20;
        for (int i=0; i < tries; ++i)
        {
            socket->connectToHost(remote.host, remote.port);
            if (socket->waitForConnected(5000/tries))
            {
                return socket;
            }
        }

        LOG_ERROR(QString("Unable to connect tcp socket in %3 tries to %1: %2").arg(hostname).arg(socket->errorString()).arg(tries));
    }
    else
    {
        if (!testSocket->waitForReadyRead(5000))
        {
            LOG_ERROR("Remote did not answer for 5 sec, aborting connection.");
        }
        else
        {
            // TODO: Read the first (empty) datagram
            QHostAddress packetHost;
            testSocket->readDatagram(0, 0, &packetHost);

            if (packetHost != QHostAddress(remote.host))
            {
                LOG_ERROR("Received connection packet from wrong host!");
            }
            else
            {
                return socket;
            }
        }
    }

    delete socket;
    return NULL;
}

QTcpServer *NetworkManager::createServerSocket()
{
    // TODO: Connect to traffic counter
    QTcpServer* server = new QTcpServer;
    return server;
}

#include "networkmanager.moc"
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -funknown-anytype -emit-llvm -o %t %s
// RUN: FileCheck -check-prefix COMMON %s < %t
// RUN: FileCheck -check-prefix X86_64 %s < %t
// RUN: %clang_cc1 -triple i386-apple-darwin10 -funknown-anytype -emit-llvm -o %t %s
// RUN: FileCheck -check-prefix COMMON %s < %t
// RUN: FileCheck -check-prefix I386 %s < %t

// x86-64 is the special case here because of its variadic convention.
// We want to ensure that it always uses a variadic convention even if
// other platforms do not.
// rdar://13731520

int test0() {
  extern __unknown_anytype test0_any;
  // COMMON: load i32* @test0_any
  return (int) test0_any;
}

int test1() {
  extern __unknown_anytype test1_any();
  // COMMON: call i32 @_Z9test1_anyv()
  return (int) test1_any();
}

extern "C" __unknown_anytype test2_any(...);
float test2() {
  // X86_64: call float (double, ...)* @test2_any(double {{[^,]+}})
  // I386: call float (double, ...)* @test2_any(double {{[^,]+}})
  return (float) test2_any(0.5f);
}

extern "C" __unknown_anytype test2a_any(...);
float test2a() {
  // X86_64: call float (float, ...)* @test2a_any(float {{[^,]+}})
  // I386: call float (float, ...)* @test2a_any(float {{[^,]+}})
  return (float) test2a_any((float) 0.5f);
}

float test3() {
  extern __unknown_anytype test3_any;
  // COMMON: [[FN:%.*]] = load float (i32)** @test3_any,
  // COMMON: call float [[FN]](i32 5)
  return ((float(*)(int)) test3_any)(5);
}

namespace test4 {
  extern __unknown_anytype test4_any1;
  extern __unknown_anytype test4_any2;

  int test() {
    // COMMON: load i32* @_ZN5test410test4_any1E
    // COMMON: load i8* @_ZN5test410test4_any2E
    return (int) test4_any1 + (char) test4_any2;
  }
}

extern "C" __unknown_anytype test5_any();
void test5() {
  // COMMON: call void @test5_any()
  return (void) test5_any();
}

extern "C" __unknown_anytype test6_any(float *);
long test6() {
  // COMMON: call i64 @test6_any(float* null)
  return (long long) test6_any(0);
}

struct Test7 {
  ~Test7();
};
extern "C" __unknown_anytype test7_any(int);
Test7 test7() {
  // COMMON: call void @test7_any({{%.*}}* sret {{%.*}}, i32 5)
  return (Test7) test7_any(5);
}

struct Test8 {
  __unknown_anytype foo();
  __unknown_anytype foo(int);

  void test();
};
void Test8::test() {
  float f;
  // COMMON: call i32 @_ZN5Test83fooEv(
  f = (int) foo();
  // COMMON: call i32 @_ZN5Test83fooEi(
  f = (int) foo(5);
  // COMMON: call i32 @_ZN5Test83fooEv(
  f = (float) this->foo();
  // COMMON: call i32 @_ZN5Test83fooEi(
  f = (float) this->foo(5);
}
void test8(Test8 *p) {
  double d;
  // COMMON: call i32 @_ZN5Test83fooEv(
  d = (double) p->foo();
  // COMMON: call i32 @_ZN5Test83fooEi(
  d = (double) p->foo(5);
  // COMMON: call i32 @_ZN5Test83fooEv(
  d = (bool) (*p).foo();
  // COMMON: call i32 @_ZN5Test83fooEi(
  d = (bool) (*p).foo(5);
}

extern "C" __unknown_anytype test9_foo;
void *test9() {
  // COMMON: ret i8* bitcast (i32* @test9_foo to i8*)
  return (int*) &test9_foo;
}

// Don't explode on this.
extern "C" __unknown_anytype test10_any(...);
void test10() {
  (void) test10_any(), (void) test10_any();
}

extern "C" __unknown_anytype malloc(...);
void test11() {
  void *s = (void*)malloc(12);
  void *d = (void*)malloc(435);
}
<commit_msg>Check for IRGen output when varag is used in -funknown-anytype  mode (in lldb use).<commit_after>// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -funknown-anytype -emit-llvm -o %t %s
// RUN: FileCheck -check-prefix COMMON %s < %t
// RUN: FileCheck -check-prefix X86_64 %s < %t
// RUN: %clang_cc1 -triple i386-apple-darwin10 -funknown-anytype -emit-llvm -o %t %s
// RUN: FileCheck -check-prefix COMMON %s < %t
// RUN: FileCheck -check-prefix I386 %s < %t

// x86-64 is the special case here because of its variadic convention.
// We want to ensure that it always uses a variadic convention even if
// other platforms do not.
// rdar://13731520

int test0() {
  extern __unknown_anytype test0_any;
  // COMMON: load i32* @test0_any
  return (int) test0_any;
}

int test1() {
  extern __unknown_anytype test1_any();
  // COMMON: call i32 @_Z9test1_anyv()
  return (int) test1_any();
}

extern "C" __unknown_anytype test2_any(...);
float test2() {
  // X86_64: call float (double, ...)* @test2_any(double {{[^,]+}})
  // I386: call float (double, ...)* @test2_any(double {{[^,]+}})
  return (float) test2_any(0.5f);
}

extern "C" __unknown_anytype test2a_any(...);
float test2a() {
  // X86_64: call float (float, ...)* @test2a_any(float {{[^,]+}})
  // I386: call float (float, ...)* @test2a_any(float {{[^,]+}})
  return (float) test2a_any((float) 0.5f);
}

float test3() {
  extern __unknown_anytype test3_any;
  // COMMON: [[FN:%.*]] = load float (i32)** @test3_any,
  // COMMON: call float [[FN]](i32 5)
  return ((float(*)(int)) test3_any)(5);
}

namespace test4 {
  extern __unknown_anytype test4_any1;
  extern __unknown_anytype test4_any2;

  int test() {
    // COMMON: load i32* @_ZN5test410test4_any1E
    // COMMON: load i8* @_ZN5test410test4_any2E
    return (int) test4_any1 + (char) test4_any2;
  }
}

extern "C" __unknown_anytype test5_any();
void test5() {
  // COMMON: call void @test5_any()
  return (void) test5_any();
}

extern "C" __unknown_anytype test6_any(float *);
long test6() {
  // COMMON: call i64 @test6_any(float* null)
  return (long long) test6_any(0);
}

struct Test7 {
  ~Test7();
};
extern "C" __unknown_anytype test7_any(int);
Test7 test7() {
  // COMMON: call void @test7_any({{%.*}}* sret {{%.*}}, i32 5)
  return (Test7) test7_any(5);
}

struct Test8 {
  __unknown_anytype foo();
  __unknown_anytype foo(int);

  void test();
};
void Test8::test() {
  float f;
  // COMMON: call i32 @_ZN5Test83fooEv(
  f = (int) foo();
  // COMMON: call i32 @_ZN5Test83fooEi(
  f = (int) foo(5);
  // COMMON: call i32 @_ZN5Test83fooEv(
  f = (float) this->foo();
  // COMMON: call i32 @_ZN5Test83fooEi(
  f = (float) this->foo(5);
}
void test8(Test8 *p) {
  double d;
  // COMMON: call i32 @_ZN5Test83fooEv(
  d = (double) p->foo();
  // COMMON: call i32 @_ZN5Test83fooEi(
  d = (double) p->foo(5);
  // COMMON: call i32 @_ZN5Test83fooEv(
  d = (bool) (*p).foo();
  // COMMON: call i32 @_ZN5Test83fooEi(
  d = (bool) (*p).foo(5);
}

extern "C" __unknown_anytype test9_foo;
void *test9() {
  // COMMON: ret i8* bitcast (i32* @test9_foo to i8*)
  return (int*) &test9_foo;
}

// Don't explode on this.
extern "C" __unknown_anytype test10_any(...);
void test10() {
  (void) test10_any(), (void) test10_any();
}

extern "C" __unknown_anytype malloc(...);
void test11() {
  void *s = (void*)malloc(12);
  // COMMON: call i8* (i32, ...)* @malloc(i32 12)
  void *d = (void*)malloc(435);
  // COMMON: call i8* (i32, ...)* @malloc(i32 435)
}
<|endoftext|>


<commit_before>// Copyright 2014 BVLC and contributors.

#include <cmath>
#include <cstring>
#include <vector>

#include "gtest/gtest.h"
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/filler.hpp"
#include "caffe/vision_layers.hpp"
#include "caffe/test/test_gradient_check_util.hpp"

#include "caffe/test/test_caffe_main.hpp"

namespace caffe {

template <typename TypeParam>
class MVNLayerTest : public MultiDeviceTest<TypeParam> {
  typedef typename TypeParam::Dtype Dtype;
 protected:
  MVNLayerTest()
      : blob_bottom_(new Blob<Dtype>(2, 3, 4, 5)),
        blob_top_(new Blob<Dtype>()) {
    // fill the values
    FillerParameter filler_param;
    GaussianFiller<Dtype> filler(filler_param);
    filler.Fill(this->blob_bottom_);
    blob_bottom_vec_.push_back(blob_bottom_);
    blob_top_vec_.push_back(blob_top_);
  }
  virtual ~MVNLayerTest() { delete blob_bottom_; delete blob_top_; }
  Blob<Dtype>* const blob_bottom_;
  Blob<Dtype>* const blob_top_;
  vector<Blob<Dtype>*> blob_bottom_vec_;
  vector<Blob<Dtype>*> blob_top_vec_;
};

TYPED_TEST_CASE(MVNLayerTest, TestDtypesAndDevices);

TYPED_TEST(MVNLayerTest, TestForward) {
  typedef typename TypeParam::Dtype Dtype;
  LayerParameter layer_param;
  MVNLayer<Dtype> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_));
  layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_));
  // Test mean
  int num = this->blob_bottom_->num();
  int channels = this->blob_bottom_->channels();
  int height = this->blob_bottom_->height();
  int width = this->blob_bottom_->width();

  for (int i = 0; i < num; ++i) {
    for (int j = 0; j < channels; ++j) {
      Dtype sum = 0, var = 0;
      for (int k = 0; k < height; ++k) {
        for (int l = 0; l < width; ++l) {
          Dtype data = this->blob_top_->data_at(i, j, k, l);
          sum += data;
          var += data * data;
        }
      }
      sum /= height * width;
      var /= height * width;

      // expect zero mean
      EXPECT_GE(sum, -0.001);
      EXPECT_LE(sum, 0.001);
      // expect unit variance
      EXPECT_GE(var, 0.999);
      EXPECT_LE(var, 1.001);
    }
  }
}

TYPED_TEST(MVNLayerTest, TestGradient) {
  typedef typename TypeParam::Dtype Dtype;
  LayerParameter layer_param;
  MVNLayer<Dtype> layer(layer_param);
  GradientChecker<Dtype> checker(1e-2, 1e-3);
  checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_),
      &(this->blob_top_vec_));
}

}  // namespace caffe
<commit_msg>addressed Jeff's comment<commit_after>// Copyright 2014 BVLC and contributors.

#include <cmath>
#include <cstring>
#include <vector>

#include "gtest/gtest.h"
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/filler.hpp"
#include "caffe/vision_layers.hpp"
#include "caffe/test/test_gradient_check_util.hpp"

#include "caffe/test/test_caffe_main.hpp"

namespace caffe {

template <typename TypeParam>
class MVNLayerTest : public MultiDeviceTest<TypeParam> {
  typedef typename TypeParam::Dtype Dtype;
 protected:
  MVNLayerTest()
      : blob_bottom_(new Blob<Dtype>(2, 3, 4, 5)),
        blob_top_(new Blob<Dtype>()) {
    // fill the values
    FillerParameter filler_param;
    GaussianFiller<Dtype> filler(filler_param);
    filler.Fill(this->blob_bottom_);
    blob_bottom_vec_.push_back(blob_bottom_);
    blob_top_vec_.push_back(blob_top_);
  }
  virtual ~MVNLayerTest() { delete blob_bottom_; delete blob_top_; }
  Blob<Dtype>* const blob_bottom_;
  Blob<Dtype>* const blob_top_;
  vector<Blob<Dtype>*> blob_bottom_vec_;
  vector<Blob<Dtype>*> blob_top_vec_;
};

TYPED_TEST_CASE(MVNLayerTest, TestDtypesAndDevices);

TYPED_TEST(MVNLayerTest, TestForward) {
  typedef typename TypeParam::Dtype Dtype;
  LayerParameter layer_param;
  MVNLayer<Dtype> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_));
  layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_));
  // Test mean
  int num = this->blob_bottom_->num();
  int channels = this->blob_bottom_->channels();
  int height = this->blob_bottom_->height();
  int width = this->blob_bottom_->width();

  for (int i = 0; i < num; ++i) {
    for (int j = 0; j < channels; ++j) {
      Dtype sum = 0, var = 0;
      for (int k = 0; k < height; ++k) {
        for (int l = 0; l < width; ++l) {
          Dtype data = this->blob_top_->data_at(i, j, k, l);
          sum += data;
          var += data * data;
        }
      }
      sum /= height * width;
      var /= height * width;

      const Dtype kErrorBound = 0.001;
      // expect zero mean
      EXPECT_NEAR(0, sum, kErrorBound);
      // expect unit variance
      EXPECT_NEAR(1, var, kErrorBound);
    }
  }
}

TYPED_TEST(MVNLayerTest, TestGradient) {
  typedef typename TypeParam::Dtype Dtype;
  LayerParameter layer_param;
  MVNLayer<Dtype> layer(layer_param);
  GradientChecker<Dtype> checker(1e-2, 1e-3);
  checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_),
      &(this->blob_top_vec_));
}

}  // namespace caffe
<|endoftext|>