From 7966568f17f7a962d92f9c4189a3a8ad3ce72228 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Thu, 18 Feb 2021 09:14:41 +0000 Subject: [PATCH 1/7] Connect Civ to/from server --- rigcommander.cpp | 7 +++++++ rigcommander.h | 2 ++ udpserver.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ udpserver.h | 4 ++++ wfmain.cpp | 8 ++++++++ 5 files changed, 73 insertions(+) diff --git a/rigcommander.cpp b/rigcommander.cpp index 3cc3686..6a0c059 100644 --- a/rigcommander.cpp +++ b/rigcommander.cpp @@ -584,6 +584,7 @@ void rigCommander::setCIVAddr(unsigned char civAddr) void rigCommander::handleNewData(const QByteArray &data) { + emit haveDataForServer(data); parseData(data); } @@ -1959,6 +1960,12 @@ void rigCommander::printHex(const QByteArray &pdata, bool printVert, bool printH qDebug() << "----- End hex dump -----"; } +void rigCommander::dataFromServer(QByteArray data) +{ + qDebug() << "emit dataForComm()"; + emit dataForComm(data); +} + diff --git a/rigcommander.h b/rigcommander.h index 77b8af0..92019e1 100644 --- a/rigcommander.h +++ b/rigcommander.h @@ -109,6 +109,7 @@ public slots: void sayMode(); void sayAll(); void getDebug(); + void dataFromServer(QByteArray data); signals: void commReady(); @@ -154,6 +155,7 @@ signals: void havePTTStatus(bool pttOn); void haveATUStatus(unsigned char status); void haveChangeBufferSize(quint16 value); + void haveDataForServer(QByteArray outData); private: diff --git a/udpserver.cpp b/udpserver.cpp index 2f90d4e..983c048 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -101,6 +101,9 @@ void udpServer::controlReceived() QNetworkDatagram datagram = udpControl->receiveDatagram(); QByteArray r = datagram.data(); CLIENT* current = Q_NULLPTR; + if (datagram.senderPort() == 65535 || datagram.senderPort() == 0) + return; + foreach(CLIENT * client, controlClients) { if (client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort()) @@ -281,6 +284,9 @@ void udpServer::civReceived() CLIENT* current = Q_NULLPTR; + if (datagram.senderPort() == 65535 || datagram.senderPort() == 0) + return; + foreach(CLIENT * client, civClients) { if (client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort()) @@ -371,6 +377,17 @@ void udpServer::civReceived() } break; default: + if (r.length() > 21) { + // First check if we are missing any packets? + quint8 temp = r[0] - 0x15; + if ((quint8)r[16] == 0xc1 && (quint8)r[17] == temp) + { + qDebug() << "Got CIV from server: " << r.mid(21); + emit haveDataFromServer(r.mid(21)); + } + } + + break; } } @@ -383,8 +400,12 @@ void udpServer::audioReceived() QByteArray r = datagram.data(); CLIENT* current = Q_NULLPTR; + if (datagram.senderPort() == 65535 || datagram.senderPort() == 0) + return; + foreach(CLIENT * client, audioClients) { + if (client != Q_NULLPTR && client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort()) { current = client; @@ -758,3 +779,34 @@ void udpServer::sendStatus(CLIENT* c) } + +#define SEND_SIZE 17 +void udpServer::dataForServer(QByteArray d) +{ + + CLIENT* current = Q_NULLPTR; + foreach(CLIENT * client, civClients) + { + qDebug() << "Sending CIV data to " << client->ipAddress.toString(); + quint8 p[SEND_SIZE]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian(client->txSeq, p + 0x06); + qToLittleEndian(client->myId, p + 0x08); + qToLittleEndian(client->remoteId, p + 0x0c); + + QByteArray t = QByteArray::fromRawData((const char*)p, sizeof(p)); + p[0x10] = (char)0xc1; + qToLittleEndian((quint16)t.length(), p + 0x11); + qToLittleEndian((quint16)sizeof(p) + t.length(), p + 0x00); + + t.append(QByteArray::fromRawData((const char*)p, sizeof(p))); + qToLittleEndian(client->connSeq, p + 0x12); + client->socket->writeDatagram(t, client->ipAddress, client->port); + client->connSeq++; + client->txSeq++; + } + + return; +} + + diff --git a/udpserver.h b/udpserver.h index 8cb66d9..ea0c6cc 100644 --- a/udpserver.h +++ b/udpserver.h @@ -31,6 +31,10 @@ public: public slots: void init(); + void dataForServer(QByteArray); + +signals: + void haveDataFromServer(QByteArray); private: diff --git a/wfmain.cpp b/wfmain.cpp index 1b0fe55..4a1b067 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -201,6 +201,8 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, QWidget *parent connect(this, SIGNAL(initServer()), udp, SLOT(init())); connect(serverThread, SIGNAL(finished()), udp, SLOT(deleteLater())); + + serverThread->start(); emit initServer(); @@ -367,6 +369,12 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, QWidget *parent // Metering connect(this, SIGNAL(getMeters(bool)), rig, SLOT(getMeters(bool))); + + // Server + connect(rig, SIGNAL(haveDataForServer(QByteArray)), udp, SLOT(dataForServer(QByteArray))); + connect(udp, SIGNAL(haveDataFromServer(QByteArray)), rig, SLOT(dataFromServer(QByteArray))); + + ui->plot->addGraph(); // primary ui->plot->addGraph(0, 0); // secondary, peaks, same axis as first? ui->waterfall->addGraph(); From cf1ee895cf497717bea1687df6a73d34eef59df1 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Thu, 18 Feb 2021 13:49:19 +0000 Subject: [PATCH 2/7] Fix error when deleting server connections I still think that maybe this should be done better? --- rigcommander.cpp | 2 +- udpserver.cpp | 228 ++++++++++++++++++++++++++++++++--------------- udpserver.h | 10 ++- 3 files changed, 163 insertions(+), 77 deletions(-) diff --git a/rigcommander.cpp b/rigcommander.cpp index ccf08ab..a8f3713 100644 --- a/rigcommander.cpp +++ b/rigcommander.cpp @@ -2420,7 +2420,7 @@ void rigCommander::printHex(const QByteArray &pdata, bool printVert, bool printH void rigCommander::dataFromServer(QByteArray data) { - qDebug() << "emit dataForComm()"; + //qDebug() << "emit dataForComm()"; emit dataForComm(data); } diff --git a/udpserver.cpp b/udpserver.cpp index 983c048..8fa684b 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -1,5 +1,7 @@ #include "udpserver.h" +#define STALE_CONNECTION 15 + udpServer::udpServer(SERVERCONFIG config) : config(config) { @@ -53,30 +55,53 @@ udpServer::~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? + if (client->idleTimer != Q_NULLPTR) + { + client->idleTimer->stop(); + delete client->idleTimer; + } + if (client->pingTimer != Q_NULLPTR) { + client->pingTimer->stop(); + delete client->pingTimer; + } + if (client->wdTimer != Q_NULLPTR) { + client->wdTimer->stop(); + delete client->wdTimer; + } + delete client; + controlClients.removeAll(client); } foreach(CLIENT * client, civClients) { - client->idleTimer->stop(); - delete client->idleTimer; - client->pingTimer->stop(); - delete client->pingTimer; - //delete& client; // Not sure how safe this is? + if (client->idleTimer != Q_NULLPTR) + { + client->idleTimer->stop(); + delete client->idleTimer; + } + if (client->pingTimer != Q_NULLPTR) { + client->pingTimer->stop(); + delete client->pingTimer; + } + delete client; + civClients.removeAll(client); } foreach(CLIENT * client, audioClients) { - client->pingTimer->stop(); - delete client->pingTimer; - //delete& client; // Not sure how safe this is? + if (client->idleTimer != Q_NULLPTR) + { + client->idleTimer->stop(); + delete client->idleTimer; + } + if (client->pingTimer != Q_NULLPTR) { + client->pingTimer->stop(); + delete client->pingTimer; + } + delete client; + audioClients.removeAll(client); } + if (udpControl != Q_NULLPTR) { udpControl->close(); delete udpControl; @@ -101,14 +126,17 @@ void udpServer::controlReceived() QNetworkDatagram datagram = udpControl->receiveDatagram(); QByteArray r = datagram.data(); CLIENT* current = Q_NULLPTR; - if (datagram.senderPort() == 65535 || datagram.senderPort() == 0) + if (datagram.senderAddress().isNull() || datagram.senderPort() == 65535 || datagram.senderPort() == 0) return; foreach(CLIENT * client, controlClients) { - if (client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort()) + if (client != Q_NULLPTR) { - current = client; + if (client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort()) + { + current = client; + } } } if (current == Q_NULLPTR) @@ -129,13 +157,13 @@ void udpServer::controlReceived() 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->pingTimer, &QTimer::timeout, this, std::bind(&udpServer::sendPing, this, &controlClients, 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)); + connect(current->wdTimer, &QTimer::timeout, this, std::bind(&udpServer::sendWatchdog, this, controlClients, 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); + qDebug() << "New Control connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port); controlClients.append(current); } @@ -167,12 +195,8 @@ void udpServer::controlReceived() { qDebug() << current->ipAddress.toString() << ": Received 'disconnect' request"; sendIdle(current, gotSeq); - current->idleTimer->stop(); - current->pingTimer->stop(); - current->wdTimer->stop(); - delete current; - controlClients.removeOne(current); - + //current->wdTimer->stop(); // Keep watchdog running to delete stale connection. + deleteConnection(&controlClients, current); } break; case (0x14): @@ -186,11 +210,11 @@ void udpServer::controlReceived() if (r[16] == (char)0x00) { current->rxPingSeq = qFromLittleEndian(r.mid(0x11, 4)); - sendPing(current, gotSeq, true); + sendPing(&controlClients, current, gotSeq, true); } else if (r[16] == (char)0x01) { // A Reply to our ping! - if (gotSeq == current->pingSeq) { + if (gotSeq == current->pingSeq || gotSeq == current->pingSeq - 1) { current->pingSeq++; } else { @@ -284,14 +308,20 @@ void udpServer::civReceived() CLIENT* current = Q_NULLPTR; - if (datagram.senderPort() == 65535 || datagram.senderPort() == 0) + if (datagram.senderAddress().isNull() || datagram.senderPort() == 65535 || datagram.senderPort() == 0) return; + QDateTime now = QDateTime::currentDateTime(); + foreach(CLIENT * client, civClients) { - if (client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort()) + if (client != Q_NULLPTR) { - current = client; + if (client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort()) + { + current = client; + } + } } if (current == Q_NULLPTR) @@ -309,11 +339,11 @@ void udpServer::civReceived() 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->pingTimer, &QTimer::timeout, this, std::bind(&udpServer::sendPing, this, &civClients, 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); + qDebug() << "New CIV connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port); civClients.append(current); } @@ -345,10 +375,7 @@ void udpServer::civReceived() { qDebug() << current->ipAddress.toString() << ": Received 'disconnect' request"; sendIdle(current, gotSeq); - current->idleTimer->stop(); - current->pingTimer->stop(); - delete current; - controlClients.removeOne(current); + deleteConnection(&civClients, current); } break; @@ -363,11 +390,11 @@ void udpServer::civReceived() if (r[16] == (char)0x00) { current->rxPingSeq = qFromLittleEndian(r.mid(0x11, 4)); - sendPing(current, gotSeq, true); + sendPing(&civClients, current, gotSeq, true); } else if (r[16] == (char)0x01) { // A Reply to our ping! - if (gotSeq == current->pingSeq) { + if (gotSeq == current->pingSeq || gotSeq == current->pingSeq - 1) { current->pingSeq++; } else { @@ -382,7 +409,7 @@ void udpServer::civReceived() quint8 temp = r[0] - 0x15; if ((quint8)r[16] == 0xc1 && (quint8)r[17] == temp) { - qDebug() << "Got CIV from server: " << r.mid(21); + //qDebug() << "Got CIV from server: " << r.mid(21); emit haveDataFromServer(r.mid(21)); } } @@ -400,15 +427,19 @@ void udpServer::audioReceived() QByteArray r = datagram.data(); CLIENT* current = Q_NULLPTR; - if (datagram.senderPort() == 65535 || datagram.senderPort() == 0) + if (datagram.senderAddress().isNull() || datagram.senderPort() == 65535 || datagram.senderPort() == 0) return; + QDateTime now = QDateTime::currentDateTime(); + foreach(CLIENT * client, audioClients) { - - if (client != Q_NULLPTR && client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort()) + if (client != Q_NULLPTR) { - current = client; + if (client->ipAddress == datagram.senderAddress() && client->port == datagram.senderPort()) + { + current = client; + } } } if (current == Q_NULLPTR) @@ -424,9 +455,9 @@ void udpServer::audioReceived() 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)); + connect(current->pingTimer, &QTimer::timeout, this, std::bind(&udpServer::sendPing, this, &audioClients, current, (quint16)0x00, false)); current->pingTimer->start(100); - qDebug() << "New connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port); + qDebug() << "New Audio connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port); audioClients.append(current); } @@ -458,10 +489,7 @@ void udpServer::audioReceived() { qDebug() << current->ipAddress.toString() << ": Received 'disconnect' request"; sendIdle(current, gotSeq); - current->pingTimer->stop(); - delete current; - controlClients.removeOne(current); - + deleteConnection(&audioClients, current); } break; case (0x14): @@ -475,9 +503,9 @@ void udpServer::audioReceived() if (r[16] == (char)0x00) { current->rxPingSeq = qFromLittleEndian(r.mid(0x11, 4)); - sendPing(current, gotSeq, true); + sendPing(&audioClients, current, gotSeq, true); } - else if (r[16] == (char)0x01) { + if (gotSeq == current->pingSeq || gotSeq == current->pingSeq - 1) { // A Reply to our ping! if (gotSeq == current->pingSeq) { current->pingSeq++; @@ -537,6 +565,8 @@ void udpServer::sendIAmReady(CLIENT* c) void udpServer::sendIdle(CLIENT* c, quint16 seq) { + QMutexLocker locker(&mutex); + if (seq == 0x00) { seq = c->txSeq; @@ -558,8 +588,20 @@ void udpServer::sendIdle(CLIENT* c, quint16 seq) #define PING_SIZE 0x15 -void udpServer::sendPing(CLIENT* c, quint16 seq, bool reply) +void udpServer::sendPing(QList *l,CLIENT* c, quint16 seq, bool reply) { + QMutexLocker locker(&mutex); + // Also use to detect "stale" connections + QDateTime now = QDateTime::currentDateTime(); + + if (c->lastHeard.secsTo(now) > STALE_CONNECTION) + { + qDebug() << "Deleting stale connection " << c->ipAddress.toString(); + deleteConnection(l, c); + return; + } + + //qDebug() << c->ipAddress.toString() << ": Sending Ping"; quint32 pingSeq = 0; @@ -723,10 +765,13 @@ void udpServer::sendTokenResponse(CLIENT* c, quint8 type) } #define WATCHDOG_SIZE 0x14 -void udpServer::sendWatchdog(CLIENT* c) +void udpServer::sendWatchdog(QList l,CLIENT* c) { + QMutexLocker locker(&mutex); + QDateTime now = QDateTime::currentDateTime(); - qint32 deciSeconds = (qint32)c->timeConnected.msecsTo(now)/100; + + qint32 deciSeconds = (qint32)c->timeConnected.msecsTo(now) / 100; quint8 p[WATCHDOG_SIZE]; memset(p, 0x0, sizeof(p)); @@ -747,6 +792,8 @@ void udpServer::sendWatchdog(CLIENT* c) void udpServer::sendStatus(CLIENT* c) { + QMutexLocker locker(&mutex); + qDebug() << c->ipAddress.toString() << ": Sending Status"; quint8 p[STATUS_SIZE]; @@ -780,33 +827,66 @@ void udpServer::sendStatus(CLIENT* c) } -#define SEND_SIZE 17 +#define SEND_SIZE 0x15 void udpServer::dataForServer(QByteArray d) { - CLIENT* current = Q_NULLPTR; + //qDebug() << "Server got:" << d; foreach(CLIENT * client, civClients) { - qDebug() << "Sending CIV data to " << client->ipAddress.toString(); - quint8 p[SEND_SIZE]; - memset(p, 0x0, sizeof(p)); - qToLittleEndian(client->txSeq, p + 0x06); - qToLittleEndian(client->myId, p + 0x08); - qToLittleEndian(client->remoteId, p + 0x0c); + if (client != Q_NULLPTR && client->connected) { + quint8 p[SEND_SIZE]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian(client->txSeq, p + 0x06); + qToLittleEndian(client->myId, p + 0x08); + qToLittleEndian(client->remoteId, p + 0x0c); - QByteArray t = QByteArray::fromRawData((const char*)p, sizeof(p)); - p[0x10] = (char)0xc1; - qToLittleEndian((quint16)t.length(), p + 0x11); - qToLittleEndian((quint16)sizeof(p) + t.length(), p + 0x00); + QByteArray t = QByteArray::fromRawData((const char*)p, sizeof(p)); + p[0x10] = (char)0xc1; + qToLittleEndian((quint16)t.length(), p + 0x11); + qToLittleEndian(client->connSeq, p + 0x12); + qToLittleEndian((quint16)sizeof(p) + t.length()+d.length(), p + 0x00); - t.append(QByteArray::fromRawData((const char*)p, sizeof(p))); - qToLittleEndian(client->connSeq, p + 0x12); - client->socket->writeDatagram(t, client->ipAddress, client->port); - client->connSeq++; - client->txSeq++; + t.append(QByteArray::fromRawData((const char*)p, sizeof(p))); + t.append(d); + + QMutexLocker locker(&mutex); + client->connSeq++; + client->txSeq++; + client->socket->writeDatagram(t, client->ipAddress, client->port); + } } return; } - +void udpServer::deleteConnection(QList *l, CLIENT* c) +{ + QList::iterator it = l->begin(); + while (it != l->end()) { + CLIENT* client = *it; + if (client != Q_NULLPTR && client == c) { + qDebug() << "Deleting connection to: " << c->ipAddress.toString() << ":" << QString::number(c->port); + if (client->idleTimer != Q_NULLPTR) { + client->idleTimer->stop(); + delete client->idleTimer; + } + if (client->pingTimer != Q_NULLPTR) { + client->pingTimer->stop(); + delete client->pingTimer; + } + if (client->wdTimer != Q_NULLPTR) { + client->wdTimer->stop(); + delete client->wdTimer; + } + qDebug() << "Number of clients: " << l->length(); + it = l->erase(it); + qDebug() << "Number of clients (after erase): " << l->length(); + } + else { + ++it; + } + } + delete c; + c = Q_NULLPTR; +} diff --git a/udpserver.h b/udpserver.h index ea0c6cc..a8fb298 100644 --- a/udpserver.h +++ b/udpserver.h @@ -75,6 +75,8 @@ private: quint8 txCodec; quint16 rxSampleRate; quint16 txSampleRate; + + }; void controlReceived(); @@ -82,14 +84,16 @@ private: void audioReceived(); void sendIAmHere(CLIENT* c); void sendIAmReady(CLIENT* c); - void sendPing(CLIENT* c, quint16 seq, bool reply); + void sendPing(QList *l,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 sendWatchdog(QList l, CLIENT* c); void sendStatus(CLIENT* c); + void deleteConnection(QList *l, CLIENT* c); + @@ -113,6 +117,8 @@ private: QByteArray data; }; + QMutex mutex; // Used for critical operations. + QList controlClients = QList(); QList civClients = QList(); QList audioClients = QList(); From 0a0eb031c621680f76c5e92a792ab0a916fab714 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Thu, 18 Feb 2021 14:15:03 +0000 Subject: [PATCH 3/7] More fixes to server connection management --- udpserver.cpp | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/udpserver.cpp b/udpserver.cpp index 8fa684b..3188c8f 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -860,33 +860,36 @@ void udpServer::dataForServer(QByteArray d) return; } + +// This function is passed a pointer to the list of connection objects and a pointer to the object itself +// Needs to stop and delete all timers, remove the connection from the list and delete the connection. void udpServer::deleteConnection(QList *l, CLIENT* c) { + qDebug() << "Deleting connection to: " << c->ipAddress.toString() << ":" << QString::number(c->port); + if (c->idleTimer != Q_NULLPTR) { + c->idleTimer->stop(); + delete c->idleTimer; + } + if (c->pingTimer != Q_NULLPTR) { + c->pingTimer->stop(); + delete c->pingTimer; + } + if (c->wdTimer != Q_NULLPTR) { + c->wdTimer->stop(); + delete c->wdTimer; + } + QList::iterator it = l->begin(); while (it != l->end()) { CLIENT* client = *it; if (client != Q_NULLPTR && client == c) { - qDebug() << "Deleting connection to: " << c->ipAddress.toString() << ":" << QString::number(c->port); - if (client->idleTimer != Q_NULLPTR) { - client->idleTimer->stop(); - delete client->idleTimer; - } - if (client->pingTimer != Q_NULLPTR) { - client->pingTimer->stop(); - delete client->pingTimer; - } - if (client->wdTimer != Q_NULLPTR) { - client->wdTimer->stop(); - delete client->wdTimer; - } - qDebug() << "Number of clients: " << l->length(); it = l->erase(it); - qDebug() << "Number of clients (after erase): " << l->length(); } else { ++it; } } - delete c; + delete c; // Is this needed or will the erase have done it? c = Q_NULLPTR; + qDebug() << "Current Number of clients connected: " << l->length(); } From 61d06213adf0336c29d160fed3168b120b7f1817 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Thu, 18 Feb 2021 15:54:26 +0000 Subject: [PATCH 4/7] Create all UDP packets using a less error-prone method --- udphandler.cpp | 291 ++++++++++++++++++------------------------------- udphandler.h | 7 +- 2 files changed, 105 insertions(+), 193 deletions(-) diff --git a/udphandler.cpp b/udphandler.cpp index d1240fa..8acd10b 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -63,7 +63,7 @@ udpHandler::udpHandler(QString ip, quint16 controlPort, quint16 civPort, quint16 connect(&tokenTimer, &QTimer::timeout, this, std::bind(&udpHandler::sendToken, this, 0x05)); connect(&areYouThereTimer, &QTimer::timeout, this, QOverload<>::of(&udpHandler::sendAreYouThere)); connect(&pingTimer, &QTimer::timeout, this, &udpBase::sendPing); - connect(&idleTimer, &QTimer::timeout, this, std::bind(&udpBase::sendIdle, this, true, 0)); + connect(&idleTimer, &QTimer::timeout, this, std::bind(&udpBase::sendControl, this, true, 0, 0)); // Start sending are you there packets - will be stopped once "I am here" received areYouThereTimer.start(AREYOUTHERE_PERIOD); @@ -287,47 +287,33 @@ void udpHandler::dataReceived() } - +#define SERIALAUDIO_SIZE 0x90 void udpHandler::sendRequestSerialAndAudio() { QByteArray usernameEncoded; passcode(username, usernameEncoded); int txSeqBufLengthMs = 50; - quint8 p[] = { - 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff), - - 0x00, 0x00, 0x00, 0x80, 0x01, 0x03, 0x00, static_cast(authInnerSendSeq & 0xff), static_cast(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(rxSampleRate >> 8 & 0xff), static_cast(rxSampleRate & 0xff), - 0x00, 0x00, static_cast(txSampleRate >> 8 & 0xff), static_cast(txSampleRate & 0xff), - 0x00, 0x00, static_cast(civPort >> 8 & 0xff), static_cast(civPort & 0xff), - 0x00, 0x00, static_cast(audioPort >> 8 & 0xff), static_cast(audioPort & 0xff), 0x00, 0x00, - static_cast(txSeqBufLengthMs >> 8 & 0xff), static_cast(txSeqBufLengthMs & 0xff), 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - + quint8 p[SERIALAUDIO_SIZE]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian(sizeof(p), p + 0x00); + qToLittleEndian(myId, p + 0x08); + qToLittleEndian(remoteId, p + 0x0c); + memcpy(p + 0x13, QByteArrayLiteral("\x80\x01\x03").constData(), 3); + qToLittleEndian(authInnerSendSeq, p + 0x16); memcpy(p + 0x1a, authId.constData(), authId.length()); memcpy(p + 0x20, replyId.constData(), replyId.length()); memcpy(p + 0x40, devName.constData(), devName.length()); memcpy(p + 0x60, usernameEncoded.constData(), usernameEncoded.length()); + memcpy(p + 0x70, QByteArrayLiteral("\x01\x01").constData(), 2); + p[0x72] = rxCodec; + p[0x73] = txCodec; + qToBigEndian(rxSampleRate, p + 0x76); + qToBigEndian(txSampleRate, p + 0x7a); + qToBigEndian(civPort, p + 0x7e); + qToBigEndian(audioPort, p + 0x82); + qToBigEndian(txSeqBufLengthMs, p + 0x86); + p[0x88] = 0x01; authInnerSendSeq++; @@ -342,11 +328,13 @@ void udpHandler::sendAreYouThere() qDebug() << this->metaObject()->className() << ": Radio not responding."; emit haveNetworkStatus("Radio not responding!"); } + qDebug() << this->metaObject()->className() << ": Sending Are You There..."; + areYouThereCounter++; - udpBase::sendAreYouThere(); + udpBase::sendControl(false,0x03,0x00); } - +#define LOGIN_SIZE 0x80 void udpHandler::sendLogin() // Only used on control stream. { @@ -359,26 +347,14 @@ void udpHandler::sendLogin() // Only used on control stream. passcode(username, usernameEncoded); passcode(password, passwordEncoded); - quint8 p[] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff), - 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, static_cast(authInnerSendSeq & 0xff), static_cast(authInnerSendSeq >> 8 & 0xff), - 0x00, static_cast(authStartID & 0xff), static_cast(authStartID >> 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, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - + quint8 p[LOGIN_SIZE]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian(sizeof(p), p + 0x00); + qToLittleEndian(myId, p + 0x08); + qToLittleEndian(remoteId, p + 0x0c); + memcpy(p + 0x13, QByteArrayLiteral("\x70\x01").constData(), 2); + qToLittleEndian(authInnerSendSeq, p + 0x17); + qToLittleEndian(authStartID, p + 0x20); memcpy(p + 0x40, usernameEncoded.constData(), usernameEncoded.length()); memcpy(p + 0x50, passwordEncoded.constData(), passwordEncoded.length()); memcpy(p + 0x60, compName.constData(), compName.length()); @@ -388,23 +364,19 @@ void udpHandler::sendLogin() // Only used on control stream. return; } - +#define TOKEN_SIZE 0x40 void udpHandler::sendToken(uint8_t magic) { - qDebug() << this->metaObject()->className() << "Sending Token request: " << magic; - quint8 p[] = { - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff), - 0x00, 0x00, 0x00, 0x30, 0x01, static_cast(magic), 0x00, static_cast(authInnerSendSeq & 0xff), static_cast((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 - }; + quint8 p[TOKEN_SIZE]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian(sizeof(p), p + 0x00); + qToLittleEndian(myId, p + 0x08); + qToLittleEndian(remoteId, p + 0x0c); + memcpy(p + 0x13, QByteArrayLiteral("\x30\x01").constData(), 2); + qToLittleEndian(magic, p + 0x15); + qToLittleEndian(authInnerSendSeq, p + 0x17); memcpy(p + 0x1a, authId.constData(), authId.length()); authInnerSendSeq++; @@ -426,13 +398,13 @@ udpCivData::udpCivData(QHostAddress local, QHostAddress ip, quint16 civPort) QUdpSocket::connect(udp, &QUdpSocket::readyRead, this, &udpCivData::dataReceived); - sendAreYouThere(); // First connect packet + sendControl(false, 0x03, 0x00); // First connect packet /* Connect various timers */ connect(&pingTimer, &QTimer::timeout, this, &udpBase::sendPing); - connect(&idleTimer, &QTimer::timeout, this, std::bind(&udpBase::sendIdle, this, true, 0)); + connect(&idleTimer, &QTimer::timeout, this, std::bind(&udpBase::sendControl, this, true, 0, 0)); // send ping packets every 100 ms (maybe change to less frequent?) pingTimer.start(PING_PERIOD); @@ -444,16 +416,20 @@ udpCivData::~udpCivData() { sendOpenClose(true); } +#define CIV_SIZE 0x15 void udpCivData::send(QByteArray d) { // qDebug() << "Sending: (" << d.length() << ") " << d; - uint16_t l = d.length(); - const quint8 p[] = { static_cast(0x15 + l), 0x00, 0x00, 0x00, 0x00, 0x00,0x00,0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff), - 0xc1, static_cast(l), 0x00, static_cast(sendSeqB & 0xff),static_cast(sendSeqB >>8 & 0xff) - }; + quint8 p[CIV_SIZE]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian((quint16)sizeof(p) + d.length(), p + 0x00); + qToLittleEndian(myId, p + 0x08); + qToLittleEndian(remoteId, p + 0x0c); + p[0x10] = 0xc1; + qToLittleEndian((quint16)d.length(), p + 0x11); + qToLittleEndian(sendSeqB, p + 0x13); + QByteArray t = QByteArray::fromRawData((const char*)p, sizeof(p)); t.append(d); sendTrackedPacket(t); @@ -462,28 +438,7 @@ void udpCivData::send(QByteArray d) } - -void udpCivData::SendIdle() -{ - const quint8 p[] = { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff) - }; - - sendTrackedPacket(QByteArray::fromRawData((const char*)p, sizeof(p))); -} - -void udpCivData::SendPeriodic() -{ - const quint8 p[] = { 0x15, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff) - }; - - sendTrackedPacket(QByteArray::fromRawData((const char*)p, sizeof(p))); - -} - +#define OPENCLOSE_SIZE 0x16 void udpCivData::sendOpenClose(bool close) { uint8_t magic = 0x05; @@ -493,12 +448,14 @@ void udpCivData::sendOpenClose(bool close) magic = 0x00; } - const quint8 p[] = { - 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff), - 0xc0, 0x01, 0x00, static_cast(sendSeqB & 0xff), static_cast(sendSeqB >>8 & 0xff),static_cast(magic) - }; + quint8 p[OPENCLOSE_SIZE]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian((quint16)sizeof(p), p + 0x00); + qToLittleEndian(myId, p + 0x08); + qToLittleEndian(remoteId, p + 0x0c); + memcpy(p + 0x10, QByteArrayLiteral("\xc0\x01").constData(), 2); + qToLittleEndian(sendSeqB, p + 0x13); + p[0x15] = magic; sendSeqB++; @@ -626,7 +583,7 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, quint txAudioThread->start(); - sendAreYouThere(); // No need to send periodic are you there as we know they are! + sendControl(false, 0x03, 0x00); // First connect packet connect(&pingTimer, &QTimer::timeout, this, &udpBase::sendPing); pingTimer.start(PING_PERIOD); // send ping packets every 100ms @@ -660,17 +617,15 @@ udpAudio::~udpAudio() - +#define TXAUDIO_SIZE 0x18 void udpAudio::sendTxAudio() { - quint8 p[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff), - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 - }; - //if (((txCodec == 0x01 || txCodec == 0x02) && audio.length() != 960) || (txCodec == 0x04 && audio.length() != 1920)) { - // qDebug() << "Unsupported TX audio length :" << audio.length() << " With codec: " << txCodec; - //} + quint8 p[TXAUDIO_SIZE]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian(myId, p + 0x08); + qToLittleEndian(remoteId, p + 0x0c); + p[0x10] = 0x80; + if (txaudio->chunkAvailable) { QByteArray audio; txaudio->getNextAudioChunk(audio); @@ -765,7 +720,7 @@ udpBase::~udpBase() { qDebug() << "Closing UDP stream :" << radioIP.toString() << ":" << port; if (udp != Q_NULLPTR) { - sendPacketDisconnect(); + sendControl(false, 0x05, 0x00); // Send disconnect udp->close(); delete udp; } @@ -792,7 +747,7 @@ void udpBase::dataReceived(QByteArray r) areYouThereCounter = 0; // I don't think that we will ever receive an "I am here" other than in response to "Are you there?" remoteId = qFromLittleEndian(r.mid(8, 4)); - sendAreYouReady(); + sendControl(false,0x06,0x01); // Send Are you ready - untracked. } else if (r.mid(0, 6) == QByteArrayLiteral("\x10\x00\x00\x00\x00\x00")) { // Just get the seqnum and ignore the rest. @@ -818,7 +773,7 @@ void udpBase::dataReceived(QByteArray r) { // Packet was not found in buffer //qDebug() << this->metaObject()->className() << ": Could not find requested packet " << gotSeq << ", sending idle."; - sendIdle(false, gotSeq); + sendControl(false, 0, gotSeq); } } else if (r.mid(0, 6) == QByteArrayLiteral("\x18\x00\x00\x00\x01\x00")) @@ -843,7 +798,7 @@ void udpBase::dataReceived(QByteArray r) if (!found) { //qDebug() << this->metaObject()->className() << ": Could not find requested packet " << gotSeq << ", sending idle."; - sendIdle(false, gotSeq); + sendControl(false, 0, gotSeq); } } } @@ -856,18 +811,24 @@ void udpBase::dataReceived(QByteArray r) // It is a ping request/response uint16_t gotSeq = qFromLittleEndian(r.mid(6, 2)); - if (r[16] == (char)0x00) + if (r[0x10] == (char)0x00) { + quint8 p[0x15]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian(sizeof(p), p + 0x00); + p[0x04] = 0x07; + qToLittleEndian(myId, p + 0x08); + qToLittleEndian(remoteId, p + 0x0c); + p[0x10] = (char)0x01; + p[0x11] = (char)r[0x11]; + p[0x12] = (char)r[0x12]; + p[0x13] = (char)r[0x13]; + p[0x14] = (char)r[0x14]; - const quint8 p[] = { 0x15, 0x00, 0x00, 0x00, 0x07, 0x00,static_cast(gotSeq & 0xff),static_cast((gotSeq >> 8) & 0xff), - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff), - 0x01,static_cast(r[17]),static_cast(r[18]),static_cast(r[19]),static_cast(r[20]) - }; QMutexLocker locker(&mutex); udp->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), radioIP, port); } - else if (r[16] == (char)0x01) { + else if (r[0x10] == (char)0x01) { if (gotSeq == pingSendSeq) { // This is response to OUR request so increment counter @@ -892,17 +853,20 @@ void udpBase::dataReceived(QByteArray r) } -void udpBase::sendIdle(bool tracked=true,quint16 seq=0) +#define CONTROL_SIZE 0x10 +// Used to send idle and other "control" style messages +void udpBase::sendControl(bool tracked=true, quint8 id=0, quint16 seq=0) { - quint8 p[] = { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff) - }; + quint8 p[CONTROL_SIZE]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian((quint16)sizeof(p), p + 0x00); + qToLittleEndian(myId, p + 0x08); + qToLittleEndian(remoteId, p + 0x0c); + p[0x04] = id; lastControlPacketSentTime = QDateTime::currentDateTime(); // Is this used? if (!tracked) { - p[6] = seq & 0xff; - p[7] = (seq >> 8) & 0xff; + qToLittleEndian(seq, p + 0x06); QMutexLocker locker(&mutex); udp->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), radioIP, port); } @@ -915,17 +879,19 @@ void udpBase::sendIdle(bool tracked=true,quint16 seq=0) return; } +#define PING_SIZE 0x15 // Send periodic ping packets void udpBase::sendPing() { - //qDebug() << this->metaObject()->className() << " tx buffer size:" << txSeqBuf.length(); + quint32 pingSeq = (quint32)((quint8)(rand() & 0xff)) | (quint16)innerSendSeq << 8 | (quint8)0x06 << 24; + + quint8 p[PING_SIZE]; + memset(p, 0x0, sizeof(p)); + qToLittleEndian((quint16)sizeof(p), p + 0x00); + qToLittleEndian(myId, p + 0x08); + qToLittleEndian(remoteId, p + 0x0c); + qToLittleEndian(pingSeq, p + 0x11); - const quint8 p[] = { 0x15, 0x00, 0x00, 0x00, 0x07, 0x00, static_cast(pingSendSeq & 0xff),static_cast(pingSendSeq >> 8 & 0xff), - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff), - 0x00, static_cast(rand()),static_cast(innerSendSeq & 0xff),static_cast(innerSendSeq >> 8 & 0xff), 0x06 - }; - //qDebug() << this->metaObject()->className() << ": Send pkt7: " << QByteArray::fromRawData((const char*)p, sizeof(p)); lastPingSentTime = QDateTime::currentDateTime(); QMutexLocker locker(&mutex); udp->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), radioIP, port); @@ -967,55 +933,6 @@ void udpBase::purgeOldEntries() } } - -/// -/// This function is used by all sockets and expects an "I am here" response. -/// -void udpBase::sendAreYouThere() -{ - qDebug() << this->metaObject()->className() << ": Sending Are You There..."; - const quint8 p[] = { 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff) - }; - - QMutexLocker locker(&mutex); - udp->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), radioIP, port); - return; -} - - -/// -/// Once an "I am here" response is received, send this -/// -void udpBase::sendAreYouReady() -{ - qDebug() << this->metaObject()->className() << ": Sending Are you ready?"; - const quint8 p[] = { 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff) - }; - - QMutexLocker locker(&mutex); - udp->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), radioIP, port); - return; -} - -void udpBase::sendPacketDisconnect() // Unmanaged packet -{ - qDebug() << "Sending Stream Disconnect"; - - const quint8 p[] = { 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - static_cast(myId & 0xff), static_cast(myId >> 8 & 0xff), static_cast(myId >> 16 & 0xff), static_cast(myId >> 24 & 0xff), - static_cast(remoteId & 0xff), static_cast(remoteId >> 8 & 0xff), static_cast(remoteId >> 16 & 0xff), static_cast(remoteId >> 24 & 0xff) - }; - - QMutexLocker locker(&mutex); - udp->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), radioIP, port); - return; -} - - /// /// passcode function used to generate secure (ish) code /// diff --git a/udphandler.h b/udphandler.h index 749b98c..5b04417 100644 --- a/udphandler.h +++ b/udphandler.h @@ -43,9 +43,8 @@ public: void init(); void dataReceived(QByteArray r); - void sendAreYouThere(); void sendPing(); // Periodic type 0x07 ping packet sending - void sendIdle(bool tracked, quint16 seq); + void sendControl(bool tracked,quint8 id, quint16 seq); QUdpSocket* udp=Q_NULLPTR; uint32_t myId = 0; @@ -80,8 +79,6 @@ public: QList txSeqBuf = QList(); std::vector< quint16 > rxSeqBuf; - void sendAreYouReady(); - void sendPacketDisconnect(); void sendTrackedPacket(QByteArray d); void purgeOldEntries(); @@ -121,8 +118,6 @@ public slots: private: void dataReceived(); - void SendIdle(); - void SendPeriodic(); void sendOpenClose(bool close); }; From b7164d762ca0af8c9f2341e2930d08cdd86304ea Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Thu, 18 Feb 2021 17:44:11 +0000 Subject: [PATCH 5/7] Fix for endian-ness of packets --- udphandler.cpp | 4 ++-- udpserver.cpp | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/udphandler.cpp b/udphandler.cpp index 8acd10b..75b6d29 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -428,7 +428,7 @@ void udpCivData::send(QByteArray d) qToLittleEndian(remoteId, p + 0x0c); p[0x10] = 0xc1; qToLittleEndian((quint16)d.length(), p + 0x11); - qToLittleEndian(sendSeqB, p + 0x13); + qToBigEndian(sendSeqB, p + 0x13); // THIS IS BIG ENDIAN! QByteArray t = QByteArray::fromRawData((const char*)p, sizeof(p)); t.append(d); @@ -501,7 +501,7 @@ void udpCivData::dataReceived() quint8 temp = r[0] - 0x15; if ((quint8)r[16] == 0xc1 && (quint8)r[17] == temp) { - emit receive(r.mid(21)); + emit receive(r.mid(0x15)); } } break; diff --git a/udpserver.cpp b/udpserver.cpp index 3188c8f..2b0c5ce 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -366,7 +366,7 @@ void udpServer::civReceived() } // This is a retransmit request else if (r.mid(0, 6) == QByteArrayLiteral("\x10\x00\x00\x00\x01\x00")) { - // Just send an idle for now! + // Just send an idle for now, we need to be able to retransmit missing packets. qDebug() << current->ipAddress.toString() << ": Received 'retransmit' request for " << gotSeq; sendIdle(current, gotSeq); @@ -840,14 +840,13 @@ void udpServer::dataForServer(QByteArray d) qToLittleEndian(client->txSeq, p + 0x06); qToLittleEndian(client->myId, p + 0x08); qToLittleEndian(client->remoteId, p + 0x0c); + p[0x10] = (char)0xc1; + qToLittleEndian((quint16)d.length(), p + 0x11); + qToBigEndian(client->connSeq, p + 0x13); // THIS IS BIG ENDIAN! QByteArray t = QByteArray::fromRawData((const char*)p, sizeof(p)); - p[0x10] = (char)0xc1; - qToLittleEndian((quint16)t.length(), p + 0x11); - qToLittleEndian(client->connSeq, p + 0x12); - qToLittleEndian((quint16)sizeof(p) + t.length()+d.length(), p + 0x00); + qToLittleEndian((quint16)t.length()+d.length(), p + 0x00); - t.append(QByteArray::fromRawData((const char*)p, sizeof(p))); t.append(d); QMutexLocker locker(&mutex); From 8c50e9486ce30feca443a3a6ce9317fbb5ac0c74 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Thu, 18 Feb 2021 18:47:47 +0000 Subject: [PATCH 6/7] Fix server compile warning --- udpserver.cpp | 4 ++-- udpserver.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/udpserver.cpp b/udpserver.cpp index 2b0c5ce..b89080f 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -159,7 +159,7 @@ void udpServer::controlReceived() current->wdTimer = new QTimer(); connect(current->pingTimer, &QTimer::timeout, this, std::bind(&udpServer::sendPing, this, &controlClients, 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, controlClients, current)); + connect(current->wdTimer, &QTimer::timeout, this, std::bind(&udpServer::sendWatchdog, this, current)); current->pingTimer->start(100); current->idleTimer->start(100); current->wdTimer->start(10000); @@ -765,7 +765,7 @@ void udpServer::sendTokenResponse(CLIENT* c, quint8 type) } #define WATCHDOG_SIZE 0x14 -void udpServer::sendWatchdog(QList l,CLIENT* c) +void udpServer::sendWatchdog(CLIENT* c) { QMutexLocker locker(&mutex); diff --git a/udpserver.h b/udpserver.h index a8fb298..94a6f24 100644 --- a/udpserver.h +++ b/udpserver.h @@ -90,7 +90,7 @@ private: void sendCapabilities(CLIENT* c); void sendConnectionInfo(CLIENT* c); void sendTokenResponse(CLIENT* c,quint8 type); - void sendWatchdog(QList l, CLIENT* c); + void sendWatchdog(CLIENT* c); void sendStatus(CLIENT* c); void deleteConnection(QList *l, CLIENT* c); From af314599e8c15c2377677a637a628f8d0abd2a0f Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Thu, 18 Feb 2021 19:12:27 +0000 Subject: [PATCH 7/7] Fix ping sending that I broke! --- udphandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udphandler.cpp b/udphandler.cpp index 75b6d29..6c59b17 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -888,10 +888,10 @@ void udpBase::sendPing() quint8 p[PING_SIZE]; memset(p, 0x0, sizeof(p)); qToLittleEndian((quint16)sizeof(p), p + 0x00); + p[0x04] = 0x07; qToLittleEndian(myId, p + 0x08); qToLittleEndian(remoteId, p + 0x0c); qToLittleEndian(pingSeq, p + 0x11); - lastPingSentTime = QDateTime::currentDateTime(); QMutexLocker locker(&mutex); udp->writeDatagram(QByteArray::fromRawData((const char*)p, sizeof(p)), radioIP, port);