New upstream version 6.0.25.06+repack

This commit is contained in:
Hibby 2025-10-10 23:37:31 +01:00
parent 7c796758d1
commit 96ac3e4a36
27 changed files with 1097 additions and 316 deletions

View file

@ -509,6 +509,14 @@ UCHAR * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen, int DoNo
return Output;
}
if (ADJBUFFER->L2DATA[0] == 0xfe) // Paula's Nodes Poll
{
memcpy(Alias, ++ptr, 6);
Output += sprintf((char *)Output, " NODES POLL from %s\r", Alias);
return Output;
}
// Display normal NET/ROM transmissions
Output += sprintf((char *)Output, " NET/ROM\r ");

12
ARDOP.c
View file

@ -567,7 +567,7 @@ static int ProcessLine(char * buf, int Port)
}
void ARDOPThread(struct TNCINFO * TNC);
void ARDOPThread(VOID * Param);
VOID ARDOPProcessDataSocketData(int port);
int ConnecttoARDOP(struct TNCINFO * TNC);
static VOID ARDOPProcessReceivedData(struct TNCINFO * TNC);
@ -2312,12 +2312,13 @@ int ConnecttoARDOP(struct TNCINFO * TNC)
return 0;
}
VOID ARDOPThread(struct TNCINFO * TNC)
VOID ARDOPThread(VOID * Param)
{
// Opens sockets and looks for data on control and data sockets.
// Socket may be TCP/IP or Serial
struct TNCINFO * TNC = (struct TNCINFO *) Param;
char Msg[255];
int err, i, ret;
u_long param=1;
@ -5758,8 +5759,7 @@ VOID ARDOPSCSPoll(struct TNCINFO * TNC)
// Probably only for Teensy with ESP01. Runs SCS Emulator over a TCP Link
VOID SerialConnecttoTCPThread(struct TNCINFO * TNC);
VOID SerialConnecttoTCPThread(VOID * Param);
int SerialConnecttoTCP(struct TNCINFO * TNC)
{
@ -5767,9 +5767,9 @@ int SerialConnecttoTCP(struct TNCINFO * TNC)
return 0;
}
VOID SerialConnecttoTCPThread(struct TNCINFO * TNC)
VOID SerialConnecttoTCPThread(VOID * Param)
{
struct TNCINFO * TNC = (struct TNCINFO *) Param;
char Msg[255];
int i;
u_long param = 1;

268
BPQINP3.c
View file

@ -35,7 +35,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
#include <fcntl.h>
//#include "vmm.h"
uint64_t timeLoadedMS = 0;
uint64_t INP3timeLoadedMS = 0;
extern int DEBUGINP3;
VOID SendNegativeInfo();
VOID SortRoutes(struct DEST_LIST * Dest);
@ -62,8 +64,8 @@ typedef struct _RTTMSG
UCHAR ALIAS[7];
UCHAR VERSION[12];
UCHAR SWVERSION[9];
UCHAR FLAGS[10];
UCHAR PADDING[147];
UCHAR FLAGS[20];
UCHAR PADDING[137];
} RTTMSG;
@ -102,14 +104,14 @@ int RTTTimeout = 6; // 1 Min (Horizon is 1 min)
VOID InitialiseRTT()
{
UCHAR temp[sizeof(RTTMsg.FLAGS) + 4];
UCHAR temp[256] = "";
memset(&RTTMsg, ' ', sizeof(struct _RTTMSG));
memcpy(RTTMsg.ID, "L3RTT: ", 7);
memcpy(RTTMsg.VERSION, "LEVEL3_V2.1 ", 12);
memcpy(RTTMsg.SWVERSION, "BPQ32001 ", 9);
_snprintf(temp, sizeof(temp), "$M%d $N ", MAXRTT); // trailing spaces extend to ensure padding if the length of characters for MAXRTT changes.
memcpy(RTTMsg.FLAGS, temp, 10); // But still limit the actual characters copied.
memcpy(RTTMsg.SWVERSION, "BPQ32002 ", 9);
_snprintf(temp, sizeof(temp), "$M%d $N $H%d ", MAXRTT, MaxHops); // trailing spaces extend to ensure padding if the length of characters for MAXRTT changes.
memcpy(RTTMsg.FLAGS, temp, 20); // But still limit the actual characters copied.
memcpy(RTTMsg.ALIAS, &MYALIASTEXT, 6);
RTTMsg.ALIAS[6] = ' ';
}
@ -141,7 +143,7 @@ VOID DeleteINP3Routes(struct ROUTE * Route)
Call1[ConvFromAX25(Route->NEIGHBOUR_CALL, Call1)] = 0;
Debugprintf("Deleting INP3 routes via %s", Call1);
if (DEBUGINP3) Debugprintf("Deleting INP3 routes via %s", Call1);
// Delete any INP3 Dest entries via this Route
@ -177,7 +179,7 @@ VOID DeleteINP3Routes(struct ROUTE * Route)
// If we are cleaning up after a sabm on an existing link (frmr or other end reloaded) then we don't need to tell anyone - the routes should be reestablished very quickly
Debugprintf("Deleting First INP3 Route to %s", Call2);
if (DEBUGINP3) Debugprintf("Deleting First INP3 Route to %s", Call2);
if (Dest->INP3ROUTE[1].ROUT_NEIGHBOUR == 0)
{
@ -186,7 +188,7 @@ VOID DeleteINP3Routes(struct ROUTE * Route)
Dest->INP3ROUTE[0].SRTT = 60000;
Dest->INP3ROUTE[0].Hops = 255;
Debugprintf("Was the only INP3 route");
if (DEBUGINP3) Debugprintf("Was the only INP3 route");
if (Dest->DEST_ROUTE == 4) // we were using it
Dest->DEST_ROUTE = 0;
@ -206,7 +208,7 @@ VOID DeleteINP3Routes(struct ROUTE * Route)
if (Dest->INP3ROUTE[1].ROUT_NEIGHBOUR == Route)
{
Debugprintf("Deleting 2nd INP3 Route to %s", Call2);
if (DEBUGINP3) Debugprintf("Deleting 2nd INP3 Route to %s", Call2);
memcpy(&Dest->INP3ROUTE[1], &Dest->INP3ROUTE[2], sizeof(struct INP3_DEST_ROUTE_ENTRY));
memset(&Dest->INP3ROUTE[2], 0, sizeof(struct INP3_DEST_ROUTE_ENTRY));
@ -215,7 +217,7 @@ VOID DeleteINP3Routes(struct ROUTE * Route)
if (Dest->INP3ROUTE[2].ROUT_NEIGHBOUR == Route)
{
Debugprintf("Deleting 3rd INP3 Route to %s", Call2);
if (DEBUGINP3) Debugprintf("Deleting 3rd INP3 Route to %s", Call2);
memset(&Dest->INP3ROUTE[2], 0, sizeof(struct INP3_DEST_ROUTE_ENTRY));
continue;
}
@ -339,10 +341,10 @@ VOID ProcessRTTReply(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff)
Route->Timeout = 0; // Got Response
sscanf(&Buff->L4DATA[6], "%d", &OrigTime);
RTT = (GetTickCount() - timeLoadedMS) - OrigTime;
RTT = (int)((GetTickCount() - INP3timeLoadedMS) / 10 - (OrigTime)); // We work internally in mS
if (RTT > 60000)
return; // Ignore if more than 60 secs
return; // Ignore if more than 60 secs (why ??)
Route->RTT = RTT;
@ -351,11 +353,13 @@ VOID ProcessRTTReply(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff)
else
Route->SRTT = ((Route->SRTT * 80)/100) + ((RTT * 20)/100);
Route->RTTIncrement = Route->SRTT / 2; // Half for one way time.
if ((Route->Status & GotRTTResponse) == 0)
{
// Link is just starting
Debugprintf("INP3 got first RTT reply from %s - Link is (Re)staring", Normcall);
if (DEBUGINP3) Debugprintf("INP3 got first RTT reply from %s - Link is (Re)staring", Normcall);
Route->Status |= GotRTTResponse;
}
@ -374,10 +378,10 @@ VOID ProcessINP3RIF(struct ROUTE * Route, UCHAR * ptr1, int msglen, int Port)
char Normcall[10];
Normcall[ConvFromAX25(Route->NEIGHBOUR_LINK->LINKCALL, Normcall)] = 0;
Debugprintf("Processing RIF from %s INP3Node %d Route SRTT %d", Normcall, Route->INP3Node, Route->SRTT);
if (DEBUGINP3) Debugprintf("Processing RIF from %s INP3Node %d Route SRTT %d", Normcall, Route->INP3Node, Route->SRTT);
if (Route->SRTT == 0)
Debugprintf("INP3 Zero SRTT");
if (DEBUGINP3) Debugprintf("INP3 Zero SRTT");
#ifdef NOINP3
@ -403,7 +407,7 @@ VOID ProcessINP3RIF(struct ROUTE * Route, UCHAR * ptr1, int msglen, int Port)
{
if (msglen < 10)
{
Debugprintf("Corrupt INP3 Message");
if (DEBUGINP3) Debugprintf("Corrupt INP3 Message");
return;
}
@ -421,7 +425,12 @@ VOID ProcessINP3RIF(struct ROUTE * Route, UCHAR * ptr1, int msglen, int Port)
// rtt is value from remote node. Add our RTT to that node
rtt += Route->SRTT;
// if other end is old bpq then value is mS otherwise 10 mS unita
if (Route->OldBPQ)
rtt /= 10;
// rtt += Route->SRTT; // Don't do this - other end has added linkrtt
msglen -= 10;
@ -439,7 +448,7 @@ VOID ProcessINP3RIF(struct ROUTE * Route, UCHAR * ptr1, int msglen, int Port)
memcpy(alias, ptr1+2, len-2);
else
{
Debugprintf("Corrupt INP3 Message");
if (DEBUGINP3) Debugprintf("Corrupt INP3 Message");
return;
}
}
@ -477,13 +486,13 @@ VOID UpdateNode(struct ROUTE * Route, UCHAR * axcall, UCHAR * alias, int hops,
if (CompareCalls(axcall, NETROMCALL))
{
Debugprintf("INP3 for our Nodecall - discarding");
if (DEBUGINP3) Debugprintf("INP3 for our Nodecall - discarding");
return;
}
if (CheckExcludeList(axcall) == 0)
{
Debugprintf("INP3 excluded - discarding");
if (DEBUGINP3) Debugprintf("INP3 excluded - discarding");
return;
}
@ -493,7 +502,7 @@ VOID UpdateNode(struct ROUTE * Route, UCHAR * axcall, UCHAR * alias, int hops,
if (CompareCalls(axcall, APPL->APPLCALL))
{
Debugprintf("INP3 for an APPLCALL - discarding");
if (DEBUGINP3) Debugprintf("INP3 for an APPLCALL - discarding");
return;
}
}
@ -502,20 +511,20 @@ VOID UpdateNode(struct ROUTE * Route, UCHAR * axcall, UCHAR * alias, int hops,
if (hops > MaxHops && hops < 255)
{
ConvFromAX25(axcall, call);
Debugprintf("INP3 Node %s Hops %d RTT %d Ignored - Hop Count too high", call, hops, rtt);
if (DEBUGINP3) Debugprintf("INP3 Node %s Hops %d RTT %d Ignored - Hop Count too high", call, hops, rtt);
return;
}
if (rtt > MAXRTT && rtt < 60000)
{
ConvFromAX25(axcall, call);
Debugprintf("INP3 Node %s Hops %d RTT %d Ignored - rtt too high", call, hops, rtt);
if (DEBUGINP3) Debugprintf("INP3 Node %s Hops %d RTT %d Ignored - rtt too high", call, hops, rtt);
return;
}
if (rtt >= 60000)
{
Debugprintf("INP3 RTT > 60000 - discarding");
if (DEBUGINP3) Debugprintf("INP3 RTT > 60000 - discarding");
return;
}
@ -524,7 +533,7 @@ VOID UpdateNode(struct ROUTE * Route, UCHAR * axcall, UCHAR * alias, int hops,
if (Dest == NULL)
{
Debugprintf("INP3 Table Full - discarding");
if (DEBUGINP3) Debugprintf("INP3 Table Full - discarding");
return; // Table Full
}
@ -548,7 +557,7 @@ VOID UpdateNode(struct ROUTE * Route, UCHAR * axcall, UCHAR * alias, int hops,
NUMBEROFNODES++;
ConvFromAX25(Dest->DEST_CALL, call);
Debugprintf("INP3 Adding New Node %s Hops %d RTT %d", call, hops, rtt);
if (DEBUGINP3) Debugprintf("INP3 Adding New Node %s Hops %d RTT %d", call, hops, rtt);
return;
@ -556,14 +565,14 @@ Found:
if (Dest->DEST_STATE & 0x80) // Application Entry
{
Debugprintf("INP3 Application Entry - discarding");
if (DEBUGINP3) Debugprintf("INP3 Application Entry - discarding");
return;
}
// Update ALIAS
ConvFromAX25(Dest->DEST_CALL, call);
Debugprintf("INP3 Updating Node %s Hops %d RTT %d", call, hops, rtt);
if (DEBUGINP3) Debugprintf("INP3 Updating Node %s Hops %d RTT %d", call, hops, rtt);
if (alias[0] > ' ')
memcpy(Dest->DEST_ALIAS, alias, 6);
@ -574,7 +583,7 @@ Found:
if (ROUTEPTR->ROUT_NEIGHBOUR == Route)
{
Debugprintf("INP3 Already have as route[0] - updating");
if (DEBUGINP3) Debugprintf("INP3 Already have as route[0] - updating");
UpdateRoute(Dest, ROUTEPTR, hops, rtt);
return;
}
@ -583,7 +592,7 @@ Found:
if (ROUTEPTR->ROUT_NEIGHBOUR == Route)
{
Debugprintf("INP3 Already have as route[1] - updating");
if (DEBUGINP3) Debugprintf("INP3 Already have as route[1] - updating");
UpdateRoute(Dest, ROUTEPTR, hops, rtt);
return;
}
@ -592,7 +601,7 @@ Found:
if (ROUTEPTR->ROUT_NEIGHBOUR == Route)
{
Debugprintf("INP3 Already have as route[2] - updating");
if (DEBUGINP3) Debugprintf("INP3 Already have as route[2] - updating");
UpdateRoute(Dest, ROUTEPTR, hops, rtt);
return;
}
@ -608,7 +617,7 @@ Found:
{
// Add here
Debugprintf("INP3 adding as route[%d]", i);
if (DEBUGINP3) Debugprintf("INP3 adding as route[%d]", i);
AddHere(ROUTEPTR, Route, hops, rtt);
SortRoutes(Dest);
return;
@ -616,7 +625,7 @@ Found:
ROUTEPTR++;
}
Debugprintf("INP3 All entries in use - see if this is better than existing");
if (DEBUGINP3) Debugprintf("INP3 All entries in use - see if this is better than existing");
// Full, see if this is better
@ -626,7 +635,7 @@ Found:
{
// We are better. Move others down and add on front
Debugprintf("INP3 Replacing route 0");
if (DEBUGINP3) Debugprintf("INP3 Replacing route 0");
memcpy(&Dest->INP3ROUTE[2], &Dest->INP3ROUTE[1], sizeof(struct INP3_DEST_ROUTE_ENTRY));
memcpy(&Dest->INP3ROUTE[1], &Dest->INP3ROUTE[0], sizeof(struct INP3_DEST_ROUTE_ENTRY));
@ -638,7 +647,7 @@ Found:
{
// We are better. Move 2nd down and add
Debugprintf("INP3 Replacing route 1");
if (DEBUGINP3) Debugprintf("INP3 Replacing route 1");
memcpy(&Dest->INP3ROUTE[2], &Dest->INP3ROUTE[1], sizeof(struct INP3_DEST_ROUTE_ENTRY));
AddHere(&Dest->INP3ROUTE[1], Route, hops, rtt);
return;
@ -648,13 +657,13 @@ Found:
{
// We are better. Add here
Debugprintf("INP3 Replacing route 2");
if (DEBUGINP3) Debugprintf("INP3 Replacing route 2");
AddHere(&Dest->INP3ROUTE[2], Route, hops, rtt);
return;
}
Debugprintf("INP3 Worse that any existing route");
if (DEBUGINP3) Debugprintf("INP3 Worse that any existing route");
// Worse than any - ignore
@ -735,7 +744,7 @@ VOID SortRoutes(struct DEST_LIST * Dest)
if (Dest->INP3ROUTE[1].ROUT_NEIGHBOUR == 0)
{
Call1[ConvFromAX25(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call1)] = 0;
Debugprintf("INP3 1 route %d %s", Dest->INP3ROUTE[0].SRTT, Call1);
if (DEBUGINP3) Debugprintf("INP3 1 route %d %s", Dest->INP3ROUTE[0].SRTT, Call1);
return; // Only One, so cant be out of order
}
if (Dest->INP3ROUTE[2].ROUT_NEIGHBOUR == 0)
@ -745,7 +754,7 @@ VOID SortRoutes(struct DEST_LIST * Dest)
Call1[ConvFromAX25(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call1)] = 0;
Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0;
Debugprintf("INP3 2 routes %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2);
if (DEBUGINP3) Debugprintf("INP3 2 routes %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2);
if (Dest->INP3ROUTE[0].SRTT <= Dest->INP3ROUTE[1].SRTT)
return;
@ -759,7 +768,7 @@ VOID SortRoutes(struct DEST_LIST * Dest)
Call1[ConvFromAX25(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call1)] = 0;
Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0;
Debugprintf("INP3 2 routes %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2);
if (DEBUGINP3) Debugprintf("INP3 2 routes %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2);
return;
}
@ -770,7 +779,7 @@ VOID SortRoutes(struct DEST_LIST * Dest)
Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0;
Call3[ConvFromAX25(Dest->INP3ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call3)] = 0;
Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3);
if (DEBUGINP3) Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3);
// In order?
@ -791,7 +800,7 @@ VOID SortRoutes(struct DEST_LIST * Dest)
Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0;
Call3[ConvFromAX25(Dest->INP3ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call3)] = 0;
Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3);
if (DEBUGINP3) Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3);
// if 3 is better than 2 swap them. As two is worse than one. three will then be worst
@ -807,7 +816,7 @@ VOID SortRoutes(struct DEST_LIST * Dest)
Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0;
Call3[ConvFromAX25(Dest->INP3ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call3)] = 0;
Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3);
if (DEBUGINP3) Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3);
// 3 is now slowest. 2 could still be better than 1
@ -824,14 +833,14 @@ VOID SortRoutes(struct DEST_LIST * Dest)
Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0;
Call3[ConvFromAX25(Dest->INP3ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call3)] = 0;
Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3);
if (DEBUGINP3) Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3);
if (Dest->INP3ROUTE[0].SRTT <= Dest->INP3ROUTE[1].SRTT && Dest->INP3ROUTE[1].SRTT <= Dest->INP3ROUTE[2].SRTT)// In order?
return;
// Something went wrong
Debugprintf("INP3 Sort Failed");
if (DEBUGINP3) Debugprintf("INP3 Sort Failed");
}
@ -871,6 +880,8 @@ VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len
{
int OtherRTT;
int Dummy;
char * ptr;
struct _RTTMSG * RTTMsg = (struct _RTTMSG *)&Buff->L4DATA[0];
char Normcall[10];
@ -885,20 +896,40 @@ VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len
return;
}
if (Route->NEIGHBOUR_LINK->LINKPORT->ALLOWINP3)
if (Route->NEIGHBOUR_LINK->LINKPORT->ALLOWINP3 || Route->NEIGHBOUR_LINK->LINKPORT->ENABLEINP3)
Route->INP3Node = 1;
if (Route->INP3Node == 0)
{
Debugprintf("Ignoring RTT Msg from %s - not using INP3", Normcall);
if (DEBUGINP3) Debugprintf("Ignoring RTT Msg from %s - not using INP3", Normcall);
ReleaseBuffer(Buff);
return; // We don't want to use INP3
}
// Extract other end's SRTT
// Get SWVERSION to see if other end is old (Buggy) BPQ
if (memcmp(RTTMsg->SWVERSION, "BPQ32001 ", 9) == 0)
Route->OldBPQ = 1;
else
Route->OldBPQ = 0;
sscanf(&Buff->L4DATA[6], "%d %d", &Dummy, &OtherRTT);
Route->NeighbourSRTT = OtherRTT * 10; // We store in mS
Route->NeighbourSRTT = OtherRTT;
// Look for $M and $H (MAXRTT MAXHOPS)
ptr = strstr(RTTMsg->FLAGS, "$M");
if (ptr)
Route->RemoteMAXRTT = atoi(ptr + 2);
ptr = strstr(RTTMsg->FLAGS, "$H");
if (ptr)
Route->RemoteMAXHOPS = atoi(ptr + 2);
// Echo Back to sender
@ -908,20 +939,8 @@ VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len
{
// Link is just starting
Debugprintf("INP3 Processing first RTT frame from %s - link is (re)starting", Normcall);
if (DEBUGINP3) Debugprintf("INP3 Processing first RTT frame from %s - link is (re)starting", Normcall);
Route->Status |= GotRTTRequest;
// I don't think we should send RIF until we get an RTT response.
if ((Route->Status & SentRTTRequest) == 0) // Not sent one yet so send it
SendRTTMsg(Route);
// No, it's the other end that must have an rrt response and we've just sent it
Route->Status |= SentOurRIF;
SendOurRIF(Route);
SendRIPToNeighbour(Route);
}
}
@ -931,6 +950,8 @@ VOID SendRTTMsg(struct ROUTE * Route)
struct _L3MESSAGEBUFFER * Msg;
char Stamp[50];
char Normcall[10];
unsigned char temp[256];
uint64_t sendTime;
Normcall[ConvFromAX25(Route->NEIGHBOUR_CALL, Normcall)] = 0;
@ -950,13 +971,25 @@ VOID SendRTTMsg(struct ROUTE * Route)
Msg->L4TXNO = 0;
Msg->L4FLAGS = L4INFO;
// The timestamp can possibly exceed 10 digits. INP3 only works on differece between send and received, so base can be reset safely.
sendTime = ((uint64_t)GetTickCount() - INP3timeLoadedMS) / 10; // 10mS units
if (sendTime > 9999999999)
sendTime = INP3timeLoadedMS = 0;
sprintf(Stamp, "%10llu %10d %10d %10d ", sendTime, Route->SRTT, Route->RTT, 0);
sprintf(Stamp, "%10llu %10d %10d %10d ", (GetTickCount() - timeLoadedMS), Route->SRTT/10, Route->RTT/10, 0);
memcpy(RTTMsg.TXTIME, Stamp, 44);
// We now allow MAXRTT and MAXHOPS to be reconfigured so should update header each time
sprintf(temp, "$M%d $N $H%d ", MAXRTT, MaxHops); // trailing spaces extend to ensure padding if the length of characters for MAXRTT changes.
memcpy(RTTMsg.FLAGS, temp, 20); // But still limit the actual characters copied.
memcpy(Msg->L4DATA, &RTTMsg, 236);
Msg->LENGTH = 256 + 1 + 7;
Msg->LENGTH = 256 + 1 + MSGHDDRLEN;
Route->Timeout = RTTTimeout;
@ -967,7 +1000,7 @@ VOID SendRTTMsg(struct ROUTE * Route)
Route->Status |= SentRTTRequest;
Debugprintf("INP3 Sending first RTT Msg to %s", Normcall);
if (DEBUGINP3) Debugprintf("INP3 Sending first RTT Msg to %s", Normcall);
}
@ -1031,12 +1064,13 @@ int BuildRIF(UCHAR * RIF, UCHAR * Call, UCHAR * Alias, int Hops, int RTT)
RIF[12+AliasLen] = 0;
RIFLen = 13 + AliasLen;
Debugprintf("INP3 sending RIF Entry %s:%s %d %d", AliasCopy, Normcall, Hops, RTT);
if (DEBUGINP3) Debugprintf("INP3 sending RIF Entry %s:%s %d %d", AliasCopy, Normcall, Hops, RTT);
return RIFLen;
}
RIF[10] = 0;
Debugprintf("INP3 sending RIF Entry %s %d %d", Normcall, Hops, RTT);
if (DEBUGINP3) Debugprintf("INP3 sending RIF Entry %s %d %d", Normcall, Hops, RTT);
return (11);
}
@ -1057,14 +1091,18 @@ VOID SendOurRIF(struct ROUTE * Route)
Normcall[ConvFromAX25(Route->NEIGHBOUR_LINK->LINKCALL, Normcall)] = 0;
Debugprintf("INP3 Sending Initial RIF to %s ", Normcall);
if (DEBUGINP3) Debugprintf("INP3 Sending Initial RIF to %s ", Normcall);
Msg->L3SRCE[0] = 0xff;
// send a RIF for our Node and all our APPLCalls
RIFLen = BuildRIF(&Msg->L3SRCE[totLen], MYCALL, MYALIASTEXT, 1, 0);
if (Route->OldBPQ)
RIFLen = BuildRIF(&Msg->L3SRCE[totLen], MYCALL, MYALIASTEXT, 1, Route->RTTIncrement * 10);
else
RIFLen = BuildRIF(&Msg->L3SRCE[totLen], MYCALL, MYALIASTEXT, 1, Route->RTTIncrement);
totLen += RIFLen;
for (App = 0; App < NumberofAppls; App++)
@ -1073,7 +1111,11 @@ VOID SendOurRIF(struct ROUTE * Route)
if (APPL->APPLQUAL > 0)
{
RIFLen = BuildRIF(&Msg->L3SRCE[totLen], APPL->APPLCALL, APPL->APPLALIAS_TEXT, 1, 0);
if (Route->OldBPQ)
RIFLen = BuildRIF(&Msg->L3SRCE[totLen], APPL->APPLCALL, APPL->APPLALIAS_TEXT, 1, Route->RTTIncrement * 10);
else
RIFLen = BuildRIF(&Msg->L3SRCE[totLen], APPL->APPLCALL, APPL->APPLALIAS_TEXT, 1, Route->RTTIncrement);
totLen += RIFLen;
}
}
@ -1131,11 +1173,10 @@ int SendRIPTimer()
else
INP3Delay = 600;
if (Route->LastConnectAttempt &&
(REALTIMETICKS - Route->LastConnectAttempt) < INP3Delay)
if (Route->LastConnectAttempt && (REALTIMETICKS - Route->LastConnectAttempt) < INP3Delay)
{
Route++;
continue; // No room for link
continue; // Not yet
}
// Try to activate link
@ -1143,7 +1184,7 @@ int SendRIPTimer()
if (Route->INP3Node)
{
Normcall[ConvFromAX25(Route->NEIGHBOUR_CALL, Normcall)] = 0;
Debugprintf("INP3 Activating link to %s", Normcall);
if (DEBUGINP3) Debugprintf("INP3 Activating link to %s", Normcall);
}
L2SETUPCROSSLINKEX(Route, 2); // Only try SABM twice
@ -1207,7 +1248,7 @@ int SendRIPTimer()
char Call [11] = "";
ConvFromAX25(Route->NEIGHBOUR_CALL, Call);
Debugprintf("BPQ32 INP3 Neighbour %s Lost", Call);
if (DEBUGINP3) Debugprintf("BPQ32 INP3 Neighbour %s Lost", Call);
Route->Status = 0; // Down
}
@ -1222,7 +1263,7 @@ int SendRIPTimer()
}
else
{
Route->BCTimer = RTTInterval;
Route->BCTimer = RTTInterval + rand() % 4;
Route->Retries = RTTRetries;
SendRTTMsg(Route);
}
@ -1261,7 +1302,7 @@ VOID SendRIF(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Msg)
Msg->LENGTH += MSGHDDRLEN + 1; // PID
Debugprintf("Sending INP3 RIF length %d to %s", Msg->LENGTH, Normcall);
if (DEBUGINP3) Debugprintf("Sending INP3 RIF length %d to %s", Msg->LENGTH, Normcall);
SendNetFrame(Route, Msg);
}
@ -1271,10 +1312,11 @@ VOID SendRIPToOtherNeighbours(UCHAR * axcall, UCHAR * alias, struct INP3_DEST_RO
struct _L3MESSAGEBUFFER * Msg;
int count, MaxRoutes = MAXNEIGHBOURS;
char Normcall[10];
int sendHops, sendTT;
Normcall[ConvFromAX25(axcall, Normcall)] = 0;
Debugprintf("INP3 SendRIPToOtherNeighbours for %s", Normcall);
if (DEBUGINP3) Debugprintf("INP3 SendRIPToOtherNeighbours for %s", Normcall);
for (count=0; count<MaxRoutes; count++)
{
@ -1282,20 +1324,32 @@ VOID SendRIPToOtherNeighbours(UCHAR * axcall, UCHAR * alias, struct INP3_DEST_RO
(Routes->Status) &&
(Routes != Entry->ROUT_NEIGHBOUR)) // Dont send to originator of route
{
sendHops = Entry->Hops + 1;
sendTT = Entry->SRTT + Entry->ROUT_NEIGHBOUR->RTTIncrement;
// send, but only if within their constraints
if ((Routes->RemoteMAXHOPS == 0 || Routes->RemoteMAXHOPS >= Entry->Hops) &&
(Routes->RemoteMAXRTT == 0 || Routes->RemoteMAXRTT >= Entry->SRTT || Entry->SRTT == 60000))
{
Msg = Routes->Msg;
if (Msg == NULL)
{
Normcall[ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall)] = 0;
Debugprintf("INP3 Building RIF to send to %s", Normcall);
if (DEBUGINP3) Debugprintf("INP3 Building RIF to send to %s", Normcall);
Msg = Routes->Msg = CreateRIFHeader(Routes);
}
if (Msg)
{
if (Routes->OldBPQ)
Msg->LENGTH += BuildRIF(&Msg->L3SRCE[Msg->LENGTH],
axcall, alias, Entry->Hops + 1, Entry->SRTT + Entry->ROUT_NEIGHBOUR->SRTT/10);
axcall, alias, sendHops, sendTT + 10);
else
Msg->LENGTH += BuildRIF(&Msg->L3SRCE[Msg->LENGTH],
axcall, alias, sendHops, sendTT);
if (Msg->LENGTH > 250 - 15)
// if (Msg->LENGTH > Routes->NBOUR_PACLEN - 11)
@ -1305,6 +1359,7 @@ VOID SendRIPToOtherNeighbours(UCHAR * axcall, UCHAR * alias, struct INP3_DEST_RO
}
}
}
}
Routes+=1;
}
}
@ -1315,11 +1370,12 @@ VOID SendRIPToNeighbour(struct ROUTE * Route)
struct DEST_LIST * Dest = DESTS;
struct INP3_DEST_ROUTE_ENTRY * Entry;
struct _L3MESSAGEBUFFER * Msg;
int sendHops, sendTT;
char Normcall[10];
Normcall[ConvFromAX25(Route->NEIGHBOUR_LINK->LINKCALL, Normcall)] = 0;
Debugprintf("INP3 Sending Our Table to %s ", Normcall);
if (DEBUGINP3) Debugprintf("INP3 Sending Our Table to %s ", Normcall);
Dest--;
@ -1331,10 +1387,17 @@ VOID SendRIPToNeighbour(struct ROUTE * Route)
Entry = &Dest->INP3ROUTE[0];
if (Entry->ROUT_NEIGHBOUR && Entry->Hops && Route != Entry->ROUT_NEIGHBOUR)
{
// Best Route not via this neighbour - send
// Best Route not via this neighbour - send, but only if within their constraints
sendHops = Entry->Hops + 1;
sendTT = Entry->SRTT + Entry->ROUT_NEIGHBOUR->RTTIncrement;
if ((Route->RemoteMAXHOPS == 0 || Route->RemoteMAXHOPS >= Entry->Hops) &&
(Route->RemoteMAXRTT == 0 || Route->RemoteMAXRTT >= Entry->SRTT || Entry->SRTT == 60000))
{
Msg = Route->Msg;
if (Msg == NULL)
@ -1343,9 +1406,10 @@ VOID SendRIPToNeighbour(struct ROUTE * Route)
if (Msg == NULL)
return;
Msg->LENGTH += BuildRIF(&Msg->L3SRCE[Msg->LENGTH],
Dest->DEST_CALL, Dest->DEST_ALIAS,
Entry->Hops + 1, Entry->SRTT + Entry->ROUT_NEIGHBOUR->SRTT/10);
if (Route->OldBPQ)
Msg->LENGTH += BuildRIF(&Msg->L3SRCE[Msg->LENGTH], Dest->DEST_CALL, Dest->DEST_ALIAS, sendHops, sendTT * 10); // old bpq bug - send mS not 10 mS units
else
Msg->LENGTH += BuildRIF(&Msg->L3SRCE[Msg->LENGTH], Dest->DEST_CALL, Dest->DEST_ALIAS, sendHops, sendTT);
if (Msg->LENGTH > 250 - 15)
{
@ -1354,6 +1418,7 @@ VOID SendRIPToNeighbour(struct ROUTE * Route)
}
}
}
}
if (Route->Msg)
{
SendRIF(Route, Route->Msg);
@ -1368,6 +1433,15 @@ VOID FlushRIFs()
for (count=0; count<MaxRoutes; count++)
{
// Make sure we've sent our local calls
if ((Routes->Status & GotRTTRequest) && (Routes->Status & GotRTTResponse) && ((Routes->Status & SentOurRIF) == 0))
{
Routes->Status |= SentOurRIF;
SendOurRIF(Routes);
SendRIPToNeighbour(Routes);
}
if (Routes->Msg)
{
char Normcall[10];
@ -1375,7 +1449,7 @@ VOID FlushRIFs()
Normcall[ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall)] = 0;
SendRIF(Routes, Routes->Msg);
Routes->Msg = NULL;
Debugprintf("INP3 Flushing RIF to %s", Normcall);
if (DEBUGINP3) Debugprintf("INP3 Flushing RIF to %s", Normcall);
}
Routes+=1;
}
@ -1426,7 +1500,7 @@ VOID SendNegativeInfo()
{
char call[11]="";
ConvFromAX25(Dest->DEST_CALL, call);
Debugprintf("INP3 Deleting Node %s", call);
if (DEBUGINP3) Debugprintf("INP3 Deleting Node %s", call);
REMOVENODE(Dest); // Clear buffers, Remove from Sorted Nodes chain, and zap entry
}
else
@ -1585,7 +1659,9 @@ UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, unsigned int msglen)
msglen -= 10;
while (*ptr1 && msglen > 0)
// Process optional fields
while (*ptr1 && msglen > 0) // Have an option
{
len = *ptr1;
opcode = *(ptr1+1);
@ -1599,18 +1675,20 @@ UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, unsigned int msglen)
{
memcpy(&alias[6 - (len - 2)], ptr1+2, len-2); // Right Justiify
}
else
if (opcode == 1 && len < 8)
else if (opcode == 1 && len < 8)
{
memcpy(IP, ptr1+2, len-2);
}
ptr1 += len;
msglen -= len;
}
ptr2+=sprintf(ptr2, " %s:%s %d %4.2d\r", alias, call, hops, rtt);
ptr1++;
msglen--; // EOP
}
msglen--; // Over EOP
return ptr2;
}
return ptr2;
}

