diff options
| author | Sebastian | 2010-05-12 19:42:27 +0200 |
|---|---|---|
| committer | Sebastian | 2010-05-12 19:42:27 +0200 |
| commit | ce3329047d378a14006ce74ec273ac59e3375303 (patch) | |
| tree | 782430f270b4c7aca1b35d5b7813518e3797c555 /src/net/pvsLocalhostCommunicator.cpp | |
| download | pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.gz pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.xz pvs-ce3329047d378a14006ce74ec273ac59e3375303.zip | |
initial import of latest svn version
Diffstat (limited to 'src/net/pvsLocalhostCommunicator.cpp')
| -rw-r--r-- | src/net/pvsLocalhostCommunicator.cpp | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/net/pvsLocalhostCommunicator.cpp b/src/net/pvsLocalhostCommunicator.cpp new file mode 100644 index 0000000..199b39c --- /dev/null +++ b/src/net/pvsLocalhostCommunicator.cpp @@ -0,0 +1,104 @@ +#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); + printf("Sending %d bytes to daemon...\n", 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) + { + printf("Error sending PVSMsg to daemon: %s\n", _sock->errorString().toUtf8().data()); + } + else + { + printf("Sent PVSMsg was incomplete.\n"); + } + stop(); + } + } +} |
