wfview/udphandler.h

324 wiersze
7.1 KiB
C
Czysty Zwykły widok Historia

2021-02-03 20:00:40 +00:00
#ifndef UDPHANDLER_H
#define UDPHANDLER_H
#include <QObject>
#include <QUdpSocket>
#include <QNetworkDatagram>
#include <QHostInfo>
#include <QTimer>
#include <QMutex>
#include <QDateTime>
2021-02-11 19:18:35 +00:00
#include <QByteArray>
2021-02-22 22:25:09 +00:00
#include <QVector>
#include <QMap>
#include <QUuid>
2021-02-03 20:00:40 +00:00
// Allow easy endian-ness conversions
#include <QtEndian>
// Needed for audio
#include <QBuffer>
2021-02-08 08:31:48 +00:00
#include <QThread>
2021-02-03 20:00:40 +00:00
#include <QDebug>
2021-02-11 19:18:35 +00:00
#include "audiohandler.h"
#include "packettypes.h"
2021-02-08 08:31:48 +00:00
struct udpPreferences {
QString ipAddress;
quint16 controlLANPort;
quint16 serialLANPort;
quint16 audioLANPort;
QString username;
QString password;
2021-03-27 16:07:17 +00:00
QString clientName;
quint8 waterfallFormat;
};
struct networkStatus {
quint8 rxAudioBufferPercent;
quint8 txAudioBufferPercent;
quint8 rxAudioLevel;
quint8 txAudioLevel;
quint16 rxLatency;
quint16 txLatency;
bool rxUnderrun;
bool txUnderrun;
quint16 rxCurrentLatency;
quint16 txCurrentLatency;
2022-01-29 22:50:58 +00:00
quint32 packetsSent=0;
quint32 packetsLost=0;
quint16 rtt=0;
quint32 networkLatency=0;
QString message;
};
void passcode(QString in, QByteArray& out);
QByteArray parseNullTerminatedString(QByteArray c, int s);
2021-02-03 20:00:40 +00:00
// Parent class that contains all common items.
class udpBase : public QObject
{
2021-02-03 20:00:40 +00:00
public:
2021-02-04 20:09:09 +00:00
~udpBase();
void init(quint16 local);
void reconnect();
void dataReceived(QByteArray r);
2021-02-22 22:25:09 +00:00
void sendPing();
2021-02-24 11:00:23 +00:00
void sendRetransmitRange(quint16 first, quint16 second, quint16 third,quint16 fourth);
2021-02-22 22:25:09 +00:00
void sendControl(bool tracked,quint8 id, quint16 seq);
2021-02-03 20:00:40 +00:00
void printHex(const QByteArray& pdata);
void printHex(const QByteArray& pdata, bool printVert, bool printHoriz);
QTime timeStarted;
QUdpSocket* udp=Q_NULLPTR;
uint32_t myId = 0;
uint32_t remoteId = 0;
uint8_t authSeq = 0x00;
2021-02-03 20:00:40 +00:00
uint16_t sendSeqB = 0;
uint16_t sendSeq = 1;
2021-02-22 22:25:09 +00:00
uint16_t lastReceivedSeq = 1;
2021-02-03 20:00:40 +00:00
uint16_t pkt0SendSeq = 0;
uint16_t periodicSeq = 0;
quint64 latency = 0;
2021-02-03 20:00:40 +00:00
QString username = "";
QString password = "";
QHostAddress radioIP;
QHostAddress localIP;
bool isAuthenticated = false;
quint16 localPort=0;
quint16 port=0;
2021-02-03 20:00:40 +00:00
bool periodicRunning = false;
bool sentPacketConnect2 = false;
QTime lastReceived =QTime::currentTime();
2021-03-03 09:50:15 +00:00
QMutex udpMutex;
QMutex txBufferMutex;
QMutex rxBufferMutex;
QMutex missingMutex;
2021-02-03 20:00:40 +00:00
struct SEQBUFENTRY {
QTime timeSent;
2021-02-03 20:00:40 +00:00
uint16_t seqNum;
QByteArray data;
2021-02-23 20:48:53 +00:00
quint8 retransmitCount;
2021-02-03 20:00:40 +00:00
};
QMap<quint16, QTime> rxSeqBuf;
QMap<quint16, SEQBUFENTRY> txSeqBuf;
QMap<quint16, int> rxMissing;
2021-02-03 20:00:40 +00:00
void sendTrackedPacket(QByteArray d);
void purgeOldEntries();
QTimer* areYouThereTimer = Q_NULLPTR; // Send are-you-there packets every second until a response is received.
QTimer* pingTimer = Q_NULLPTR; // Start sending pings immediately.
QTimer* idleTimer = Q_NULLPTR; // Start watchdog once we are connected.
QTimer* watchdogTimer = Q_NULLPTR;
QTimer* retransmitTimer = Q_NULLPTR;
QDateTime lastPingSentTime;
uint16_t pingSendSeq = 0;
quint16 areYouThereCounter=0;
quint32 packetsSent=0;
quint32 packetsLost=0;
2021-03-22 09:10:03 +00:00
quint16 seqPrefix = 0;
QString connectionType="";
int congestion = 0;
private:
void sendRetransmitRequest();
2021-02-03 20:00:40 +00:00
};
// Class for all (pseudo) serial communications
class udpCivData : public udpBase
2021-02-03 20:00:40 +00:00
{
Q_OBJECT
public:
udpCivData(QHostAddress local, QHostAddress ip, quint16 civPort, bool splitWf, quint16 lport);
~udpCivData();
2021-02-03 20:00:40 +00:00
QMutex serialmutex;
signals:
int receive(QByteArray);
2021-02-03 20:00:40 +00:00
public slots:
void send(QByteArray d);
2021-02-03 20:00:40 +00:00
private:
void watchdog();
void dataReceived();
void sendOpenClose(bool close);
QTimer* startCivDataTimer = Q_NULLPTR;
bool splitWaterfall = false;
2021-02-03 20:00:40 +00:00
};
// Class for all audio communications.
class udpAudio : public udpBase
{
Q_OBJECT
public:
udpAudio(QHostAddress local, QHostAddress ip, quint16 aport, quint16 lport, audioSetup rxSetup, audioSetup txSetup);
~udpAudio();
2021-02-08 08:31:48 +00:00
int audioLatency = 0;
2021-02-08 08:31:48 +00:00
signals:
2021-03-22 09:10:03 +00:00
void haveAudioData(audioPacket data);
2021-06-04 07:24:26 +00:00
void setupTxAudio(audioSetup setup);
void setupRxAudio(audioSetup setup);
void haveChangeLatency(quint16 value);
void haveSetVolume(unsigned char value);
void haveRxLevels(quint16 amplitude, quint16 latency, quint16 current, bool under);
void haveTxLevels(quint16 amplitude, quint16 latency, quint16 current, bool under);
public slots:
void changeLatency(quint16 value);
void setVolume(unsigned char value);
void getRxLevels(quint16 amplitude, quint16 latency, quint16 current, bool under);
void getTxLevels(quint16 amplitude, quint16 latency, quint16 current, bool under);
2022-04-10 22:13:51 +00:00
void receiveAudioData(audioPacket audio);
2021-02-11 19:18:35 +00:00
2021-02-03 20:00:40 +00:00
private:
2021-02-12 23:56:02 +00:00
void sendTxAudio();
void dataReceived();
void watchdog();
2021-02-03 20:00:40 +00:00
uint16_t sendAudioSeq = 0;
2021-03-22 09:10:03 +00:00
audioHandler* rxaudio = Q_NULLPTR;
QThread* rxAudioThread = Q_NULLPTR;
2021-02-08 08:31:48 +00:00
2021-03-22 09:10:03 +00:00
audioHandler* txaudio = Q_NULLPTR;
QThread* txAudioThread = Q_NULLPTR;
2022-04-10 22:13:51 +00:00
QTimer* txAudioTimer = Q_NULLPTR;
2021-06-06 21:11:48 +00:00
bool enableTx = true;
2021-02-12 23:56:02 +00:00
QMutex audioMutex;
2021-02-03 20:00:40 +00:00
};
// Class to handle the connection/disconnection of the radio.
class udpHandler: public udpBase
{
Q_OBJECT
public:
2021-06-04 07:24:26 +00:00
udpHandler(udpPreferences prefs, audioSetup rxAudio, audioSetup txAudio);
2021-02-03 20:00:40 +00:00
~udpHandler();
bool streamOpened = false;
2021-02-03 20:00:40 +00:00
udpCivData* civ = Q_NULLPTR;
udpAudio* audio = Q_NULLPTR;
2021-02-03 20:00:40 +00:00
unsigned char numRadios;
QList<radio_cap_packet> radios;
2021-02-03 20:00:40 +00:00
public slots:
void receiveDataFromUserToRig(QByteArray); // This slot will send data on to
void receiveFromCivStream(QByteArray);
void receiveAudioData(const audioPacket &data);
void changeLatency(quint16 value);
void setVolume(unsigned char value);
void init();
void setCurrentRadio(quint8 radio);
void getRxLevels(quint16 amplitude, quint16 latency, quint16 current, bool under);
void getTxLevels(quint16 amplitude, quint16 latency, quint16 current, bool under);
2022-01-21 23:58:18 +00:00
2021-02-03 20:00:40 +00:00
signals:
void haveDataFromPort(QByteArray data); // emit this when we have data, connect to rigcommander
void haveAudioData(audioPacket data); // emit this when we have data, connect to rigcommander
void haveNetworkError(QString, QString);
void haveChangeLatency(quint16 value);
void haveSetVolume(unsigned char value);
void haveNetworkStatus(networkStatus);
void haveBaudRate(quint32 baudrate);
void requestRadioSelection(QList<radio_cap_packet> radios);
void setRadioUsage(quint8, quint8 busy, QString name, QString mac);
2021-02-03 20:00:40 +00:00
private:
void sendAreYouThere();
void dataReceived();
void sendRequestStream();
void sendLogin();
void sendToken(uint8_t magic);
2021-02-03 20:00:40 +00:00
bool gotA8ReplyID = false;
bool gotAuthOK = false;
bool sentPacketLogin = false;
bool sentPacketConnect = false;
bool sentPacketConnect2 = false;
2021-02-07 17:40:38 +00:00
bool radioInUse = false;
quint16 controlPort;
quint16 civPort;
2021-02-13 23:28:28 +00:00
quint16 audioPort;
quint16 civLocalPort;
quint16 audioLocalPort;
2021-06-04 07:24:26 +00:00
audioSetup rxSetup;
audioSetup txSetup;
quint16 reauthInterval = 60000;
QString devName;
QString compName;
QString audioType;
//QByteArray replyId;
quint16 tokRequest;
quint32 token;
// These are for stream ident info.
quint8 macaddress[8];
2022-01-29 22:50:58 +00:00
quint8 guid[GUIDLEN];
2022-01-21 23:58:18 +00:00
bool useGuid = false;
2021-02-21 15:06:27 +00:00
QByteArray usernameEncoded;
QByteArray passwordEncoded;
QTimer* tokenTimer = Q_NULLPTR;
QTimer* areYouThereTimer = Q_NULLPTR;
bool highBandwidthConnection = false;
2021-05-18 08:32:56 +00:00
quint8 civId = 0;
quint16 rxSampleRates = 0;
quint16 txSampleRates = 0;
networkStatus status;
bool splitWf = false;
2021-02-03 20:00:40 +00:00
};
#endif