diff --git a/AGWCode.cpp b/AGWCode.cpp index 00e319f..4c44124 100644 --- a/AGWCode.cpp +++ b/AGWCode.cpp @@ -262,7 +262,7 @@ void doAGWBeacon() char ports[80]; char * ptr, * context; - int DataLen = (int)strlen(AGWBeaconMsg); + int DataLen; strcpy(ports, AGWBeaconPorts); // strtok changes it @@ -282,8 +282,9 @@ void doAGWBeacon() { while (ptr) { - AGW_frame_header(Msg, atoi(ptr) - 1, 'M', 240, AGWTermCall, AGWBeaconDest, DataLen); + DataLen = (int)strlen(AGWBeaconMsg); + AGW_frame_header(Msg, atoi(ptr) - 1, 'M', 240, AGWTermCall, AGWBeaconDest, DataLen); memcpy(&Msg[AGWHDDRRLEN], AGWBeaconMsg, DataLen); DataLen += AGWHDDRRLEN; AGWSock->write((char *)Msg, DataLen); @@ -587,7 +588,7 @@ void QtTermTCP::onAGWSocketStateChanged(QAbstractSocket::SocketState socketState if (Sess) { AGWUsers->MonSess = Sess; - Sess->AGWSession = sender; // Flag as in use +// Sess->AGWSession = sender; // Flag as in use if (TermMode == MDI) Sess->setWindowTitle("AGW Monitor Window"); @@ -864,7 +865,8 @@ void Send_AGW_Ds_Frame(void * Sess) UCHAR Msg[512]; AGW_frame_header(Msg, AGW->port, 'd', 240, AGW->corrcall, AGW->mycall, 0); - AGW->socket->write((char *)Msg, AGWHDDRRLEN); + if (AGW->socket) + AGW->socket->write((char *)Msg, AGWHDDRRLEN); } @@ -1036,9 +1038,9 @@ void on_AGW_C_frame(AGWUser * AGW, struct AGWHeader * Frame, byte * Msg) Sess = newWindow((QObject *)mythis, Listen, ""); } } - else + else if (TermMode == Tabbed) { - // Single or Tabbed - look for free session + // Single Tabbed - look for free session for (i = 0; i < _sessions.size(); ++i) @@ -1051,15 +1053,33 @@ void on_AGW_C_frame(AGWUser * AGW, struct AGWHeader * Frame, byte * Msg) break; } } + } + else + { + // Single - Only one available + S = _sessions.at(0); - if (Sess == NULL) - { - // Clear connection - - return; - } + if (S->clientSocket == NULL && S->AGWSession == NULL && S->KISSSession == NULL) + Sess = S; } + if (Sess == NULL) + { + // Clear connection by sendinf d fraame + + UCHAR Msg[512]; + + int snd_ch = Frame->Port; + char * CallFrom = Frame->callfrom; + char * CallTo = Frame->callto; + + AGW_frame_header(Msg, Frame->Port, 'd', 240, Frame->callto, Frame->callfrom, 0); + if (AGW->socket) + AGW->socket->write((char *)Msg, AGWHDDRRLEN); + + return; + } + if (Sess) { sprintf(Title, "Connected to %s", CallFrom); diff --git a/KISSConfig.ui b/KISSConfig.ui index b0c1ead..0aede23 100644 --- a/KISSConfig.ui +++ b/KISSConfig.ui @@ -7,7 +7,7 @@ 0 0 432 - 319 + 399 @@ -17,7 +17,7 @@ 40 - 262 + 360 351 33 @@ -58,7 +58,7 @@ 10 - 120 + 168 401 57 @@ -140,7 +140,7 @@ 10 - 70 + 118 411 51 @@ -202,7 +202,7 @@ 12 - 12 + 10 149 21 @@ -215,7 +215,7 @@ 158 - 10 + 9 23 25 @@ -231,7 +231,7 @@ 214 - 13 + 11 61 17 @@ -243,7 +243,7 @@ - 286 + 292 10 91 22 @@ -254,7 +254,7 @@ 25 - 192 + 240 47 13 @@ -267,7 +267,7 @@ 98 - 189 + 240 47 22 @@ -277,7 +277,7 @@ 213 - 192 + 240 66 16 @@ -290,7 +290,7 @@ 288 - 189 + 240 47 22 @@ -300,9 +300,9 @@ 25 - 226 + 270 47 - 13 + 20 @@ -313,7 +313,7 @@ 98 - 223 + 270 36 22 @@ -323,7 +323,7 @@ 213 - 225 + 273 47 13 @@ -336,7 +336,7 @@ 288 - 222 + 270 36 22 @@ -346,7 +346,7 @@ 12 - 38 + 35 149 21 @@ -359,7 +359,7 @@ 158 - 38 + 34 23 21 @@ -371,6 +371,132 @@ + + + + 160 + 60 + 20 + 20 + + + + Qt::RightToLeft + + + + + + + + + 12 + 60 + 141 + 20 + + + + Enable checksum + + + + + + 160 + 84 + 20 + 20 + + + + Qt::RightToLeft + + + + + + + + + 12 + 85 + 141 + 20 + + + + Enable ACKMODE + + + + + + 150 + 300 + 111 + 21 + + + + Qt::RightToLeft + + + Set TXDelay + + + + + + 99 + 300 + 36 + 22 + + + + + + + 26 + 302 + 71 + 16 + + + + TXDelay + + + + + + 200 + 80 + 151 + 30 + + + + Open MH Window + + + + + + 390 + 83 + 20 + 20 + + + + Qt::RightToLeft + + + + + diff --git a/QtTermTCP.cpp b/QtTermTCP.cpp index 6328adb..397e11e 100644 --- a/QtTermTCP.cpp +++ b/QtTermTCP.cpp @@ -1,6 +1,8 @@ // Qt Version of BPQTermTCP -#define VersionString "0.0.0.73" +// Application icon design by Red PE1RRR + +#define VersionString "0.0.0.79" // .12 Save font weight @@ -8,7 +10,7 @@ // .14 Add YAPP and Listen Mode // .15 Reuse windows in Listen Mode // .17 MDI Version 7/1/20 -// .18 Fix input window losing focus when data arrives on other window +// .18 Fix input window losing focus when data arrivn other window // .19 Fix Scrollback // .20 WinXP compatibility changes // .21 Save Window Positions @@ -104,7 +106,26 @@ // .73 November 2023 // Raise RTS on KISS serial port +// .74 April 2024 +// Support BPQKISS TNCs with CHECKSUM and/or ACKMODE enabled +// .75 May 2024 +// Flush Monitor log file every minute + +// .76 August 2024 +// Fix using digs in KISS UI mode. +// Add option to send TXDELAY to KISS TNC + +// .77 +// Support multichannel KISS TNCs (Beta 1) +// Fix using AGW listen in single terminal mode + +// .78 +// Fix restoring monitor flags when connecting to current host + + +// .79 +// Add KISS MHEARD Window (Feb 2025) #define _CRT_SECURE_NO_WARNINGS @@ -126,6 +147,7 @@ #include #include #include +#include #ifdef USESERIAL #include #include @@ -308,12 +330,23 @@ extern "C" int KISSMonEnable; extern "C" int KISSLocalTime; extern "C" int KISSMonNodes; extern "C" int KISSListen; +extern "C" int KISSChecksum; +extern "C" int KISSAckMode; +extern "C" int KISSMH; + +extern "C" short txtail[5]; +extern "C" short txdelay[5]; +extern "C" int sendTXDelay[4]; + + char SerialPort[80] = ""; char KISSHost[128] = "127.0.0.1"; int KISSPortNum = 1000; int KISSBAUD = 19200; -char MYCALL[32]; +char KISSMYCALL[32]; +char KISSVia[128]; // Digi String + extern "C" UCHAR axMYCALL[7]; // Mycall in ax.25 int KISSMode = 0; // Connected (0) or UI (1) @@ -531,6 +564,7 @@ void AGWMonWindowClosing(Ui_ListenSession *Sess); void AGWWindowClosing(Ui_ListenSession *Sess); extern "C" void KISSDataReceived(void * socket, unsigned char * data, int length); void closeSerialPort(); +int newMHWindow(QObject * parent, int Type, const char * Label); extern void initUTF8(); int checkUTF8(unsigned char * Msg, int Len, unsigned char * out); @@ -708,12 +742,39 @@ void DoTermResize(Ui_ListenSession * Sess) } } + +extern "C" Ui_ListenSession * MHWindow; + bool QtTermTCP::eventFilter(QObject* obj, QEvent *event) { // See if from a Listening Session Ui_ListenSession * Sess; + if (obj == MHWindow) + { + if (event->type() == QEvent::Resize) + { + QRect r = MHWindow->rect(); + + int H, Width, Border = 3; + + Width = r.width() - 6; + H = r.height() - 6; + + MHWindow->monWindow->setGeometry(QRect(Border, Border, Width, H)); + return true; + } + if (event->type() == QEvent::Close) + { + QSettings mysettings(GetConfPath(), QSettings::IniFormat); + mysettings.setValue("MHgeometry", MHWindow->saveGeometry()); + SaveSettings(); + MHWindow = 0; + } + } + + for (int i = 0; i < _sessions.size(); ++i) { Sess = _sessions.at(i); @@ -874,6 +935,14 @@ bool QtTermTCP::eventFilter(QObject* obj, QEvent *event) if (k->button() == Qt::RightButton) { + // Get clipboard data and process a line at a time + + QClipboard *clipboard = QGuiApplication::clipboard(); + QString Text = clipboard->text(); + QByteArray ba = Text.toLocal8Bit(); + char * Msg = ba.data(); + + Sess->inputWindow->paste(); return true; } @@ -986,9 +1055,9 @@ Ui_ListenSession * newWindow(QObject * parent, int Type, const char * Label) QSettings settings(GetConfPath(), QSettings::IniFormat); #ifdef ANDROID - QFont font = QFont(settings->value("FontFamily", "Driod Sans Mono").value(), - settings->value("PointSize", 12).toInt(), - settings->value("Weight", 50).toInt()); + QFont font = QFont(settings.value("FontFamily", "Driod Sans Mono").value(), + settings.value("PointSize", 12).toInt(), + settings.value("Weight", 50).toInt()); #else QFont font = QFont(settings.value("FontFamily", "Courier New").value(), settings.value("PointSize", 10).toInt(), @@ -1300,6 +1369,12 @@ QtTermTCP::QtTermTCP(QWidget *parent) : QMainWindow(parent) updateWindowMenu(); + if (KISSEnable && KISSMH) + { + newMHWindow(this, 0, "KISS MH"); + MHWindow->restoreGeometry(mysettings.value("MHgeometry").toByteArray()); + } + connectMenu = mymenuBar->addMenu(tr("&Connect")); actHost[16] = new QAction("AGW Connect", this); @@ -1642,6 +1717,10 @@ QtTermTCP::QtTermTCP(QWidget *parent) : QMainWindow(parent) connect(timer2, SIGNAL(timeout()), this, SLOT(KISSTimerSlot())); timer2->start(100); + QTimer *timer3 = new QTimer(this); + connect(timer3, SIGNAL(timeout()), this, SLOT(SlowTimerSlot())); + timer3->start(60000); + // Run timer now to connect to AGW if configured MyTimerSlot(); @@ -1657,7 +1736,7 @@ QtTermTCP::QtTermTCP(QWidget *parent) : QMainWindow(parent) OpenPTTPort(); memset(axMYCALL, 0, 7); - ConvToAX25(MYCALL, axMYCALL); + ConvToAX25(KISSMYCALL, axMYCALL); // Do any autoconnects @@ -2726,7 +2805,8 @@ void QtTermTCP::LreturnPressed(Ui_ListenSession * Sess) strcpy(Msg, Msgptr); strcat(Msg, "\r"); - Send_UI(0, 0xF0, MYCALL, Sess->UIDEST, (unsigned char *)Msg, (int)strlen(Msg)); + + Send_UI(Sess->UIPORT, 0xF0, KISSMYCALL, Sess->UIDEST, Sess->UIPATH, (unsigned char *)Msg, (int)strlen(Msg)); WritetoOutputWindowEx(Sess, (unsigned char *)Msg, (int)strlen(Msg), Sess->termWindow, &Sess->OutputSaveLen, Sess->OutputSave, EchoText); // Black @@ -2818,7 +2898,8 @@ void QtTermTCP::LreturnPressed(Ui_ListenSession * Sess) strcat(Msg, "\r"); Sess->clientSocket->write(Msg); - + Sess->clientSocket->flush(); +// QThread::msleep(1500); // Try to force as separate packets WritetoOutputWindowEx(Sess, (unsigned char *)Msg, (int)strlen(Msg), Sess->termWindow, &Sess->OutputSaveLen, Sess->OutputSave, EchoText); // Black @@ -2853,6 +2934,23 @@ void QtTermTCP::LreturnPressed(Ui_ListenSession * Sess) connect(Sess->clientSocket, SIGNAL(readyRead()), this, SLOT(readyRead())); connect(Sess->clientSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChanged(QAbstractSocket::SocketState))); + + // Set Monitor Params for this host + + sscanf(MonParams[Sess->CurrentHost], "%llx %x %x %x %x %x", + &Sess->portmask, &Sess->mtxparam, &Sess->mcomparam, + &Sess->MonitorNODES, &Sess->MonitorColour, &Sess->monUI); + + Sess->mlocaltime = (Sess->mtxparam >> 7); + Sess->mtxparam &= 1; + + MonLocalTime->setChecked(Sess->mlocaltime); + MonTX->setChecked(Sess->mtxparam); + MonSup->setChecked(Sess->mcomparam); + MonUI->setChecked(Sess->monUI); + MonNodes->setChecked(Sess->MonitorNODES); + MonColour->setChecked(Sess->MonitorColour); + Sess->clientSocket->connectToHost(&Host[Sess->CurrentHost][0], Port[Sess->CurrentHost]); } @@ -3450,6 +3548,8 @@ void getAX25Params(int chan) void GetPortSettings(int Chan) { + txdelay[Chan] = getAX25Param("TXDelay", 250).toInt(); + sendTXDelay[Chan] = getAX25Param("sendTXDelay", 0).toInt(); maxframe[Chan] = getAX25Param("Maxframe", 4).toInt(); fracks[Chan] = getAX25Param("Retries", 10).toInt(); frack_time[Chan] = getAX25Param("FrackTime", 8).toInt(); @@ -3541,10 +3641,14 @@ void GetSettings() KISSMonNodes = settings->value("KISSMonNodes", 0).toInt(); KISSListen = settings->value("KISSListen", 1).toInt(); - strcpy(MYCALL, settings->value("MYCALL", "").toString().toUtf8()); + KISSChecksum = settings->value("KISSChecksum", 0).toInt(); + KISSAckMode = settings->value("KISSAckMode", 0).toInt(); + KISSMH = settings->value("KISSMH", 1).toInt(); + strcpy(KISSMYCALL, settings->value("MYCALL", "").toString().toUtf8()); strcpy(KISSHost, settings->value("KISSHost", "127.0.0.1").toString().toUtf8()); KISSPortNum = settings->value("KISSPort", 8100).toInt(); KISSMode = settings->value("KISSMode", 0).toInt(); + strcpy(KISSVia, settings->value("KISSVia", "").toString().toUtf8()); strcpy(SerialPort, settings->value("KISSSerialPort", "None").toString().toUtf8()); KISSBAUD = settings->value("KISSBAUD", 19200).toInt(); @@ -3647,7 +3751,8 @@ void saveAX25Params(int chan) void SavePortSettings(int Chan) { - saveAX25Param("Retries", fracks[Chan]); + saveAX25Param("TXDelay", txdelay[Chan]); + saveAX25Param("sendTXDelay", sendTXDelay[Chan]); saveAX25Param("Maxframe", maxframe[Chan]); saveAX25Param("Paclen", kisspaclen[Chan]); saveAX25Param("FrackTime", frack_time[Chan]); @@ -3770,12 +3875,17 @@ extern "C" void SaveSettings() settings->setValue("KISSMonNodes", KISSMonNodes); settings->setValue("KISSListen", KISSListen); - settings->setValue("MYCALL", MYCALL); + settings->setValue("KISSChecksum", KISSChecksum); + settings->setValue("KISSAckMode", KISSAckMode); + settings->setValue("KISSMH", KISSMH); + settings->setValue("MYCALL", KISSMYCALL); settings->setValue("KISSHost", KISSHost); settings->setValue("KISSMode", KISSMode); settings->setValue("KISSPort", KISSPortNum); settings->setValue("KISSSerialPort", SerialPort); settings->setValue("KISSBAUD", KISSBAUD); + settings->setValue("KISSVia", KISSVia); + saveAX25Params(0); settings->setValue("VARAEnable", VARAEnable); @@ -3852,6 +3962,10 @@ void QtTermTCP::closeEvent(QCloseEvent *event) #endif if (process) process->close(); + + if (MHWindow) + MHWindow->close(); + } } @@ -3893,6 +4007,11 @@ QtTermTCP::~QtTermTCP() mysettings.setValue("geometry", saveGeometry()); mysettings.setValue("windowState", saveState()); + if (MHWindow) + { + mysettings.setValue("MHgeometry", MHWindow->saveGeometry()); + MHWindow->close(); + } SaveSettings(); } @@ -3958,6 +4077,27 @@ void QtTermTCP::MyTimerSlot() } +void QtTermTCP::SlowTimerSlot() +{ + // Runs every 60 S + + Ui_ListenSession * Sess; + + for (int i = 0; i < _sessions.size(); ++i) + { + Sess = _sessions.at(i); + + if (Sess->monLogfile) + { + Sess->monLogfile->close(); + Sess->monLogfile = nullptr; + } + } + +} + + + extern "C" void myBeep(QString * WAV) { if (useBeep) @@ -4025,7 +4165,13 @@ void QtTermTCP::KISSSlot() deviceUI = &UI; KISS->KISSEnable->setChecked(KISSEnable); KISS->KISSListen->setChecked(KISSListen); - KISS->MYCALL->setText(MYCALL); + KISS->KISSChecksum->setChecked(KISSChecksum); + KISS->KISSACKMODE->setChecked(KISSAckMode); + KISS->KISSMH->setChecked(KISSMH); + KISS->MYCALL->setText(KISSMYCALL); + + KISS->TXDELAY->setText(QString::number(txdelay[0])); + KISS->SetTXDelay->setChecked(sendTXDelay[0]); // connect(KISS->SerialPort, SIGNAL(currentIndexChanged(int)), this, SLOT(PTTPortChanged(int))); @@ -4079,12 +4225,15 @@ void QtTermTCP::KISSaccept() KISSEnable = KISS->KISSEnable->isChecked(); KISSListen = KISS->KISSListen->isChecked(); + KISSChecksum = KISS->KISSChecksum->isChecked(); + KISSAckMode = KISS->KISSACKMODE->isChecked(); + KISSMH = KISS->KISSMH->isChecked(); actHost[18]->setVisible(KISSEnable); // Show KISS Connect Line - strcpy(MYCALL, KISS->MYCALL->text().toUtf8().toUpper()); + strcpy(KISSMYCALL, KISS->MYCALL->text().toUtf8().toUpper()); memset(axMYCALL, 0, 7); - ConvToAX25(MYCALL, axMYCALL); + ConvToAX25(KISSMYCALL, axMYCALL); Q = KISS->Port->text(); KISSPortNum = Q.toInt(); @@ -4106,8 +4255,11 @@ void QtTermTCP::KISSaccept() Q = KISS->Retries->text(); fracks[0] = Q.toInt(); - myStatusBar->setVisible(AGWEnable | VARAEnable | KISSEnable); + Q = KISS->TXDELAY->text(); + txdelay[0] = Q.toInt(); + sendTXDelay[0] = KISS->SetTXDelay->isChecked(); + myStatusBar->setVisible(AGWEnable | VARAEnable | KISSEnable); if (KISSEnable != OldEnable || KISSPortNum != OldPort || strcmp(oldHost, KISSHost) != 0 || @@ -4131,6 +4283,26 @@ void QtTermTCP::KISSaccept() } } + if (KISSEnable == 0 && MHWindow) + { + MHWindow->close(); + MHWindow = 0; + } + + if (KISSEnable && KISSMH && MHWindow == 0) + { + newMHWindow(this, 0, "KISS MH"); + QSettings mysettings(GetConfPath(), QSettings::IniFormat); + MHWindow->restoreGeometry(mysettings.value("MHgeometry").toByteArray()); + } + + if (!KISSMH && MHWindow) + { + MHWindow->close(); + MHWindow = 0; + } + + delete(KISS); SaveSettings(); deviceUI->accept(); @@ -4602,10 +4774,15 @@ void QtTermTCP::onNewConnection() datas.chop(2); datas.truncate(10); // Just in case! + strlop(datas.data(), 13); + + if (datas.data()[0] == 0) + datas.append("UNKNOWN\0"); + datas.append('\0'); - sprintf(Title, "Inward Connect from %s:%d Call " + datas, - Host.data(), clientSocket->peerPort()); + sprintf(Title, "Inward Connect from %s:%d Call %s", + Host.data(), clientSocket->peerPort(), datas.data()); if (TermMode == MDI) { @@ -6349,6 +6526,7 @@ void ClosePTTPort() #endif } +#ifndef ANDRIOD void CM108_set_ptt(int PTTState) { @@ -6413,7 +6591,7 @@ void CM108_set_ptt(int PTTState) } - +#endif void QtTermTCP::RadioPTT(bool PTTState) { @@ -6652,6 +6830,16 @@ void QtTermTCP::onKISSSocketStateChanged(QAbstractSocket::SocketState socketStat KISS_add_stream(sender); + // send TXDelay if enabled + + if (sendTXDelay[0]) + { + unsigned char Msg[5] = { FEND, 1, 25 , FEND }; + + Msg[2] = txdelay[0] / 10; + KISSSock->write((char *)Msg, 4); + } + // Attach a Monitor Window if available Ui_ListenSession * Sess = NULL; @@ -6923,6 +7111,16 @@ int QtTermTCP::openSerialPort() KISS_add_stream(m_serial); + // send TXDelay if enabled + + if (sendTXDelay[0]) + { + unsigned char Msg[5] = { FEND, 1, 25 , FEND }; + + Msg[2] = txdelay[0] / 10; + m_serial->write((char *)Msg, 4); + } + // Attach a Monitor Window if available Ui_ListenSession * Sess = NULL; @@ -6937,7 +7135,7 @@ int QtTermTCP::openSerialPort() S = _sessions.at(i); // for (Ui_ListenSession * S: _sessions) - // { + // if ((S->SessionType == Mon) && S->clientSocket == NULL && S->KISSSession == NULL) { Sess = S; @@ -7831,7 +8029,7 @@ void WriteMonitorLog(Ui_ListenSession * Sess, char * Msg) Sess->monLogfile = new QFile(FN); if (Sess->monLogfile) - Sess->monLogfile->open(QIODevice::WriteOnly | QIODevice::Text); + Sess->monLogfile->open(QIODevice::Append); else return; } @@ -7862,3 +8060,106 @@ void WriteMonitorLog(Ui_ListenSession * Sess, char * Msg) } +// Create MH Window + + + +int newMHWindow(QObject * parent, int Type, const char * Label) +{ + Ui_ListenSession * Sess = new(Ui_ListenSession); + + MHWindow = Sess; + + // Need to explicity initialise on Qt4 + + Sess->termWindow = NULL; + Sess->monWindow = NULL; + Sess->inputWindow = NULL; + + Sess->StackIndex = 0; + Sess->InputMode = 0; + Sess->SlowTimer = 0; + Sess->MonData = 0; + Sess->OutputSaveLen = 0; + Sess->MonSaveLen = 0; + Sess->PortMonString[0] = 0; + Sess->portmask = 0; + Sess->portmask = 1; + Sess->mtxparam = 1; + Sess->mlocaltime = 0; + Sess->mcomparam = 1; + Sess->monUI = 0; + Sess->MonitorNODES = 0; + Sess->MonitorColour = 1; + Sess->CurrentHost = 0; + + Sess->SessionType = Type; + Sess->clientSocket = NULL; + Sess->AGWSession = NULL; + Sess->AGWMonSession = NULL; + Sess->KISSSession = NULL; + Sess->KISSMode = 0; + Sess->TTActive = 0; + Sess->TTFlashToggle = 0; + Sess->pageBuffer[0] = 0; + Sess->Tab = 0; + + Sess->LogMonitor = false; + Sess->monSpan = (char *) ""; + Sess->monLogfile = nullptr; + Sess->sessNo = sessNo++; + + QSettings settings(GetConfPath(), QSettings::IniFormat); + +#ifdef ANDROID + QFont font = QFont(settings.value("FontFamily", "Driod Sans Mono").value(), + settings.value("PointSize", 12).toInt(), + settings.value("Weight", 50).toInt()); +#else + QFont font = QFont(settings.value("FontFamily", "Courier New").value(), + settings.value("PointSize", 10).toInt(), + settings.value("Weight", 50).toInt()); +#endif + + Sess->monWindow = new QTextEdit(Sess); + Sess->monWindow->setReadOnly(1); + Sess->monWindow->document()->setMaximumBlockCount(10000); + Sess->monWindow->setFont(font); + Sess->monWindow->setStyleSheet(monStyleSheet); + + Sess->setWindowTitle(Label); + + Sess->installEventFilter(mythis); + + Sess->show(); + + + + Sess->monWindow->setGeometry(QRect(2, 2, 400, 400)); + Sess->setGeometry(QRect(400, 400, 400, 400)); + + + QSize Size(800, 602); // Not actually used, but Event constructor needs it + + QResizeEvent event(Size, Size); + + QApplication::sendEvent(Sess, &event); // Resize Widgets to fix Window + + return true; +} + +extern "C" void WritetoMHWindow(char * Buffer) +{ + unsigned char Copy[8192]; + unsigned char * ptr1, *ptr2; + unsigned char Line[8192]; + unsigned char out[8192]; + int outlen; + + int num; + + if (MHWindow == NULL || MHWindow->monWindow == NULL) + return; + + MHWindow->monWindow->setText(Buffer); +} diff --git a/QtTermTCP.h b/QtTermTCP.h index 7f477c3..81c8449 100644 --- a/QtTermTCP.h +++ b/QtTermTCP.h @@ -100,6 +100,7 @@ public: void * AGWMonSession; void * KISSSession; int KISSMode; // Connected or UI + int UIPORT; char UIDEST[32]; char UIPATH[128]; @@ -159,6 +160,7 @@ private slots: void LDisconnect(Ui_ListenSession * LUI); void SetupHosts(); void MyTimerSlot(); + void SlowTimerSlot(); void KISSTimerSlot(); void ListenSlot(); void AGWSlot(); diff --git a/QtTermTCP.pro b/QtTermTCP.pro index aeb5e0b..4f31da1 100644 --- a/QtTermTCP.pro +++ b/QtTermTCP.pro @@ -49,4 +49,6 @@ RESOURCES += QtTermTCP.qrc RC_ICONS = QtTermTCP.ico +ICONS = QtTermTCP.icns + QMAKE_LFLAGS += -no-pie diff --git a/QtTermTCP.pro.user b/QtTermTCP.pro.user index 4bbf667..00b803e 100644 --- a/QtTermTCP.pro.user +++ b/QtTermTCP.pro.user @@ -1,14 +1,14 @@ - + EnvironmentId - {49a2cf38-2251-47e3-97df-4ecaa9d41931} + {6e41d268-43e9-43ac-b8fa-a3c083d547a3} ProjectExplorer.Project.ActiveTarget - 0 + 0 ProjectExplorer.Project.EditorSettings @@ -28,7 +28,7 @@ QmlJSGlobal - 2 + 2 UTF-8 false 4 @@ -37,6 +37,7 @@ true true 1 + false true false 0 @@ -45,6 +46,7 @@ 0 8 true + false 1 true true @@ -52,6 +54,7 @@ *.md, *.MD, Makefile false true + true @@ -59,6 +62,7 @@ true + false true true true @@ -67,15 +71,12 @@ 0 true - - -fno-delayed-template-parsing - - true - Builtin.Questionable + true true Builtin.DefaultTidyAndClazy - 3 + 0 + true @@ -87,35 +88,28 @@ ProjectExplorer.Project.Target.0 Desktop - Desktop Qt 5.14.2 MSVC2015 64bit - Desktop Qt 5.14.2 MSVC2015 64bit - qt.qt5.5142.win64_msvc2015_64_kit - 0 - 0 - 0 + Qt 5.15.10 (5.15.10_1) + Qt 5.15.10 (5.15.10_1) + {6c3e99da-2293-4df8-901e-49e24d493aeb} + 0 + 0 + 0 - true 0 - C:\Users\John\OneDrive\Dev\Source\QT\build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Debug - C:/Users/John/OneDrive/Dev/Source/QT/build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Debug + /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Debug + /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Debug true QtProjectManager.QMakeBuildStep - false true Qt4ProjectManager.MakeStep - - false - - - false - 2 + 2 Build Build ProjectExplorer.BuildSteps.Build @@ -124,13 +118,9 @@ true Qt4ProjectManager.MakeStep - - true clean - - false - 1 + 1 Clean Clean ProjectExplorer.BuildSteps.Clean @@ -138,36 +128,27 @@ 2 false + false Debug Qt4ProjectManager.Qt4BuildConfiguration 2 - 2 - 2 - true - 2 - C:\Users\John\OneDrive\Dev\Source\QT\build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Release - C:/Users/John/OneDrive/Dev/Source/QT/build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Release + /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Release + /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Release true QtProjectManager.QMakeBuildStep - false true Qt4ProjectManager.MakeStep - - false - - - false - 2 + 2 Build Build ProjectExplorer.BuildSteps.Build @@ -176,13 +157,9 @@ true Qt4ProjectManager.MakeStep - - true clean - - false - 1 + 1 Clean Clean ProjectExplorer.BuildSteps.Clean @@ -190,36 +167,29 @@ 2 false + false Release Qt4ProjectManager.Qt4BuildConfiguration 0 0 - 2 - true 0 - C:\Users\John\OneDrive\Dev\Source\QT\build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Profile - C:/Users/John/OneDrive/Dev/Source/QT/build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Profile + /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Profile + /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Profile true QtProjectManager.QMakeBuildStep - false true Qt4ProjectManager.MakeStep - - false - - - false - 2 + 2 Build Build ProjectExplorer.BuildSteps.Build @@ -228,13 +198,9 @@ true Qt4ProjectManager.MakeStep - - true clean - - false - 1 + 1 Clean Clean ProjectExplorer.BuildSteps.Clean @@ -242,6 +208,7 @@ 2 false + false Profile Qt4ProjectManager.Qt4BuildConfiguration @@ -249,10 +216,10 @@ 0 0 - 3 + 3 - 0 + 0 Deploy Deploy ProjectExplorer.BuildSteps.Deploy @@ -262,89 +229,28 @@ false ProjectExplorer.DefaultDeployConfiguration - 1 - + 1 - dwarf - - cpu-cycles - - - 250 - - -e - cpu-cycles - --call-graph - dwarf,4096 - -F - 250 - - -F true - 4096 - false - false - 1000 - true - - false - false - false - false - true - 0.01 - 10 - true - kcachegrind - 1 - 25 - - 1 true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 2 - Qt4ProjectManager.Qt4RunConfiguration:C:/Users/John/OneDrive/Dev/Source/QT/QtTermTCP/QtTermTCP.pro - C:/Users/John/OneDrive/Dev/Source/QT/QtTermTCP/QtTermTCP.pro - - false - - false + false + Qt4ProjectManager.Qt4RunConfiguration:/Volumes/Source/QT/QtTermTCP2/QtTermTCP.pro + /Volumes/Source/QT/QtTermTCP2/QtTermTCP.pro true true - false - false true - - C:/Users/John/OneDrive/Dev/Source/QT/build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Debug + /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Debug/QtTermTCP.app/Contents/MacOS - 1 + 1 ProjectExplorer.Project.TargetCount - 1 + 1 ProjectExplorer.Project.Updater.FileVersion diff --git a/QtTermTCP.vcxproj b/QtTermTCP.vcxproj index 506de1f..8b8c32d 100644 --- a/QtTermTCP.vcxproj +++ b/QtTermTCP.vcxproj @@ -114,7 +114,7 @@ 5.14.2 - core;network;gui;widgets;serialport + core;network;gui;widgets;serialport;multimedia 5.14.2_msvc2017 @@ -122,7 +122,7 @@ 5.14.2 - core;network;gui;widgets;serialport + core;network;gui;widgets;serialport;multimedia 5.14.2_msvc2017_64 @@ -153,7 +153,7 @@ true - shell32.lib;setupapi.lib;C:\Qt\Qt5.14.2\5.14.2\msvc2017\lib\Qt5Multimedia.lib;%(AdditionalDependencies) + shell32.lib;setupapi.lib;%(AdditionalDependencies) C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) -no-pie "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) true @@ -279,7 +279,7 @@ true - shell32.lib;setupapi.lib;%(AdditionalDependencies);C:\Qt\Qt5.14.2\5.14.2\msvc2017\lib\Qt5Multimediad.lib + shell32.lib;setupapi.lib;%(AdditionalDependencies); C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) -no-pie "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) true diff --git a/QtTermTCP.vcxproj.user b/QtTermTCP.vcxproj.user index c34359b..114a6e2 100644 --- a/QtTermTCP.vcxproj.user +++ b/QtTermTCP.vcxproj.user @@ -1,12 +1,14 @@  - $(APPDATA) + C:\DevProgs\BPQ32\Release WindowsLocalDebugger + C:\Dev\Msdev2005\Projects\QtTermTCP\Win32\Debug\QtTermTCP.exe - ..\..\..\..\..\DevProgs\BPQ32 + C:\DevProgs\BPQ32\Release WindowsLocalDebugger + C:\Dev\Msdev2005\Projects\QtTermTCP\Win32\Debug\QtTermTCP.exe 2022-05-19T07:28:47.9186341Z @@ -15,15 +17,15 @@ 2022-05-19T07:28:58.9302359Z - 2023-10-14T13:14:56.5532991Z + 2025-02-19T10:20:19.7224236Z - 2023-10-14T13:14:56.7231497Z + 2025-02-19T10:20:19.9860750Z - 2023-10-14T13:14:55.9367569Z + 2025-02-19T10:20:19.2704826Z - 2023-10-14T13:14:56.2561805Z + 2025-02-19T10:20:19.4132585Z \ No newline at end of file diff --git a/TabDialog.cpp b/TabDialog.cpp index 98d3ed9..8e5e17b 100644 --- a/TabDialog.cpp +++ b/TabDialog.cpp @@ -56,7 +56,7 @@ extern char UserName[MAXHOSTS + 1][80]; extern char Password[MAXHOSTS + 1][80]; extern char SessName[MAXHOSTS + 1][80]; -extern char MYCALL[32]; +extern char KISSMYCALL[32]; QLineEdit *TermCall; QGroupBox *groupBox; @@ -114,6 +114,7 @@ extern char * AGWPortList; extern QStringList AGWToCalls; extern int KISSMode; +extern char KISSVia[128]; // Digi String extern Ui_ListenSession * ActiveSession; @@ -470,7 +471,7 @@ KISSConnect::KISSConnect(QWidget *parent) : QDialog(parent) scrollArea = new QScrollArea(this); scrollArea->setObjectName(QString::fromUtf8("scrollArea")); - scrollArea->setGeometry(QRect(5, 5, 250, 200)); + scrollArea->setGeometry(QRect(5, 5, 260, 200)); scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); scrollArea->setWidgetResizable(false); @@ -503,6 +504,13 @@ KISSConnect::KISSConnect(QWidget *parent) : QDialog(parent) layout->addSpacing(10); layout->addLayout(formLayout2); + Chan = new QComboBox(); + Chan->setEditable(false); + Chan->setInsertPolicy(QComboBox::NoInsert); + Chan->addItems(QStringList() << "A" << "B" << "C" << "D"); + + formLayout2->addRow(new QLabel("Modem Channel"), Chan); + wCallTo = new QComboBox(); wCallTo->setEditable(true); wCallTo->setInsertPolicy(QComboBox::NoInsert); @@ -510,6 +518,7 @@ KISSConnect::KISSConnect(QWidget *parent) : QDialog(parent) formLayout2->addRow(new QLabel("Call To"), wCallTo); Digis = new QLineEdit(); + formLayout2->addRow(new QLabel("Digis"), Digis); layout->addSpacing(2); @@ -523,6 +532,9 @@ KISSConnect::KISSConnect(QWidget *parent) : QDialog(parent) wCallTo->addItems(AGWToCalls); + Digis->setText(KISSVia); + Digis->resize(400, 20); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(myaccept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(myreject())); } @@ -544,16 +556,20 @@ void KISSConnect::myaccept() { QVariant Q; - char CallTo[32]; - char Via[128]; + char CallTo[128];; + char Port[3]; + strcpy(CallTo, wCallTo->currentText().toUpper().toUtf8()); - strcpy(Via, Digis->text().toUpper().toUtf8()); + strcpy(KISSVia, Digis->text().toUpper().toUtf8()); + memcpy(Port, Chan->currentText().toUpper().toUtf8(), 1); + + int PortNo = Port[0] - 'A'; TAX25Port * AX25Sess = 0; // Check for duplicate session - AX25Sess = get_user_port_by_calls(0, MYCALL, CallTo); + AX25Sess = get_user_port_by_calls(0, KISSMYCALL, CallTo); if (AX25Sess) { @@ -561,7 +577,7 @@ void KISSConnect::myaccept() char Msg[256]; - int Len = sprintf(Msg, "You already have a session between %s and %s so can't connect\r", MYCALL, CallTo); + int Len = sprintf(Msg, "You already have a session between %s and %s so can't connect\r", KISSMYCALL, CallTo); WritetoOutputWindow(ActiveSession, (unsigned char *)Msg, Len); // KISSConnect::accept(); @@ -581,7 +597,7 @@ void KISSConnect::myaccept() if (KISSMode == 0) { - ActiveSession->KISSSession = KISSConnectOut(ActiveSession, MYCALL, CallTo, Via, 0, (void *)KISSSock); + ActiveSession->KISSSession = KISSConnectOut(ActiveSession, KISSMYCALL, CallTo, KISSVia, PortNo, (void *)KISSSock); WritetoOutputWindow(ActiveSession, (unsigned char *)"Connecting...\r", 14); discAction->setEnabled(true); } @@ -597,7 +613,8 @@ void KISSConnect::myaccept() ActiveSession->KISSSession = (void *)&DummyPort; // Dummy marker to show session in use strcpy(ActiveSession->UIDEST, CallTo); - strcpy(ActiveSession->UIPATH, Via); + strcpy(ActiveSession->UIPATH, KISSVia); + ActiveSession->UIPORT = PortNo; if (TermMode == Tabbed) Len = sprintf(Msg, "UI %s", CallTo); diff --git a/TabDialog.h b/TabDialog.h index cd21067..a3a58be 100644 --- a/TabDialog.h +++ b/TabDialog.h @@ -146,6 +146,7 @@ public: public: QLineEdit * wCallFrom; QComboBox * wCallTo; + QComboBox * Chan; QLineEdit * Digis; QLineEdit * UIDest; QListWidget * RadioPorts; diff --git a/ax25.c b/ax25.c index f212148..b7f52af 100644 --- a/ax25.c +++ b/ax25.c @@ -20,9 +20,13 @@ along with QtSoundModem. If not, see http://www.gnu.org/licenses // UZ7HO Soundmodem Port by John Wiseman G8BPQ +// This is a simplified version for QtTermTCP + #include "ax25.h" #include +extern int KISSChecksum; + #ifdef WIN32 __declspec(dllimport) unsigned short __stdcall htons(__in unsigned short hostshort); @@ -40,7 +44,7 @@ void decode_frame(Byte * frame, int len, Byte * path, string * data, void SetSessLabel(void * Sess, char * label); void setMenus(int State); - +void MHPROC(unsigned char * Packet, int Len); /* unit ax25; @@ -224,6 +228,8 @@ Byte users[4] = { 0,0,0,0 }; short txtail[5] = { 50, 50, 50, 50, 50 }; short txdelay[5] = { 400, 400, 400, 400, 400 }; +int sendTXDelay[4] = { 0, 0, 0, 0 }; + short modem_def[5] = { 1, 1, 1, 1, 1 }; @@ -861,7 +867,7 @@ int get_addr(char * Calls, UCHAR * AXCalls) char * ptr, *Context; int n = 8; // Max digis - memset(AXCalls, 0, 70); + memset(AXCalls, 0, 72); ptr = strtok_s(Calls, " ,", &Context); @@ -877,7 +883,7 @@ int get_addr(char * Calls, UCHAR * AXCalls) ptr = strtok_s(NULL, " ,", &Context); - if (ConvToAX25(ptr, axptr) == 0) + if (ptr == 0 || ConvToAX25(ptr, axptr) == 0) return FALSE; axptr += 7; @@ -2495,6 +2501,7 @@ void KISSDataReceived(void * socket, unsigned char * data, int length) void analiz_frame(int snd_ch, string * frame, void * socket, boolean fecflag); +void KISSSendtoServer(void * Socket, char * Data, int Length); void ProcessKISSFrame(void * socket, UCHAR * Msg, int Len) { @@ -2505,8 +2512,6 @@ void ProcessKISSFrame(void * socket, UCHAR * Msg, int Len) int Chan; int Opcode; string * TXMSG; - unsigned short CRC; - UCHAR CRCString[2]; ptr1 = ptr2 = Msg; @@ -2564,46 +2569,65 @@ void ProcessKISSFrame(void * socket, UCHAR * Msg, int Len) if (Chan > 3) return; + // This is a lot simpler than QtSM, as frames will always be immediately processed locally, so ack mode isn't needed. + // but if enabled ack can be sent immediately + // checksum if needed + switch (Opcode) { case KISS_ACKMODE: + { + // send ack - // How best to do ACKMODE?? I think pass whole frame including CMD and ack bytes to all_frame_buf + unsigned char ACK[16]; + unsigned char * ackptr = ACK; - // But ack should only be sent to client that sent the message - needs more thought! + *ackptr++ = FEND; + *ackptr++ = Msg[0]; // opcode and channel - TXMSG = newString(); - stringAdd(TXMSG, &Msg[0], Len); // include Control + *ackptr++ = Msg[1]; + *ackptr++ = Msg[2]; // ACK Bytes + *ackptr++ = FEND; - CRC = get_fcs(&Msg[3], Len - 3); // exclude control and ack bytes + KISSSendtoServer(socket, ACK, 5); - CRCString[0] = CRC & 0xff; - CRCString[1] = CRC >> 8; + // remove ack bytes - stringAdd(TXMSG, CRCString, 2); + memmove(&Msg[1], &Msg[3], Len - 2); - // Ackmode needs to know where to send ack back to, so save socket on end of data - - stringAdd(TXMSG, (unsigned char *)&socket, sizeof(socket)); - - // if KISS Optimise see if frame is really needed - - if (!KISS_opt[Chan]) - Add(&KISS.buffer[Chan], TXMSG); - else - { - if (add_raw_frames(Chan, TXMSG, &KISS.buffer[Chan])) - Add(&KISS.buffer[Chan], TXMSG); - } - - - return; + // drop through to KISS Data + Len -= 2; + } case KISS_DATA: + if (KISSChecksum) + { + // SUM MESSAGE, AND IF DUFF DISCARD. IF OK DECREMENT COUNT TO REMOVE SUM + + int sumlen = Len; + char * ptr = &Msg[0]; + UCHAR sum = 0; + + while (sumlen--) + { + sum ^= *(ptr++); + } + + if (sum) + { + Debugprintf("KISS Checksum Error"); + return; + } + + Len--; // Remove Checksum + } + TXMSG = newString(); stringAdd(TXMSG, &Msg[1], Len - 1); // include Control + MHPROC(TXMSG->Data, TXMSG->Length); + analiz_frame(Chan, TXMSG, socket, 0); free(TXMSG); @@ -2702,7 +2726,7 @@ TAX25Port * KISSConnectOut(void * Sess, char * CallFrom, char * CallTo, char * D strcpy((char *)AX25Sess->Path, (char *)axpath); reverse_addr(axpath, AX25Sess->ReversePath, AX25Sess->pathLen); - set_link(AX25Sess, AX25Sess->Path); + set_link(AX25Sess, AX25Sess->Path); // Sends SABM return AX25Sess; } return 0; @@ -2997,6 +3021,221 @@ char * frame_monitor(string * frame, char * code, int tx_stat) return FrameData; } +typedef struct _MHSTRUC +{ + UCHAR MHCALL[7]; + UCHAR MHDIGIS[7][8]; + time_t MHTIME; + int MHCOUNT; + unsigned char MHDIGI; + char MHFreq[12]; + char MHLocator[6]; +} MHSTRUC, *PMHSTRUC; + + +#define MHENTRIES 30 + +MHSTRUC MHEARD[(MHENTRIES + 1) * sizeof(MHSTRUC)] = { 0 }; + +int CompareCalls(UCHAR * c1, UCHAR * c2) +{ + // COMPARE AX25 CALLSIGNS IGNORING EXTRA BITS IN SSID + + if (memcmp(c1, c2, 6)) + return FALSE; // No Match + + if ((c1[6] & 0x1e) == (c2[6] & 0x1e)) + return TRUE; + + return FALSE; +} + +static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +void * MHWindow = 0; +void WritetoMHWindow(char * Buffer); +int KISSMH = 0; + +char * FormatMH(PMHSTRUC MH) +{ + struct tm * TM; + static char MHTime[50]; + time_t szClock; + char LOC[7]; + + memcpy(LOC, MH->MHLocator, 6); + LOC[6] = 0; + + szClock = MH->MHTIME; +// else +// szClock = time(NULL) - MH->MHTIME; + + TM = gmtime(&szClock); + + sprintf(MHTime, "%s %02d %.2d:%.2d:%.2d %s %s", + month[TM->tm_mon], TM->tm_mday, TM->tm_hour, TM->tm_min, TM->tm_sec, MH->MHFreq, LOC); + + return MHTime; +} + + + + +void MHPROC(unsigned char * Packet, int Len) +{ + PMHSTRUC MH = &MHEARD[0]; + PMHSTRUC MHBASE = MH; + int i; + int OldCount = 0; + char Freq[64] = ""; + char DIGI = '*'; + + MESSAGE Frame; + MESSAGE * Buffer = &Frame; + + memcpy(Buffer->DEST, Packet, Len); + + + // if port has a freq associated with it use it + + + // if (Buffer->ORIGIN[6] & 1) + DIGI = 0; // Don't think we want to do this + +// See if in list + + for (i = 0; i < MHENTRIES; i++) + { + if ((MH->MHCALL[0] == 0) || (CompareCalls(Buffer->ORIGIN, MH->MHCALL) && MH->MHDIGI == DIGI)) // Spare or our entry + { + OldCount = MH->MHCOUNT; + goto DoMove; + } + MH++; + } + + // TABLE FULL AND ENTRY NOT FOUND - MOVE DOWN ONE, AND ADD TO TOP + + i = MHENTRIES - 1; + + // Move others down and add at front +DoMove: + if (i != 0) // First + memmove(MHBASE + 1, MHBASE, i * sizeof(MHSTRUC)); + + memcpy(MHBASE->MHCALL, Buffer->ORIGIN, 7 * 9); // Save Digis + MHBASE->MHDIGI = DIGI; + MHBASE->MHTIME = time(NULL); + MHBASE->MHCOUNT = ++OldCount; + strcpy(MHBASE->MHFreq, Freq); + MHBASE->MHLocator[0] = 0; + + if (MHWindow) + { + int count = MHENTRIES; + int n; + char Normcall[20]; + char From[10]; + char DigiList[100]; + char * Output; + int len; + char Digi = 0; + char MHPage[MHENTRIES * 100]; + char * Bufferptr = MHPage; + unsigned char * ptr; + + MH = &MHEARD[0]; + + // Note that the MHDIGIS field may contain rubbish. You have to check End of Address bit to find + // how many digis there are + + Bufferptr += sprintf(Bufferptr, "Callsign Last heard Pkts RX via Digi\r"); + Bufferptr += sprintf(Bufferptr, "\r"); + + while (count--) + { + if (MH->MHCALL[0] == 0) + break; + + Digi = 0; + + len = ConvFromAX25(MH->MHCALL, Normcall); + + Normcall[len++] = MH->MHDIGI; + Normcall[len++] = 0; + + n = 8; // Max number of digi-peaters + + ptr = &MH->MHCALL[6]; // End of Address bit + + Output = &DigiList[0]; + + if ((*ptr & 1) == 0) + { + // at least one digi + + strcpy(Output, "via "); + Output += 4; + + while ((*ptr & 1) == 0) + { + // MORE TO COME + + From[ConvFromAX25(ptr + 1, From)] = 0; + Output += sprintf((char *)Output, "%s", From); + + ptr += 7; + n--; + + if (n == 0) + break; + + // See if digi actioned - put a * on last actioned + + if (*ptr & 0x80) + { + if (*ptr & 1) // if last address, must need * + { + *(Output++) = '*'; + Digi = '*'; + } + + else + if ((ptr[7] & 0x80) == 0) // Repeased by next? + { + *(Output++) = '*'; // No, so need * + Digi = '*'; + } + + } + *(Output++) = ','; + } + *(--Output) = 0; // remove last comma + } + else + *(Output) = 0; + + // if we used a digi set * on call and display via string + + + if (Digi) + Normcall[len++] = Digi; + else + DigiList[0] = 0; // Dont show list if not used + + Normcall[len++] = 0; + + ptr = FormatMH(MH); + + Bufferptr += sprintf(Bufferptr, "%-10s %-10s %-10d %-30s\r", Normcall, ptr, MH->MHCOUNT, DigiList); + + MH++; + } + + WritetoMHWindow(MHPage); + } + return; +} diff --git a/ax25.h b/ax25.h index d554b20..06c2fd3 100644 --- a/ax25.h +++ b/ax25.h @@ -228,7 +228,7 @@ extern "C" void WriteDebugLog(char * Mess); extern "C" void SendtoTerm(Ui_ListenSession * Sess, char * Msg, int Len); extern "C" void ClearSessLabel(Ui_ListenSession * Sess); extern "C" void rst_timer(TAX25Port * AX25Sess); -extern "C" void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, Byte * Msg, int MsgLen); +extern "C" void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, char * Via, Byte * Msg, int MsgLen); #else void monitor_frame(int snd_ch, string * frame, char * code, int tx, int excluded); void SendtoTerm(void * Sess, char * Msg, int Len); @@ -236,7 +236,7 @@ void ClearSessLabel(void * Sess); void WriteDebugLog(char * Mess); void AX25_disc(TAX25Port * AX25Sess, Byte mode); void rst_timer(TAX25Port * AX25Sess); -void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, Byte * Msg, int MsgLen); +void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, char * via, Byte * Msg, int MsgLen); #endif BOOL ConvToAX25(char * callsign, unsigned char * ax25call); diff --git a/ax25_l2.c b/ax25_l2.c index e4dabb7..0806ef3 100644 --- a/ax25_l2.c +++ b/ax25_l2.c @@ -20,12 +20,18 @@ along with QtSoundModem. If not, see http://www.gnu.org/licenses // UZ7HO Soundmodem Port by John Wiseman G8BPQ +// This is a simplified version for QtTermTCP + + + #include "ax25.h" UCHAR TimerEvent = TIMER_EVENT_OFF; extern int busy; int listenEnable; int KISSListen = 1; +int KISSChecksum = 0; +int KISSAckMode = 0; void * KISSSockCopy[4]; extern UCHAR axMYCALL[7] = ""; // Mycall in ax.25 @@ -301,6 +307,32 @@ int KISS_encode(UCHAR * KISSBuffer, int port, string * frame) (*ptr2++) = c; } } + + // Add checksum if needed + + if (KISSChecksum) + { + c = TXCCC; + + // We don't support TNCX with Checksum + + switch (c) + { + case FEND: + (*ptr2++) = FESC; + (*ptr2++) = TFEND; + break; + + case FESC: + (*ptr2++) = FESC; + (*ptr2++) = TFESC; + break; + + default: + (*ptr2++) = c; + } + } + (*ptr2++) = FEND; return (int)(ptr2 - KISSBuffer); @@ -317,23 +349,13 @@ void add_pkt_buf(TAX25Port * AX25Sess, string * data) // ? Don't we just send to TNC? - Length = KISS_encode(KISSBuffer, 0, data); + Length = KISS_encode(KISSBuffer, AX25Sess->snd_ch, data); KISSSendtoServer(AX25Sess->socket, KISSBuffer, Length); monitor_frame(0, data, "", 1, 0); // Monitor freeString(data); - -// while (i < AX25Sess->frame_buf.Count && !found) -// { -// found = compareStrings(Strings(&AX25Sess->frame_buf, i++), data); -// } - -// if (found) -// freeString(data); -// else -// Add(&AX25Sess->frame_buf, data); } void add_I_FRM(TAX25Port * AX25Sess) @@ -1227,20 +1249,9 @@ void timer_event() for (snd_ch = 0; snd_ch < 4; snd_ch++) { //reset the slottime timer - if (dyn_frack[snd_ch]) - { - UpdateActiveConnects(snd_ch); - if (users[snd_ch] > 0) - active = users[snd_ch] - 1; - else - active = 0; - frack = frack_time[snd_ch] + frack_time[snd_ch] * active * 0.5; - } - else - frack = frack_time[snd_ch]; + frack = frack_time[snd_ch]; - // for (port = 0; port < port_num; port++) { AX25Sess = &AX25Port[snd_ch][port]; @@ -1703,10 +1714,12 @@ void analiz_frame(int snd_ch, string * frame, void * socket, boolean fecflag) int get_addr(char * Calls, UCHAR * AXCalls); -void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, Byte * Msg, int MsgLen) +void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, char * via, Byte * Msg, int MsgLen) { - Byte path[80]; - char Calls[80]; + char Addrs[256]; + Byte path[256]; + int destlen = 0; + string * Data = newString(); string * Frame; @@ -1715,17 +1728,19 @@ void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, Byte * Msg, int stringAdd(Data, Msg, MsgLen); - sprintf(Calls, "%s,%s", CallTo, CallFrom); + // We Need Dest, Source, Digis in path, with end of address bit set appropriately. - get_addr(Calls, path); + sprintf(Addrs, "%s %s %s", CallTo, CallFrom, via); + + destlen = get_addr(Addrs, path); Frame = make_frame(Data, path, PID, 0, 0, U_FRM, U_UI, FALSE, SET_F, SET_C); // ? Don't we just send to TNC? - Length = KISS_encode(KISSBuffer, 0, Frame); + Length = KISS_encode(KISSBuffer, port, Frame); - KISSSendtoServer(KISSSockCopy[port], KISSBuffer, Length); + KISSSendtoServer(KISSSockCopy[0], KISSBuffer, Length); monitor_frame(0, Frame, "", 1, 0); // Monitor freeString(Frame); diff --git a/debug/moc_predefs.h b/debug/moc_predefs.h index 6d708a1..62e1baa 100644 --- a/debug/moc_predefs.h +++ b/debug/moc_predefs.h @@ -1,7 +1,7 @@ #define _MSC_EXTENSIONS #define _INTEGRAL_MAX_BITS 64 #define _MSC_VER 1916 -#define _MSC_FULL_VER 191627043 +#define _MSC_FULL_VER 191627051 #define _MSC_BUILD 0 #define _WIN32 #define _M_IX86 600 diff --git a/release/moc_predefs.h b/release/moc_predefs.h index 54e9037..cf82b6d 100644 --- a/release/moc_predefs.h +++ b/release/moc_predefs.h @@ -1,7 +1,7 @@ #define _MSC_EXTENSIONS #define _INTEGRAL_MAX_BITS 64 #define _MSC_VER 1916 -#define _MSC_FULL_VER 191627043 +#define _MSC_FULL_VER 191627051 #define _MSC_BUILD 0 #define _WIN32 #define _M_IX86 600