Binary file not shown.

View file

@ -45,6 +45,8 @@ extern VOID Q_ADD();
VOID __cdecl Debugprintf(const char * format, ...);
TRANSPORTENTRY * NRRSession;
time_t NRRTime;
/*
datagrams (and other things) to be transported in Netrom L3 frames.
@ -76,6 +78,7 @@ VOID NRRecordRoute(UCHAR * Buff, int Len)
UCHAR * BUFFER = GetBuff();
UCHAR * ptr1;
struct _MESSAGE * Msg;
time_t Now = time(NULL);
if (BUFFER == NULL)
return;
@ -84,7 +87,7 @@ VOID NRRecordRoute(UCHAR * Buff, int Len)
*ptr1++ = 0xf0; // PID
ptr1 += sprintf(ptr1, "NRR Response:");
ptr1 += sprintf(ptr1, "NRR Response in (probably) %d Secs :", (int)(Now - NRRTime));
Buff += 21 + MSGHDDRLEN;
Len -= (21 + MSGHDDRLEN);
@ -172,6 +175,7 @@ VOID SendNRRecordRoute(struct DEST_LIST * DEST, TRANSPORTENTRY * Session)
return;
NRRSession = Session; // Save Session Pointer for reply
NRRTime = time(NULL);
Msg->Port = 0;
Msg->L3PID = NRPID;

17
Bpq32.c
View file

@ -1180,7 +1180,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
// Fix processing of the Winlink API /account/exists response (82)
// Fix sending CTEXT to L4 connects to Node when FULL_CTEXT is not set
// Version 6.0.25.?
// Version 6.0.25.1 Sept 2025
// Fix 64 bit compatibility problems in SCSTracker and UZ7HO drivers
// Add Chat PACLEN config (5)
@ -1284,6 +1284,16 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
// Fix Webmail autorefresh extra threads problem (websock connection lost handling) (82)
// Fix overwriting application alias (83)
// Version 6.0.26.?
// Fix for compiling with gcc15 (2)
// Fix possble stuck L2 session caused by window being set to zero (3)
// Improvments to INP3 (4, 5)
// Add Node API /api/tcpqueues (5)
// Add sending link events to OARC API (disabled by default) (6)
#define CKernel
#include "Versions.h"
@ -1445,6 +1455,7 @@ extern HWND hIPResWnd;
extern BOOL IPMinimized;
extern int NODESINPROGRESS;
extern int NODESToOnePort;
extern VOID * CURRENTNODE;
@ -1514,7 +1525,7 @@ extern char ReportDest[7];
extern UCHAR ConfigDirectory[260];
extern uint64_t timeLoadedMS;
extern uint64_t INP3timeLoadedMS;
VOID __cdecl Debugprintf(const char * format, ...);
VOID __cdecl Consoleprintf(const char * format, ...);
@ -2403,7 +2414,7 @@ FirstInit()
EnumProcessesPtr = (FARPROCX)GetProcAddress(ExtDriver,"EnumProcesses");
}
timeLoadedMS = GetTickCount();
INP3timeLoadedMS = GetTickCount();
srand(time(NULL));

139
Cmd.c
View file

@ -73,7 +73,7 @@ int seeifInterlockneeded(struct PORTCONTROL * PORT);
int CompareNode(const void *a, const void *b);
int CompareAlias(const void *a, const void *b);
int CompareRoutes(const void * a, const void * b);
void SendVARANetromNodes(struct TNCINFO * TNC, MESSAGE *Buffer);
extern VOID KISSTX(struct KISSINFO * KISS, PMESSAGE Buffer);
@ -86,6 +86,7 @@ UCHAR SAVEDAPPLFLAGS = 0;
UCHAR ALIASINVOKED = 0;
extern int MONTOFILEFLAG;
VOID * CMDPTR = 0;
@ -155,13 +156,15 @@ char * ALIASPTR = &CMDALIAS[0][0];
extern int RigReconfigFlag;
extern int DEBUGINP3;
extern int PREFERINP3ROUTES;
struct CMDX COMMANDS[];
int CMDXLEN = sizeof (struct CMDX);
VOID SENDNODESMSG();
VOID SENDNODESMSG(int Portnum);
VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID STOPCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID STARTCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
@ -249,10 +252,81 @@ char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char
return Bufferptr + MsgLen;
}
VOID POLLNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
int Portnum = atoi(CmdTail);
struct PORTCONTROL * PORT = 0;
MESSAGE * Buffer;
UCHAR * ptr1;
if (Portnum)
PORT = GetPortTableEntryFromPortNum(Portnum);
if (Portnum == 0 || PORT == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (PORT->PORTQUALITY == 0 || PORT->INP3ONLY)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Quality = 0 or INP3 Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Buffer = GetBuff();
if (Buffer == 0)
return;
Buffer->PORT = Portnum;
memcpy(Buffer->ORIGIN, NETROMCALL, 7);
memcpy(Buffer->DEST, NODECALL, 7);
Buffer->ORIGIN[6] |= 0x61; // SET CMD END AND RESERVED BITS
Buffer->CTL = UI;
Buffer->PID = 0xCF; // Netrom
ptr1 = &Buffer->L2DATA[0];
*(ptr1++) = 0xfe; // Nodes Poll Flag
memcpy(ptr1, MYALIASTEXT, 6);
ptr1+= 6;
Buffer->LENGTH = (int)(ptr1 - (UCHAR *)Buffer);
if (PORT->TNC && PORT->TNC->Hardware == H_VARA)
SendVARANetromNodes(PORT->TNC, Buffer);
else
PUT_ON_PORT_Q(PORT, Buffer);
strcpy(Bufferptr, OKMSG);
Bufferptr += (int)strlen(OKMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID SENDNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
SENDNODESMSG();
int Portnum = atoi(CmdTail);
struct PORTCONTROL * PORT;
if (Portnum)
{
PORT = GetPortTableEntryFromPortNum(Portnum);
if (PORT == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
}
SENDNODESMSG(Portnum);
strcpy(Bufferptr, OKMSG);
Bufferptr += (int)strlen(OKMSG);
@ -1300,6 +1374,17 @@ VOID CMDL00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct C
else
Bufferptr = Cmdprintf(Session, Bufferptr, " S=%d P=%d T=%d V=%d Q=%d\r",
LINK->L2STATE, LINK->LINKPORT->PORTNUMBER, LINK->LINKTYPE, 2 - LINK->VER1FLAG, Count);
if (Count > 16 || LINK->LINKWINDOW == 0)
{
// Dump Link State
int secs = time(NULL) - LINK->LASTFRAMESENT;
Bufferptr = Cmdprintf(Session, Bufferptr, " Debug Info: LINK->LINKNS %d LINK->LINKOWS %d SDTSLOT %d LINKWINDOW %d L2FLAGS %d\r", LINK->LINKNS, LINK->LINKOWS, LINK->SDTSLOT, LINK->LINKWINDOW, LINK->L2FLAGS);
Bufferptr = Cmdprintf(Session, Bufferptr, " Debug Info: Slots %x %x %x %x %x %x %x %x\r", LINK->FRAMES[0], LINK->FRAMES[1], LINK->FRAMES[2], LINK->FRAMES[3],
LINK->FRAMES[4], LINK->FRAMES[5], LINK->FRAMES[6], LINK->FRAMES[7]);
}
}
LINK++;
}
@ -1622,8 +1707,8 @@ char * DisplayRoute(TRANSPORTENTRY * Session, char * Bufferptr, struct ROUTE *
if (Routes->INP3Node) // INP3 Enabled?
{
double srtt = Routes->SRTT/1000.0;
double nsrtt = Routes->NeighbourSRTT/1000.0;
double srtt = Routes->SRTT/100.0;
double nsrtt = Routes->NeighbourSRTT/100.0;
Bufferptr = Cmdprintf(Session, Bufferptr, " %4.2fs %4.2fs", srtt, nsrtt);
}
@ -2169,6 +2254,32 @@ VOID DoNetromConnect(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIS
return;
}
BOOL CheckLink(UCHAR * LinkCall, UCHAR * OurCall, int Port)
{
// Check if a link exists betwwn a pair of calls on a port. Return TRUE if found
struct _LINKTABLE * LINK = LINKS;
int n = MAXLINKS;
while (n--)
{
if (LINK->LINKCALL[0] == 0) // Spare
{
LINK++;
continue;
}
if ((LINK->LINKPORT->PORTNUMBER == Port) && CompareCalls(LINK->LINKCALL, LinkCall) && CompareCalls(LINK->OURCALL, OurCall))
return TRUE;
LINK++;
}
// ENTRY NOT FOUND
return FALSE;
}
BOOL FindLink(UCHAR * LinkCall, UCHAR * OurCall, int Port, struct _LINKTABLE ** REQLINK)
{
struct _LINKTABLE * LINK = LINKS;
@ -2194,6 +2305,7 @@ BOOL FindLink(UCHAR * LinkCall, UCHAR * OurCall, int Port, struct _LINKTABLE **
LINK++;
}
// ENTRY NOT FOUND - FIRSTSPARE HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL
*REQLINK = FIRSTSPARE;
@ -2388,6 +2500,9 @@ NoPort:
// Convert to an APPL command, so any alias is actioned
memcpy(Session->APPL,APPL->APPLCMD, 12);
// SEE IF THERE IS AN ALIAS DEFINDED FOR THIS COMMAND
if (APPL->APPLHASALIAS && APPL->APPLALIASVAL[0] != 0x20)
@ -2939,7 +3054,7 @@ char * DoOneNode(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIST *
if (Neighbour)
{
double srtt = Route->SRTT/1000.0;
double srtt = Route->SRTT/100.0;
len = ConvFromAX25(Neighbour->NEIGHBOUR_CALL, Normcall);
Normcall[len] = 0;
@ -2988,7 +3103,7 @@ int DoINP3ViaEntry(struct DEST_LIST * Dest, int n, char * line, int cursor)
if (Dest->INP3ROUTE[n].ROUT_NEIGHBOUR != 0)
{
srtt = Dest->INP3ROUTE[n].SRTT/1000.0;
srtt = Dest->INP3ROUTE[n].SRTT/100.0;
len=ConvFromAX25(Dest->INP3ROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Portcall);
Portcall[len]=0;
@ -4258,6 +4373,7 @@ struct CMDX COMMANDS[] =
"RIGRECONFIG ",8, &RIGRECONFIG, 0,
"RESTART ",7, &RESTART,0,
"RESTARTTNC ",10,&RESTARTTNC,0,
"POLLNODES ",8, &POLLNODES,0,
"SENDNODES ",8, &SENDNODES,0,
"EXTRESTART ",10, EXTPORTVAL, offsetof(EXTPORTDATA, EXTRESTART),
"TXDELAY ",3, PORTVAL, offsetof(PORTCONTROLX, PORTTXDELAY),
@ -4275,6 +4391,10 @@ struct CMDX COMMANDS[] =
"MAXUSERS ",4,PORTVAL, offsetof(PORTCONTROLX, USERS),
"L3ONLY ",6,PORTVAL, offsetof(PORTCONTROLX, PORTL3FLAG),
"BBSALIAS ",4,PORTVAL, offsetof(PORTCONTROLX, PORTBBSFLAG),
"INP3ONLY ",8,PORTVAL, offsetof(PORTCONTROLX, INP3ONLY),
"ALLOWINP3 ",9,PORTVAL, offsetof(PORTCONTROLX, ALLOWINP3),
"ENABLEINP3 ",10,PORTVAL, offsetof(PORTCONTROLX, ENABLEINP3),
"MONTOFILE ",9,SWITCHVAL,(size_t)&MONTOFILEFLAG,
"VALIDCALLS ",5,VALNODES,0,
"WL2KSYSOP ",5,WL2KSYSOP,0,
"STOPPORT ",4,STOPPORT,0,
@ -4286,6 +4406,7 @@ struct CMDX COMMANDS[] =
"KISS ",4,KISSCMD,0,
"GETPORTCTEXT",9,GetPortCTEXT, 0,
#ifdef EXCLUDEBITS
"EXCLUDE ",4,ListExcludedCalls,0,
@ -4310,6 +4431,10 @@ struct CMDX COMMANDS[] =
"L4DELAY ",7,SWITCHVAL,(size_t)&L4DELAY,
"L4WINDOW ",6,SWITCHVAL,(size_t)&L4DEFAULTWINDOW,
"BTINTERVAL ",5,SWITCHVAL,(size_t)&BTINTERVAL,
"DEBUGINP3 ",8,SWITCHVAL,(size_t)&DEBUGINP3,
"MAXHOPS ",7,SWITCHVAL,(size_t)&MaxHops,
"PREFERINP3 ",10,SWITCHVAL,(size_t)&PREFERINP3ROUTES,
"MAXRTT ",6,SWITCHVALW,(size_t)&MAXRTT,
"PASSWORD ", 8, PWDCMD, 0,
"************", 12, APPLCMD, 0,

View file

@ -79,6 +79,7 @@ extern VOID * ENDBUFFERPOOL;
extern int PoolBuilt;
extern int EnableOARCAPI;
// Read/Write length field in a buffer header
@ -3313,8 +3314,12 @@ SOCKADDR_IN reportdest = {0};
SOCKET ReportSocket = 0;
SOCKET NodeAPISocket = 0 ;
SOCKADDR_IN Chatreportdest = {0};
SOCKADDR_IN UDPreportdest = {0};
extern char LOCATOR[]; // Locator for Reporting - may be Maidenhead or LAT:LON
extern char MAPCOMMENT[]; // Locator for Reporting - may be Maidenhead or LAT:LON
extern char LOC[7]; // Maidenhead Locator for Reporting
@ -3670,11 +3675,16 @@ pthread_t ResolveUpdateThreadId = 0;
char NodeMapServer[80] = "update.g8bpq.net";
char ChatMapServer[80] = "chatupdate.g8bpq.net";
char NodeAPIServer[80] = "node-api.packet.oarc.uk";
int NodeAPIPort = 13579;
VOID ResolveUpdateThread(void * Unused)
{
struct hostent * HostEnt1;
struct hostent * HostEnt2;
struct hostent * HostEnt3;
ResolveUpdateThreadId = GetCurrentThreadId();
@ -3702,6 +3712,14 @@ VOID ResolveUpdateThread(void * Unused)
if (HostEnt2)
memcpy(&Chatreportdest.sin_addr.s_addr,HostEnt2->h_addr,4);
Debugprintf("Resolving %s", NodeAPIServer);
HostEnt3 = gethostbyname(NodeAPIServer);
if (HostEnt3)
memcpy(&UDPreportdest.sin_addr.s_addr,HostEnt3->h_addr,4);
if (HostEnt1 && HostEnt2)
{
Sleep(1000 * 60 * 30);
@ -3742,6 +3760,13 @@ VOID OpenReportingSockets()
ConvToAX25("DUMMY-1", ReportDest);
}
UDPreportdest.sin_family = AF_INET;
UDPreportdest.sin_port = htons(NodeAPIPort);
if (EnableOARCAPI)
NodeAPISocket = socket(AF_INET, SOCK_DGRAM, 0);
// Set up Chat Report even if no LOCATOR reportdest.sin_family = AF_INET;
// Socket must be opened in MailChat Process
@ -5194,14 +5219,14 @@ skipit:
}
}
void SendDataToPktMapThread();
void SendDataToPktMapThread(void * Param);
void SendDataToPktMap()
{
_beginthread(SendDataToPktMapThread,2048000,0);
}
void SendDataToPktMapThread()
void SendDataToPktMapThread(void * Param)
{
char Return[256] = "";
char Request[64];

View file

@ -43,8 +43,16 @@ void MQTTReportSession(char * Msg);
extern int MQTT;
int UDPSeq = 0;
extern SOCKET NodeAPISocket;
extern SOCKADDR_IN UDPreportdest;
extern char Modenames[19][10];
extern char NODECALLLOPPED[10];
// Runs use specified routine on certain event
#ifndef WIN32
@ -117,7 +125,11 @@ DllExport void APIENTRY RunEventProgram(char * Program, char * Param)
void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK)
{
// Incoming SABM
// Incoming SABM accepted
char UDPMsg[1024];
int udplen;
LINK->ConnectTime = time(NULL);
LINK->bytesTXed = LINK->bytesRXed = 0;
@ -125,7 +137,18 @@ void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _
strcpy(LINK->callingCall, remotecall);
strcpy(LINK->receivingCall, ourcall);
strcpy(LINK->Direction, "In");
if (NodeAPISocket)
{
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall);
Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
void hookL2SessionDeleted(struct _LINKTABLE * LINK)
{
@ -141,12 +164,14 @@ void hookL2SessionDeleted(struct _LINKTABLE * LINK)
else
{
char Msg[256];
char timestamp[16];
char timestamp[64];
time_t sessionTime = time(NULL) - LINK->ConnectTime;
double avBytesSent = LINK->bytesTXed / (sessionTime / 60.0);
double avBytesRXed = LINK->bytesRXed / (sessionTime / 60.0);
time_t Now = time(NULL);
struct tm * TM = localtime(&Now);
char UDPMsg[1024];
int udplen;
sprintf(timestamp, "%02d:%02d:%02d", TM->tm_hour, TM->tm_min, TM->tm_sec);
@ -164,6 +189,21 @@ void hookL2SessionDeleted(struct _LINKTABLE * LINK)
if (MQTT)
MQTTReportSession(Msg);
if (NodeAPISocket)
{
if (strcmp(LINK->Direction, "Out") == 0)
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkDownEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall);
else
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkDownEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall);
Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
LINK->ConnectTime = 0;
@ -186,6 +226,27 @@ void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _L
strcpy(LINK->Direction, "Out");
}
void hookL2SessionConnected(struct _LINKTABLE * LINK)
{
// UA received in reponse to SABM
char UDPMsg[1024];
int udplen;
if (NodeAPISocket)
{
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall);
Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
void hookL4SessionAttempt(struct STREAMINFO * STREAM, char * remotecall, char * ourcall)
{
// Outgoing Connect
@ -210,6 +271,20 @@ void hookL4SessionAccepted(struct STREAMINFO * STREAM, char * remotecall, char *
strcpy(STREAM->Direction, "In");
}
/*
{
"eventSource": "circuit",
"time": "2025-10-08T14:05:54+00:00",
"id": 23,
"direction": "incoming",
"port": "0",
"remote": "G8PZT@G8PZT:15aa",
"local": "GE8PZT:0017",
"event": "disconnect",
"@type": "event"
}
*/
void hookL4SessionDeleted(struct TNCINFO * TNC, struct STREAMINFO * STREAM)
{
char Msg[256];

View file

@ -426,7 +426,7 @@ VOID ChatExpandAndSendMessage(ChatCIRCUIT * conn, char * Msg, int LOG)
len = RemoveLF(NewMessage, (int)strlen(NewMessage));
ChatWriteLogLine(conn, '>', NewMessage, len, LOG);
ChatWriteLogLine(conn, '>', NewMessage, len, LOG_CHAT);
ChatQueueMsg(conn, NewMessage, len);
}

