kopia lustrzana https://gitlab.com/eliggett/wfview
Merge remote-tracking branch 'origin/master' into ui-enhance
commit
d5886aa748
78
CHANGELOG
78
CHANGELOG
|
@ -1,20 +1,30 @@
|
|||
# CHANGELOG
|
||||
|
||||
- 20210511
|
||||
- 20210514 Make UDP port textboxes expanding.
|
||||
|
||||
Fixes for virtual serial port in Windows.
|
||||
Fixes to UDP server
|
||||
|
||||
Hopefully improve stability of pty by filtering traffic for any other CIV id.
|
||||
|
||||
- 20210513 Additional search path for macports compatibility (macOS only).
|
||||
|
||||
Slower polling for older rigs using lower serial baud.
|
||||
|
||||
Fix CI-V packet length bug in udphandler
|
||||
|
||||
Set pty serial port to NULL by default
|
||||
|
||||
- 20210512 Fix for crash on MacOS
|
||||
|
||||
- 20210511 Fixes for virtual serial port in Windows.
|
||||
|
||||
Initial commit of pty rewrite
|
||||
There is a new combobox in Settings which shows the file that the pty device is mapped to.
|
||||
You can select from ~/rig-pty[1-8] which should work if you have multiple instances of wfview.
|
||||
|
||||
- 20210509
|
||||
- 20210509 Enhanced accessibility for the UI.
|
||||
|
||||
Enhanced accessibility for the UI.
|
||||
|
||||
- 20210508
|
||||
|
||||
Data Mode now sends the currently selected filter.
|
||||
- 20210508 Data Mode now sends the currently selected filter.
|
||||
|
||||
Removed -march=native compiler and linker flags. This should make the
|
||||
binary builds more compatible, and also eliminate an issue on Pop! OS,
|
||||
|
@ -22,9 +32,7 @@
|
|||
|
||||
Preliminary IC910H support
|
||||
|
||||
- 20210507
|
||||
|
||||
Added serial port iterators for the IC-7610 and IC-R8600. Untested.
|
||||
- 20210507 Added serial port iterators for the IC-7610 and IC-R8600. Untested.
|
||||
|
||||
removing debug info we didn't need.
|
||||
|
||||
|
@ -52,34 +60,24 @@
|
|||
pttyHandler doesn't use pty parameter in Linux so set to Q_UNUSED to eliminate warning
|
||||
|
||||
|
||||
- 20210506
|
||||
|
||||
Force DTR/RTS to false to stop rigs going into TX if USB Send is enabled
|
||||
- 20210506 Force DTR/RTS to false to stop rigs going into TX if USB Send is enabled
|
||||
|
||||
Convert project to 32bit default on Windows and remove beginnings of VSPE code.
|
||||
|
||||
|
||||
- 20210505
|
||||
|
||||
Add code to select virtual serial port
|
||||
- 20210505 Add code to select virtual serial port
|
||||
|
||||
fixed a typo in mint instructions and ubuntu instructions
|
||||
|
||||
- 20210504
|
||||
|
||||
fixed the display instead of rigcaps so that ant sel starts with 1 instead of 0
|
||||
- 20210504 fixed the display instead of rigcaps so that ant sel starts with 1 instead of 0
|
||||
|
||||
Fix to add a blank user line in server if no users are configured.
|
||||
|
||||
small changes where to find the release; removed the src/build target directory requirement as the release unpacks in ./dist
|
||||
|
||||
- 20310503
|
||||
- 20310503 Fix for Built-in audio on MacOS
|
||||
|
||||
Fix for Built-in audio on MacOS
|
||||
|
||||
- 20210501
|
||||
|
||||
Fixed bug 007, which allowed negative frequencies to be dialed.
|
||||
- 20210501 Fixed bug 007, which allowed negative frequencies to be dialed.
|
||||
|
||||
Double-clicking the waterfall now obeys the tuning step and rounding
|
||||
option in the settings.
|
||||
|
@ -96,14 +94,10 @@
|
|||
|
||||
Added more modes for the IC-R8600.
|
||||
|
||||
- 20210430
|
||||
|
||||
Different timing on command polling for serial rigs.
|
||||
- 20210430 Different timing on command polling for serial rigs.
|
||||
|
||||
|
||||
- 20210427
|
||||
|
||||
Minor changes to hide sat button until we have time to work on that
|
||||
- 20210427 Minor changes to hide sat button until we have time to work on that
|
||||
feature.
|
||||
|
||||
Additional bands added, Airband, WFM
|
||||
|
@ -120,9 +114,7 @@
|
|||
|
||||
changed the modeSelectCombo-addItem sequence a bit to have modes grouped; CW and CW-R are now grouped, as well as RTTY/RTTY-R; AM and FM are grouped now
|
||||
|
||||
- 20210426
|
||||
|
||||
Well, that was fun. Color preferences now work, and colors can be
|
||||
- 20210426 Well, that was fun. Color preferences now work, and colors can be
|
||||
modified from the preference file for custom plot colors.
|
||||
|
||||
The preference file now stores colors as unsigned int. To convert the
|
||||
|
@ -137,9 +129,7 @@
|
|||
|
||||
started rough docs for the usermanual
|
||||
|
||||
- 20210425
|
||||
|
||||
More work on rigctld
|
||||
- 20210425 More work on rigctld
|
||||
|
||||
Faster polling. Clarified in comments around line 309 in wfmain.cpp.
|
||||
|
||||
|
@ -152,16 +142,12 @@
|
|||
state queries to 100ms. May consider faster queries on startup since we
|
||||
are going to need more things queried on startup.
|
||||
|
||||
- 20210424
|
||||
|
||||
Receiver Incremental Tuning is in. The UI does not check the rig's
|
||||
- 20210424 Receiver Incremental Tuning is in. The UI does not check the rig's
|
||||
initial state yet, but the functions are partially in rigCommander for
|
||||
that purpose.
|
||||
|
||||
|
||||
- 20210423
|
||||
|
||||
Found two missing defaults in switch cases inside rigcommander.cpp.
|
||||
- 20210423 Found two missing defaults in switch cases inside rigcommander.cpp.
|
||||
|
||||
Modified rig power management to stop command ques (s-meter and others).
|
||||
Upon rig power up, the command queue is repurposed as a 3 second delay
|
||||
|
@ -173,9 +159,7 @@
|
|||
|
||||
powerOff should work now.
|
||||
|
||||
- 20210420
|
||||
|
||||
rigctl working (sort of) with WSJT-X
|
||||
- 20210420 rigctl working (sort of) with WSJT-X
|
||||
|
||||
- 20210419 Initial commit of rigctld (doesn't currently do anything useful!)
|
||||
|
||||
|
|
|
@ -828,7 +828,7 @@ bool audioHandler::init(const quint8 bits, const quint8 channels, const quint16
|
|||
|
||||
void audioHandler::setVolume(unsigned char volume)
|
||||
{
|
||||
qDebug(logAudio()) << (isInput ? "Input" : "Output") << "setVolume: " << volume << "(" << (qreal)(volume/255.0) << ")";
|
||||
//qDebug(logAudio()) << (isInput ? "Input" : "Output") << "setVolume: " << volume << "(" << (qreal)(volume/255.0) << ")";
|
||||
if (audioOutput != Q_NULLPTR) {
|
||||
audioOutput->setVolume((qreal)(volume / 255.0));
|
||||
}
|
||||
|
|
|
@ -189,6 +189,18 @@ void pttyHandler::receiveDataIn(int fd) {
|
|||
port->commitTransaction();
|
||||
#endif
|
||||
|
||||
int lastFE = inPortData.lastIndexOf((char)0xfe);
|
||||
if (civId == 0 && inPortData.length() > lastFE + 2 && (quint8)inPortData[lastFE + 2] > (quint8)0xdf && (quint8)inPortData[lastFE + 2] < (quint8)0xef) {
|
||||
// This is (should be) the remotes CIV id.
|
||||
civId = (quint8)inPortData[lastFE + 2];
|
||||
qDebug(logSerial()) << "pty detected remote CI-V:" << hex << civId;
|
||||
}
|
||||
else if (civId != 0 && inPortData.length() > lastFE + 2 && (quint8)inPortData[lastFE + 2] != civId)
|
||||
{
|
||||
civId = (quint8)inPortData[lastFE + 2];
|
||||
qDebug(logSerial()) << "pty remote CI-V changed:" << hex << (quint8)civId;
|
||||
}
|
||||
|
||||
// filter 1A 05 01 12/27 = C-IV transceive command before forwarding on.
|
||||
if (inPortData.contains(QByteArrayLiteral("\x1a\x05\x01\x12")) || inPortData.contains(QByteArrayLiteral("\x1a\x05\x01\x27")))
|
||||
{
|
||||
|
@ -200,7 +212,7 @@ void pttyHandler::receiveDataIn(int fd) {
|
|||
sendDataOut(inPortData); // Echo command back
|
||||
sendDataOut(reply);
|
||||
}
|
||||
else
|
||||
else if (inPortData.length() > lastFE + 2 && ((quint8)inPortData[lastFE + 1] == civId || (quint8)inPortData[lastFE + 2] == civId))
|
||||
{
|
||||
emit haveDataFromPort(inPortData);
|
||||
//qDebug(logSerial()) << "Data from pseudo term:";
|
||||
|
|
|
@ -67,7 +67,7 @@ private:
|
|||
void printHex(const QByteArray& pdata, bool printVert, bool printHoriz);
|
||||
|
||||
QSocketNotifier *ptReader = nullptr;
|
||||
|
||||
quint8 civId=0;
|
||||
};
|
||||
|
||||
#endif // PTTYHANDLER_H
|
||||
|
|
83
rigctld.cpp
83
rigctld.cpp
|
@ -2,7 +2,6 @@
|
|||
#include "logcategories.h"
|
||||
|
||||
|
||||
|
||||
rigCtlD::rigCtlD(QObject* parent) :
|
||||
QTcpServer(parent)
|
||||
{
|
||||
|
@ -16,13 +15,16 @@ void rigCtlD::receiveFrequency(freqt freq)
|
|||
{
|
||||
emit setFrequency(freq);
|
||||
}
|
||||
|
||||
void rigCtlD::receiveStateInfo(rigStateStruct* state)
|
||||
{
|
||||
qDebug("Setting rig state");
|
||||
rigState = state;
|
||||
}
|
||||
|
||||
int rigCtlD::startServer(qint16 port)
|
||||
|
||||
|
||||
int rigCtlD::startServer(qint16 port)
|
||||
{
|
||||
if (!this->listen(QHostAddress::Any, port)) {
|
||||
qDebug(logRigCtlD()) << "could not start on port " << port;
|
||||
|
@ -41,7 +43,7 @@ void rigCtlD::incomingConnection(qintptr socket) {
|
|||
}
|
||||
|
||||
|
||||
void rigCtlD::stopServer()
|
||||
void rigCtlD::stopServer()
|
||||
{
|
||||
qDebug(logRigCtlD()) << "stopping server";
|
||||
emit onStopped();
|
||||
|
@ -53,8 +55,9 @@ void rigCtlD::receiveRigCaps(rigCapabilities caps)
|
|||
this->rigCaps = caps;
|
||||
}
|
||||
|
||||
rigCtlClient::rigCtlClient(int socketId, rigCapabilities caps,rigStateStruct *state, rigCtlD *parent) : QObject(parent)
|
||||
rigCtlClient::rigCtlClient(int socketId, rigCapabilities caps, rigStateStruct* state, rigCtlD* parent) : QObject(parent)
|
||||
{
|
||||
|
||||
commandBuffer.clear();
|
||||
sessionId = socketId;
|
||||
rigCaps = caps;
|
||||
|
@ -78,16 +81,24 @@ void rigCtlClient::socketReadyRead()
|
|||
commandBuffer.append(data);
|
||||
static QString sep = " ";
|
||||
static int num = 0;
|
||||
bool longReply = false;
|
||||
if (commandBuffer.endsWith('\n'))
|
||||
{
|
||||
// Process command
|
||||
qDebug(logRigCtlD()) << sessionId << "command received" << commandBuffer;
|
||||
commandBuffer.chop(1); // Remove \n character
|
||||
if (commandBuffer.endsWith('\r'))
|
||||
{
|
||||
commandBuffer.chop(1); // Remove \n character
|
||||
}
|
||||
|
||||
// We have a full line so process command.
|
||||
|
||||
if (rigState == Q_NULLPTR)
|
||||
{
|
||||
qDebug(logRigCtlD()) << "no rigState!";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug(logRigCtlD()) << sessionId << "command received" << commandBuffer;
|
||||
if (commandBuffer[num] == ";" || commandBuffer[num] == "|" || commandBuffer[num] == ",")
|
||||
{
|
||||
sep = commandBuffer[num].toLatin1();
|
||||
|
@ -98,45 +109,59 @@ void rigCtlClient::socketReadyRead()
|
|||
sep = "\n";
|
||||
}
|
||||
|
||||
if (commandBuffer[num] == "q")
|
||||
else if (commandBuffer[num].toLower() == "q")
|
||||
{
|
||||
closeSocket();
|
||||
}
|
||||
if (commandBuffer.contains("\\chk_vfo"))
|
||||
else if (commandBuffer[num] == "#")
|
||||
{
|
||||
sendData(QString("0\n"));
|
||||
return;
|
||||
}
|
||||
if (commandBuffer.contains("\\dump_state"))
|
||||
else if (commandBuffer[num] == "\\")
|
||||
{
|
||||
num++;
|
||||
longReply = true;
|
||||
}
|
||||
QStringList command = commandBuffer.mid(num).split(" ");
|
||||
|
||||
|
||||
if (command[0] == 0xf0 || command[0]=="chk_vfo")
|
||||
{
|
||||
if (longReply)
|
||||
sendData(QString("0\n"));
|
||||
else
|
||||
sendData(QString("0\n"));
|
||||
}
|
||||
else if (command[0] == "dump_state")
|
||||
{
|
||||
// Currently send "fake" state information until I can work out what is required!
|
||||
sendData(QString("1\n1\n0\n150000.000000 1500000000.000000 0x1ff -1 -1 0x16000003 0xf\n0 0 0 0 0 0 0\n0 0 0 0 0 0 0\n0x1ff 1\n0x1ff 0\n0 0\n0x1e 2400\n0x2 500\n0x1 8000\n0x1 2400\n0x20 15000\n0x20 8000\n0x40 230000\n0 0\n9990\n9990\n10000\n0\n10\n10 20 30\n0x3effffff\n0x3effffff\n0x7fffffff\n0x7fffffff\n0x7fffffff\n0x7fffffff\ndone\n"));
|
||||
}
|
||||
if (commandBuffer[num] == "f" || commandBuffer.contains("\\get_freq"))
|
||||
else if (command[0] == "f" || command[0] == "get_freq")
|
||||
{
|
||||
sendData(QString("%1\n").arg(rigState->vfoAFreq.Hz));
|
||||
}
|
||||
else if (commandBuffer[num] == "F" || commandBuffer.contains("\\set_freq"))
|
||||
else if (command[0] == "F" || command[0] == "set_freq")
|
||||
{
|
||||
const QRegExp rx(QLatin1Literal("[^0-9]+"));
|
||||
auto&& parts = commandBuffer.split(rx);
|
||||
freqt freq;
|
||||
if (parts.length() > 1) {
|
||||
freq.Hz = parts[1].toInt();
|
||||
if (command.length()>1)
|
||||
{
|
||||
freqt freq;
|
||||
freq.Hz = command[1].toInt();
|
||||
emit parent->setFrequency(freq);
|
||||
}
|
||||
sendData(QString("RPRT 0\n"));
|
||||
}
|
||||
else if (commandBuffer[num] == "1" || commandBuffer.contains("\\dump_caps"))
|
||||
else if (command[0] == "1" || command[0] == "dump_caps")
|
||||
{
|
||||
dumpCaps(sep);
|
||||
}
|
||||
else if (commandBuffer[num] == "t")
|
||||
else if (command[0] == "t")
|
||||
{
|
||||
sendData(QString("%1\n").arg(rigState->ptt));
|
||||
}
|
||||
else if (commandBuffer[num] == "T")
|
||||
else if (command[0] == "T")
|
||||
{
|
||||
if (commandBuffer[num + 2] == "0") {
|
||||
if (command.length()>1 && command[1] == "0") {
|
||||
emit parent->setPTT(false);
|
||||
}
|
||||
else {
|
||||
|
@ -144,26 +169,24 @@ void rigCtlClient::socketReadyRead()
|
|||
}
|
||||
sendData(QString("RPRT 0\n"));
|
||||
}
|
||||
else if (commandBuffer[num] == "v")
|
||||
else if (command[0] == "v" || command[0] == "get_vfo")
|
||||
{
|
||||
sendData(QString("VFOA\n"));
|
||||
}
|
||||
else if (commandBuffer[num] == "m")
|
||||
else if (command[0] == "m" || command[0] == "get_mode")
|
||||
{
|
||||
sendData(QString("%1\n%2\n").arg(getMode(rigState->mode,rigState->datamode)).arg(getFilter(rigState->mode,rigState->filter)));
|
||||
}
|
||||
else if (commandBuffer[num] == "M")
|
||||
else if (command[0] == "M" || command[0] == "set_mode")
|
||||
{
|
||||
// Set mode
|
||||
const QRegExp rx(QLatin1Literal("\\s+"));
|
||||
auto&& parts = commandBuffer.split(rx);
|
||||
if (parts.length() > 1) {
|
||||
qDebug(logRigCtlD()) << "setting mode: " << getMode(parts[1]);
|
||||
emit parent->setMode(getMode(parts[1]), 0x06);
|
||||
if (command.length() > 1) {
|
||||
qDebug(logRigCtlD()) << "setting mode: " << getMode(command[1]);
|
||||
emit parent->setMode(getMode(command[1]), 0x06);
|
||||
}
|
||||
sendData(QString("RPRT 0\n"));
|
||||
}
|
||||
else if (commandBuffer[num] == "s")
|
||||
else if (command[0] == "s" || command[0] == "get_split_vfo")
|
||||
{
|
||||
sendData(QString("0\nVFOA\n"));
|
||||
}
|
||||
|
|
35
rigctld.h
35
rigctld.h
|
@ -8,8 +8,40 @@
|
|||
#include <QSet>
|
||||
#include <QDataStream>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <typeindex>
|
||||
|
||||
#include "rigcommander.h"
|
||||
|
||||
typedef void (*voidFunction)(void);
|
||||
struct Interface {
|
||||
|
||||
std::map<std::string, std::pair<voidFunction, std::type_index>> m1;
|
||||
|
||||
template<typename T>
|
||||
void insert(std::string s1, std::string s2, T f1) {
|
||||
auto tt = std::type_index(typeid(f1));
|
||||
m1.insert(std::make_pair(s1,
|
||||
std::make_pair((voidFunction)f1, tt)));
|
||||
m1.insert(std::make_pair(s2,
|
||||
std::make_pair((voidFunction)f1, tt)));
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
T searchAndCall(std::string s1, Args&&... args) {
|
||||
auto mapIter = m1.find(s1);
|
||||
/*chk if not end*/
|
||||
auto mapVal = mapIter->second;
|
||||
|
||||
// auto typeCastedFun = reinterpret_cast<T(*)(Args ...)>(mapVal.first);
|
||||
auto typeCastedFun = (T(*)(Args ...))(mapVal.first);
|
||||
|
||||
//compare the types is equal or not
|
||||
assert(mapVal.second == std::type_index(typeid(typeCastedFun)));
|
||||
return typeCastedFun(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
class rigCtlD : public QTcpServer
|
||||
{
|
||||
|
@ -71,6 +103,9 @@ private:
|
|||
QString getMode(unsigned char mode, bool datamode);
|
||||
unsigned char getMode(QString modeString);
|
||||
QString getFilter(unsigned char mode, unsigned char filter);
|
||||
|
||||
Interface commands;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
204
udpserver.cpp
204
udpserver.cpp
|
@ -56,13 +56,13 @@ void udpServer::init()
|
|||
udpAudio = new QUdpSocket(this);
|
||||
udpAudio->bind(config.audioPort);
|
||||
QUdpSocket::connect(udpAudio, &QUdpSocket::readyRead, this, &udpServer::audioReceived);
|
||||
|
||||
}
|
||||
|
||||
udpServer::~udpServer()
|
||||
{
|
||||
qDebug(logUdpServer()) << "Closing udpServer";
|
||||
|
||||
connMutex.lock();
|
||||
|
||||
foreach(CLIENT * client, controlClients)
|
||||
{
|
||||
|
@ -153,6 +153,9 @@ udpServer::~udpServer()
|
|||
udpAudio->close();
|
||||
delete udpAudio;
|
||||
}
|
||||
|
||||
connMutex.unlock();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -187,6 +190,7 @@ void udpServer::controlReceived()
|
|||
if (current == Q_NULLPTR)
|
||||
{
|
||||
current = new CLIENT();
|
||||
current->type = "Control";
|
||||
current->connected = true;
|
||||
current->isStreaming = false;
|
||||
current->timeConnected = QDateTime::currentDateTime();
|
||||
|
@ -217,8 +221,11 @@ void udpServer::controlReceived()
|
|||
|
||||
|
||||
current->commonCap = 0x8010;
|
||||
qDebug(logUdpServer()) << "New Control connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port);
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": New Control connection created";
|
||||
connMutex.lock();
|
||||
controlClients.append(current);
|
||||
connMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
current->lastHeard = QDateTime::currentDateTime();
|
||||
|
@ -352,7 +359,7 @@ void udpServer::controlReceived()
|
|||
sendStatus(current);
|
||||
current->authInnerSeq = 0x00;
|
||||
sendConnectionInfo(current);
|
||||
qDebug(logUdpServer()) << "rxCodec:" << current->rxCodec << " txCodec:" << current->txCodec <<
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": rxCodec:" << current->rxCodec << " txCodec:" << current->txCodec <<
|
||||
" rxSampleRate" << current->rxSampleRate <<
|
||||
" txSampleRate" << current->rxSampleRate <<
|
||||
" txBufferLen" << current->txBufferLen;
|
||||
|
@ -470,6 +477,8 @@ void udpServer::civReceived()
|
|||
if (current == Q_NULLPTR)
|
||||
{
|
||||
current = new CLIENT();
|
||||
current->type = "CIV";
|
||||
current->civId = 0;
|
||||
current->connected = true;
|
||||
current->timeConnected = QDateTime::currentDateTime();
|
||||
current->ipAddress = datagram.senderAddress();
|
||||
|
@ -485,7 +494,7 @@ void udpServer::civReceived()
|
|||
|
||||
current->idleTimer = new QTimer();
|
||||
connect(current->idleTimer, &QTimer::timeout, this, std::bind(&udpServer::sendControl, this, current, 0x00, (quint16)0x00));
|
||||
current->idleTimer->start(100);
|
||||
//current->idleTimer->start(100); // Start idleTimer after receiving iamready.
|
||||
|
||||
current->wdTimer = new QTimer();
|
||||
connect(current->wdTimer, &QTimer::timeout, this, std::bind(&udpServer::watchdog, this, current));
|
||||
|
@ -495,15 +504,19 @@ void udpServer::civReceived()
|
|||
connect(current->retransmitTimer, &QTimer::timeout, this, std::bind(&udpServer::sendRetransmitRequest, this, current));
|
||||
current->retransmitTimer->start(RETRANSMIT_PERIOD);
|
||||
|
||||
qDebug(logUdpServer()) << "New CIV connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port);
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): New connection created";
|
||||
connMutex.lock();
|
||||
civClients.append(current);
|
||||
connMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
switch (r.length())
|
||||
{
|
||||
case (CONTROL_SIZE):
|
||||
/* case (CONTROL_SIZE):
|
||||
{
|
||||
}
|
||||
*/
|
||||
case (PING_SIZE):
|
||||
{
|
||||
ping_packet_t in = (ping_packet_t)r.constData();
|
||||
|
@ -534,20 +547,40 @@ void udpServer::civReceived()
|
|||
default:
|
||||
{
|
||||
|
||||
if (r.length() > 0x15) {
|
||||
if (r.length() > 0x18) {
|
||||
data_packet_t in = (data_packet_t)r.constData();
|
||||
if (in->type != 0x01)
|
||||
{
|
||||
if (quint16(in->datalen + 0x15) == (quint16)in->len)
|
||||
{
|
||||
// Strip all '0xFE' command preambles first:
|
||||
int lastFE = r.lastIndexOf((char)0xfe);
|
||||
//qDebug(logUdpServer()) << "Got:" << r.mid(lastFE);
|
||||
if (current->civId == 0 && r.length() > lastFE + 2 && (quint8)r[lastFE + 2] > (quint8)0xdf && (quint8)r[lastFE + 2] < (quint8)0xef) {
|
||||
// This is (should be) the remotes CIV id.
|
||||
current->civId = (quint8)r[lastFE + 2];
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": Detected remote CI-V:" << hex << current->civId;
|
||||
}
|
||||
else if (current->civId != 0 && r.length() > lastFE + 2 && (quint8)r[lastFE + 2] != current->civId)
|
||||
{
|
||||
current->civId = (quint8)r[lastFE + 2];
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": Detected different remote CI-V:" << hex << current->civId;
|
||||
}
|
||||
|
||||
emit haveDataFromServer(r.mid(0x15));
|
||||
}
|
||||
else {
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": Datalen mismatch " << quint16(in->datalen + 0x15) << ":" << (quint16)in->len;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
//break;
|
||||
}
|
||||
}
|
||||
commonReceived(&civClients, current, r);
|
||||
if (current != Q_NULLPTR) {
|
||||
udpServer::commonReceived(&civClients, current, r);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -577,6 +610,7 @@ void udpServer::audioReceived()
|
|||
if (current == Q_NULLPTR)
|
||||
{
|
||||
current = new CLIENT();
|
||||
current->type = "Audio";
|
||||
current->connected = true;
|
||||
current->timeConnected = QDateTime::currentDateTime();
|
||||
current->ipAddress = datagram.senderAddress();
|
||||
|
@ -598,10 +632,14 @@ void udpServer::audioReceived()
|
|||
connect(current->retransmitTimer, &QTimer::timeout, this, std::bind(&udpServer::sendRetransmitRequest, this, current));
|
||||
current->retransmitTimer->start(RETRANSMIT_PERIOD);
|
||||
current->seqPrefix = 0;
|
||||
qDebug(logUdpServer()) << "New Audio connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port);
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): New connection created";
|
||||
connMutex.lock();
|
||||
audioClients.append(current);
|
||||
connMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
|
||||
switch (r.length())
|
||||
{
|
||||
case (PING_SIZE):
|
||||
|
@ -666,7 +704,7 @@ void udpServer::audioReceived()
|
|||
|
||||
}
|
||||
if (current != Q_NULLPTR) {
|
||||
commonReceived(&audioClients, current, r);
|
||||
udpServer::commonReceived(&audioClients, current, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -680,7 +718,7 @@ void udpServer::commonReceived(QList<CLIENT*>* l,CLIENT* current, QByteArray r)
|
|||
if (r.length() < 0x10)
|
||||
{
|
||||
// Invalid packet
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": Invalid packet received, len: " << r.length();
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): Invalid packet received, len: " << r.length();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -690,20 +728,23 @@ void udpServer::commonReceived(QList<CLIENT*>* l,CLIENT* current, QByteArray r)
|
|||
{
|
||||
control_packet_t in = (control_packet_t)r.constData();
|
||||
if (in->type == 0x03) {
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": Received 'are you there'";
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): Received 'are you there'";
|
||||
current->remoteId = in->sentid;
|
||||
sendControl(current, 0x04, in->seq);
|
||||
} // This is This is "Are you ready" in response to "I am here".
|
||||
else if (in->type == 0x06)
|
||||
{
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": Received 'Are you ready'";
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): Received 'Are you ready'";
|
||||
current->remoteId = in->sentid;
|
||||
sendControl(current, 0x06, in->seq);
|
||||
if (current->idleTimer != Q_NULLPTR && !current->idleTimer->isActive()) {
|
||||
current->idleTimer->start(100);
|
||||
}
|
||||
} // This is a retransmit request
|
||||
else if (in->type == 0x01)
|
||||
{
|
||||
// Single packet request
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": Received 'retransmit' request for " << in->seq;
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): Received 'retransmit' request for " << in->seq;
|
||||
|
||||
auto match = std::find_if(current->txSeqBuf.begin(), current->txSeqBuf.end(), [&cs = in->seq](SEQBUFENTRY& s) {
|
||||
return s.seqNum == cs;
|
||||
|
@ -712,10 +753,11 @@ void udpServer::commonReceived(QList<CLIENT*>* l,CLIENT* current, QByteArray r)
|
|||
if (match != current->txSeqBuf.end() && match->retransmitCount < 5) {
|
||||
// Found matching entry?
|
||||
// Don't constantly retransmit the same packet, give-up eventually
|
||||
QMutexLocker locker(&mutex);
|
||||
qDebug(logUdpServer()) << this->metaObject()->className() << ": Sending retransmit of " << hex << match->seqNum;
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): Sending retransmit of " << hex << match->seqNum;
|
||||
match->retransmitCount++;
|
||||
udpMutex.lock();
|
||||
current->socket->writeDatagram(match->data, current->ipAddress, current->port);
|
||||
udpMutex.unlock();
|
||||
} else {
|
||||
// Just send an idle!
|
||||
sendControl(current, 0x00, in->seq);
|
||||
|
@ -725,7 +767,7 @@ void udpServer::commonReceived(QList<CLIENT*>* l,CLIENT* current, QByteArray r)
|
|||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -740,7 +782,7 @@ void udpServer::commonReceived(QList<CLIENT*>* l,CLIENT* current, QByteArray r)
|
|||
return s.seqNum == cs;
|
||||
});
|
||||
if (match == current->txSeqBuf.end()) {
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ":" << current->port << ": Requested packet " << hex << in->seq << " not found";
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): Requested packet " << hex << in->seq << " not found";
|
||||
// Just send idle packet.
|
||||
sendControl(current, 0, in->seq);
|
||||
}
|
||||
|
@ -748,18 +790,22 @@ void udpServer::commonReceived(QList<CLIENT*>* l,CLIENT* current, QByteArray r)
|
|||
{
|
||||
// Found matching entry?
|
||||
// Send "untracked" as it has already been sent once.
|
||||
QMutexLocker locker(&mutex);
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ":" << current->port << ": Sending retransmit of " << hex << match->seqNum;
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): Sending retransmit of " << hex << match->seqNum;
|
||||
match->retransmitCount++;
|
||||
udpMutex.lock();
|
||||
current->socket->writeDatagram(match->data, current->ipAddress, current->port);
|
||||
udpMutex.unlock();
|
||||
match++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (in->len != PING_SIZE && in->type == 0x00 && in->seq != 0x00)
|
||||
else if (in->type == 0x00 && in->seq != 0x00)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
if (current->rxSeqBuf.isEmpty())
|
||||
//if (current->type == "CIV") {
|
||||
// qDebug(logUdpServer()) << "Got:" << in->seq;
|
||||
//}
|
||||
current->rxMutex.lock();
|
||||
if (current->rxSeqBuf.isEmpty())
|
||||
{
|
||||
current->rxSeqBuf.append(in->seq);
|
||||
}
|
||||
|
@ -768,25 +814,30 @@ void udpServer::commonReceived(QList<CLIENT*>* l,CLIENT* current, QByteArray r)
|
|||
std::sort(current->rxSeqBuf.begin(), current->rxSeqBuf.end());
|
||||
if (in->seq < current->rxSeqBuf.front())
|
||||
{
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": ******* seq number may have rolled over ****** previous highest: " << hex << current->rxSeqBuf.back() << " current: " << hex << in->seq;
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): ******* seq number may have rolled over ****** previous highest: " << hex << current->rxSeqBuf.back() << " current: " << hex << in->seq;
|
||||
// Looks like it has rolled over so clear buffer and start again.
|
||||
current->rxSeqBuf.clear();
|
||||
current->rxMutex.unlock(); // Must unlock the Mutex!
|
||||
return;
|
||||
}
|
||||
|
||||
if (!current->rxSeqBuf.contains(in->seq))
|
||||
{
|
||||
// Add incoming packet to the received buffer and if it is in the missing buffer, remove it.
|
||||
|
||||
current->rxSeqBuf.append(in->seq);
|
||||
// Check whether this is one of our missing ones!
|
||||
current->missMutex.lock();
|
||||
auto s = std::find_if(current->rxMissing.begin(), current->rxMissing.end(), [&cs = in->seq](SEQBUFENTRY& s) { return s.seqNum == cs; });
|
||||
if (s != current->rxMissing.end())
|
||||
{
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << ": Missing SEQ has been received! " << hex << in->seq;
|
||||
qDebug(logUdpServer()) << current->ipAddress.toString() << "(" << current->type << "): Missing SEQ has been received! " << hex << in->seq;
|
||||
s = current->rxMissing.erase(s);
|
||||
}
|
||||
current->missMutex.unlock();
|
||||
}
|
||||
}
|
||||
current->rxMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -796,7 +847,6 @@ void udpServer::sendControl(CLIENT* c, quint8 type, quint16 seq)
|
|||
{
|
||||
|
||||
//qDebug(logUdpServer()) << c->ipAddress.toString() << ": Sending control packet: " << type;
|
||||
QMutexLocker locker(&mutex);
|
||||
|
||||
control_packet p;
|
||||
memset(p.packet, 0x0, CONTROL_SIZE); // We can't be sure it is initialized with 0x00!
|
||||
|
@ -808,19 +858,26 @@ void udpServer::sendControl(CLIENT* c, quint8 type, quint16 seq)
|
|||
if (seq == 0x00)
|
||||
{
|
||||
p.seq = c->txSeq;
|
||||
c->txMutex.lock();
|
||||
c->txSeqBuf.append(SEQBUFENTRY());
|
||||
c->txSeqBuf.last().seqNum = seq;
|
||||
c->txSeqBuf.last().timeSent = QTime::currentTime();
|
||||
c->txSeqBuf.last().retransmitCount = 0;
|
||||
c->txSeqBuf.last().data = QByteArray::fromRawData((const char*)p.packet, sizeof(p));
|
||||
udpMutex.lock();
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p.packet, sizeof(p)), c->ipAddress, c->port);
|
||||
udpMutex.unlock();
|
||||
c->txSeq++;
|
||||
if (c->idleTimer != Q_NULLPTR)
|
||||
c->idleTimer->start(100);
|
||||
//if (c->idleTimer != Q_NULLPTR) {
|
||||
// c->idleTimer->start(100);
|
||||
//}
|
||||
c->txMutex.unlock();
|
||||
}
|
||||
else {
|
||||
p.seq = seq;
|
||||
udpMutex.lock();
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p.packet, sizeof(p)), c->ipAddress, c->port);
|
||||
udpMutex.unlock();
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -830,13 +887,12 @@ void udpServer::sendControl(CLIENT* c, quint8 type, quint16 seq)
|
|||
|
||||
void udpServer::sendPing(QList<CLIENT*> *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(logUdpServer()) << "Deleting stale connection " << c->ipAddress.toString();
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << "(" << c->type << "): Deleting stale connection ";
|
||||
deleteConnection(l, c);
|
||||
return;
|
||||
}
|
||||
|
@ -867,14 +923,16 @@ void udpServer::sendPing(QList<CLIENT*> *l,CLIENT* c, quint16 seq, bool reply)
|
|||
p.time = pingTime;
|
||||
p.reply = (char)reply;
|
||||
|
||||
udpMutex.lock();
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p.packet, sizeof(p)), c->ipAddress, c->port);
|
||||
udpMutex.unlock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void udpServer::sendLoginResponse(CLIENT* c, bool allowed)
|
||||
{
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << ": Sending Login response: " << c->txSeq;
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << "(" << c->type << "): Sending Login response: " << c->txSeq;
|
||||
|
||||
login_response_packet p;
|
||||
memset(p.packet, 0x0, sizeof(p)); // We can't be sure it is initialized with 0x00!
|
||||
|
@ -904,24 +962,27 @@ void udpServer::sendLoginResponse(CLIENT* c, bool allowed)
|
|||
strcpy(p.connection,"WFVIEW");
|
||||
}
|
||||
|
||||
QMutexLocker locker(&mutex);
|
||||
c->txMutex.lock();
|
||||
c->txSeqBuf.append(SEQBUFENTRY());
|
||||
c->txSeqBuf.last().seqNum = c->txSeq;
|
||||
c->txSeqBuf.last().timeSent = QTime::currentTime();
|
||||
c->txSeqBuf.last().retransmitCount = 0;
|
||||
c->txSeqBuf.last().data = QByteArray::fromRawData((const char*)p.packet, sizeof(p));
|
||||
|
||||
udpMutex.lock();
|
||||
c->socket->writeDatagram(c->txSeqBuf.last().data, c->ipAddress, c->port);
|
||||
udpMutex.unlock();
|
||||
c->txSeq++;
|
||||
if (c->idleTimer != Q_NULLPTR)
|
||||
c->idleTimer->start(100);
|
||||
|
||||
c->txMutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
void udpServer::sendCapabilities(CLIENT* c)
|
||||
{
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << ": Sending Capabilities :" << c->txSeq;
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << "(" << c->type << "): Sending Capabilities :" << c->txSeq;
|
||||
|
||||
capabilities_packet p;
|
||||
memset(p.packet, 0x0, sizeof(p)); // We can't be sure it is initialized with 0x00!
|
||||
|
@ -1016,19 +1077,23 @@ void udpServer::sendCapabilities(CLIENT* c)
|
|||
p.capf = 0x5001;
|
||||
p.capg = 0x0190;
|
||||
|
||||
QMutexLocker locker(&mutex);
|
||||
c->txMutex.lock();
|
||||
c->txSeqBuf.append(SEQBUFENTRY());
|
||||
c->txSeqBuf.last().seqNum = p.seq;
|
||||
c->txSeqBuf.last().timeSent = QTime::currentTime();
|
||||
c->txSeqBuf.last().retransmitCount = 0;
|
||||
c->txSeqBuf.last().data = QByteArray::fromRawData((const char*)p.packet, sizeof(p));
|
||||
|
||||
|
||||
udpMutex.lock();
|
||||
c->socket->writeDatagram(c->txSeqBuf.last().data, c->ipAddress, c->port);
|
||||
udpMutex.unlock();
|
||||
|
||||
if (c->idleTimer != Q_NULLPTR)
|
||||
c->idleTimer->start(100);
|
||||
|
||||
c->txSeq++;
|
||||
c->txMutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1036,7 +1101,7 @@ void udpServer::sendCapabilities(CLIENT* c)
|
|||
// Also used to display currently connected used information.
|
||||
void udpServer::sendConnectionInfo(CLIENT* c)
|
||||
{
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << ": Sending ConnectionInfo :" << c->txSeq;
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << "(" << c->type << "): Sending ConnectionInfo :" << c->txSeq;
|
||||
conninfo_packet p;
|
||||
memset(p.packet, 0x0, sizeof(p));
|
||||
p.len = sizeof(p);
|
||||
|
@ -1066,25 +1131,28 @@ void udpServer::sendConnectionInfo(CLIENT* c)
|
|||
p.identb = c->identb;
|
||||
}
|
||||
|
||||
QMutexLocker locker(&mutex);
|
||||
c->txMutex.lock();
|
||||
c->txSeqBuf.append(SEQBUFENTRY());
|
||||
c->txSeqBuf.last().seqNum = p.seq;
|
||||
c->txSeqBuf.last().timeSent = QTime::currentTime();
|
||||
c->txSeqBuf.last().retransmitCount = 0;
|
||||
c->txSeqBuf.last().data = QByteArray::fromRawData((const char*)p.packet, sizeof(p));
|
||||
|
||||
udpMutex.lock();
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p.packet, sizeof(p)), c->ipAddress, c->port);
|
||||
udpMutex.unlock();
|
||||
|
||||
if (c->idleTimer != Q_NULLPTR)
|
||||
c->idleTimer->start(100);
|
||||
|
||||
c->txSeq++;
|
||||
c->txMutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
void udpServer::sendTokenResponse(CLIENT* c, quint8 type)
|
||||
{
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << ": Sending Token response for type: " << type;
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << "(" << c->type << "): Sending Token response for type: " << type;
|
||||
|
||||
token_packet p;
|
||||
memset(p.packet, 0x0, sizeof(p)); // We can't be sure it is initialized with 0x00!
|
||||
|
@ -1102,19 +1170,22 @@ void udpServer::sendTokenResponse(CLIENT* c, quint8 type)
|
|||
p.commoncap = c->commonCap;
|
||||
p.res = type;
|
||||
|
||||
QMutexLocker locker(&mutex);
|
||||
c->txMutex.lock();
|
||||
c->txSeqBuf.append(SEQBUFENTRY());
|
||||
c->txSeqBuf.last().seqNum = p.seq;
|
||||
c->txSeqBuf.last().timeSent = QTime::currentTime();
|
||||
c->txSeqBuf.last().retransmitCount = 0;
|
||||
c->txSeqBuf.last().data = QByteArray::fromRawData((const char*)p.packet, sizeof(p));
|
||||
|
||||
udpMutex.lock();
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p.packet, sizeof(p)), c->ipAddress, c->port);
|
||||
udpMutex.unlock();
|
||||
|
||||
if (c->idleTimer != Q_NULLPTR)
|
||||
c->idleTimer->start(100);
|
||||
|
||||
c->txSeq++;
|
||||
c->txMutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1122,22 +1193,25 @@ void udpServer::sendTokenResponse(CLIENT* c, quint8 type)
|
|||
|
||||
void udpServer::watchdog(CLIENT* c)
|
||||
{
|
||||
|
||||
c->txMutex.lock();
|
||||
//qDebug(logUdpServer()) << c->ipAddress.toString() << ":" << c->port << ":Buffers tx:"<< c->txSeqBuf.length() << " rx:" << c->rxSeqBuf.length();
|
||||
QMutexLocker locker(&mutex);
|
||||
// Erase old entries from the tx packet buffer. Keep the first 100 sent packets as we seem to get asked for these?
|
||||
if (!c->txSeqBuf.isEmpty())
|
||||
{
|
||||
c->txSeqBuf.erase(std::remove_if(c->txSeqBuf.begin(), c->txSeqBuf.end(), [](const SEQBUFENTRY& v)
|
||||
{ return v.timeSent.secsTo(QTime::currentTime()) > PURGE_SECONDS; }), c->txSeqBuf.end());
|
||||
}
|
||||
c->txMutex.unlock();
|
||||
|
||||
// Erase old entries from the missing packets buffer
|
||||
c->missMutex.lock();
|
||||
if (!c->rxMissing.isEmpty()) {
|
||||
c->rxMissing.erase(std::remove_if(c->rxMissing.begin(), c->rxMissing.end(), [](const SEQBUFENTRY& v)
|
||||
{ return v.timeSent.secsTo(QTime::currentTime()) > PURGE_SECONDS; }), c->rxMissing.end());
|
||||
}
|
||||
c->missMutex.unlock();
|
||||
|
||||
c->rxMutex.lock();
|
||||
if (!c->rxSeqBuf.isEmpty()) {
|
||||
std::sort(c->rxSeqBuf.begin(), c->rxSeqBuf.end());
|
||||
|
||||
|
@ -1146,12 +1220,13 @@ void udpServer::watchdog(CLIENT* c)
|
|||
c->rxSeqBuf.remove(0, 200);
|
||||
}
|
||||
}
|
||||
c->rxMutex.unlock();
|
||||
}
|
||||
|
||||
void udpServer::sendStatus(CLIENT* c)
|
||||
{
|
||||
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << ": Sending Status";
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << "(" << c->type << "): Sending Status";
|
||||
|
||||
status_packet p;
|
||||
memset(p.packet, 0x0, sizeof(p)); // We can't be sure it is initialized with 0x00!
|
||||
|
@ -1178,14 +1253,17 @@ void udpServer::sendStatus(CLIENT* c)
|
|||
|
||||
|
||||
c->txSeq++;
|
||||
QMutexLocker locker(&mutex);
|
||||
c->txMutex.lock();
|
||||
c->txSeqBuf.append(SEQBUFENTRY());
|
||||
c->txSeqBuf.last().seqNum = p.seq;
|
||||
c->txSeqBuf.last().timeSent = QTime::currentTime();
|
||||
c->txSeqBuf.last().retransmitCount = 0;
|
||||
c->txSeqBuf.last().data = QByteArray::fromRawData((const char*)p.packet, sizeof(p));
|
||||
c->txMutex.unlock();
|
||||
|
||||
udpMutex.lock();
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p.packet, sizeof(p)), c->ipAddress, c->port);
|
||||
udpMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
|
@ -1196,7 +1274,8 @@ void udpServer::dataForServer(QByteArray d)
|
|||
//qDebug(logUdpServer()) << "Server got:" << d;
|
||||
foreach(CLIENT * client, civClients)
|
||||
{
|
||||
if (client != Q_NULLPTR && client->connected) {
|
||||
int lastFE = d.lastIndexOf((quint8)0xfe);
|
||||
if (client != Q_NULLPTR && client->connected && d.length() > lastFE+2 && ((quint8)d[lastFE + 1] == client->civId || (quint8)d[lastFE + 2] == client->civId)) {
|
||||
data_packet p;
|
||||
memset(p.packet, 0x0, sizeof(p)); // We can't be sure it is initialized with 0x00!
|
||||
p.len = (quint16)d.length() + sizeof(p);
|
||||
|
@ -1208,15 +1287,18 @@ void udpServer::dataForServer(QByteArray d)
|
|||
p.sendseq = client->innerSeq;
|
||||
QByteArray t = QByteArray::fromRawData((const char*)p.packet, sizeof(p));
|
||||
t.append(d);
|
||||
QMutexLocker locker(&mutex);
|
||||
client->txMutex.lock();
|
||||
client->txSeqBuf.append(SEQBUFENTRY());
|
||||
client->txSeqBuf.last().seqNum = p.seq;
|
||||
client->txSeqBuf.last().timeSent = QTime::currentTime();
|
||||
client->txSeqBuf.last().retransmitCount = 0;
|
||||
client->txSeqBuf.last().data = t;
|
||||
client->txMutex.unlock();
|
||||
|
||||
//qDebug(logUdpServer()) << "Sending:" << d;
|
||||
udpMutex.lock();
|
||||
client->socket->writeDatagram(t, client->ipAddress, client->port);
|
||||
|
||||
udpMutex.unlock();
|
||||
client->txSeq++;
|
||||
client->innerSeq++;
|
||||
}
|
||||
|
@ -1260,13 +1342,17 @@ void udpServer::receiveAudioData(const audioPacket &d)
|
|||
p.seq = client->txSeq;
|
||||
QByteArray t = QByteArray::fromRawData((const char*)p.packet, sizeof(p));
|
||||
t.append(d.datain);
|
||||
QMutexLocker locker(&mutex);
|
||||
client->txMutex.lock();
|
||||
client->txSeqBuf.append(SEQBUFENTRY());
|
||||
client->txSeqBuf.last().seqNum = p.seq;
|
||||
client->txSeqBuf.last().timeSent = QTime::currentTime();
|
||||
client->txSeqBuf.last().retransmitCount = 0;
|
||||
client->txSeqBuf.last().data = t;
|
||||
client->txMutex.unlock();
|
||||
|
||||
udpMutex.lock();
|
||||
client->socket->writeDatagram(t, client->ipAddress, client->port);
|
||||
udpMutex.unlock();
|
||||
|
||||
client->txSeq++;
|
||||
client->sendAudioSeq++;
|
||||
|
@ -1284,7 +1370,7 @@ void udpServer::receiveAudioData(const audioPacket &d)
|
|||
void udpServer::sendRetransmitRequest(CLIENT *c)
|
||||
{
|
||||
|
||||
QMutexLocker locker(&mutex);
|
||||
c->missMutex.lock();
|
||||
|
||||
QByteArray missingSeqs;
|
||||
|
||||
|
@ -1297,12 +1383,12 @@ void udpServer::sendRetransmitRequest(CLIENT *c)
|
|||
{
|
||||
for (quint16 j = *i + 1; j < *(i + 1); j++)
|
||||
{
|
||||
qDebug(logUdpServer()) << this->metaObject()->className() << ": Found missing seq between " << *i << " : " << *(i + 1) << " (" << j << ")";
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << "(" << c->type << "): Found missing seq between " << *i << " : " << *(i + 1) << " (" << j << ")";
|
||||
auto s = std::find_if(c->rxMissing.begin(), c->rxMissing.end(), [&cs = j](SEQBUFENTRY& s) { return s.seqNum == cs; });
|
||||
if (s == c->rxMissing.end())
|
||||
{
|
||||
// We haven't seen this missing packet before
|
||||
qDebug(logUdpServer()) << this->metaObject()->className() << ": Adding to missing buffer (len="<< c->rxMissing.length() << "): " << j;
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << "(" << c->type << "): Adding to missing buffer (len="<< c->rxMissing.length() << "): " << j;
|
||||
c->rxMissing.append(SEQBUFENTRY());
|
||||
c->rxMissing.last().seqNum = j;
|
||||
c->rxMissing.last().retransmitCount = 0;
|
||||
|
@ -1314,7 +1400,9 @@ void udpServer::sendRetransmitRequest(CLIENT *c)
|
|||
{
|
||||
// We have tried 4 times to request this packet, time to give up!
|
||||
s = c->rxMissing.erase(s);
|
||||
c->rxMutex.lock();
|
||||
c->rxSeqBuf.append(j); // Final thing is to add to received buffer!
|
||||
c->rxMutex.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1322,7 +1410,9 @@ void udpServer::sendRetransmitRequest(CLIENT *c)
|
|||
}
|
||||
else {
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << ": Too many missing, flushing buffers";
|
||||
c->rxMutex.lock();
|
||||
c->rxSeqBuf.clear();
|
||||
c->rxMutex.unlock();
|
||||
missingSeqs.clear();
|
||||
break;
|
||||
}
|
||||
|
@ -1353,16 +1443,22 @@ void udpServer::sendRetransmitRequest(CLIENT *c)
|
|||
if (missingSeqs.length() == 4) // This is just a single missing packet so send using a control.
|
||||
{
|
||||
p.seq = (missingSeqs[0] & 0xff) | (quint16)(missingSeqs[1] << 8);
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << ": sending request for missing packet : " << hex << p.seq;
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << "(" << c->type << "): sending request for missing packet : " << hex << p.seq;
|
||||
udpMutex.lock();
|
||||
c->socket->writeDatagram(QByteArray::fromRawData((const char*)p.packet, sizeof(p)), c->ipAddress, c->port);
|
||||
udpMutex.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << ": sending request for multiple missing packets : " << missingSeqs.toHex();
|
||||
qDebug(logUdpServer()) << c->ipAddress.toString() << "(" << c->type << "): sending request for multiple missing packets : " << missingSeqs.toHex();
|
||||
missingSeqs.insert(0, p.packet, sizeof(p.packet));
|
||||
udpMutex.lock();
|
||||
c->socket->writeDatagram(missingSeqs, c->ipAddress, c->port);
|
||||
udpMutex.unlock();
|
||||
}
|
||||
}
|
||||
c->missMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1374,6 +1470,8 @@ void udpServer::sendRetransmitRequest(CLIENT *c)
|
|||
/// <param name="c"></param>
|
||||
void udpServer::deleteConnection(QList<CLIENT*> *l, CLIENT* c)
|
||||
{
|
||||
connMutex.lock();
|
||||
|
||||
qDebug(logUdpServer()) << "Deleting connection to: " << c->ipAddress.toString() << ":" << QString::number(c->port);
|
||||
if (c->idleTimer != Q_NULLPTR) {
|
||||
c->idleTimer->stop();
|
||||
|
@ -1430,4 +1528,6 @@ void udpServer::deleteConnection(QList<CLIENT*> *l, CLIENT* c)
|
|||
}
|
||||
|
||||
}
|
||||
connMutex.unlock();
|
||||
|
||||
}
|
||||
|
|
10
udpserver.h
10
udpserver.h
|
@ -58,6 +58,7 @@ private:
|
|||
|
||||
struct CLIENT {
|
||||
bool connected = false;
|
||||
QString type;
|
||||
QHostAddress ipAddress;
|
||||
quint16 port;
|
||||
QByteArray clientName;
|
||||
|
@ -102,7 +103,13 @@ private:
|
|||
QVector <SEQBUFENTRY> txSeqBuf;
|
||||
QVector <quint16> rxSeqBuf;
|
||||
QVector <SEQBUFENTRY> rxMissing;
|
||||
QMutex txMutex;
|
||||
QMutex rxMutex;
|
||||
QMutex missMutex;
|
||||
|
||||
quint16 seqPrefix;
|
||||
|
||||
quint8 civId;
|
||||
};
|
||||
|
||||
void controlReceived();
|
||||
|
@ -136,7 +143,8 @@ private:
|
|||
|
||||
quint8 rigciv = 0xa2;
|
||||
|
||||
QMutex mutex; // Used for critical operations.
|
||||
QMutex udpMutex; // Used for critical operations.
|
||||
QMutex connMutex;
|
||||
|
||||
QList <CLIENT*> controlClients = QList<CLIENT*>();
|
||||
QList <CLIENT*> civClients = QList<CLIENT*>();
|
||||
|
|
|
@ -145,16 +145,22 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="controlPortText">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
|
@ -163,6 +169,9 @@
|
|||
<property name="text">
|
||||
<string>50001</string>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -195,13 +204,13 @@
|
|||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
|
@ -236,13 +245,13 @@
|
|||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
|
|
Ładowanie…
Reference in New Issue