1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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);
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();
}
}
}
|