qttermtcp/AGWCode.cpp

1606 lines
30 KiB
C++

// AGW Interface
#include "QtTermTCP.h"
#include "TabDialog.h"
#include <time.h>
#include <QVBoxLayout>
#include <QLabel>
#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<Ui_ListenSession *> _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<myTcpSocket*>(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<myTcpSocket*>(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(&copy[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);
}
}