// AGW Interface #include "QtTermTCP.h" #include "TabDialog.h" #include #include #include #ifndef WIN32 #define strtok_s strtok_r #endif #define UCHAR unsigned char #define byte unsigned char myTcpSocket * AGWSock; extern QColor monRxText; extern QColor monTxText; extern QColor outputText; extern QColor EchoText; extern QColor WarningText; extern QColor newTabText; extern QTabWidget *tabWidget; extern QWidget * mythis; extern int AGWEnable; extern int AGWMonEnable; extern int AGWLocalTime; extern int AGWMonNodes; extern char AGWTermCall[12]; extern char AGWBeaconDest[12]; extern char AGWBeaconPath[80]; extern int AGWBeaconInterval; extern char AGWBeaconPorts[80]; extern char AGWBeaconMsg[260]; extern char AGWHost[128]; extern int AGWPortNum; extern int AGWPaclen; extern Ui_ListenSession * KISSMonSess; extern char listenCText[4096]; extern int ConnectBeep; extern QList _sessions; extern QLabel * Status1; extern QLabel * Status2; extern QLabel * Status3; extern QLabel * Status4; extern QMenu *connectMenu; extern QAction *discAction; extern QAction *YAPPSend; extern QAction *actHost[17]; // Session Type Equates #define Term 1 #define Mon 2 #define Listen 4 extern int TermMode; #define Single 0 #define MDI 1 #define Tabbed 2 extern int singlemodeFormat; typedef struct AGWUser_t { QTcpSocket *socket; unsigned char data_in[8192]; int data_in_len; unsigned char AGW_frame_buf[512]; int Monitor; int Monitor_raw; Ui_ListenSession * MonSess; // Window for Monitor info } AGWUser; struct AGWHeader { int Port; unsigned char DataKind; unsigned char filler2; unsigned char PID; unsigned char filler3; char callfrom[10]; char callto[10]; int DataLength; int reserved; }; #define AGWHDDRRLEN sizeof(struct AGWHeader) typedef struct TAGWPort_t { byte PID; int port; char corrcall[10]; char mycall[10]; int Active; QTcpSocket * socket; Ui_ListenSession * Sess; // Terminal Session } TAGWPort; int AGWConnected = 0; int AGWConnecting = 0; char * AGWPortList = NULL; #define max_sessions 8 TAGWPort AGWPort[max_sessions]; #define LSB 29 #define MSB 30 #define MON_ON '1' #define MON_OFF '0' #define MODE_OUR 0 #define MODE_OTHER 1 #define MODE_RETRY 2 // Don't think we will support more than one, but leave in option AGWUser *AGWUsers = NULL; // List of currently connected clients void AGW_add_socket(QTcpSocket * socket); void AGW_Process_Input(AGWUser * AGW); void Send_AGW_X_Frame(QTcpSocket* socket, char * CallFrom); void Send_AGW_G_Frame(QTcpSocket* socket); void Send_AGW_m_Frame(QTcpSocket* socket); void Send_AGW_R_Frame(QTcpSocket* socket); Ui_ListenSession * FindFreeWindow(); Ui_ListenSession * newWindow(QObject * parent, int Type, const char * Label = nullptr); void AGW_frame_header(UCHAR * Msg, char AGWPort, char DataKind, unsigned char PID, const char * CallFrom, const char * CallTo, int Len); void Debugprintf(const char * format, ...) { char Mess[10000]; va_list arglist; va_start(arglist, format); vsprintf(Mess, format, arglist); qDebug() << Mess; return; } int ConvToAX25(char * callsign, unsigned char * ax25call) { int i; memset(ax25call, 0x40, 6); // in case short ax25call[6] = 0x60; // default SSID for (i = 0; i < 7; i++) { if (callsign[i] == '-') { // // process ssid and return // i = atoi(&callsign[i + 1]); if (i < 16) { ax25call[6] |= i << 1; return (1); } return (0); } if (callsign[i] == 0 || callsign[i] == 13 || callsign[i] == ' ' || callsign[i] == ',') { // // End of call - no ssid // return (1); } ax25call[i] = callsign[i] << 1; } // // Too many chars // return (0); } int ConvFromAX25(unsigned char * incall, char * outcall) { int in, out = 0; unsigned char chr; memset(outcall, 0x20, 10); for (in = 0; in < 6; in++) { chr = incall[in]; if (chr == 0x40) break; chr >>= 1; outcall[out++] = chr; } chr = incall[6]; // ssid if (chr == 0x42) { outcall[out++] = '-'; outcall[out++] = 'T'; return out; } if (chr == 0x44) { outcall[out++] = '-'; outcall[out++] = 'R'; return out; } chr >>= 1; chr &= 15; if (chr > 0) { outcall[out++] = '-'; if (chr > 9) { chr -= 10; outcall[out++] = '1'; } chr += 48; outcall[out++] = chr; } return (out); } void doAGWBeacon() { if (AGWBeaconDest[0] && AGWBeaconPorts[0]) { // Send as M or V depending on Digis UCHAR Msg[512]; char ports[80]; char * ptr, * context; int DataLen = (int)strlen(AGWBeaconMsg); strcpy(ports, AGWBeaconPorts); // strtok changes it // Replace newlines with CR while ((ptr = strchr(AGWBeaconMsg, 10))) *ptr = 13; ptr = strtok_s(ports, " ,", &context); if (AGWBeaconPath[0]) { } else { while (ptr) { AGW_frame_header(Msg, atoi(ptr) - 1, 'M', 240, AGWTermCall, AGWBeaconDest, DataLen); memcpy(&Msg[AGWHDDRRLEN], AGWBeaconMsg, DataLen); DataLen += AGWHDDRRLEN; AGWSock->write((char *)Msg, DataLen); ptr = strtok_s(NULL, " ,", &context); } } } } TAGWPort * get_free_port() { int i = 0; while (i < max_sessions) { if (AGWPort[i].Active == 0) return &AGWPort[i]; i++; } return nullptr; } TAGWPort * findSession(int AGWChan, char * MyCall, char * OtherCall) { int i = 0; TAGWPort * Sess = nullptr; while (i < max_sessions) { Sess = &AGWPort[i]; if (Sess->Active && Sess->port == AGWChan && strcmp(Sess->corrcall, OtherCall) == 0 && strcmp(Sess->mycall, MyCall) == 0) return Sess; i++; } return nullptr; } void QtTermTCP::AGWdisplayError(QAbstractSocket::SocketError socketError) { switch (socketError) { case QAbstractSocket::RemoteHostClosedError: break; case QAbstractSocket::HostNotFoundError: QMessageBox::information(this, tr("QtTermTCP"), tr("AGW host was not found. Please check the " "host name and port settings.")); Status1->setText("AGW Connection Failed"); break; case QAbstractSocket::ConnectionRefusedError: Status1->setText("AGW Connection Refused"); break; default: Status1->setText("AGW Connection Failed"); } AGWConnecting = 0; AGWConnected = 0; } void QtTermTCP::AGWreadyRead() { int Read; unsigned char Buffer[4096]; myTcpSocket* Socket = static_cast(QObject::sender()); // read the data from the socket Read = Socket->read((char *)Buffer, 4095); int AGWHeaderLen = sizeof(struct AGWHeader); AGWUser * AGW = NULL; AGW = AGWUsers; if (AGW == NULL) return; memcpy(&AGW->data_in[AGW->data_in_len], Buffer, Read); AGW->data_in_len += Read; while (AGW->data_in_len >= AGWHeaderLen) // Make sure have at least header { struct AGWHeader * Hddr = (struct AGWHeader *)AGW->data_in; int AgwLen = Hddr->DataLength + AGWHeaderLen; if (AGW->data_in_len >= AgwLen) { // Have frame as well AGW_Process_Input(AGW); AGW->data_in_len -= AgwLen; memmove(AGW->data_in, &AGW->data_in[AgwLen], AGW->data_in_len); } else return; // Wait for the data } } void QtTermTCP::onAGWSocketStateChanged(QAbstractSocket::SocketState socketState) { myTcpSocket* sender = static_cast(QObject::sender()); Ui_ListenSession * Sess = (Ui_ListenSession *)sender->Sess; int i; if (socketState == QAbstractSocket::UnconnectedState) { // Close any connections Status1->setText("AGW Disconnected"); actHost[16]->setVisible(0); int i = 0; TAGWPort * AGW = nullptr; for (i = 0; i < max_sessions; i++) { AGW = &AGWPort[i]; if (AGW->Active && AGW->socket) { AGW->Active = 0; AGW->socket = nullptr; Sess = AGW->Sess; if (Sess) { // Send Disconnected char Msg[] = "Disconnected\r"; WritetoOutputWindowEx(Sess, (unsigned char *)Msg, (int)strlen(Msg), Sess->termWindow, &Sess->OutputSaveLen, Sess->OutputSave, WarningText); // Red if (TermMode == MDI) { if (Sess->SessionType == Mon) // Mon Only Sess->setWindowTitle("Monitor Session Disconnected"); else Sess->setWindowTitle("Disconnected"); } else if (TermMode == Tabbed) { if (Sess->SessionType == Mon) // Mon Only tabWidget->setTabText(Sess->Tab, "Monitor"); else { char Label[32]; sprintf(Label, "Sess %d", Sess->Tab + 1); tabWidget->setTabText(Sess->Tab, Label); } } else if (TermMode == Single) { if (Sess->SessionType == Mon) // Mon Only mythis->setWindowTitle("Monitor Session Disconnected"); else mythis->setWindowTitle("Disconnected"); } setMenus(false); // if Single Split or Monitor leave session allocated to AGW if (TermMode == Single && (Sess->SessionType & Mon)) { return; } Sess->AGWSession = nullptr; AGW->Sess = nullptr; } } } // Free the monitor Window if (AGWUsers && AGWUsers->MonSess) { Sess = AGWUsers->MonSess; char Msg[] = "Disconnected\r"; WritetoOutputWindowEx(Sess, (unsigned char *)Msg, (int)strlen(Msg), Sess->monWindow, &Sess->OutputSaveLen, Sess->OutputSave, WarningText); // Red if (TermMode == MDI) Sess->setWindowTitle("Monitor Session Disconnected"); else if (TermMode == Tabbed) tabWidget->setTabText(Sess->Tab, "Monitor"); Sess->AGWSession = nullptr; AGWUsers->MonSess = nullptr; } if (TermMode == Single && (singlemodeFormat & Mon)) { //Re-renable TCP connects for (int i = 0; i < MAXHOSTS; i++) actHost[i]->setVisible(1); } AGWConnected = 0; } else if (socketState == QAbstractSocket::ConnectedState) { AGWConnected = 1; AGWConnecting = 0; Status1->setText("AGW Connected"); AGW_add_socket(sender); actHost[16]->setVisible(1); // Enable AGW Connect Line // Send X frame to register Term Call if (AGWTermCall[0]) Send_AGW_X_Frame(sender, AGWTermCall); Send_AGW_G_Frame(sender); // Request Port List // Attach a Monitor Window if available Ui_ListenSession * Sess = NULL; Ui_ListenSession * S; if (TermMode == MDI) { // See if an old session can be reused for (int i = 0; i < _sessions.size(); ++i) { S = _sessions.at(i); // for (Ui_ListenSession * S: _sessions) // { if ((S->SessionType == Mon) && S->clientSocket == NULL && S->AGWSession == NULL && S->KISSSession == NULL && (AGWUsers == NULL || (S != AGWUsers->MonSess)) && S != KISSMonSess) { Sess = S; break; } } // Create a window if none found, else reuse old if (Sess == NULL) { Sess = newWindow((QObject *)mythis, Mon, ""); } } else if (TermMode == Tabbed) { // Tabbed - look for free session for (i = 8; i; i--) { S = _sessions.at(i); if (S->clientSocket == NULL && S->KISSSession == NULL && S->AGWSession == NULL && (AGWUsers == NULL || (S != AGWUsers->MonSess)) && S != KISSMonSess) { Sess = S; break; } } } else if (TermMode == Single && (singlemodeFormat & Mon)) { S = _sessions.at(0); if (S->clientSocket == NULL && S->AGWSession == NULL && S->KISSSession == NULL && (AGWUsers == NULL || (S != AGWUsers->MonSess)) && S != KISSMonSess) Sess = S; } if (Sess) { AGWUsers->MonSess = Sess; Sess->AGWSession = sender; // Flag as in use if (TermMode == MDI) Sess->setWindowTitle("AGW Monitor Window"); else if (TermMode == Tabbed) tabWidget->setTabText(Sess->Tab, "AGW Mon"); else if (TermMode == Single) mythis->setWindowTitle("AGW Monitor Window"); if (TermMode == Single && (singlemodeFormat & Mon)) { // Can't be connected, so leave state alone, but disable TCP connects for (int i = 0; i < MAXHOSTS; i++) actHost[i]->setVisible(0); } else if (TermMode != Tabbed) // Not ideal, but AGW mon window is unlikely to be active window { discAction->setEnabled(false); YAPPSend->setEnabled(false); connectMenu->setEnabled(false); } Sess->mlocaltime = AGWLocalTime; Sess->MonitorNODES = AGWMonNodes; Send_AGW_R_Frame(sender); // Request Version Send_AGW_m_Frame(sender); // Request Monitor Frames } } } void QtTermTCP::ConnecttoAGW() { delete(AGWSock); AGWSock = new myTcpSocket(); connect(AGWSock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(AGWdisplayError(QAbstractSocket::SocketError))); connect(AGWSock, SIGNAL(readyRead()), this, SLOT(AGWreadyRead())); connect(AGWSock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onAGWSocketStateChanged(QAbstractSocket::SocketState))); AGWSock->connectToHost(AGWHost, AGWPortNum); Status1->setText("AGW Connecting"); return; } int AGWBeaconTimer = 0; void QtTermTCP::AGWTimer() { // Runs every 10 Seconds if (AGWConnected == 0 && AGWConnecting == 0) { AGWConnecting = true; ConnecttoAGW(); } if (AGWBeaconInterval) { AGWBeaconTimer++; if (AGWBeaconTimer >= AGWBeaconInterval * 6) { AGWBeaconTimer = 0; if (AGWConnected) doAGWBeacon(); } } } void AGW_del_socket(void * socket) { if (AGWUsers->socket == socket) { free(AGWUsers); AGWUsers = nullptr; } } void AGW_add_socket(QTcpSocket * socket) { AGWUser * User = (struct AGWUser_t *)malloc(sizeof(struct AGWUser_t)); // One Client memset(User, 0, sizeof(struct AGWUser_t)); User->socket = socket; AGWUsers = User; }; void AGWWindowClosing(Ui_ListenSession *Sess) { if (AGWUsers && AGWUsers->MonSess == Sess) AGWUsers->MonSess = NULL; } void AGW_frame_header(UCHAR * Msg, char AGWPort, char DataKind, unsigned char PID, const char * CallFrom, const char * CallTo, int Len) { struct AGWHeader * Hddr = (struct AGWHeader *)Msg; memset(Hddr, 0, sizeof(struct AGWHeader)); Hddr->Port = AGWPort; Hddr->DataLength = Len; Hddr->DataKind = DataKind; Hddr->PID = PID; strcpy(Hddr->callfrom, CallFrom); strcpy(Hddr->callto, CallTo); }; /* // AGW to APP frames UCHAR * AGW_R_Frame() { UCHAR * Msg = AGW_frame_header(0, 'R', 0, "", "", 8); // stringAdd(Msg, (UCHAR *)AGWVersion, 8); return Msg; }; */ void Send_AGW_X_Frame(QTcpSocket* socket, char * CallFrom) { UCHAR Msg[512]; AGW_frame_header(Msg, 0, 'X', 0, CallFrom, "", 0); socket->write((char *)Msg, AGWHDDRRLEN); } void Send_AGW_G_Frame(QTcpSocket* socket) { UCHAR Msg[512]; AGW_frame_header(Msg, 0, 'G', 0, "", "", 0); socket->write((char *)Msg, AGWHDDRRLEN); } void Send_AGW_m_Frame(QTcpSocket* socket) { UCHAR Msg[512]; // Request Monitoring. Add Extended form if connected to BPQ AGW_frame_header(Msg, 0, 'm', 0, "", "", 12); Msg[AGWHDDRRLEN] = AGWLocalTime; Msg[AGWHDDRRLEN + 1] = AGWMonNodes; Msg[AGWHDDRRLEN + 2] = AGWMonEnable; Msg[AGWHDDRRLEN + 3] = 0; memcpy(&Msg[AGWHDDRRLEN + 4], (void *)&AGWUsers->MonSess->portmask, 8); socket->write((char *)Msg, AGWHDDRRLEN + 12); } void Send_AGW_R_Frame(QTcpSocket* socket) { UCHAR Msg[512]; // Request Version AGW_frame_header(Msg, 0, 'R', 0, "", "", 0); socket->write((char *)Msg, AGWHDDRRLEN); } /* UCHAR * AGW_Y_Frame(int port, char * CallFrom, char *CallTo, int frame_outstanding) { UCHAR * Msg; Msg = AGW_frame_header(port, 'Y', 0, CallFrom, CallTo, 4); stringAdd(Msg, (UCHAR *)&frame_outstanding, 4); return Msg; } */ void Send_AGW_C_Frame(Ui_ListenSession * Sess, int Port, char * CallFrom, char * CallTo, char * Data, int DataLen) { UCHAR Msg[512]; char Title[64]; // We should allocate a AGW session record TAGWPort * AX25Sess; // FIrst check that we don't already have a session between these calla if (Port == -1) return; Debugprintf("Send_AGW_C_Frame"); AX25Sess = findSession(Port, CallTo, CallFrom); if (AX25Sess) { // Seems this can be called twice if (Sess->AGWSession == nullptr) QMessageBox::information(mythis, "QtTermTCP", "You already have a conenction to that call"); return; } AX25Sess = get_free_port(); if (AX25Sess) { AX25Sess->Active = 1; AX25Sess->port = Port; AX25Sess->Sess = Sess; // Crosslink AGW and Term Sessions AX25Sess->PID = 240; Sess->AGWSession = AX25Sess; strcpy(AX25Sess->mycall, CallTo); strcpy(AX25Sess->corrcall, CallFrom); AX25Sess->socket = AGWSock; if (DataLen) // Digis so use 'v' frame { AGW_frame_header(Msg, Port, 'v', 240, CallFrom, CallTo, DataLen); memcpy(&Msg[AGWHDDRRLEN], (UCHAR *)Data, DataLen); } else { AGW_frame_header(Msg, Port, 'C', 240, CallFrom, CallTo, DataLen); } DataLen += AGWHDDRRLEN; AGWSock->write((char *)Msg, DataLen); sprintf(Title, "Connecting to %s", CallTo); if (TermMode == MDI) Sess->setWindowTitle(Title); else if (TermMode == Tabbed) tabWidget->setTabText(Sess->Tab, "Connecting"); else if (TermMode == Single) mythis->setWindowTitle(Title); } } void Send_AGW_Ds_Frame(void * Sess) { TAGWPort * AGW = (TAGWPort *)Sess; UCHAR Msg[512]; AGW_frame_header(Msg, AGW->port, 'd', 240, AGW->corrcall, AGW->mycall, 0); AGW->socket->write((char *)Msg, AGWHDDRRLEN); } void Send_AGW_D_Frame(TAGWPort * AGW, UCHAR * Data, int DataLen) { UCHAR Msg[512]; AGW_frame_header(Msg, AGW->port, 'D', AGW->PID, AGW->corrcall, AGW->mycall, DataLen); memcpy(&Msg[AGWHDDRRLEN], Data, DataLen); DataLen += AGWHDDRRLEN; AGW->socket->write((char *)Msg, DataLen); } /* UCHAR * AGW_T_Frame(int port, char * CallFrom, char * CallTo, char * Data) { UCHAR * Msg; int DataLen; DataLen = strlen(Data); Msg = AGW_frame_header(port, 'T', 0, CallFrom, CallTo, DataLen); stringAdd(Msg, (byte *)Data, DataLen); return Msg; } // Raw Monitor UCHAR * AGW_K_Frame(int port, int PID, char * CallFrom, char * CallTo, UCHAR * Data, int DataLen) { UCHAR Msg[512]; DataLen = Data->Length; AGW_frame_header(Msg, port, 'K', PID, CallFrom, CallTo, DataLen); // stringAdd(Msg, Data->Data, Data->Length); // freeString(Data); return Msg; } // APP to AGW frames void on_AGW_P_frame(AGWUser * AGW) { } */ void on_AGW_G_frame(unsigned char * Data) { if (AGWPortList) free(AGWPortList); AGWPortList = (char *)strdup((char *)Data); }; /* void on_AGW_Ms_frame(AGWUser * AGW) { AGW->Monitor ^= 1; // Flip State } void on_AGW_R_frame(AGWUser * AGW) { // AGW_send_to_app(AGW->socket, AGW_R_Frame()); } void on_AGW_Y_frame(void * socket, int snd_ch, char * CallFrom, char * CallTo) { int frames; TAGWPort * AX25Sess; // AX25Sess = get_user_port_by_calls(snd_ch, CallFrom, CallTo); // if (AX25Sess) // { //frames = AX25port[snd_ch][user_port].in_data_buf.Count; // frames = AX25Sess->in_data_buf.Count + AX25Sess->I_frame_buf.Count; // ; // AGW_send_to_app(socket, AGW_Y_Frame(snd_ch, CallFrom, CallTo, frames)); // } } // UI Transmit void on_AGW_M_frame(int port, byte PID, char * CallFrom, char *CallTo, byte * Msg, int MsgLen) { byte path[80]; char Calls[80]; UCHAR * Data = newString(); stringAdd(Data, Msg, MsgLen); sprintf(Calls, "%s,%s", CallTo, CallFrom); get_addr(Calls, 0, 0, path); Add(&all_frame_buf[port], make_frame(Data, path, PID, 0, 0, U_FRM, U_UI, FALSE, SET_F, SET_C)); } */ void on_AGW_C_frame(AGWUser * AGW, struct AGWHeader * Frame, byte * Msg) { int snd_ch = Frame->Port; char * CallFrom = Frame->callfrom; char * CallTo = Frame->callto; char Title[64]; int i = 0; TAGWPort * AX25Sess; // Connection received - may be incoming or response to our connect // See if incoming if (strstr((char *)Msg, (const char *)"CONNECTED To")) { // incoming call AX25Sess = get_free_port(); if (AX25Sess) { // Look for/create Terminal Window for connection Ui_ListenSession * Sess = NULL; Ui_ListenSession * S; if (TermMode == MDI) { // See if an old session can be reused for (int i = 0; i < _sessions.size(); ++i) { S = _sessions.at(i); // for (Ui_ListenSession * S: _sessions) // { if ((S->SessionType & Listen) && S->clientSocket == NULL) { Sess = S; break; } } // Create a window if none found, else reuse old if (Sess == NULL) { Sess = newWindow((QObject *)mythis, Listen, ""); } } else { // Single or Tabbed - look for free session for (i = 0; i < _sessions.size(); ++i) { S = _sessions.at(i); if (S->clientSocket == NULL && S->AGWSession == NULL && S->KISSSession == NULL) { Sess = S; break; } } if (Sess == NULL) { // Clear connection return; } } if (Sess) { sprintf(Title, "Connected to %s", CallFrom); QApplication::alert(mythis, 0); if (TermMode == MDI) { Sess->setWindowTitle(Title); } else if (TermMode == Tabbed) { tabWidget->setTabText(i, CallFrom); tabWidget->tabBar()->setTabTextColor(i, newTabText); } else if (TermMode == Single) mythis->setWindowTitle(Title); AX25Sess->Active = 1; AX25Sess->port = snd_ch; AX25Sess->Sess = Sess; // Crosslink AGW and Term Sessions AX25Sess->PID = 240;; Sess->AGWSession = AX25Sess; strcpy(AX25Sess->mycall, CallFrom); strcpy(AX25Sess->corrcall, CallTo); AX25Sess->socket = AGW->socket; setMenus(true); if (ConnectBeep) myBeep(&ConnectWAV); // Send CText if defined if (listenCText[0]) Send_AGW_D_Frame(AX25Sess, (unsigned char *)listenCText, (int)strlen(listenCText)); // Send Message to Terminal char Msg[80]; sprintf(Msg, "Incoming AGW Connection from %s\r\r", CallFrom); WritetoOutputWindow(Sess, (unsigned char *)Msg, (int)strlen(Msg)); return; } } } // Reply to out connect request - look for our connection AX25Sess = findSession(snd_ch, CallFrom, CallTo); if (AX25Sess) { Ui_ListenSession * Sess = AX25Sess->Sess; sprintf(Title, "Connected to %s", CallFrom); if (TermMode == MDI) Sess->setWindowTitle(Title); else if (TermMode == Tabbed) tabWidget->setTabText(Sess->Tab, CallFrom); else if (TermMode == Single) mythis->setWindowTitle(Title); setMenus(true); int Len = sprintf(Title, "*** Connected to %s\r", CallFrom); ProcessReceivedData(Sess, (unsigned char *)Title, Len); } } void on_AGW_D_frame(int snd_ch, char * CallFrom, char * CallTo, byte * Msg, int Len) { TAGWPort * AX25Sess; AX25Sess = findSession(snd_ch, CallFrom, CallTo); if (AX25Sess) { ProcessReceivedData(AX25Sess->Sess, Msg, Len); } } extern "C" void WritetoMonWindow(Ui_ListenSession * Sess, unsigned char * Msg, int len); void on_AGW_Mon_frame(byte * Msg, int Len, char Type) { if (AGWUsers && AGWUsers->MonSess && AGWUsers->MonSess->monWindow) { unsigned char copy[512]; copy[0] = 0x1b; if (Type == 'T') copy[1] = 91; else copy[1] = 17; memcpy(©[2], Msg, Len); WritetoMonWindow(AGWUsers->MonSess, copy, Len + 2); } } void on_AGW_Ds_frame(int AGWChan, char * CallFrom, char * CallTo, struct AGWHeader * Frame) { TAGWPort * AX25Sess; char * Msg = (char *)Frame; Msg = &Msg[36]; char Reply[128] = ""; memcpy(Reply, Msg, Frame->DataLength); // Disconnect Sessiom AX25Sess = findSession(AGWChan, CallFrom, CallTo); if (AX25Sess) { Ui_ListenSession * Sess = AX25Sess->Sess; WritetoOutputWindowEx(Sess, (unsigned char *)Reply, (int)strlen(Reply), Sess->termWindow, &Sess->OutputSaveLen, Sess->OutputSave, WarningText); // Red if (TermMode == MDI) { if (Sess->SessionType == Mon) // Mon Only Sess->setWindowTitle("Monitor Session Disconnected"); else Sess->setWindowTitle("Disconnected"); } else if (TermMode == Tabbed) { if (Sess->SessionType == Mon) // Mon Only tabWidget->setTabText(Sess->Tab, "Monitor"); else { char Label[32]; sprintf(Label, "Sess %d", Sess->Tab + 1); tabWidget->setTabText(Sess->Tab, Label); } } else if (TermMode == Single) { if (Sess->SessionType == Mon) // Mon Only mythis->setWindowTitle("Monitor Session Disconnected"); else mythis->setWindowTitle("Disconnected"); } Sess->AGWSession = nullptr; AX25Sess->Sess = nullptr; AX25Sess->Active = 0; setMenus(false); } else { // Session not found } } void AGW_AX25_data_in(void * Sess, UCHAR * data, int Len) { TAGWPort * AX25Sess = (TAGWPort *)Sess; int len = 250, sendlen; UCHAR pkt[512]; while (Len) { if (Len > len) sendlen = len; else sendlen = Len; memcpy(pkt, data, sendlen); Len -= sendlen; memmove(data, &data[sendlen], Len); Send_AGW_D_Frame(AX25Sess, pkt, sendlen); } } /* void AGW_frame_monitor(byte snd_ch, byte * path, UCHAR * data, byte pid, byte nr, byte ns, byte f_type, byte f_id, byte rpt, byte pf, byte cr, byte RX) { char mon_frm[512]; char AGW_path[256]; UCHAR * AGW_data; const char * frm; byte * datap = data->Data; byte _data[512]; byte * p_data = _data; int _datalen; char agw_port; char CallFrom[10], CallTo[10], Digi[80]; int i; const char * ctrl; int len; AGWUser * AGW; UNUSED(rpt); len = data->Length; // if (pid == 0xCF) // data = parse_NETROM(data, f_id); // IP parsing // else if (pid == 0xCC) // data = parse_IP(data); // ARP parsing // else if (pid == 0xCD) // data = parse_ARP(data); // if (len > 0) { for (i = 0; i < len; i++) { if (datap[i] > 31 || datap[i] == 13 || datap[i] == 9) *(p_data++) = datap[i]; } } _datalen = p_data - _data; if (_datalen) { byte * ptr = _data; i = 0; // remove successive cr or cr on end while (i < _datalen) while (i < _datalen) { if ((_data[i] == 13) && (_data[i + 1] = 13)) i++; else *(ptr++) = _data[i++]; } if (*(ptr - 1) == 13) ptr--; *ptr = 0; _datalen = ptr - _data; } agw_port = snd_ch; get_monitor_path(path, CallTo, CallFrom, Digi); ctrl = ""; frm = ""; switch (f_id) { case I_I: frm = "I"; if (cr == SET_C && pf == SET_P) ctrl = " P"; break; case S_RR: frm = "RR"; if (pf == SET_P) ctrl = " P/F"; break; case S_RNR: frm = "RNR"; if (pf == SET_P) ctrl = " P/F"; break; case S_REJ: frm = "REJ"; if (pf == SET_P) ctrl = " P/F"; break; case U_SABM: frm = "SABM"; if (cr == SET_C && pf == SET_P) ctrl = " P"; break; case U_DISC: frm = "DISC"; if (cr == SET_C && pf == SET_P) ctrl = " P"; break; case U_DM: frm = "DM"; if ((cr == SET_R) && (pf == SET_P)) ctrl = " F "; break; case U_UA: frm = "UA"; if ((cr == SET_R) && (pf == SET_P)) ctrl = " F "; break; case U_FRMR: frm = "FRMR"; if ((cr == SET_R) && (pf == SET_P)) ctrl = " F "; break; case U_UI: frm = "UI"; if ((pf == SET_P)) ctrl = " P/F"; } if (Digi[0]) sprintf(AGW_path, " %d:Fm %s To %s Via %s <%s", snd_ch + 1, CallFrom, CallTo, Digi, frm); else sprintf(AGW_path, " %d:Fm %s To %s <%s", snd_ch + 1, CallFrom, CallTo, frm); switch (f_type) { case I_FRM: //mon_frm = AGW_path + ctrl + ' R' + inttostr(nr) + ' S' + inttostr(ns) + ' pid=' + dec2hex(pid) + ' Len=' + inttostr(len) + ' >' + time_now + #13 + _data + #13#13; sprintf(mon_frm, "%s%s R%d S%d pid=%X Len=%d >[%s]\r%s\r", AGW_path, ctrl, nr, ns, pid, len, ShortDateTime(), _data); break; case U_FRM: if (f_id == U_UI) { sprintf(mon_frm, "%s pid=%X Len=%d >[%s]\r%s\r", AGW_path, pid, len, ShortDateTime(), _data); // "= AGW_path + ctrl + '>' + time_now + #13; } else if (f_id == U_FRMR) { // _data = copy(_data + #0#0#0, 1, 3); // mon_frm = AGW_path + ctrl + '>' + time_now + #13 + inttohex((byte(data[1]) shl 16) or (byte(data[2]) shl 8) or byte(data[3]), 6) + #13#13; } else sprintf(mon_frm, "%s%s>[%s]\r", AGW_path, ctrl, ShortDateTime()); // "= AGW_path + ctrl + '>' + time_now + #13; break; case S_FRM: // mon_frm = AGW_path + ctrl + ' R' + inttostr(nr) + ' >' + time_now + #13; sprintf(mon_frm, "%s%s R%d>[%s]\r", AGW_path, ctrl, nr, ShortDateTime()); // "= AGW_path + ctrl + '>' + time_now + #13; break; } // stringAdd(mon_frm, "", 1); // Add 0 at the end of each frame // I think we send to all AGW sockets for (i = 0; i < AGWConCount; i++) { AGW = AGWUsers[i]; if (AGW->Monitor) { if (RX) { case f_id of I_I : AGW_data = AGW_I_frame(agw_port,CallFrom,CallTo,mon_frm); S_RR : AGW_data = AGW_S_frame(agw_port,CallFrom,CallTo,mon_frm); S_RNR : AGW_data = AGW_S_frame(agw_port,CallFrom,CallTo,mon_frm); S_REJ : AGW_data = AGW_S_frame(agw_port,CallFrom,CallTo,mon_frm); U_SABM: AGW_data = AGW_S_frame(agw_port,CallFrom,CallTo,mon_frm); U_DISC: AGW_data = AGW_S_frame(agw_port,CallFrom,CallTo,mon_frm); U_DM : AGW_data = AGW_S_frame(agw_port,CallFrom,CallTo,mon_frm); U_UA : AGW_data = AGW_S_frame(agw_port,CallFrom,CallTo,mon_frm); U_FRMR: AGW_data = AGW_S_frame(agw_port,CallFrom,CallTo,mon_frm); U_UI : AGW_data = AGW_U_frame(agw_port,CallFrom,CallTo,mon_frm); AGW_send_to_app(AGW->socket, AGW_data); } else { AGW_data = AGW_T_Frame(agw_port, CallFrom, CallTo, mon_frm); AGW_send_to_app(AGW->socket, AGW_data); } } } } */ void AGW_Process_Input(AGWUser * AGW) { struct AGWHeader * Frame = (struct AGWHeader *)AGW->data_in; byte * Data = &AGW->data_in[36]; switch (Frame->DataKind) { case 'P': // on_AGW_P_frame(AGW); // return; case 'X': // Registration response - no need to process return; case 'G': on_AGW_G_frame(Data); return; /* case 'x': on_AGW_Xs_frame(Frame->callfrom); return; case 'm': on_AGW_Ms_frame(AGW); return; case 'R': on_AGW_R_frame(AGW); return; // 'g': on_AGW_Gs_frame(AGW,Frame->Port); // 'H': on_AGW_H_frame(AGW,Frame->Port); // 'y': on_AGW_Ys_frame(AGW,Frame->Port); case 'Y': on_AGW_Y_frame(AGW->socket, Frame->Port, Frame->callfrom, Frame->callto); break; case 'M': on_AGW_M_frame(Frame->Port, Frame->PID, Frame->callfrom, Frame->callto, Data, Frame->DataLength); break; */ case 'C': // case 'v': // Call with digis on_AGW_C_frame(AGW, Frame, Data); return; case 'D': on_AGW_D_frame(Frame->Port, Frame->callfrom, Frame->callto, Data, Frame->DataLength); return; case 'd': on_AGW_Ds_frame(Frame->Port, Frame->callfrom, Frame->callto, Frame); return; case 'U': case 'S': case 'I': case 'T': // Monitor Data if (AGWMonEnable) on_AGW_Mon_frame(Data, Frame->DataLength, Frame->DataKind); return; /* // 'V': on_AGW_V_frame(AGW,Frame->Port,PID,CallFrom,CallTo,Data); // 'c': on_AGW_Cs_frame(sAGWocket,Frame->Port,PID,CallFrom,CallTo); case 'K': on_AGW_K_frame(Frame); return; case 'k': on_AGW_Ks_frame(AGW); return; */ default: Debugprintf("AGW %c", Frame->DataKind); } }