diff --git a/AGWMoncode.c b/AGWMoncode.c index da9f81e..b4e0451 100644 --- a/AGWMoncode.c +++ b/AGWMoncode.c @@ -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 "); diff --git a/ARDOP.c b/ARDOP.c index ade0ecf..048c67f 100644 --- a/ARDOP.c +++ b/ARDOP.c @@ -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; diff --git a/BPQINP3.c b/BPQINP3.c index a62ecba..b1f79bc 100644 --- a/BPQINP3.c +++ b/BPQINP3.c @@ -35,7 +35,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include //#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. - sprintf(Stamp, "%10llu %10d %10d %10d ", (GetTickCount() - timeLoadedMS), Route->SRTT/10, Route->RTT/10, 0); + 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); + 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; countStatus) && (Routes != Entry->ROUT_NEIGHBOUR)) // Dont send to originator of route { - Msg = Routes->Msg; - - if (Msg == NULL) - { - Normcall[ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall)] = 0; - Debugprintf("INP3 Building RIF to send to %s", Normcall); - Msg = Routes->Msg = CreateRIFHeader(Routes); - } + sendHops = Entry->Hops + 1; + sendTT = Entry->SRTT + Entry->ROUT_NEIGHBOUR->RTTIncrement; - if (Msg) + // 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->LENGTH += BuildRIF(&Msg->L3SRCE[Msg->LENGTH], - axcall, alias, Entry->Hops + 1, Entry->SRTT + Entry->ROUT_NEIGHBOUR->SRTT/10); + Msg = Routes->Msg; - if (Msg->LENGTH > 250 - 15) -// if (Msg->LENGTH > Routes->NBOUR_PACLEN - 11) + if (Msg == NULL) { - SendRIF(Routes, Msg); - Routes->Msg = NULL; + Normcall[ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall)] = 0; + 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, 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) + { + SendRIF(Routes, Msg); + Routes->Msg = NULL; + } } } } @@ -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,26 +1387,35 @@ 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 - - Msg = Route->Msg; - - if (Msg == NULL) - Msg = Route->Msg = CreateRIFHeader(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); + // Best Route not via this neighbour - send, but only if within their constraints - if (Msg->LENGTH > 250 - 15) + 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)) { - SendRIF(Route, Msg); - Route->Msg = NULL; + Msg = Route->Msg; + + if (Msg == NULL) + Msg = Route->Msg = CreateRIFHeader(Route); + + if (Msg == NULL) + return; + + 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) + { + SendRIF(Route, Msg); + Route->Msg = NULL; + } } } } @@ -1368,6 +1433,15 @@ VOID FlushRIFs() for (count=0; countStatus & 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) - { - memcpy(IP, ptr1+2, len-2); - } - ptr2+=sprintf(ptr2, " %s:%s %d %4.2d\r", alias, call, hops, rtt); + else if (opcode == 1 && len < 8) + { + memcpy(IP, ptr1+2, len-2); + } - ptr1++; - msglen--; // EOP + ptr1 += len; + msglen -= len; } - return ptr2; + ptr2+=sprintf(ptr2, " %s:%s %d %4.2d\r", alias, call, hops, rtt); + + ptr1++; + msglen--; // Over EOP + } return ptr2; } diff --git a/BPQMail.aps b/BPQMail.aps index 96bcae6..b3373cd 100644 Binary files a/BPQMail.aps and b/BPQMail.aps differ diff --git a/BPQNRR.c b/BPQNRR.c index 7a54777..b557e2f 100644 --- a/BPQNRR.c +++ b/BPQNRR.c @@ -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; diff --git a/Bpq32.c b/Bpq32.c index a7a6627..61078a0 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -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" @@ -1444,7 +1454,8 @@ extern char MYCALL[]; // 7 chars, ax.25 format extern HWND hIPResWnd; extern BOOL IPMinimized; -extern int NODESINPROGRESS; +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)); diff --git a/Cmd.c b/Cmd.c index 70a061e..d53d65d 100644 --- a/Cmd.c +++ b/Cmd.c @@ -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, diff --git a/CommonCode.c b/CommonCode.c index 9c0032d..4129429 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -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]; diff --git a/Events.c b/Events.c index fdbb96b..c64210d 100644 --- a/Events.c +++ b/Events.c @@ -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,8 +137,19 @@ 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) { // calculate session time and av bytes/min in and out @@ -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]; diff --git a/HanksRT.c b/HanksRT.c index 8831faa..c828fd5 100644 --- a/HanksRT.c +++ b/HanksRT.c @@ -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); } diff --git a/L2Code.c b/L2Code.c index 0fd8ecd..c0da433 100644 --- a/L2Code.c +++ b/L2Code.c @@ -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; @@ -445,6 +448,8 @@ TRYBBS: if ((PORT->PERMITTEDAPPLS & APPLMASK) != 0) { 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) { - ProcessXIDCommand(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG); + // 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,87 +1090,128 @@ VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * return; } - - if (LINK->L2STATE == 1) + if (CTLlessPF == XID) { - // XID State. Should be XID response if 2.2 ok or DM/FRMR if not + // XID command or response on active session. + + // if Command and state = 2 then other end missed XID Response. Process command again - if (MSGFLAG & RESP) + if ((MSGFLAG & CMDBIT)) { - if (CTLlessPF == DM || CTLlessPF == FRMR) + if (LINK->L2STATE == 2) { - // Doesn't support XID - Send SABM + // I think we can just process as normal. - LINK->L2STATE = 2; - LINK->Ver2point2 = FALSE; - LINK->L2TIMER = 1; // Use retry to send SABM + ProcessXIDCommand(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG); + return; } - else if (CTLlessPF == XID) + + if (LINK->L2STATE == 1) // We've just sent XID so is probably XID Collision { - // Process response to make sure ok, Send SABM or DISC + // I think we can just process as normal. If we don't send a response the other end may not switch to 2.2 - LINK->L2STATE = 2; - LINK->Ver2point2 = TRUE;// Must support 2.2 if responded to XID - - // if Compress enabled set it - - ptr = &ADJBUFFER->PID; - - if (*ptr++ == 0x82 && *ptr++ == 0x80) - { - int Type; - int Len; - unsigned int value; - int xidlen = *(ptr++) << 8; - xidlen += *ptr++; - - // XID is set of Type, Len, Value n-tuples - - while (xidlen > 0) - { - Type = *ptr++; - Len = *ptr++; - - value = 0; - xidlen -= (Len + 2); - - while (Len--) - { - value <<=8; - value += *ptr++; - } - switch(Type) - { - case 17: - - // Compression - - if (L2Compress) - LINK->AllowCompress = 1; - - } - } - - } - - LINK->L2TIMER = 1; // Use retry to send SABM + 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; } - - // Command on existing session. Could be due to other end missing - // the XID response, so if XID just resend response + // XID Response + + // if Link State = 1 this is a normal response. Check it then send SABM + + if (LINK->L2STATE == 1) + { + LINK->L2STATE = 2; + LINK->Ver2point2 = TRUE;// Must support 2.2 if responded to XID + + // if Compress enabled set it + + ptr = &ADJBUFFER->PID; + + if (*ptr++ == 0x82 && *ptr++ == 0x80) + { + int Type; + int Len; + unsigned int value; + int xidlen = *(ptr++) << 8; + xidlen += *ptr++; + + // XID is set of Type, Len, Value n-tuples + + while (xidlen > 0) + { + Type = *ptr++; + Len = *ptr++; + + value = 0; + xidlen -= (Len + 2); + + while (Len--) + { + value <<=8; + value += *ptr++; + } + switch(Type) + { + case 17: + + // Compression + + if (L2Compress) + LINK->AllowCompress = 1; + + } + } + + } + + LINK->LINKWINDOW = PORT->PORTWINDOW; // Just in case! + LINK->L2TIMER = 1; // Use retry to send SABM + + ReleaseBuffer(Buffer); + return; + } + + // 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); - return; + // 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; + } } @@ -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 @@ -3375,7 +3453,7 @@ VOID L2TimerProc() { SendSupervisCmd(LINK); LINK++; - continue; + continue; } } @@ -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 diff --git a/L3Code.c b/L3Code.c index 7c1d5b8..22b46fb 100644 --- a/L3Code.c +++ b/L3Code.c @@ -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; - L3CURRENTPORT = PORTTABLE; + NODESToOnePort = Portnum; + + if (Portnum) // Nodes to one port only + { + L3CURRENTPORT = GetPortTableEntryFromPortNum(Portnum); + + if (L3CURRENTPORT == 0) + { + NODESToOnePort = 0; + return; + } + } + else + L3CURRENTPORT = PORTTABLE; + SENDNEXTNODESFRAGMENT(); } @@ -785,16 +810,19 @@ 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; } } - L3CURRENTPORT = PORT; + if (NODESToOnePort == 0) // CurrentPort already set if NODESToOnePort + L3CURRENTPORT = PORT; DEST = CURRENTNODE = DESTS; // START OF LIST NODESINPROGRESS = 1; @@ -851,13 +879,24 @@ VOID SENDNEXTNODESFRAGMENT() if (DEST >= ENDDESTLIST) { CURRENTNODE = 0; // Finished on this port - L3CURRENTPORT = PORT->PORTPOINTER; - if (L3CURRENTPORT == NULL) - { - // Finished + // if sending to only one port then stop + + if (NODESToOnePort) + { + NODESToOnePort = 0; NODESINPROGRESS = 0; } + else + { + L3CURRENTPORT = PORT->PORTPOINTER; + if (L3CURRENTPORT == NULL) + { + // Finished + + NODESINPROGRESS = 0; + } + } goto Sendit; } @@ -1044,7 +1083,7 @@ VOID L3TimerProc() L3TIMER = L3INTERVAL; UPDATEDESTLIST(); - SENDNODESMSG(); + SENDNODESMSG(0); } } diff --git a/L4Code.c b/L4Code.c index f6fdb79..5416a17 100644 --- a/L4Code.c +++ b/L4Code.c @@ -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); diff --git a/LinBPQ.c b/LinBPQ.c index 689b5f4..acd5c23 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -84,7 +84,7 @@ void RHPPoll(); VOID GetPGConfig(); void SendBBSDataToPktMap(); -extern uint64_t timeLoadedMS; +extern uint64_t INP3timeLoadedMS; BOOL IncludesMail = FALSE; BOOL IncludesChat = FALSE; @@ -839,15 +839,14 @@ int main(int argc, char * argv[]) #endif #endif - // Disable Console Terminal if stdout redirected - +// 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 diff --git a/Moncode.c b/Moncode.c index b539f1f..5857655 100644 --- a/Moncode.c +++ b/Moncode.c @@ -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; +} + diff --git a/RigControl.c b/RigControl.c index 279f085..2b268c0 100644 --- a/RigControl.c +++ b/RigControl.c @@ -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; diff --git a/Versions.h b/Versions.h index ccf1ddd..8b75625 100644 --- a/Versions.h +++ b/Versions.h @@ -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" diff --git a/asmstrucs.h b/asmstrucs.h index 968f5fb..d22ecae 100644 --- a/asmstrucs.h +++ b/asmstrucs.h @@ -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 { @@ -230,12 +221,13 @@ typedef struct ROUTE BOOL NoKeepAlive; // Suppress Keepalive Processing int LastConnectAttempt; // To stop us trying too often - int Status; // + 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) diff --git a/bpqaxip.c b/bpqaxip.c index d5afb62..3491bbd 100644 --- a/bpqaxip.c +++ b/bpqaxip.c @@ -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); @@ -692,7 +692,7 @@ static size_t ExtProc(int fn, int port, PMESSAGE buff) else Consoleprintf("Failed to reread config file - leaving config unchanged"); - _beginthread(OpenSockets, 0, PORT ); + _beginthread(OpenSockets, 0, PORT); GetAXIPCache(PORT); @@ -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; diff --git a/cMain.c b/cMain.c index c722147..45f1384 100644 --- a/cMain.c +++ b/cMain.c @@ -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; } ; diff --git a/compatbits.h b/compatbits.h index 8cdc714..9707771 100644 --- a/compatbits.h +++ b/compatbits.h @@ -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 diff --git a/config.c b/config.c index a1b39a2..167bd83 100644 --- a/config.c +++ b/config.c @@ -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++) { diff --git a/configstructs.h b/configstructs.h index 9fb75cf..30c4c28 100644 --- a/configstructs.h +++ b/configstructs.h @@ -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 diff --git a/datadefs.c b/datadefs.c index f68c1c4..54766ab 100644 --- a/datadefs.c +++ b/datadefs.c @@ -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 diff --git a/kiss.c b/kiss.c index 2f2f071..c456088 100644 --- a/kiss.c +++ b/kiss.c @@ -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; diff --git a/mailapi.c b/mailapi.c index 064fa92..1b44d47 100644 --- a/mailapi.c +++ b/mailapi.c @@ -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; diff --git a/nodeapi.c b/nodeapi.c index acab7e8..ca0ad14 100644 --- a/nodeapi.c +++ b/nodeapi.c @@ -9,6 +9,7 @@ #include #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 }; @@ -799,37 +802,192 @@ int sendLinks(char * response, char * token, char * param, int Local) int sendPortMHList(char * response, char * token, char * param, int Local) { - struct PORTCONTROL * PORTVEC ; - int n; - int port = 0; + struct PORTCONTROL * PORTVEC ; + int n; + int port = 0; - if (param[0] = '?' || param[0] == '/') - port = atoi(¶m[1]); + if (param[0] = '?' || param[0] == '/') + port = atoi(¶m[1]); - PORTVEC = GetPortTableEntryFromPortNum(port); - response[0] = 0; + PORTVEC = GetPortTableEntryFromPortNum(port); + response[0] = 0; - if (PORTVEC == 0) - return send_http_response(response, "401 Invalid API Call"); + if (PORTVEC == 0) + return send_http_response(response, "401 Invalid API Call"); - n = sprintf(response,"{\"mheard\":[\r\n"); + n = sprintf(response,"{\"mheard\":[\r\n"); - BuildPortMH(&response[n], PORTVEC ); + BuildPortMH(&response[n], PORTVEC ); - if (response[n] == 0) // 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); + if (response[n] == 0) // 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); } +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(¶m[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