#ifndef UDPHANDLER_H #define UDPHANDLER_H #include #include #include #include #include #include #include #include #include #include #include // Allow easy endian-ness conversions #include // Needed for audio #include #include #include #include "audiohandler.h" #include "packettypes.h" struct udpPreferences { QString ipAddress; quint16 controlLANPort; quint16 serialLANPort; quint16 audioLANPort; QString username; QString password; 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; 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); // Parent class that contains all common items. class udpBase : public QObject { public: ~udpBase(); void init(quint16 local); void reconnect(); void dataReceived(QByteArray r); void sendPing(); void sendRetransmitRange(quint16 first, quint16 second, quint16 third,quint16 fourth); void sendControl(bool tracked,quint8 id, quint16 seq); 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; uint16_t authSeq = 0x30; uint16_t sendSeqB = 0; uint16_t sendSeq = 1; uint16_t lastReceivedSeq = 1; uint16_t pkt0SendSeq = 0; uint16_t periodicSeq = 0; quint64 latency = 0; QString username = ""; QString password = ""; QHostAddress radioIP; QHostAddress localIP; bool isAuthenticated = false; quint16 localPort=0; quint16 port=0; bool periodicRunning = false; bool sentPacketConnect2 = false; QTime lastReceived =QTime::currentTime(); QMutex udpMutex; QMutex txBufferMutex; QMutex rxBufferMutex; QMutex missingMutex; struct SEQBUFENTRY { QTime timeSent; uint16_t seqNum; QByteArray data; quint8 retransmitCount; }; QMap rxSeqBuf; QMap txSeqBuf; QMap rxMissing; 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; quint16 seqPrefix = 0; QString connectionType=""; int congestion = 0; private: void sendRetransmitRequest(); }; // Class for all (pseudo) serial communications class udpCivData : public udpBase { Q_OBJECT public: udpCivData(QHostAddress local, QHostAddress ip, quint16 civPort, bool splitWf, quint16 lport); ~udpCivData(); QMutex serialmutex; signals: int receive(QByteArray); public slots: void send(QByteArray d); private: void watchdog(); void dataReceived(); void sendOpenClose(bool close); QTimer* startCivDataTimer = Q_NULLPTR; bool splitWaterfall = false; }; // 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(); int audioLatency = 0; signals: void haveAudioData(audioPacket data); 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); void receiveAudioData(audioPacket audio); private: void sendTxAudio(); void dataReceived(); void watchdog(); uint16_t sendAudioSeq = 0; audioHandler* rxaudio = Q_NULLPTR; QThread* rxAudioThread = Q_NULLPTR; audioHandler* txaudio = Q_NULLPTR; QThread* txAudioThread = Q_NULLPTR; QTimer* txAudioTimer = Q_NULLPTR; bool enableTx = true; QMutex audioMutex; }; // Class to handle the connection/disconnection of the radio. class udpHandler: public udpBase { Q_OBJECT public: udpHandler(udpPreferences prefs, audioSetup rxAudio, audioSetup txAudio); ~udpHandler(); bool streamOpened = false; udpCivData* civ = Q_NULLPTR; udpAudio* audio = Q_NULLPTR; unsigned char numRadios; QList radios; 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); 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 radios); void setRadioUsage(quint8, quint8 busy, QString name, QString mac); private: void sendAreYouThere(); void dataReceived(); void sendRequestStream(); void sendLogin(); void sendToken(uint8_t magic); bool gotA8ReplyID = false; bool gotAuthOK = false; bool sentPacketLogin = false; bool sentPacketConnect = false; bool sentPacketConnect2 = false; bool radioInUse = false; quint16 controlPort; quint16 civPort; quint16 audioPort; quint16 civLocalPort; quint16 audioLocalPort; 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]; quint8 guid[GUIDLEN]; bool useGuid = false; QByteArray usernameEncoded; QByteArray passwordEncoded; QTimer* tokenTimer = Q_NULLPTR; QTimer* areYouThereTimer = Q_NULLPTR; bool highBandwidthConnection = false; quint8 civId = 0; quint16 rxSampleRates = 0; quint16 txSampleRates = 0; networkStatus status; bool splitWf = false; }; #endif