kopia lustrzana https://gitlab.com/eliggett/wfview
Merge remote-tracking branch 'origin/lan-alpha' into ui-enhance
commit
74c6d65e1d
|
@ -298,18 +298,25 @@ void udpHandler::sendRequestSerialAndAudio()
|
|||
0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
static_cast<quint8>(myId & 0xff), static_cast<quint8>(myId >> 8 & 0xff), static_cast<quint8>(myId >> 16 & 0xff), static_cast<quint8>(myId >> 24 & 0xff),
|
||||
static_cast<quint8>(remoteId & 0xff), static_cast<quint8>(remoteId >> 8 & 0xff), static_cast<quint8>(remoteId >> 16 & 0xff), static_cast<quint8>(remoteId >> 24 & 0xff),
|
||||
|
||||
0x00, 0x00, 0x00, 0x80, 0x01, 0x03, 0x00, static_cast<quint8>(authInnerSendSeq & 0xff), static_cast<quint8>(authInnerSendSeq >> 8 & 0xff), 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x01, 0x01, rxCodec, txCodec, 0x00, 0x00, static_cast<quint8>(rxSampleRate >> 8 & 0xff), static_cast<quint8>(rxSampleRate & 0xff),
|
||||
0x00, 0x00, static_cast<quint8>(txSampleRate >> 8 & 0xff), static_cast<quint8>(txSampleRate & 0xff),
|
||||
0x00, 0x00, static_cast<quint8>(civPort >> 8 & 0xff), static_cast<quint8>(civPort & 0xff),
|
||||
|
@ -346,6 +353,7 @@ void udpHandler::sendLogin() // Only used on control stream.
|
|||
qDebug() << this->metaObject()->className() << ": Sending login packet";
|
||||
|
||||
uint16_t authStartID = rand() | rand() << 8;
|
||||
//uint16_t authStartID = 0x7866;
|
||||
QByteArray usernameEncoded;
|
||||
QByteArray passwordEncoded;
|
||||
passcode(username, usernameEncoded);
|
||||
|
|
|
@ -0,0 +1,760 @@
|
|||
#include "udpserver.h"
|
||||
|
||||
udpServer::udpServer(SERVERCONFIG config) :
|
||||
config(config)
|
||||
{
|
||||
qDebug() << "Starting udp server";
|
||||
}
|
||||
|
||||
void udpServer::init()
|
||||
{
|
||||
|
||||
srand(time(NULL)); // Generate random key
|
||||
|
||||
// Convoluted way to find the external IP address, there must be a better way????
|
||||
QString localhostname = QHostInfo::localHostName();
|
||||
QList<QHostAddress> hostList = QHostInfo::fromName(localhostname).addresses();
|
||||
foreach(const QHostAddress & address, hostList)
|
||||
{
|
||||
if (address.protocol() == QAbstractSocket::IPv4Protocol && address.isLoopback() == false)
|
||||
{
|
||||
localIP = QHostAddress(address.toString());
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t addr = localIP.toIPv4Address();
|
||||
|
||||
qDebug() << " Got: " << QHostAddress(addr).toString();
|
||||
|
||||
|
||||
controlId = (addr >> 8 & 0xff) << 24 | (addr & 0xff) << 16 | (config.controlPort & 0xffff);
|
||||
civId = (addr >> 8 & 0xff) << 24 | (addr & 0xff) << 16 | (config.civPort & 0xffff);
|
||||
audioId = (addr >> 8 & 0xff) << 24 | (addr & 0xff) << 16 | (config.audioPort & 0xffff);
|
||||
|
||||
udpControl = new QUdpSocket(this);
|
||||
udpControl->bind(config.controlPort);
|
||||
|
||||
udpCiv = new QUdpSocket(this);
|
||||
udpAudio = new QUdpSocket(this);
|
||||
|
||||
udpAudio->bind(config.audioPort);
|
||||
udpCiv->bind(config.civPort);
|
||||
|
||||
QUdpSocket::connect(udpControl, &QUdpSocket::readyRead, this, &udpServer::controlReceived);
|
||||
QUdpSocket::connect(udpAudio, &QUdpSocket::readyRead, this, &udpServer::audioReceived);
|
||||
QUdpSocket::connect(udpCiv, &QUdpSocket::readyRead, this, &udpServer::civReceived);
|
||||
|
||||
}
|
||||
|
||||
udpServer::~udpServer()
|
||||
{
|
||||
qDebug() << "Closing udpServer";
|
||||
|
||||
|
||||
foreach(CLIENT * client, controlClients)
|
||||
{
|
||||
client->idleTimer->stop();
|
||||
delete client->idleTimer;
|
||||
client->pingTimer->stop();
|
||||
delete client->pingTimer;
|
||||
client->wdTimer->stop();
|
||||
delete client->wdTimer;
|
||||
//delete& client; // Not sure how safe this is?
|
||||
}
|
||||
foreach(CLIENT * client, civClients)
|
||||
{
|
||||
client->idleTimer->stop();
|
||||
delete client->idleTimer;
|
||||
client->pingTimer->stop();
|
||||
delete client->pingTimer;
|
||||
//delete& client; // Not sure how safe this is?
|
||||
}
|
||||
foreach(CLIENT * client, audioClients)
|
||||
{
|
||||
client->pingTimer->stop();
|
||||
delete client->pingTimer;
|
||||
//delete& client; // Not sure how safe this is?
|
||||
}
|
||||
|
||||
|
||||
if (udpControl != Q_NULLPTR) {
|
||||
udpControl->close();
|
||||
delete udpControl;
|
||||
}
|
||||
if (udpCiv != Q_NULLPTR) {
|
||||
udpCiv->close();
|
||||
delete udpCiv;
|
||||
}
|
||||
if (udpAudio != Q_NULLPTR) {
|
||||
udpAudio->close();
|
||||
delete udpAudio;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void udpServer::controlReceived()
|
||||
{
|
||||
// Received data on control port.
|
||||
while (udpControl->hasPendingDatagrams()) {
|
||||
QNetworkDatagram datagram = udpControl->receiveDatagram();
|
||||
QByteArray r = datagram.data();
|
||||
CLIENT* current = Q_NULLPTR;
|
||||
foreach(CLIENT * client, controlClients)
|
||||
{
|
||||
if (client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort())
|
||||
{
|
||||
current = client;
|
||||
}
|
||||
}
|
||||
if (current == Q_NULLPTR)
|
||||
{
|
||||
current = new CLIENT();
|
||||
current->connected = true;
|
||||
current->isStreaming = false;
|
||||
current->timeConnected = QDateTime::currentDateTime();
|
||||
current->ipAddress = datagram.senderAddress();
|
||||
current->port = datagram.senderPort();
|
||||
current->civPort = config.civPort;
|
||||
current->audioPort = config.audioPort;
|
||||
current->myId = controlId;
|
||||
current->remoteId = qFromLittleEndian<quint32>(r.mid(8, 4));
|
||||
current->socket = udpControl;
|
||||
current->innerPingSeq = (quint16)rand();
|
||||
current->pingSeq = (quint8)rand() << 8 | (quint8)rand();
|
||||
current->pingTimer = new QTimer();
|
||||
current->idleTimer = new QTimer();
|
||||
current->wdTimer = new QTimer();
|
||||
connect(current->pingTimer, &QTimer::timeout, this, std::bind(&udpServer::sendPing, this, current, (quint16)0x00, false));
|
||||
connect(current->idleTimer, &QTimer::timeout, this, std::bind(&udpServer::sendIdle, this, current, (quint16)0x00));
|
||||
connect(current->wdTimer, &QTimer::timeout, this, std::bind(&udpServer::sendWatchdog, this, current));
|
||||
current->pingTimer->start(100);
|
||||
current->idleTimer->start(100);
|
||||
current->wdTimer->start(10000);
|
||||
qDebug() << "New connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port);
|
||||
controlClients.append(current);
|
||||
}
|
||||
|
||||
current->lastHeard = QDateTime::currentDateTime();
|
||||
quint16 gotSeq = qFromLittleEndian<quint16>(r.mid(0x06, 2));
|
||||
|
||||
switch (r.length())
|
||||
{
|
||||
case (0x10):
|
||||
if (r.mid(0, 8) == QByteArrayLiteral("\x10\x00\x00\x00\x03\x00\x00\x00")) {
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'are you there'";
|
||||
current->remoteId = qFromLittleEndian<quint32>(r.mid(8, 4));
|
||||
sendIAmHere(current);
|
||||
} // This is This is "Are you ready" in response to "I am here".
|
||||
else if (r.mid(0, 8) == QByteArrayLiteral("\x10\x00\x00\x00\x06\x00\x01\x00"))
|
||||
{
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'Are you ready'";
|
||||
current->remoteId = qFromLittleEndian<quint32>(r.mid(8, 4));
|
||||
sendIAmReady(current);
|
||||
} // This is a retransmit request
|
||||
else if (r.mid(0, 6) == QByteArrayLiteral("\x10\x00\x00\x00\x01\x00"))
|
||||
{
|
||||
// Just send an idle for now!
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'retransmit' request for " << gotSeq;
|
||||
sendIdle(current, gotSeq);
|
||||
|
||||
} // This is a disconnect request
|
||||
else if (r.mid(0, 6) == QByteArrayLiteral("\x10\x00\x00\x00\x05\x00"))
|
||||
{
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'disconnect' request";
|
||||
sendIdle(current, gotSeq);
|
||||
current->idleTimer->stop();
|
||||
current->pingTimer->stop();
|
||||
current->wdTimer->stop();
|
||||
delete current;
|
||||
controlClients.removeOne(current);
|
||||
|
||||
}
|
||||
break;
|
||||
case (0x14):
|
||||
// Watchdog packet.
|
||||
break;
|
||||
case (0x15):
|
||||
if (r.mid(1, 5) == QByteArrayLiteral("\x00\x00\x00\x07\x00"))
|
||||
{
|
||||
// It is a ping request/response
|
||||
|
||||
if (r[16] == (char)0x00)
|
||||
{
|
||||
current->rxPingSeq = qFromLittleEndian<quint32>(r.mid(0x11, 4));
|
||||
sendPing(current, gotSeq, true);
|
||||
}
|
||||
else if (r[16] == (char)0x01) {
|
||||
// A Reply to our ping!
|
||||
if (gotSeq == current->pingSeq) {
|
||||
current->pingSeq++;
|
||||
}
|
||||
else {
|
||||
qDebug() << current->ipAddress.toString() << ": Server got out of sequence ping reply. Got: " << gotSeq << " expecting: " << current->pingSeq;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case (0x40):
|
||||
// Token request
|
||||
current->authInnerSeq = qFromLittleEndian<quint32>(r.mid(0x16, 4));
|
||||
if (r[0x15] == (char)0x02) {
|
||||
// Request for new token
|
||||
//current->tokenTx = (quint16)rand();
|
||||
qDebug() << current->ipAddress.toString() << ": Received create token request";
|
||||
sendCapabilities(current);
|
||||
current->authInnerSeq = 0x00;
|
||||
sendConnectionInfo(current);
|
||||
}
|
||||
else {
|
||||
qDebug() << current->ipAddress.toString() << ": Received token request";
|
||||
sendTokenResponse(current, r[0x15]);
|
||||
}
|
||||
break;
|
||||
case (0x80):
|
||||
if (r.mid(0, 8) == QByteArrayLiteral("\x80\x00\x00\x00\x00\x00\x01\x00"))
|
||||
{
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'login'";
|
||||
bool userOk = false;
|
||||
foreach(SERVERUSER user, config.users)
|
||||
{
|
||||
QByteArray usercomp;
|
||||
passcode(user.username, usercomp);
|
||||
QByteArray passcomp;
|
||||
passcode(user.password, passcomp);
|
||||
if (r.mid(0x40, usercomp.length()) == usercomp && r.mid(0x50, passcomp.length()) == passcomp)
|
||||
{
|
||||
userOk = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Generate login response
|
||||
current->clientName = parseNullTerminatedString(r, 0x60);
|
||||
current->authInnerSeq = qFromLittleEndian<quint32>(r.mid(0x16, 4));
|
||||
current->tokenRx = qFromLittleEndian<quint16>(r.mid(0x1a, 2));
|
||||
current->tokenTx = (quint32)((quint16)rand() | (quint16)rand() << 16);
|
||||
|
||||
if (userOk) {
|
||||
sendLoginResponse(current, gotSeq, true);
|
||||
}
|
||||
else {
|
||||
qDebug() << "Username no match!";
|
||||
sendLoginResponse(current, gotSeq, false);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 0x90:
|
||||
qDebug() << current->ipAddress.toString() << ": Received request for radio connection";
|
||||
// Request to start audio and civ!
|
||||
current->isStreaming = true;
|
||||
current->rxCodec = r[0x72];
|
||||
current->txCodec = r[0x73];
|
||||
current->rxSampleRate = qFromBigEndian<quint16>(r.mid(0x76, 2));
|
||||
current->txSampleRate = qFromBigEndian<quint16>(r.mid(0x7a, 2));
|
||||
//current->civPort = qFromBigEndian<quint16>(r.mid(0x7e, 2)); // Ignore port sent from client and tell it which to use
|
||||
//current->audioPort = qFromBigEndian<quint16>(r.mid(0x82, 2));
|
||||
current->txBufferLen = qFromBigEndian<quint16>(r.mid(0x86, 2));
|
||||
current->authInnerSeq = qFromLittleEndian<quint32>(r.mid(0x16, 4));
|
||||
current->connSeq = qFromLittleEndian<quint32>(r.mid(0x2c, 4));
|
||||
sendStatus(current);
|
||||
sendConnectionInfo(current);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
qDebug() << "Unknown length packet received: " << r.length();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void udpServer::civReceived()
|
||||
{
|
||||
while (udpCiv->hasPendingDatagrams()) {
|
||||
QNetworkDatagram datagram = udpCiv->receiveDatagram();
|
||||
QByteArray r = datagram.data();
|
||||
|
||||
CLIENT* current = Q_NULLPTR;
|
||||
|
||||
foreach(CLIENT * client, civClients)
|
||||
{
|
||||
if (client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort())
|
||||
{
|
||||
current = client;
|
||||
}
|
||||
}
|
||||
if (current == Q_NULLPTR)
|
||||
{
|
||||
current = new CLIENT();
|
||||
current->connected = true;
|
||||
current->timeConnected = QDateTime::currentDateTime();
|
||||
current->ipAddress = datagram.senderAddress();
|
||||
current->port = datagram.senderPort();
|
||||
current->myId = civId;
|
||||
current->remoteId = qFromLittleEndian<quint32>(r.mid(8, 4));
|
||||
current->socket = udpCiv;
|
||||
current->innerPingSeq = (quint16)rand();
|
||||
current->pingSeq = (quint8)rand() << 8 | (quint8)rand();
|
||||
current->pingTimer = new QTimer();
|
||||
current->idleTimer = new QTimer();
|
||||
current->wdTimer = new QTimer();
|
||||
connect(current->pingTimer, &QTimer::timeout, this, std::bind(&udpServer::sendPing, this, current, (quint16)0x00, false));
|
||||
connect(current->idleTimer, &QTimer::timeout, this, std::bind(&udpServer::sendIdle, this, current, (quint16)0x00));
|
||||
current->pingTimer->start(100);
|
||||
current->idleTimer->start(100);
|
||||
qDebug() << "New connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port);
|
||||
civClients.append(current);
|
||||
}
|
||||
|
||||
current->lastHeard = QDateTime::currentDateTime();
|
||||
quint16 gotSeq = qFromLittleEndian<quint16>(r.mid(0x06, 2));
|
||||
|
||||
switch (r.length())
|
||||
{
|
||||
case (0x10):
|
||||
if (r.mid(0, 8) == QByteArrayLiteral("\x10\x00\x00\x00\x03\x00\x00\x00")) {
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'are you there'";
|
||||
current->remoteId = qFromLittleEndian<quint32>(r.mid(8, 4));
|
||||
sendIAmHere(current);
|
||||
} // This is This is "Are you ready" in response to "I am here".
|
||||
else if (r.mid(0, 8) == QByteArrayLiteral("\x10\x00\x00\x00\x06\x00\x01\x00"))
|
||||
{
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'Are you ready'";
|
||||
current->remoteId = qFromLittleEndian<quint32>(r.mid(8, 4));
|
||||
sendIAmReady(current);
|
||||
} // This is a retransmit request
|
||||
else if (r.mid(0, 6) == QByteArrayLiteral("\x10\x00\x00\x00\x01\x00"))
|
||||
{
|
||||
// Just send an idle for now!
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'retransmit' request for " << gotSeq;
|
||||
sendIdle(current, gotSeq);
|
||||
|
||||
} // This is a disconnect request
|
||||
else if (r.mid(0, 6) == QByteArrayLiteral("\x10\x00\x00\x00\x05\x00"))
|
||||
{
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'disconnect' request";
|
||||
sendIdle(current, gotSeq);
|
||||
current->idleTimer->stop();
|
||||
current->pingTimer->stop();
|
||||
delete current;
|
||||
controlClients.removeOne(current);
|
||||
|
||||
}
|
||||
break;
|
||||
case (0x14):
|
||||
// Watchdog packet.
|
||||
break;
|
||||
case (0x15):
|
||||
if (r.mid(1, 5) == QByteArrayLiteral("\x00\x00\x00\x07\x00"))
|
||||
{
|
||||
// It is a ping request/response
|
||||
|
||||
if (r[16] == (char)0x00)
|
||||
{
|
||||
current->rxPingSeq = qFromLittleEndian<quint32>(r.mid(0x11, 4));
|
||||
sendPing(current, gotSeq, true);
|
||||
}
|
||||
else if (r[16] == (char)0x01) {
|
||||
// A Reply to our ping!
|
||||
if (gotSeq == current->pingSeq) {
|
||||
current->pingSeq++;
|
||||
}
|
||||
else {
|
||||
qDebug() << current->ipAddress.toString() << ": Civ got out of sequence ping reply. Got: " << gotSeq << " expecting: " << current->pingSeq;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void udpServer::audioReceived()
|
||||
{
|
||||
while (udpAudio->hasPendingDatagrams()) {
|
||||
QNetworkDatagram datagram = udpAudio->receiveDatagram();
|
||||
QByteArray r = datagram.data();
|
||||
CLIENT* current = Q_NULLPTR;
|
||||
|
||||
foreach(CLIENT * client, audioClients)
|
||||
{
|
||||
if (client != Q_NULLPTR && client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort())
|
||||
{
|
||||
current = client;
|
||||
}
|
||||
}
|
||||
if (current == Q_NULLPTR)
|
||||
{
|
||||
current = new CLIENT();
|
||||
current->connected = true;
|
||||
current->timeConnected = QDateTime::currentDateTime();
|
||||
current->ipAddress = datagram.senderAddress();
|
||||
current->port = datagram.senderPort();
|
||||
current->myId = audioId;
|
||||
current->remoteId = qFromLittleEndian<quint32>(r.mid(8, 4));
|
||||
current->socket = udpAudio;
|
||||
current->innerPingSeq = (quint16)rand();
|
||||
current->pingSeq = (quint8)rand() << 8 | (quint8)rand();
|
||||
current->pingTimer = new QTimer();
|
||||
connect(current->pingTimer, &QTimer::timeout, this, std::bind(&udpServer::sendPing, this, current, (quint16)0x00, false));
|
||||
current->pingTimer->start(100);
|
||||
qDebug() << "New connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port);
|
||||
audioClients.append(current);
|
||||
}
|
||||
|
||||
current->lastHeard = QDateTime::currentDateTime();
|
||||
quint16 gotSeq = qFromLittleEndian<quint16>(r.mid(0x06, 2));
|
||||
|
||||
switch (r.length())
|
||||
{
|
||||
case (0x10):
|
||||
if (r.mid(0, 8) == QByteArrayLiteral("\x10\x00\x00\x00\x03\x00\x00\x00")) {
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'are you there'";
|
||||
current->remoteId = qFromLittleEndian<quint32>(r.mid(8, 4));
|
||||
sendIAmHere(current);
|
||||
} // This is This is "Are you ready" in response to "I am here".
|
||||
else if (r.mid(0, 8) == QByteArrayLiteral("\x10\x00\x00\x00\x06\x00\x01\x00"))
|
||||
{
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'Are you ready'";
|
||||
current->remoteId = qFromLittleEndian<quint32>(r.mid(8, 4));
|
||||
sendIAmReady(current);
|
||||
} // This is a retransmit request
|
||||
else if (r.mid(0, 6) == QByteArrayLiteral("\x10\x00\x00\x00\x01\x00"))
|
||||
{
|
||||
// Just send an idle for now!
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'retransmit' request for " << gotSeq;
|
||||
sendIdle(current, gotSeq);
|
||||
|
||||
} // This is a disconnect request
|
||||
else if (r.mid(0, 6) == QByteArrayLiteral("\x10\x00\x00\x00\x05\x00"))
|
||||
{
|
||||
qDebug() << current->ipAddress.toString() << ": Received 'disconnect' request";
|
||||
sendIdle(current, gotSeq);
|
||||
current->pingTimer->stop();
|
||||
delete current;
|
||||
controlClients.removeOne(current);
|
||||
|
||||
}
|
||||
break;
|
||||
case (0x14):
|
||||
// Watchdog packet.
|
||||
break;
|
||||
case (0x15):
|
||||
if (r.mid(1, 5) == QByteArrayLiteral("\x00\x00\x00\x07\x00"))
|
||||
{
|
||||
// It is a ping request/response
|
||||
|
||||
if (r[16] == (char)0x00)
|
||||
{
|
||||
current->rxPingSeq = qFromLittleEndian<quint32>(r.mid(0x11, 4));
|
||||
sendPing(current, gotSeq, true);
|
||||
}
|
||||
else if (r[16] == (char)0x01) {
|
||||
// A Reply to our ping!
|
||||
if (gotSeq == current->pingSeq) {
|
||||
current->pingSeq++;
|
||||
}
|
||||
else {
|
||||
qDebug() << current->ipAddress.toString() << ": Civ got out of sequence ping reply. Got: " << gotSeq << " expecting: " << current->pingSeq;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define IDLE_SIZE 0x10
|
||||
|
||||
void udpServer::sendIAmHere(CLIENT* c)
|
||||
{
|
||||
qDebug() << c->ipAddress.toString() << ": Sending I am here...";
|
||||
|
||||
quint8 p[IDLE_SIZE];
|
||||
memset(p, 0x0, sizeof(p));
|
||||
qToLittleEndian(sizeof(p), p + 0x00);
|
||||
p[0x04] = (char)0x04;
|
||||
qToLittleEndian(c->txSeq, p + 0x06);
|
||||
qToLittleEndian(c->myId, p + 0x08);
|
||||
qToLittleEndian(c->remoteId, p + 0x0c);
|
||||
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
c->txSeq++;
|
||||
return;
|
||||
}
|
||||
|
||||
void udpServer::sendIAmReady(CLIENT* c)
|
||||
{
|
||||
qDebug() << c->ipAddress.toString() << ": Sending I am ready...";
|
||||
|
||||
quint8 p[IDLE_SIZE];
|
||||
memset(p, 0x0, sizeof(p));
|
||||
qToLittleEndian(sizeof(p), p + 0x00);
|
||||
p[0x04] = (char)0x06;
|
||||
qToLittleEndian(c->txSeq, p + 0x06);
|
||||
qToLittleEndian(c->myId, p + 0x08);
|
||||
qToLittleEndian(c->remoteId, p + 0x0c);
|
||||
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
c->txSeq++;
|
||||
return;
|
||||
}
|
||||
|
||||
void udpServer::sendIdle(CLIENT* c, quint16 seq)
|
||||
{
|
||||
if (seq == 0x00)
|
||||
{
|
||||
seq = c->txSeq;
|
||||
c->txSeq++;
|
||||
}
|
||||
|
||||
quint8 p[IDLE_SIZE];
|
||||
memset(p, 0x0, sizeof(p));
|
||||
qToLittleEndian(sizeof(p), p + 0x00);
|
||||
qToLittleEndian(seq, p + 0x06);
|
||||
qToLittleEndian(c->myId, p + 0x08);
|
||||
qToLittleEndian(c->remoteId, p + 0x0c);
|
||||
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define PING_SIZE 0x15
|
||||
void udpServer::sendPing(CLIENT* c, quint16 seq, bool reply)
|
||||
{
|
||||
//qDebug() << c->ipAddress.toString() << ": Sending Ping";
|
||||
|
||||
quint32 pingSeq = 0;
|
||||
quint8 pingReply = 0;
|
||||
if (reply) {
|
||||
pingSeq = c->rxPingSeq;
|
||||
pingReply = 1;
|
||||
}
|
||||
else {
|
||||
pingSeq = (quint32)((quint8)(rand() & 0xff)) | (quint16)c->innerPingSeq << 8 | (quint8)0x06 << 24;
|
||||
seq = c->pingSeq;
|
||||
}
|
||||
|
||||
// First byte of pings "from" server can be either 0x00 or packet length!
|
||||
|
||||
quint8 p[PING_SIZE];
|
||||
memset(p, 0x0, sizeof(p));
|
||||
if (!reply) {
|
||||
qToLittleEndian(sizeof(p), p + 0x00);
|
||||
}
|
||||
p[0x04] = (char)0x07;
|
||||
qToLittleEndian(seq, p + 0x06);
|
||||
qToLittleEndian(c->myId, p + 0x08);
|
||||
qToLittleEndian(c->remoteId, p + 0x0c);
|
||||
qToLittleEndian(pingSeq, p + 0x11);
|
||||
p[0x10] = pingReply;
|
||||
|
||||
c->innerPingSeq++;
|
||||
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
return;
|
||||
}
|
||||
|
||||
#define LOGINRESP_SIZE 0x60
|
||||
void udpServer::sendLoginResponse(CLIENT* c,quint16 seq, bool allowed)
|
||||
{
|
||||
qDebug() << c->ipAddress.toString() << ": Sending Login response: " << c->txSeq;
|
||||
|
||||
quint8 p[LOGINRESP_SIZE];
|
||||
memset(p, 0x0, sizeof(p));
|
||||
qToLittleEndian(sizeof(p), p + 0x00);
|
||||
qToLittleEndian(seq, p + 0x06);
|
||||
qToLittleEndian(c->myId, p + 0x08);
|
||||
qToLittleEndian(c->remoteId, p + 0x0c);
|
||||
memcpy(p + 0x13, QByteArrayLiteral("\x50\x02\00").constData(), 3);
|
||||
qToLittleEndian(c->authInnerSeq, p + 0x16);
|
||||
qToLittleEndian(c->tokenRx, p + 0x1a);
|
||||
qToLittleEndian(c->tokenTx, p + 0x1c);
|
||||
|
||||
if (!allowed) {
|
||||
memcpy(p + 0x30, QByteArrayLiteral("\xFF\xFF\xFF\xFE").constData(), 4);
|
||||
c->idleTimer->stop();
|
||||
c->pingTimer->stop();
|
||||
c->wdTimer->stop();
|
||||
}
|
||||
else {
|
||||
//memcpy(p + 0x40, QByteArrayLiteral("FTTH").constData(), 4);
|
||||
memcpy(p + 0x40, QByteArrayLiteral("WFVIEW").constData(), 6);
|
||||
}
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
c->idleTimer->start(100);
|
||||
return;
|
||||
}
|
||||
|
||||
#define CAP_SIZE 0xa8
|
||||
void udpServer::sendCapabilities(CLIENT* c)
|
||||
{
|
||||
qDebug() << c->ipAddress.toString() << ": Sending Capabilities :" << c->txSeq;
|
||||
|
||||
quint8 p[CAP_SIZE];
|
||||
memset(p, 0x0, sizeof(p));
|
||||
qToLittleEndian(sizeof(p), p + 0x00);
|
||||
qToLittleEndian(c->txSeq, p + 0x06);
|
||||
qToLittleEndian(c->myId, p + 0x08);
|
||||
qToLittleEndian(c->remoteId, p + 0x0c);
|
||||
memcpy(p + 0x13, QByteArrayLiteral("\x98\x02\02").constData(), 3);
|
||||
qToLittleEndian(c->authInnerSeq, p + 0x16);
|
||||
qToLittleEndian(c->tokenRx, p + 0x1a);
|
||||
qToLittleEndian(c->tokenTx, p + 0x1c);
|
||||
p[0x41] = (char)0x01;
|
||||
p[0x49] = (char)0x10;
|
||||
p[0x4a] = (char)0x80;
|
||||
memcpy(p + 0x49, QByteArrayLiteral("\x10\x80").constData(), 2);
|
||||
memcpy(p + 0x4d, QByteArrayLiteral("\x90\xc7\x0b\xe7").constData(), 4); // IC9700
|
||||
memcpy(p + 0x92, QByteArrayLiteral("\x3f\x07\x00\x01\x8b\x01\x8b\x01\x01\x01\x00\x00\x4b").constData(), 13);
|
||||
memcpy(p + 0xa0, QByteArrayLiteral("\x01\x50\x00\x90\x01").constData(), 5);
|
||||
|
||||
p[0x94] = rigciv;
|
||||
p[0x51] = (char)0x64;
|
||||
memcpy(p + 0x52, rigname.toLocal8Bit(), rigname.length());
|
||||
memcpy(p + 0x72, QByteArrayLiteral("ICOM_VAUDIO").constData(), 11);
|
||||
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
c->idleTimer->start(100);
|
||||
c->txSeq++;
|
||||
return;
|
||||
}
|
||||
|
||||
// When client has requested civ/audio connection, this will contain their details
|
||||
// Also used to display currently connected used information.
|
||||
#define CONNINFO_SIZE 0x90
|
||||
void udpServer::sendConnectionInfo(CLIENT* c)
|
||||
{
|
||||
qDebug() << c->ipAddress.toString() << ": Sending ConnectionInfo :" << c->txSeq;
|
||||
quint8 p[CONNINFO_SIZE];
|
||||
memset(p, 0x0, sizeof(p));
|
||||
qToLittleEndian(sizeof(p), p + 0x00);
|
||||
qToLittleEndian(c->txSeq, p + 0x06);
|
||||
qToLittleEndian(c->myId, p + 0x08);
|
||||
qToLittleEndian(c->remoteId, p + 0x0c);
|
||||
p[0x13] = (char)0x80;
|
||||
p[0x14] = (char)0x03;
|
||||
qToLittleEndian(c->authInnerSeq, p + 0x16);
|
||||
qToLittleEndian(c->tokenRx, p + 0x1a);
|
||||
qToLittleEndian(c->tokenTx, p + 0x1c);
|
||||
p[0x27] = (char)0x10;
|
||||
p[0x28] = (char)0x80;
|
||||
memcpy(p + 0x2b, QByteArrayLiteral("\x90\xc7\x0b\xe7\x64").constData(), 5); // THIS SHOULD BE DYNAMIC?
|
||||
|
||||
// 0x1a-0x1f is authid (random number?
|
||||
// memcpy(p + 0x40, QByteArrayLiteral("IC-7851").constData(), 7);
|
||||
|
||||
memcpy(p + 0x40, rigname.toLocal8Bit(), rigname.length());
|
||||
|
||||
// This is the current streaming client (should we support multiple clients?)
|
||||
if (c->isStreaming) {
|
||||
p[0x60] = (char)0x01;
|
||||
memcpy(p + 0x64, c->clientName.constData(), c->clientName.length());
|
||||
qToBigEndian(c->ipAddress.toIPv4Address(), p + 0x84);
|
||||
qToLittleEndian(c->connSeq, p + 0x2c);
|
||||
|
||||
}
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
c->idleTimer->start(100);
|
||||
c->txSeq++;
|
||||
return;
|
||||
}
|
||||
|
||||
#define TOKEN_SIZE 0x40
|
||||
void udpServer::sendTokenResponse(CLIENT* c, quint8 type)
|
||||
{
|
||||
qDebug() << c->ipAddress.toString() << ": Sending Token response for type: " << type;
|
||||
|
||||
quint8 p[TOKEN_SIZE];
|
||||
memset(p, 0x0, sizeof(p));
|
||||
qToLittleEndian(sizeof(p), p + 0x00);
|
||||
qToLittleEndian(c->txSeq, p + 0x06);
|
||||
qToLittleEndian(c->myId, p + 0x08);
|
||||
qToLittleEndian(c->remoteId, p + 0x0c);
|
||||
p[0x13] = (char)0x30;
|
||||
p[0x14] = (char)0x02;
|
||||
p[0x15] = (char)type;
|
||||
qToLittleEndian(c->authInnerSeq, p + 0x16);
|
||||
qToLittleEndian(c->tokenRx, p + 0x1a);
|
||||
qToLittleEndian(c->tokenTx, p + 0x1c);
|
||||
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
c->idleTimer->start(100);
|
||||
c->txSeq++;
|
||||
return;
|
||||
}
|
||||
|
||||
#define WATCHDOG_SIZE 0x14
|
||||
void udpServer::sendWatchdog(CLIENT* c)
|
||||
{
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
qint32 deciSeconds = (qint32)c->timeConnected.msecsTo(now)/100;
|
||||
|
||||
quint8 p[WATCHDOG_SIZE];
|
||||
memset(p, 0x0, sizeof(p));
|
||||
qToLittleEndian(sizeof(p), p + 0x00);
|
||||
p[0x04] = (char)0x01;
|
||||
qToLittleEndian(c->myId, p + 0x08);
|
||||
qToLittleEndian(c->remoteId, p + 0x0c);
|
||||
qToLittleEndian(deciSeconds, p + 0x10);
|
||||
qToLittleEndian(deciSeconds+1, p + 0x12);
|
||||
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
#define STATUS_SIZE 0x50
|
||||
|
||||
void udpServer::sendStatus(CLIENT* c)
|
||||
{
|
||||
qDebug() << c->ipAddress.toString() << ": Sending Status";
|
||||
|
||||
quint8 p[STATUS_SIZE];
|
||||
memset(p, 0x0, sizeof(p));
|
||||
qToLittleEndian(sizeof(p), p + 0x00);
|
||||
qToLittleEndian(c->txSeq, p + 0x06);
|
||||
qToLittleEndian(c->myId, p + 0x08);
|
||||
qToLittleEndian(c->remoteId, p + 0x0c);
|
||||
p[0x13] = (char)0x40;
|
||||
p[0x14] = (char)0x02;
|
||||
p[0x15] = (char)0x03;
|
||||
qToLittleEndian(c->authInnerSeq, p + 0x16);
|
||||
qToLittleEndian(c->tokenRx, p + 0x1a);
|
||||
qToLittleEndian(c->tokenTx, p + 0x1c);
|
||||
p[0x27] = (char)0x10;
|
||||
p[0x28] = (char)0x80;
|
||||
p[0x2b] = (char)0x90;
|
||||
qToLittleEndian(c->connSeq, p + 0x2c);
|
||||
|
||||
qToBigEndian(c->civPort, p + 0x42);
|
||||
qToBigEndian(c->audioPort, p + 0x46);
|
||||
|
||||
// Send this to reject the request to tx/rx audio/civ
|
||||
//memcpy(p + 0x30, QByteArrayLiteral("\xff\xff\xff\xfe").constData(), 4);
|
||||
|
||||
|
||||
c->txSeq++;
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), c->ipAddress, c->port);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
#ifndef UDPSERVER_H
|
||||
#define UDPSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUdpSocket>
|
||||
#include <QNetworkDatagram>
|
||||
#include <QHostInfo>
|
||||
#include <QTimer>
|
||||
#include <QMutex>
|
||||
#include <QDateTime>
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
|
||||
// Allow easy endian-ness conversions
|
||||
#include <QtEndian>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <udpserversetup.h>
|
||||
|
||||
extern void passcode(QString in,QByteArray& out);
|
||||
extern QByteArray parseNullTerminatedString(QByteArray c, int s);
|
||||
|
||||
class udpServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
udpServer(SERVERCONFIG config);
|
||||
~udpServer();
|
||||
|
||||
public slots:
|
||||
void init();
|
||||
|
||||
private:
|
||||
|
||||
struct CLIENT {
|
||||
bool connected = false;
|
||||
QHostAddress ipAddress;
|
||||
quint16 port;
|
||||
QByteArray clientName;
|
||||
QDateTime timeConnected;
|
||||
QDateTime lastHeard;
|
||||
bool isStreaming;
|
||||
quint16 civPort;
|
||||
quint16 audioPort;
|
||||
quint16 txBufferLen;
|
||||
quint32 myId;
|
||||
quint32 remoteId;
|
||||
quint32 txSeq=0;
|
||||
quint32 rxSeq;
|
||||
quint32 connSeq;
|
||||
quint16 pingSeq;
|
||||
quint32 rxPingSeq; // 32bit as has other info
|
||||
quint32 authInnerSeq;
|
||||
quint16 authSeq;
|
||||
quint16 innerPingSeq;
|
||||
quint16 innerSeq;
|
||||
quint16 tokenRx;
|
||||
quint32 tokenTx;
|
||||
quint8 wdseq;
|
||||
QUdpSocket* socket;
|
||||
|
||||
|
||||
QTimer* pingTimer;
|
||||
QTimer* idleTimer;
|
||||
QTimer* wdTimer;
|
||||
|
||||
// Only used for audio.
|
||||
quint8 rxCodec;
|
||||
quint8 txCodec;
|
||||
quint16 rxSampleRate;
|
||||
quint16 txSampleRate;
|
||||
};
|
||||
|
||||
void controlReceived();
|
||||
void civReceived();
|
||||
void audioReceived();
|
||||
void sendIAmHere(CLIENT* c);
|
||||
void sendIAmReady(CLIENT* c);
|
||||
void sendPing(CLIENT* c, quint16 seq, bool reply);
|
||||
void sendIdle(CLIENT* c, quint16 seq);
|
||||
void sendLoginResponse(CLIENT* c, quint16 seq, bool allowed);
|
||||
void sendCapabilities(CLIENT* c);
|
||||
void sendConnectionInfo(CLIENT* c);
|
||||
void sendTokenResponse(CLIENT* c,quint8 type);
|
||||
void sendWatchdog(CLIENT* c);
|
||||
void sendStatus(CLIENT* c);
|
||||
|
||||
|
||||
|
||||
SERVERCONFIG config;
|
||||
|
||||
QUdpSocket* udpControl = Q_NULLPTR;
|
||||
QUdpSocket* udpCiv = Q_NULLPTR;
|
||||
QUdpSocket* udpAudio = Q_NULLPTR;
|
||||
QHostAddress localIP;
|
||||
|
||||
quint32 controlId = 0;
|
||||
quint32 civId = 0;
|
||||
quint32 audioId = 0;
|
||||
|
||||
QString rigname = "IC-9700";
|
||||
quint8 rigciv = 0xa2;
|
||||
|
||||
struct SEQBUFENTRY {
|
||||
time_t timeSent;
|
||||
uint16_t seqNum;
|
||||
QByteArray data;
|
||||
};
|
||||
|
||||
QList <CLIENT*> controlClients = QList<CLIENT*>();
|
||||
QList <CLIENT*> civClients = QList<CLIENT*>();
|
||||
QList <CLIENT*> audioClients = QList<CLIENT*>();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // UDPSERVER_H
|
|
@ -6,10 +6,82 @@ udpServerSetup::udpServerSetup(QWidget* parent) :
|
|||
ui(new Ui::udpServerSetup)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->enableCheckbox->setChecked(true);
|
||||
// Get any stored config information from the main form.
|
||||
SERVERCONFIG config;
|
||||
emit serverConfig(config,false); // Just send blank server config.
|
||||
}
|
||||
|
||||
udpServerSetup::~udpServerSetup()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// Slot to receive config.
|
||||
void udpServerSetup::receiveServerConfig(SERVERCONFIG conf)
|
||||
{
|
||||
qDebug() << "Getting server config";
|
||||
|
||||
ui->enableCheckbox->setChecked(conf.enabled);
|
||||
ui->controlPortText->setText(QString::number(conf.controlPort));
|
||||
ui->civPortText->setText(QString::number(conf.civPort));
|
||||
ui->audioPortText->setText(QString::number(conf.audioPort));
|
||||
|
||||
int row = 0;
|
||||
foreach (SERVERUSER user, conf.users)
|
||||
{
|
||||
if (ui->usersTable->rowCount() <= row) {
|
||||
ui->usersTable->insertRow(ui->usersTable->rowCount());
|
||||
}
|
||||
ui->usersTable->setItem(row, 0, new QTableWidgetItem(user.username));
|
||||
ui->usersTable->setItem(row, 1, new QTableWidgetItem(user.password));
|
||||
row++;
|
||||
}
|
||||
// Delete any rows no longer needed
|
||||
for (int count = row; count < ui->usersTable->rowCount(); count++)
|
||||
{
|
||||
ui->usersTable->removeRow(count);
|
||||
}
|
||||
ui->usersTable->insertRow(ui->usersTable->rowCount());
|
||||
//ui->usersTable->setHorizontalHeaderItem(ui->usersTable->rowCount() - 1, new QTableWidgetItem("User " + QString::number(row + 1)));
|
||||
|
||||
}
|
||||
|
||||
void udpServerSetup::accept()
|
||||
{
|
||||
qDebug() << "Server config stored";
|
||||
SERVERCONFIG config;
|
||||
config.enabled = ui->enableCheckbox->isChecked();
|
||||
config.controlPort = ui->controlPortText->text().toInt();
|
||||
config.civPort = ui->civPortText->text().toInt();
|
||||
config.audioPort = ui->audioPortText->text().toInt();
|
||||
|
||||
config.users.clear();
|
||||
|
||||
for (int row = 0; row < ui->usersTable->model()->rowCount(); row++)
|
||||
{
|
||||
if (ui->usersTable->item(row, 0) != NULL && ui->usersTable->item(row, 1) != NULL)
|
||||
{
|
||||
SERVERUSER user;
|
||||
user.username = ui->usersTable->item(row, 0)->text();
|
||||
user.password = ui->usersTable->item(row, 1)->text();
|
||||
config.users.append(user);
|
||||
|
||||
}
|
||||
else {
|
||||
ui->usersTable->removeRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
emit serverConfig(config,true);
|
||||
this->hide();
|
||||
}
|
||||
|
||||
|
||||
void udpServerSetup::on_usersTable_cellClicked(int row, int col)
|
||||
{
|
||||
qDebug() << "Clicked on " << row << "," << col;
|
||||
if (row == ui->usersTable->model()->rowCount() - 1 && ui->usersTable->item(row, 0) != NULL && ui->usersTable->item(row, 1) != NULL) {
|
||||
ui->usersTable->insertRow(ui->usersTable->rowCount());
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,23 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
struct SERVERUSER {
|
||||
QString username;
|
||||
QString password;
|
||||
quint8 userType;
|
||||
};
|
||||
|
||||
struct SERVERCONFIG {
|
||||
bool enabled;
|
||||
quint16 controlPort;
|
||||
quint16 civPort;
|
||||
quint16 audioPort;
|
||||
QList <SERVERUSER> users;
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class udpServerSetup;
|
||||
}
|
||||
|
@ -15,8 +32,18 @@ public:
|
|||
explicit udpServerSetup(QWidget* parent = 0);
|
||||
~udpServerSetup();
|
||||
|
||||
private slots:
|
||||
void on_usersTable_cellClicked(int row, int col);
|
||||
|
||||
public slots:
|
||||
void receiveServerConfig(SERVERCONFIG conf);
|
||||
|
||||
signals:
|
||||
void serverConfig(SERVERCONFIG conf, bool store);
|
||||
|
||||
private:
|
||||
Ui::udpServerSetup* ui;
|
||||
void accept();
|
||||
};
|
||||
|
||||
#endif // UDPSERVER_H
|
||||
|
|
|
@ -307,56 +307,6 @@
|
|||
<attribute name="verticalHeaderStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>User 1</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>User 2</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>User 3</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>User 4</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>User 5</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>User 6</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>User 7</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>User 8</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>User 9</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>User 10</string>
|
||||
</property>
|
||||
</row>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Username</string>
|
||||
|
|
76
wfmain.cpp
76
wfmain.cpp
|
@ -27,6 +27,10 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, QWidget *parent
|
|||
sat = new satelliteSetup();
|
||||
srv = new udpServerSetup();
|
||||
|
||||
connect(this, SIGNAL(sendServerConfig(SERVERCONFIG)), srv, SLOT(receiveServerConfig(SERVERCONFIG)));
|
||||
connect(srv, SIGNAL(serverConfig(SERVERCONFIG, bool)), this, SLOT(serverConfigRequested(SERVERCONFIG, bool)));
|
||||
|
||||
|
||||
|
||||
haveRigCaps = false;
|
||||
|
||||
|
@ -187,6 +191,20 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, QWidget *parent
|
|||
// serialPortRig = prefs.serialPortRadio;
|
||||
// }
|
||||
|
||||
// Start server if enabled in config
|
||||
if (serverConfig.enabled) {
|
||||
udp = new udpServer(serverConfig);
|
||||
|
||||
serverThread = new QThread(this);
|
||||
|
||||
udp->moveToThread(serverThread);
|
||||
|
||||
connect(this, SIGNAL(initServer()), udp, SLOT(init()));
|
||||
connect(serverThread, SIGNAL(finished()), udp, SLOT(deleteLater()));
|
||||
serverThread->start();
|
||||
|
||||
emit initServer();
|
||||
}
|
||||
|
||||
plot = ui->plot; // rename it waterfall.
|
||||
wf = ui->waterfall;
|
||||
|
@ -421,6 +439,10 @@ wfmain::~wfmain()
|
|||
{
|
||||
rigThread->quit();
|
||||
rigThread->wait();
|
||||
if (serverThread != Q_NULLPTR) {
|
||||
serverThread->quit();
|
||||
serverThread->wait();
|
||||
}
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
@ -771,6 +793,25 @@ void wfmain::loadSettings()
|
|||
ui->audioOutputCombo->setCurrentIndex(audioInputIndex);
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Server");
|
||||
|
||||
serverConfig.enabled = settings.value("ServerEnabled", false).toBool();
|
||||
serverConfig.controlPort = settings.value("ServerControlPort", 50001).toInt();
|
||||
serverConfig.civPort = settings.value("ServerCivPort", 50002).toInt();
|
||||
serverConfig.audioPort = settings.value("ServerAudioPort", 50003).toInt();
|
||||
int numUsers = settings.value("ServerNumUsers", 2).toInt();
|
||||
serverConfig.users.clear();
|
||||
for (int f = 0; f < numUsers; f++)
|
||||
{
|
||||
SERVERUSER user;
|
||||
user.username = settings.value("ServerUsername_" + QString::number(f), "").toString();
|
||||
user.password = settings.value("ServerPassword_" + QString::number(f), "").toString();
|
||||
serverConfig.users.append(user);
|
||||
}
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
// Memory channels
|
||||
|
||||
settings.beginGroup("Memory");
|
||||
|
@ -804,6 +845,9 @@ void wfmain::loadSettings()
|
|||
|
||||
settings.endArray();
|
||||
settings.endGroup();
|
||||
|
||||
emit sendServerConfig(serverConfig);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -922,6 +966,22 @@ void wfmain::saveSettings()
|
|||
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Server");
|
||||
|
||||
settings.setValue("ServerEnabled", serverConfig.enabled);
|
||||
settings.setValue("ServerControlPort", serverConfig.controlPort);
|
||||
settings.setValue("ServerCivPort", serverConfig.civPort);
|
||||
settings.setValue("ServerAudioPort", serverConfig.audioPort);
|
||||
settings.setValue("ServerNumUsers", serverConfig.users.count());
|
||||
for (int f = 0; f < serverConfig.users.count(); f++)
|
||||
{
|
||||
settings.setValue("ServerUsername_" + QString::number(f), serverConfig.users[f].username);
|
||||
settings.setValue("ServerPassword_" + QString::number(f), serverConfig.users[f].password);
|
||||
}
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
|
||||
|
||||
settings.sync(); // Automatic, not needed (supposedly)
|
||||
}
|
||||
|
@ -2692,3 +2752,19 @@ void wfmain::on_debugBtn_clicked()
|
|||
|
||||
}
|
||||
|
||||
// Slot to send/receive server config.
|
||||
// If store is true then write to config otherwise send current config by signal
|
||||
void wfmain::serverConfigRequested(SERVERCONFIG conf, bool store)
|
||||
{
|
||||
|
||||
if (!store) {
|
||||
emit sendServerConfig(serverConfig);
|
||||
}
|
||||
else {
|
||||
// Store config in file!
|
||||
qDebug() << "Storing server config";
|
||||
serverConfig = conf;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
15
wfmain.h
15
wfmain.h
|
@ -19,6 +19,7 @@
|
|||
#include "calibrationwindow.h"
|
||||
#include "satellitesetup.h"
|
||||
#include "udpserversetup.h"
|
||||
#include "udpserver.h"
|
||||
|
||||
#include <qcustomplot.h>
|
||||
#include <qserialportinfo.h>
|
||||
|
@ -98,6 +99,8 @@ signals:
|
|||
QString username, QString password, quint16 buffer, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec);
|
||||
void sendCloseComm();
|
||||
void sendChangeBufferSize(quint16 value);
|
||||
void initServer();
|
||||
void sendServerConfig(SERVERCONFIG conf);
|
||||
|
||||
private slots:
|
||||
void shortcutF1();
|
||||
|
@ -180,6 +183,7 @@ private slots:
|
|||
void handlePlotScroll(QWheelEvent *);
|
||||
void runDelayedCommand();
|
||||
void showStatusBarText(QString text);
|
||||
void serverConfigRequested(SERVERCONFIG conf, bool store);
|
||||
|
||||
// void on_getFreqBtn_clicked();
|
||||
|
||||
|
@ -397,13 +401,14 @@ private:
|
|||
|
||||
|
||||
rigCommander * rig=Q_NULLPTR;
|
||||
QThread * rigThread=Q_NULLPTR;
|
||||
QThread* rigThread = Q_NULLPTR;
|
||||
QCPColorMap * colorMap;
|
||||
QCPColorMapData * colorMapData;
|
||||
QCPColorScale * colorScale;
|
||||
QTimer * delayedCommand;
|
||||
QTimer * pttTimer;
|
||||
|
||||
|
||||
QStringList modes;
|
||||
int currentModeIndex;
|
||||
QStringList spans;
|
||||
|
@ -509,11 +514,17 @@ private:
|
|||
|
||||
calibrationWindow *cal;
|
||||
satelliteSetup *sat;
|
||||
udpServerSetup* srv;
|
||||
udpServerSetup *srv;
|
||||
udpServer *udp;
|
||||
QThread *serverThread = Q_NULLPTR;
|
||||
|
||||
void bandStackBtnClick();
|
||||
bool waitingForBandStackRtn;
|
||||
char bandStkBand;
|
||||
char bandStkRegCode;
|
||||
|
||||
SERVERCONFIG serverConfig;
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(struct rigCapabilities) ;
|
||||
|
|
|
@ -84,7 +84,8 @@ SOURCES += main.cpp\
|
|||
audiohandler.cpp \
|
||||
calibrationwindow.cpp \
|
||||
satellitesetup.cpp \
|
||||
udpserversetup.cpp
|
||||
udpserversetup.cpp \
|
||||
udpserver.cpp
|
||||
|
||||
HEADERS += wfmain.h \
|
||||
commhandler.h \
|
||||
|
@ -96,7 +97,8 @@ HEADERS += wfmain.h \
|
|||
audiohandler.h \
|
||||
calibrationwindow.h \
|
||||
satellitesetup.h \
|
||||
udpserversetup.h
|
||||
udpserversetup.h \
|
||||
udpserver.h
|
||||
|
||||
|
||||
FORMS += wfmain.ui \
|
||||
|
|
Ładowanie…
Reference in New Issue