151
L2Code.c
View file

@ -64,7 +64,7 @@ VOID L2SENDRESPONSE(struct _LINKTABLE * LINK, int CMD);
VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD);
VOID ACKMSG(struct _LINKTABLE * LINK);
VOID InformPartner(struct _LINKTABLE * LINK, int Reason);
UINT RR_OR_RNR(struct _LINKTABLE * LINK);
UINT RR_OR_RNR(struct _LINKTABLE * LINK, int CMD);
VOID L2TIMEOUT(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT);
VOID CLEAROUTLINK(struct _LINKTABLE * LINK);
VOID SENDFRMR(struct _LINKTABLE * LINK);
@ -99,6 +99,7 @@ VOID L2SENDXID(struct _LINKTABLE * LINK);
VOID __cdecl Debugprintf(const char * format, ...);
VOID Q_IP_MSG(MESSAGE * Buffer);
VOID PROCESSNODEMESSAGE(MESSAGE * Msg, struct PORTCONTROL * PORT);
VOID PROCESSNODESPOLL(struct PORTCONTROL * PORT);
VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG);
BOOL CompareAliases(UCHAR * c1, UCHAR * c2);
VOID L2FORUS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG);
@ -120,8 +121,10 @@ int CheckKissInterlock(struct PORTCONTROL * MYPORT, int Exclusive);
void hookL2SessionAccepted(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK);
void hookL2SessionDeleted(struct _LINKTABLE * LINK);
void hookL2SessionAttempt(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK);
void hookL2SessionConnected(struct _LINKTABLE * LINK);
int L2Compressit(unsigned char * Out, int OutSize, unsigned char * In, int Len);
VOID DeleteINP3Routes(struct ROUTE * Route);
VOID SendRTTMsg(struct ROUTE * Route);
extern int REALTIMETICKS;
@ -446,6 +449,8 @@ TRYBBS:
{
ALIASMSG = 0;
strcpy(LINK->ApplName, APPL->APPLCMD);
if (CompareCalls(Buffer->DEST, APPL->APPLCALL))
goto FORUS;
@ -479,9 +484,9 @@ NOWTRY_NODES:
if (CompareCalls(Buffer->DEST, NODECALL))
{
if (Buffer->L2DATA[0] == 0xff) // Valid NODES Broadcast
{
PROCESSNODEMESSAGE(Buffer, PORT);
}
else if (Buffer->L2DATA[0] == 0xfe) // Paula's NODES Poll (request Nodes broadcast on port)
PROCESSNODESPOLL(PORT);
}
ReleaseBuffer(Buffer);
@ -808,7 +813,15 @@ VOID L2FORUS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buff
if (CTLlessPF == XID)
{
// We could possibly get an XID response if packet is badly delayed and we had timed out
if ((MSGFLAG & CMDBIT)) // Command
ProcessXIDCommand(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG);
else
{
Debugprintf("Unexpected XID response with no session");
ReleaseBuffer(Buffer); // Ignore if not
}
return;
}
@ -929,6 +942,7 @@ VOID ProcessXIDCommand(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESS
LINK->L2STATE = 1; // XID received
LINK->Ver2point2 = TRUE; // Must support 2.2 if sent XID
LINK->L2TIME = PORT->PORTT1;
LINK->LINKWINDOW = PORT->PORTWINDOW; // Just in case!
LINK->LINKPORT = PORT;
@ -1076,25 +1090,47 @@ VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
return;
}
if (CTLlessPF == XID)
{
// XID command or response on active session.
// if Command and state = 2 then other end missed XID Response. Process command again
if ((MSGFLAG & CMDBIT))
{
if (LINK->L2STATE == 2)
{
// I think we can just process as normal.
ProcessXIDCommand(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG);
return;
}
if (LINK->L2STATE == 1) // We've just sent XID so is probably XID Collision
{
// I think we can just process as normal. If we don't send a response the other end may not switch to 2.2
ProcessXIDCommand(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG);
return;
}
// XID Command on active session. Other end may be restarting. Reset session
InformPartner(LINK, NORMALCLOSE); // SEND DISC TO OTHER END
LINK->CIRCUITPOINTER = 0;
// I think it is safer to ignore it. The retry will be processed normally as XID command with no session
ReleaseBuffer(Buffer);
return;
}
// XID Response
// if Link State = 1 this is a normal response. Check it then send SABM
if (LINK->L2STATE == 1)
{
// XID State. Should be XID response if 2.2 ok or DM/FRMR if not
if (MSGFLAG & RESP)
{
if (CTLlessPF == DM || CTLlessPF == FRMR)
{
// Doesn't support XID - Send SABM
LINK->L2STATE = 2;
LINK->Ver2point2 = FALSE;
LINK->L2TIMER = 1; // Use retry to send SABM
}
else if (CTLlessPF == XID)
{
// Process response to make sure ok, Send SABM or DISC
LINK->L2STATE = 2;
LINK->Ver2point2 = TRUE;// Must support 2.2 if responded to XID
@ -1139,25 +1175,44 @@ VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
}
LINK->LINKWINDOW = PORT->PORTWINDOW; // Just in case!
LINK->L2TIMER = 1; // Use retry to send SABM
}
ReleaseBuffer(Buffer);
return;
}
// Command on existing session. Could be due to other end missing
// the XID response, so if XID just resend response
// XID response, not in state 1.
// This "shouldn't happen"
Debugprintf("Unexpected XID response, State = %d", LINK->L2STATE);
// Discard
ReleaseBuffer(Buffer);
return;
}
if (CTLlessPF == XID && (MSGFLAG & CMDBIT))
{
// XID Command on active session. Other end may be restarting. Send Response
ProcessXIDCommand(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG);
// Not XID
// if state = 1 then unexpected response to XID
if (LINK->L2STATE == 1)
{
if (CTLlessPF == DM || CTLlessPF == FRMR)
{
// Doesn't support XID - Send SABM
LINK->L2STATE = 2;
LINK->Ver2point2 = FALSE;
LINK->L2TIMER = 1; // Use retry to send SABM
ReleaseBuffer(Buffer);
return;
}
}
if (CTLlessPF == SABM)
@ -1288,6 +1343,16 @@ VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffe
Debugprintf("INP3 Incoming connect from %s", fromCall);
DeleteINP3Routes(ROUTE);
}
else
{
if (PORT->ENABLEINP3)
{
// We will offer INP3 by sending an RTT probe.
SendRTTMsg(ROUTE);
}
}
}
if (NO_CTEXT == 1)
@ -1388,6 +1453,8 @@ VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffe
return;
}
strcpy(Session->APPL, LINK->ApplName);
// NOW TRY A BBS CONNECT
// IF APPL CONNECT, SEE IF APPL HAS AN ALIAS
@ -1987,15 +2054,26 @@ VOID L2_PROCESS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * B
{
Debugprintf("INP3 Route to %s connected", fromCall);
}
else
{
if (PORT->ENABLEINP3)
{
// We will offer INP3 by sending an RTT probe.
SendRTTMsg(ROUTE);
}
}
}
hookL2SessionConnected(LINK);
SendL2ToMonMap(PORT, fromCall, '+', 'O');
LINK->L2STATE = 5;
LINK->L2TIMER = 0; // CANCEL TIMER
LINK->L2RETRIES = 0;
LINK->L2SLOTIM, T3; // SET FRAME SENT RECENTLY
LINK->L2SLOTIM = T3; // SET FRAME SENT RECENTLY
// IF VERSION 1 MSG, SET FLAG
@ -2274,7 +2352,7 @@ VOID SFRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, UCHAR CTL, UCHA
if (LINK->LAST_F_TIME + 15 > REALTIMETICKS)
return; // DISCARD
CTL = RR_OR_RNR(LINK);
CTL = RR_OR_RNR(LINK, FALSE); // Sending response
CTL |= LINK->LINKNR << 5; // SHIFT N(R) TO TOP 3 BITS
CTL |= PFBIT;
@ -2981,9 +3059,9 @@ VOID SDETX(struct _LINKTABLE * LINK)
// **** Debug code **** look for stuck links
if (LINK->LASTFRAMESENT && (time(NULL) - LINK->LASTFRAMESENT) > 60) // No send for 60 secs
if (LINK->LINKWINDOW == 0 || LINK->LASTFRAMESENT == 0 || (time(NULL) - LINK->LASTFRAMESENT) > 60) // No send for 60 secs
{
if (COUNT_AT_L2(LINK) > 16)
if (COUNT_AT_L2(LINK) > 16 || LINK->LINKWINDOW == 0)
{
// Dump Link State
@ -3316,7 +3394,7 @@ VOID L2TimerProc()
{
// Was busy
if (RR_OR_RNR(LINK) != RNR) // SEE IF STILL BUSY
if (RR_OR_RNR(LINK, 0) != RNR) // SEE IF STILL BUSY
{
// Not still busy - tell other end
@ -3432,7 +3510,7 @@ VOID SendSupervisCmd(struct _LINKTABLE * LINK)
LINK->L2ACKREQ = 0; // CLEAR ACK NEEDED
CTL = RR_OR_RNR(LINK);
CTL = RR_OR_RNR(LINK, TRUE);
// MOV L2STATE[EBX],5 ; CANCEL REJ - ACTUALLY GOING TO 'PENDING ACK'
@ -3450,7 +3528,7 @@ void SEND_RR_RESP(struct _LINKTABLE * LINK, UCHAR PF)
{
UCHAR CTL;
CTL = RR_OR_RNR(LINK);
CTL = RR_OR_RNR(LINK, FALSE);
// MOV L2STATE[EBX],5 ; CANCEL REJ - ACTUALLY GOING TO 'PENDING ACK'
@ -3801,6 +3879,7 @@ VOID L2SENDXID(struct _LINKTABLE * LINK)
if (PORT)
{
LINK->LINKWINDOW = PORT->PORTWINDOW; // Just in case!
Buffer->PORT = PORT->PORTNUMBER;
PUT_ON_PORT_Q(PORT, Buffer);
}
@ -3944,7 +4023,7 @@ VOID InformPartner(struct _LINKTABLE * LINK, int Reason)
}
UINT RR_OR_RNR(struct _LINKTABLE * LINK)
UINT RR_OR_RNR(struct _LINKTABLE * LINK, int CMD)
{
UCHAR Temp;
TRANSPORTENTRY * Session;
@ -4026,7 +4105,9 @@ stayinREJ2:
// Dont send SREJ if clearing RNR - causes FRMR
if (SaveRNRSent)
// Latest Spec says shouldn't send SREJ as Command
if (SaveRNRSent || CMD == 1)
return REJ;
if (LINK->Ver2point2) // We only allow 2.2 with SREJ Multi

View file

@ -60,6 +60,10 @@ VOID L3TRYNEXTDEST(struct ROUTE * ROUTE);
VOID SendNETROMRoute(struct PORTCONTROL * PORT, unsigned char * axcall);
void SendVARANetromNodes(struct TNCINFO * TNC, MESSAGE *Buffer);
void SendVARANetromMsg(struct TNCINFO * TNC,L3MESSAGEBUFFER * Buffer);
VOID SENDNODESMSG(int Portnum);
extern int NODESINPROGRESS;
extern int NODESToOnePort;
extern BOOL NODESINPROGRESS ;;
PPORTCONTROL L3CURRENTPORT;
@ -241,6 +245,13 @@ char Call1[10];
char Call2[10];
char Call3[10];
VOID PROCESSNODESPOLL(struct PORTCONTROL * PORT)
{
// Pauls G8BPT's request NODES Broadcast
SENDNODESMSG(PORT->PORTNUMBER);
return;
}
VOID PROCESSNODEMESSAGE(MESSAGE * Msg, struct PORTCONTROL * PORT)
{
// PROCESS A NET/ROM 'NODES' MESSAGE
@ -744,12 +755,26 @@ VOID L3BG();
VOID SENDNEXTNODESFRAGMENT();
VOID SENDNODESMSG()
VOID SENDNODESMSG(int Portnum)
{
if (NODESINPROGRESS)
return;
NODESToOnePort = Portnum;
if (Portnum) // Nodes to one port only
{
L3CURRENTPORT = GetPortTableEntryFromPortNum(Portnum);
if (L3CURRENTPORT == 0)
{
NODESToOnePort = 0;
return;
}
}
else
L3CURRENTPORT = PORTTABLE;
SENDNEXTNODESFRAGMENT();
}
@ -785,15 +810,18 @@ VOID SENDNEXTNODESFRAGMENT()
// No NODES to this port, so go to next
PORT = PORT->PORTPOINTER;
if (PORT == NULL)
if (PORT == NULL || NODESToOnePort)
{
// Finished
NODESToOnePort = 0;
NODESINPROGRESS = 0;
return;
}
}
if (NODESToOnePort == 0) // CurrentPort already set if NODESToOnePort
L3CURRENTPORT = PORT;
DEST = CURRENTNODE = DESTS; // START OF LIST
@ -851,6 +879,16 @@ VOID SENDNEXTNODESFRAGMENT()
if (DEST >= ENDDESTLIST)
{
CURRENTNODE = 0; // Finished on this port
// if sending to only one port then stop
if (NODESToOnePort)
{
NODESToOnePort = 0;
NODESINPROGRESS = 0;
}
else
{
L3CURRENTPORT = PORT->PORTPOINTER;
if (L3CURRENTPORT == NULL)
{
@ -858,6 +896,7 @@ VOID SENDNEXTNODESFRAGMENT()
NODESINPROGRESS = 0;
}
}
goto Sendit;
}
@ -1044,7 +1083,7 @@ VOID L3TimerProc()
L3TIMER = L3INTERVAL;
UPDATEDESTLIST();
SENDNODESMSG();
SENDNODESMSG(0);
}
}

View file

@ -791,7 +791,7 @@ VOID L4BG()
complen = L2Compressit(Compressed, 8192, toCompress, toCompressLen);
Debugprintf("%d %d %d%%", toCompressLen, complen, ((toCompressLen - complen) * 100) / toCompressLen);
// Debugprintf("%d %d %d%%", toCompressLen, complen, ((toCompressLen - complen) * 100) / toCompressLen);
// Send compressed
@ -826,7 +826,7 @@ VOID L4BG()
Len = ChunkSize;
complen = L2Compressit(Compressed, 8192, CompressPtr, Len);
Debugprintf("Chunked %d %d %d%%", Len, complen, ((Len - complen) * 100) / Len);
// Debugprintf("Chunked %d %d %d%%", Len, complen, ((Len - complen) * 100) / Len);
sendChunk(L4, Compressed, complen, savePort);

View file

@ -84,7 +84,7 @@ void RHPPoll();
VOID GetPGConfig();
void SendBBSDataToPktMap();
extern uint64_t timeLoadedMS;
extern uint64_t INP3timeLoadedMS;
BOOL IncludesMail = FALSE;
BOOL IncludesChat = FALSE;
@ -840,14 +840,13 @@ int main(int argc, char * argv[])
#endif
// Disable Console Terminal if stdout redirected
// printf("STDOUT %d\n",isatty(STDOUT_FILENO));
// printf("STDIN %d\n",isatty(STDIN_FILENO));
if (!isatty(STDOUT_FILENO) || !isatty(STDIN_FILENO))
Redirected = 1;
timeLoadedMS = GetTickCount();
INP3timeLoadedMS = GetTickCount();
#endif

View file

@ -691,6 +691,14 @@ char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen)
return Output;
}
if (ADJBUFFER->L2DATA[0] == 0xfe) // Paula's Nodes Poll
{
memcpy(Alias, ++ptr, 6);
Output += sprintf((char *)Output, " NODES POLL from %s\r", Alias);
return Output;
}
// Display normal NET/ROM transmissions
Output += sprintf((char *)Output, " NET/ROM\r ");
@ -985,3 +993,87 @@ char * DISPLAYARPDATAGRAM(UCHAR * Datagram, UCHAR * Output)
ptr[15], ptr[16], ptr[17], ptr[18], Dest, ptr[26], ptr[27], ptr[28], ptr[29]);
}
char Lastpacketlog[256];
int PacketLogDelay = 30000;
extern BPQVECSTRUC * FILEMONVECTOR;
extern UCHAR LogDirectory[260];
void WritePacketLogThread(void * param)
{
char FN[256];
time_t T;
struct tm * tm;
FILE * Handle;
int MsgLen;
MESSAGE * MSG;
MESSAGE * Q;
char buffer[512];
while(1)
{
BOOL SaveMTX = MTX;
BOOL SaveMCOM = MCOM;
BOOL SaveMUI = MUIONLY;
Sleep(PacketLogDelay);
// Get chain of queued packets under semaphore
GetSemaphore(&Semaphore, 101);
Q = FILEMONVECTOR->HOSTTRACEQ;
FILEMONVECTOR->HOSTTRACEQ = 0;
FreeSemaphore(&Semaphore);
if (Q == 0)
continue;
// Open log file and write decoded packets
T = time(NULL);
tm = gmtime(&T);
if (LogDirectory[0] == 0)
{
strcpy(FN, "logs/PacketLog");
}
else
{
strcpy(FN, LogDirectory);
strcat(FN, "/");
strcat(FN, "logs/PacketLog");
}
sprintf(&FN[strlen(FN)], "_%04d%02d%02d.log", tm->tm_year +1900, tm->tm_mon+1, tm->tm_mday);
Handle = fopen(FN, "ab");
if (Handle == NULL)
return;
while (Q)
{
MSG = Q;
Q = MSG->CHAIN; // get first
IntSetTraceOptionsEx(MMASK, 1, 1, 0);
MsgLen = IntDecodeFrame(MSG, buffer, MSG->Timestamp, 0xffffffffffffffff, FALSE, FALSE);
IntSetTraceOptionsEx(MMASK, SaveMTX, SaveMCOM, SaveMUI);
fwrite(buffer , 1, MsgLen, Handle);
GetSemaphore(&Semaphore, 101);
ReleaseBuffer(MSG);
FreeSemaphore(&Semaphore);
}
fclose(Handle);
}
return;
}

