summaryrefslogblamecommitdiffstats
path: root/src/net/pvsLocalhostCommunicator.cpp
blob: 20783bb4a247848f5a6d5eb533d7bbc67fc268b7 (plain) (tree)




















































































                                                                                                           
                                                              







                                                                        
                                                                                               


                
                                                      




                   
#include "pvsLocalhostCommunicator.h"
#include "src/util/consoleLogger.h"
#include "src/net/pvsMsg.h"

static QHostAddress localhost(QHostAddress::LocalHost);
#define localport 14913

PVSLocalhostCommunicator::PVSLocalhostCommunicator(QString path)
{
    _isServer = _isRunning = false;
    _sock = NULL;
}

void PVSLocalhostCommunicator::run()
{
    if (_isRunning)
        return;

    // First try to run as server
    _sock = new QUdpSocket();
    // We'll bind only to localhost, so nobody else can send commands (from remote hosts)
    // Otherwise we had to check the remote addr when receiving a datagram, but this
    // wouldn't be as secure since you can easily fake it
    _sock->bind(localhost, localport); // QUdpSocket::DontShareAddress? would need root
    connect(_sock, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));

    if (_sock->state() == QAbstractSocket::BoundState)
    {
        // OK, we are the first daemon to run
        _isServer = true;
        _isRunning = true;
        return;
    }
    if (_sock->bind())
    {
        _isRunning = true;
    }
}

void PVSLocalhostCommunicator::stop()
{
    _isRunning = false;
    _sock->deleteLater();
    _sock = NULL;
}

void PVSLocalhostCommunicator::sock_dataArrival()
{
    if (_sock == NULL) return;

    qint64 dsize;
    while ((dsize = _sock->pendingDatagramSize()) > -1)   // returns -1 if no more datagrams are pending
    {
        if (dsize < 4)   // anything shorter than 4 bytes is not a valid PVSMsg anyways, so take a shortcut
        {
            char x;
            _sock->readDatagram(&x, 1, NULL, NULL);
            continue; // discard the packet and see if there is more
        }

        PVSMsg receiver;
        receiver.readMessage(_sock, true);

        if (receiver.isMsgComplete())
        {
            // we received a message, so fire away
            ConsoleLog writeNetwork(QString("Received UDS command: ").append(receiver.getIdent()));
            _daemonDispatcher.fire(receiver.getIdent(), receiver);
        } // If the msg is not complete we have to discard it, since UDP
        // is packet oriented and we could not say for sure if the next one
        // would be the continuation of this msg.
        // Usually on the loopback interface it is safe to send datagrams
        // up to 8kb, so this is not be an issue anyway.
    }
}

void PVSLocalhostCommunicator::sendCommand(QString ident, QString cmd)
{
    if (_isRunning && !_isServer && _sock != NULL)
    {
        PVSMsg sender(PVSDAEMON, ident, cmd);
        char *data;
        int len;
        sender.getBinaryData(data, len);
        QByteArray qba(data, len);
        qDebug("Sending %d bytes to daemon...", qba.length());
        qint64 result = _sock->writeDatagram(qba, localhost, localport);
        _sock->waitForBytesWritten(100);

        // simply bail out on an error or disconnect or whatever
        if (result != len)
        {
            if (result == -1)
            {
                qDebug("Error sending PVSMsg to daemon: %s", qPrintable(_sock->errorString()));
            }
            else
            {
                qDebug("Sent PVSMsg was incomplete.");
            }
            stop();
        }
    }
}