View file

@ -110,7 +110,7 @@ VOID ConnecttoFLRIG(struct RIGPORTINFO * PORT);
int DecodeHAMLIBAddr(struct RIGPORTINFO * PORT, char * ptr);
void ProcessHAMLIBFrame(struct RIGPORTINFO * PORT, int Length);
VOID HAMLIBPoll(struct RIGPORTINFO * PORT);
void HAMLIBSlaveThread(struct RIGINFO * RIG);
void HAMLIBSlaveThread(VOID * Param);
void CheckAndProcessRTLUDP(struct RIGPORTINFO * PORT);
VOID RTLUDPPoll(struct RIGPORTINFO * PORT);
VOID ConnecttoRTLUDP(struct RIGPORTINFO * PORT);
@ -122,8 +122,8 @@ VOID ProcessSDRRadioFrame(struct RIGPORTINFO * PORT, int Length);
VOID SDRRadioPoll(struct RIGPORTINFO * PORT);
VOID SetupPortRIGPointers();
VOID PTTCATThread(struct RIGINFO *RIG);
VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT);
VOID PTTCATThread(void * Param);
// ----- G7TAJ ----
VOID ConnecttoSDRANGEL(struct RIGPORTINFO * PORT);
@ -7484,8 +7484,9 @@ VOID SetupPortRIGPointers()
#ifdef WIN32
VOID PTTCATThread(struct RIGINFO *RIG)
VOID PTTCATThread(void * Param)
{
struct RIGINFO * RIG = (struct RIGINFO *)Param;
DWORD dwLength = 0;
int Length, ret, i;
UCHAR * ptr1;
@ -8471,7 +8472,7 @@ int DecodeHAMLIBAddr(struct RIGPORTINFO * PORT, char * ptr)
return 1;
}
VOID HAMLIBThread(struct RIGPORTINFO * PORT);
VOID HAMLIBThread(void * Param);
VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT)
{
@ -8481,10 +8482,11 @@ VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT)
return ;
}
VOID HAMLIBThread(struct RIGPORTINFO * PORT)
VOID HAMLIBThread(void * Param)
{
// Opens sockets and looks for data
struct RIGPORTINFO * PORT = (struct RIGPORTINFO * )Param;
char Msg[255];
int err, i, ret;
u_long param=1;
@ -8606,10 +8608,11 @@ Lost:
void HAMLIBSlaveThread(struct RIGINFO * RIG)
void HAMLIBSlaveThread(VOID * Param)
{
// Wait for connections and messages from HAMLIB Clients
struct RIGINFO * RIG = (struct RIGINFO *)Param;
fd_set readfs;
fd_set errorfs;
struct timeval timeout;
@ -8925,7 +8928,7 @@ VOID FLRIGSendCommand(struct RIGPORTINFO * PORT, char * Command, char * Value)
VOID FLRIGThread(struct RIGPORTINFO * PORT);
VOID FLRIGThread(VOID * Param);
VOID ConnecttoFLRIG(struct RIGPORTINFO * PORT)
{
@ -8934,10 +8937,11 @@ VOID ConnecttoFLRIG(struct RIGPORTINFO * PORT)
return ;
}
VOID FLRIGThread(struct RIGPORTINFO * PORT)
VOID FLRIGThread(VOID * Param)
{
// Opens sockets and looks for data
struct RIGPORTINFO * PORT = (struct RIGPORTINFO *)Param;
char Msg[255];
int err, i, ret;
u_long param=1;
@ -10177,7 +10181,7 @@ void ProcessSDRANGELFrame(struct RIGPORTINFO * PORT)
VOID SDRANGELThread(struct RIGPORTINFO * PORT);
VOID SDRANGELThread(VOID * Param);
VOID ConnecttoSDRANGEL(struct RIGPORTINFO * PORT)
{
@ -10186,9 +10190,11 @@ VOID ConnecttoSDRANGEL(struct RIGPORTINFO * PORT)
return ;
}
VOID SDRANGELThread(struct RIGPORTINFO * PORT)
VOID SDRANGELThread(VOID * Param)
{
// Opens sockets and looks for data
struct RIGPORTINFO * PORT = (struct RIGPORTINFO *)Param;
char Msg[512];
int err, i, ret;
u_long param=1;

View file

@ -10,15 +10,15 @@
#endif
#define KVers 6,0,25,1
#define KVerstring "6.0.25.1\0"
#define KVers 6,0,25,6
#define KVerstring "6.0.25.6\0"
#ifdef CKernel
#define Vers KVers
#define Verstring KVerstring
#define Datestring "August 2025"
#define Datestring "October 2025"
#define VerComments "G8BPQ Packet Switch (C Version)" KVerstring
#define VerCopyright "Copyright © 2001-2025 John Wiseman G8BPQ\0"
#define VerDesc "BPQ32 Switch\0"

View file

@ -64,15 +64,6 @@ extern int ENDOFDATA;
extern int L3LIVES;
extern int NUMBEROFNODES;
struct CMDX
{
char String[12]; // COMMAND STRING
UCHAR CMDLEN; // SIGNIFICANT LENGTH
// VOID (*CMDPROC)(struct _TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);// COMMAND PROCESSOR
VOID (*CMDPROC)();// COMMAND PROCESSOR
size_t CMDFLAG; // FLAG/VALUE Offset
};
struct APPLCONFIG
{
@ -231,11 +222,12 @@ typedef struct ROUTE
int LastConnectAttempt; // To stop us trying too often
int Status; //
int OldBPQ; // Set if other end is BPQ sending RIF in mS
int LastRTT; // Last Value Reported
int RTT; // Current
int SRTT; // Smoothed RTT
int NeighbourSRTT; // Other End SRTT
// int RTTIncrement; // Average of Ours and Neighbours SRTT in 10 ms
int RTTIncrement; // Average of Ours and Neighbours SRTT in 10 ms - smoothed neighbor transport time (SNTT) in spec
int BCTimer; // Time to next L3RTT Broadcast
int Timeout; // Lost Response Timer
int Retries; // Lost Response Count
@ -244,6 +236,8 @@ typedef struct ROUTE
int OtherendsRouteQual; // Route quality used by other end.
int OtherendLocked; // Route quality locked by ROUTES entry.
int FirstTimeFlag; // Set once quality has been set by direct receive
int RemoteMAXRTT; // For INP3
int RemoteMAXHOPS;
} *PROUTE;
@ -701,7 +695,8 @@ typedef struct PORTCONTROL
BOOL NormalizeQuality; // Normalise Node Qualities
BOOL IgnoreUnlocked; // Ignore Unlocked routes
BOOL INP3ONLY; // Default to INP3 and disallow NODES
BOOL ALLOWINP3;
BOOL ALLOWINP3; // Accept INP3 if offered by other end
BOOL ENABLEINP3; // Send INP3 RTT probes to discovered neighbours
void (* UIHook)(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG); // Used for KISSARQ
struct PORTCONTROL * HookPort;
@ -981,6 +976,8 @@ typedef struct _LINKTABLE
int Received;
int ReceivedAfterExpansion;
char ApplName[16];
} LINKTABLE;
@ -1472,6 +1469,16 @@ struct AXIPPORTINFO
};
struct CMDX
{
char String[12]; // COMMAND STRING
UCHAR CMDLEN; // SIGNIFICANT LENGTH
VOID (*CMDPROC)(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);// COMMAND PROCESSOR
// VOID (*CMDPROC)();// COMMAND PROCESSOR
size_t CMDFLAG; // FLAG/VALUE Offset
};
#define Disconnect(stream) SessionControl(stream,2,0)
#define Connect(stream) SessionControl(stream,1,0)

View file

@ -192,8 +192,8 @@ extern UCHAR BPQDirectory[];
extern int OffsetH, OffsetW;
static void ResolveNames(struct AXIPPORTINFO * PORT);
void OpenSockets(struct AXIPPORTINFO * PORT);
static void ResolveNames(VOID * Param);
void OpenSockets(VOID * Param);
void CloseSockets(struct AXIPPORTINFO * PORT);
@ -221,7 +221,7 @@ int KissDecode(UCHAR * inbuff, int len);
int Socket_Accept(int SocketId);
int Socket_Connect(int SocketId, int Error);
int Socket_Data(int sock, int error, int eventcode);
VOID TCPConnectThread(struct arp_table_entry * arp);
VOID TCPConnectThread(VOID * Param);
VOID __cdecl Debugprintf(const char * format, ...);
VOID __cdecl Consoleprintf(const char * format, ...);
BOOL OpenListeningSocket(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp);
@ -844,8 +844,9 @@ int InitAXIP(int Port)
return (TRUE);
}
void OpenSockets(struct AXIPPORTINFO * PORT)
void OpenSockets(void * Param)
{
struct AXIPPORTINFO * PORT = (struct AXIPPORTINFO *)Param;
char Msg[255];
int err;
u_long param=1;
@ -1528,8 +1529,9 @@ static void CreateResolverWindow(struct AXIPPORTINFO * PORT)
extern HWND hWndPopup;
static void ResolveNames(struct AXIPPORTINFO * PORT)
static void ResolveNames(VOID * Param)
{
struct AXIPPORTINFO * PORT = (struct AXIPPORTINFO *)Param;
int count = 0;
PORT->ResolveNamesThreadId = GetCurrentThreadId(); // Detect if another started
@ -2996,8 +2998,9 @@ int KissDecode(UCHAR * inbuff, int len)
return txptr;
}
VOID TCPConnectThread(struct arp_table_entry * arp)
VOID TCPConnectThread(void * Param)
{
struct arp_table_entry * arp = (struct arp_table_entry *)Param;
char Msg[255];
int err, i;
u_long param=1;

35
cMain.c
View file

@ -54,6 +54,7 @@ void MQTTTimer();
void SaveMH();
VOID InformPartner(struct _LINKTABLE * LINK, int Reason);
VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD);
void WritePacketLogThread(void * param);
#include "configstructs.h"
@ -61,6 +62,7 @@ VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD);
extern struct CONFIGTABLE xxcfg;
extern BOOL needAIS;
extern int needADSB;
extern int EnableOARCAPI;
struct PORTCONFIG * PortRec;
@ -181,6 +183,7 @@ extern VOID * ENDPOOL;
extern void * APPL_Q; // Queue of frames for APRS Appl
extern BOOL APRSActive;
extern int DEBUGINP3;
#define BPQHOSTSTREAMS 64
@ -194,9 +197,12 @@ BPQVECSTRUC * TELNETMONVECPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS];
BPQVECSTRUC * AGWMONVECPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS + 1];
BPQVECSTRUC * APRSMONVECPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS + 2];
BPQVECSTRUC * IPHOSTVECTORPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS + 3];
BPQVECSTRUC * FILEMONVECTOR = &BPQHOSTVECTOR[BPQHOSTSTREAMS + 4];
int BPQVECLENGTH = sizeof(BPQVECSTRUC);
int MONTOFILEFLAG = 0;
int NODEORDER = 0;
UCHAR LINKEDFLAG = 0;
@ -250,6 +256,8 @@ int CFLAG = 0; // C =HOST Command
VOID * IDMSG_Q = NULL; // ID/BEACONS WAITING TO BE SENT
int NODESINPROGRESS = 0;
int NODESToOnePort = 0; // Set to port num to send NODES to only one port.
VOID * CURRENTNODE = NULL; // NEXT _NODE TO SEND
VOID * DESTHEADER = NULL; // HEAD OF SORTED NODES CHAIN
@ -862,6 +870,11 @@ BOOL Start()
PREFERINP3ROUTES = cfg->C_PREFERINP3ROUTES;
if (cfg->C_DEBUGINP3)
DEBUGINP3 = 0;
EnableOARCAPI = cfg->C_OARCAPI;
if (cfg->C_OnlyVer2point0)
SUPPORT2point2 = 0;
@ -992,6 +1005,7 @@ BOOL Start()
PORT->IgnoreUnlocked = PortRec->IGNOREUNLOCKED;
PORT->INP3ONLY = PortRec->INP3ONLY;
PORT->ALLOWINP3 = PortRec->AllowINP3;
PORT->ENABLEINP3 = PortRec->EnableINP3;
PORT->PORTWINDOW = (UCHAR)PortRec->MAXFRAME;
@ -1564,6 +1578,10 @@ BOOL Start()
upnpInit();
// Start Monitor to file thread
_beginthread(WritePacketLogThread, 0, NULL);
lastSaveSecs = CurrentSecs = lastSlowSecs = time(NULL);
return 0;
@ -2514,9 +2532,9 @@ ENDOFLIST:
{
// Stuck link debug check
if (LINK->LASTFRAMESENT && (time(NULL) - LINK->LASTFRAMESENT) > 60) // No send for 60 secs
if (LINK->LINKWINDOW == 0 || LINK->LASTFRAMESENT == 0 || (time(NULL) - LINK->LASTFRAMESENT) > 60) // No send for 60 secs
{
if (COUNT_AT_L2(LINK) > 16)
if (COUNT_AT_L2(LINK) > 16 || LINK->LINKWINDOW == 0)
{
// Dump Link State
@ -2675,6 +2693,19 @@ int BPQTRACE(MESSAGE * Msg, BOOL TOAPRS)
L4++;
}
// And to the Monitor to File system.
if (MONTOFILEFLAG) // Trace Enabled?
{
Buffer = GetBuff();
if (Buffer)
{
memcpy(&Buffer->PORT, &Msg->PORT, BUFFLEN - sizeof(void *)); // Dont copy chain word
C_Q_ADD(&FILEMONVECTOR->HOSTTRACEQ, Buffer);
}
}
return TRUE;
}
;

View file

@ -49,7 +49,39 @@ Stuff to make compiling on WINDOWS and LINUX easier
int pthread_equal(pthread_t T1, pthread_t T2);
uintptr_t _beginthread(void(__cdecl *start_address)(void *), unsigned stack_size, void *arglist);
uintptr_t _beginthread(void(__cdecl start_address)(void *), unsigned stack_size, void *arglist);
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf c99_snprintf
#define vsnprintf c99_vsnprintf
__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
{
int count = -1;
if (size != 0)
count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
{
int count;
va_list ap;
va_start(ap, format);
count = c99_vsnprintf(outBuf, size, format, ap);
va_end(ap);
return count;
}
#endif
#else
@ -152,9 +184,7 @@ int stricmp(const unsigned char * pStr1, const unsigned char *pStr2);
char * strupr(char* s);
char * strlwr(char* s);
pthread_t _beginthread(void(*start_address)(), unsigned stack_size, VOID * arglist);
pthread_t _beginthread(void(start_address)(void *), unsigned stack_size, VOID * arglist);
#define WSAGetLastError() errno
#define GetLastError() errno

View file

@ -309,7 +309,7 @@ static char *keywords[] =
"LogL4Connects", "LogAllConnects", "SAVEMH", "ENABLEADIFLOG", "ENABLEEVENTS", "SAVEAPRSMSGS",
"EnableM0LTEMap", "MQTT", "MQTT_HOST", "MQTT_PORT", "MQTT_USER", "MQTT_PASS",
"L4Compress", "L4CompMaxframe", "L4CompPaclen", "L2Compress", "L2CompMaxframe",
"L2CompPaclen", "PREFERINP3ROUTES", "OnlyVer2point0"
"L2CompPaclen", "PREFERINP3ROUTES", "OnlyVer2point0", "DEBUGINP3", "ENABLEOARCAPI"
}; /* parameter keywords */
static void * offset[] =
@ -332,7 +332,7 @@ static void * offset[] =
&xxcfg.C_LogL4Connects, &xxcfg.C_LogAllConnects, &xxcfg.C_SaveMH, &xxcfg.C_ADIF, &xxcfg.C_EVENTS, &xxcfg.C_SaveAPRSMsgs,
&xxcfg.C_M0LTEMap, &xxcfg.C_MQTT, &xxcfg.C_MQTT_HOST, &xxcfg.C_MQTT_PORT, &xxcfg.C_MQTT_USER, &xxcfg.C_MQTT_PASS,
&xxcfg.C_L4Compress, &xxcfg.C_L4CompMaxframe, &xxcfg.C_L4CompPaclen, &xxcfg.C_L2Compress, &xxcfg.C_L2CompMaxframe,
&xxcfg.C_L2CompPaclen, &xxcfg.C_PREFERINP3ROUTES, &xxcfg.C_OnlyVer2point0}; /* offset for corresponding data in config file */
&xxcfg.C_L2CompPaclen, &xxcfg.C_PREFERINP3ROUTES, &xxcfg.C_OnlyVer2point0, &xxcfg.C_DEBUGINP3, &xxcfg.C_OARCAPI}; /* offset for corresponding data in config file */
static int routine[] =
{
@ -354,7 +354,7 @@ static int routine[] =
2, 2, 1, 2, 2, 2,
2, 2, 0, 1, 20, 20,
1, 1, 1, 1, 1,
1, 1, 1} ; // Routine to process param
1, 1, 1, 1, 1}; // Routine to process param
int PARAMLIM = sizeof(routine)/sizeof(int);
//int NUMBEROFKEYWORDS = sizeof(routine)/sizeof(int);
@ -376,7 +376,7 @@ static char *pkeywords[] =
"BCALL", "DIGIMASK", "NOKEEPALIVES", "COMPORT", "DRIVER", "WL2KREPORT", "UIONLY",
"UDPPORT", "IPADDR", "I2CBUS", "I2CDEVICE", "UDPTXPORT", "UDPRXPORT", "NONORMALIZE",
"IGNOREUNLOCKEDROUTES", "INP3ONLY", "TCPPORT", "RIGPORT", "PERMITTEDAPPLS", "HIDE",
"SMARTID", "KISSCOMMAND", "SendtoM0LTEMap", "PortFreq", "M0LTEMapInfo", "QTSMPort", "ALLOWINP3"}; /* parameter keywords */
"SMARTID", "KISSCOMMAND", "SendtoM0LTEMap", "PortFreq", "M0LTEMapInfo", "QTSMPort", "ALLOWINP3", "ENABLEINP3"}; /* parameter keywords */
static void * poffset[] =
{
@ -390,7 +390,7 @@ static void * poffset[] =
&xxp.BCALL, &xxp.DIGIMASK, &xxp.DefaultNoKeepAlives, &xxp.IOADDR, &xxp.DLLNAME, &xxp.WL2K, &xxp.UIONLY,
&xxp.IOADDR, &xxp.IPADDR, &xxp.INTLEVEL, &xxp.IOADDR, &xxp.IOADDR, &xxp.ListenPort, &xxp.NoNormalize,
&xxp.IGNOREUNLOCKED, &xxp.INP3ONLY, &xxp.TCPPORT, &xxp.RIGPORT, &xxp.PERMITTEDAPPLS, &xxp.Hide,
&xxp.SmartID, &xxp.KissParams, &xxp.SendtoM0LTEMap, &xxp.PortFreq, &xxp.M0LTEMapInfo, &xxp.QtSMPort, &xxp.AllowINP3}; /* offset for corresponding data in config file */
&xxp.SmartID, &xxp.KissParams, &xxp.SendtoM0LTEMap, &xxp.PortFreq, &xxp.M0LTEMapInfo, &xxp.QtSMPort, &xxp.AllowINP3, &xxp.EnableINP3}; /* offset for corresponding data in config file */
static int proutine[] =
{
@ -404,7 +404,7 @@ static int proutine[] =
0, 1, 2, 18, 15, 16, 2,
1, 17, 1, 1, 1, 1, 2,
2, 2, 1, 1, 19, 2,
1, 20, 1, 21, 22, 1, 1}; /* routine to process parameter */
1, 20, 1, 21, 22, 1, 1, 1}; /* routine to process parameter */
int PPARAMLIM = sizeof(proutine)/sizeof(int);
@ -601,7 +601,6 @@ BOOL ProcessConfig()
for (i=0;i<24;i++)
paramok[45+i]=1; /* or APPLCALLS, APPLALIASS APPLQUAL */
paramok[69]=1; // BText optional
@ -630,7 +629,9 @@ BOOL ProcessConfig()
paramok[90]=1; // L2Compress Maxframe
paramok[91]=1; // L2Compress Paclen
paramok[92]=1; // PREFERINP3ROUTES
paramok[93]=1; // C_ONLYVer2point0
paramok[93]=1; // ONLYVer2point0
paramok[94]=1; // DEBUGINP3
paramok[95]=1; // EnableOARCAPI
for (i=0; i < PARAMLIM; i++)
{

View file

@ -82,6 +82,7 @@ struct PORTCONFIG
char * M0LTEMapInfo;
int QtSMPort;
int AllowINP3;
int EnableINP3;
};
struct ROUTECONFIG
@ -179,6 +180,8 @@ struct CONFIGTABLE
int C_L2CompPaclen;
int C_PREFERINP3ROUTES;
int C_OnlyVer2point0;
int C_DEBUGINP3;
int C_OARCAPI;
//#define ApplOffset 80000 // Applications offset in config buffer

View file

@ -35,6 +35,9 @@ int RFOnly = 0;
int MAXRTT = 9000; // 90 secs
int MaxHops = 4;
int DEBUGINP3 = 0;
int EnableOARCAPI = 0;
int RTTInterval = 24; // 4 Minutes

10
kiss.c
View file

@ -1905,7 +1905,7 @@ int i2cPoll(struct PORTCONTROL * PORT, NPASYINFO npKISSINFO)
// KISS Over TCP Routines
VOID ConnecttoTCPThread(NPASYINFO ASY);
VOID ConnecttoTCPThread(void * Param);
int ConnecttoTCP(NPASYINFO ASY)
{
@ -1914,8 +1914,9 @@ int ConnecttoTCP(NPASYINFO ASY)
return 0;
}
VOID ConnecttoTCPThread(NPASYINFO ASY)
VOID ConnecttoTCPThread(void * Param)
{
NPASYINFO ASY = (NPASYINFO)Param;
char Msg[255];
int err,i;
u_long param=1;
@ -2131,7 +2132,7 @@ int KISSGetTCPMessage(NPASYINFO ASY)
// Interface to QtSM Managmemt Interface
VOID QtSMThread(struct PORTCONTROL * PORT);
VOID QtSMThread(void * Param);
VOID ConnecttoQtSM(struct PORTCONTROL * PORT)
{
@ -2141,11 +2142,12 @@ VOID ConnecttoQtSM(struct PORTCONTROL * PORT)
return ;
}
VOID QtSMThread(struct PORTCONTROL * PORT)
VOID QtSMThread(void * Param)
{
// This is the Managemt Interface in QtSM. It receives PTT ON/OFF msgs from QtSM and allows changing modem mode and freq.
// Also will collect link usage stats
struct PORTCONTROL * PORT = (struct PORTCONTROL *)Param;
char Msg[255];
int err, i, ret;
u_long param = 1;

View file

@ -852,14 +852,14 @@ double LatFromLOC = 0;
double LonFromLOC = 0;
#endif
void SendBBSDataToPktMapThread();
void SendBBSDataToPktMapThread(void * Param);
void SendBBSDataToPktMap()
{
_beginthread(SendBBSDataToPktMapThread, 0, 0);
}
void SendBBSDataToPktMapThread()
void SendBBSDataToPktMapThread(void * Param)
{
char Request[64];
char * Params;

158
nodeapi.c
View file

@ -9,6 +9,7 @@
#include <stdlib.h>
#include "tncinfo.h"
#include "asmstrucs.h"
#include "telnetserver.h"
#include "kiss.h"
// Constants
@ -56,6 +57,7 @@ int sendUserList(char * response, char * token, char * Rest, int Local);
int sendInfo(char * response, char * token, char * Rest, int Local);
int sendLinks(char * response, char * token, char * Rest, int Local);
int sendPortMHList(char * response, char * token, char * Rest, int Local);
int sendPortQState(char * response, char * token, char * Rest, int Local);
int sendWhatsPacState(char * response, char * token, char * param, int Local);
int sendWhatsPacConfig(char * response, char * token, char * param, int Local);
@ -74,6 +76,7 @@ struct API APIList[] =
"/api/links", 10, sendLinks, 0,
"/api/users", 10, sendUserList, 0,
"/api/mheard", 11, sendPortMHList, 0,
"/api/tcpqueues", 14, sendPortQState, 0,
"/api/v1/config", 14, sendWhatsPacConfig, AuthSysop,
"/api/v1/state", 13, sendWhatsPacState, AuthSysop
};
@ -827,9 +830,164 @@ int sendPortMHList(char * response, char * token, char * param, int Local)
strcat(response, "\r\n]}\r\n");
// printf("MH for port %d:\r\n%s\r\n", PORTVEC->PORTNUMBER, response);
}
return strlen(response);
}
int sendPortQState(char * response, char * token, char * param, int Local)
{
struct TNCINFO * TNC;
struct TCPINFO * TCP;
struct ConnectionInfo * Conn;
struct STREAMINFO * STREAM;
int Stream;
int tcpqueue;
int Queued;
int n;
int port = 0;
char Type[10];
char Appl[20];
int radioport = 0;
if (param[0] = '?' || param[0] == '/')
port = atoi(&param[1]);
TNC = TNCInfo[port];
// At the moment only supports Telnet Ports
if (TNC == 0 || TNC->Hardware != H_TELNET)
return send_http_response(response, "401 Invalid API Call");
response[0] = 0;
TCP = TNC->TCPInfo;
if (TCP == 0)
return send_http_response(response, "401 Invalid API Call");
n = sprintf(response,"{\"QState\":[\r\n");
for (Stream = 0; Stream <= TCP->MaxSessions; Stream++)
{
char Call[10];
STREAM = &TNC->Streams[Stream];
Conn = TNC->Streams[Stream].ConnectionInfo;
// if connected to the node
if (Conn->SocketActive)
{
TRANSPORTENTRY * Sess1 = TNC->PortRecord->ATTACHEDSESSIONS[Stream];
TRANSPORTENTRY * Sess2 = NULL;
if (Sess1)
Sess2 = Sess1->L4CROSSLINK;
else
continue;
radioport = 0;
// Can't use TXCount - it is Semaphored=
Queued = C_Q_COUNT(&TNC->Streams[Stream].PACTORtoBPQ_Q);
Queued += C_Q_COUNT((UINT *)&TNC->PortRecord->PORTCONTROL.PORTRX_Q);
if (Sess2)
Queued += CountFramesQueuedOnSession(Sess2);
if (Sess1)
Queued += CountFramesQueuedOnSession(Sess1);
// CountFramesQueuedOnSession(TRANSPORTENTRY * Session)
tcpqueue = Conn->FromHostBuffPutptr - Conn->FromHostBuffGetptr;
if (Sess2)
Sess1 = Sess2;
Call[ConvFromAX25(Sess1->L4USER, Call)] = 0;
if (Sess1->L4CIRCUITTYPE & BPQHOST)
strcpy(Type, "Host");
else if (Sess1->L4CIRCUITTYPE & SESSION)
{
struct DEST_LIST * DEST = Sess1->L4TARGET.DEST;
strcpy(Type, "NETROM");
if (DEST)
{
int ActiveRoute = DEST->DEST_ROUTE;
if (ActiveRoute)
{
struct ROUTE * ROUTE = DEST->NRROUTE[ActiveRoute - 1].ROUT_NEIGHBOUR;
if (ROUTE)
{
struct _LINKTABLE * LINK = ROUTE->NEIGHBOUR_LINK;
if (LINK && LINK->LINKPORT)
radioport = LINK->LINKPORT->PORTNUMBER;
}
}
}
}
else if (Sess1->L4CIRCUITTYPE & PACTOR)
{
// PACTOR Type - Frames are queued on the Port Entry
struct PORTCONTROL * PORT = Sess1->L4TARGET.PORT;
strcpy(Type, "HFLINK");
if (PORT)
radioport = PORT->PORTNUMBER;
}
else
{
struct _LINKTABLE * LINK = Sess1->L4TARGET.LINK;
strcpy(Type, "L2 Link");
if (LINK && LINK->LINKPORT)
radioport = LINK->LINKPORT->PORTNUMBER;
}
memcpy(Appl, Sess1->APPL, 16);
strlop(Appl, ' ');
n += sprintf(&response[n], "{\"APPL\": \"%s\", \"callSign\": \"%s\", \"type\": \"%s\", \"tcpqueue\": %d, \"packets\": %d, \"port\": %d},\r\n" , Appl, Call, Type, tcpqueue, Queued, radioport);
}
}
if (n < 20) // No entries
{
response[strlen(response) - 2] = '\0'; // remove \r\n
strcat(response, "]}\r\n");
}
else
{
response[strlen(response)-3 ] = '\0'; // remove ,\r\n
strcat(response, "\r\n]}\r\n");
// printf("MH for port %d:\r\n%s\r\n", PORTVEC->PORTNUMBER, response);
}
return strlen(response);
}
// WhatsPac configuration interface
// WhatsPac also uses Paula's Remote Host Protocol (RHP). This is in a separate module