From d7b0d25ddb64850a2943f33d2450557629605bc9 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Sun, 23 Nov 2025 11:51:15 +0000 Subject: [PATCH] 6.0.25.12 hacky merge due t it not ffing. --- BPQINP3.c | 85 ++-- Bpq32.c | 9 +- Cmd.c | 187 +++++++-- Events.c | 4 +- L4Code.c | 31 +- LinBPQ.c | 8 +- NETROMTCP.c | 1044 ++++++++++++++++++++++++++++++++++++++++++++++++++ Versions.h | 8 + compatbits.c | 27 ++ compatbits.h | 3 +- 10 files changed, 1331 insertions(+), 75 deletions(-) diff --git a/BPQINP3.c b/BPQINP3.c index de4bf76..d87aa69 100644 --- a/BPQINP3.c +++ b/BPQINP3.c @@ -35,8 +35,6 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include //#include "vmm.h" -uint64_t INP3timeLoadedMS = 0; - extern int DEBUGINP3; VOID SendNegativeInfo(); @@ -64,11 +62,16 @@ static VOID SendNetFrame(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame) typedef struct _RTTMSG { - UCHAR ID[7]; - UCHAR TXTIME[11]; - UCHAR SMOOTHEDRTT[11]; - UCHAR LASTRTT[11]; - UCHAR POINTER[11]; + UCHAR ID[6]; + UCHAR Space1; + UCHAR TXTIME[10]; + UCHAR Space2; + UCHAR SMOOTHEDRTT[10]; + UCHAR Space3; + UCHAR LASTRTT[10]; + UCHAR Space4; + UCHAR RTTID[10]; + UCHAR Space5; UCHAR ALIAS[7]; UCHAR VERSION[12]; UCHAR SWVERSION[9]; @@ -110,6 +113,8 @@ extern int RTTInterval; // 4 Minutes int RTTRetries = 2; int RTTTimeout = 6; // 1 Min (Horizon is 1 min) +uint32_t RTTID = 1; + VOID InitialiseRTT() { UCHAR temp[256] = ""; @@ -161,10 +166,11 @@ VOID DeleteINP3Routes(struct ROUTE * Route) Route->BCTimer = 0; Route->Status = 0; Route->Timeout = 0; + Route->NeighbourSRTT = 0; Dest--; - // Delete any Dest entries via this Route + // Delete any Dest entries via this Route for (i=0; i < MAXDESTS; i++) { @@ -340,8 +346,8 @@ VOID TellINP3LinkSetupFailed(struct ROUTE * Route) VOID ProcessRTTReply(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff) { - int RTT; - unsigned int OrigTime; + uint32_t RTT; + uint32_t OrigTime; char Normcall[10]; @@ -349,10 +355,10 @@ VOID ProcessRTTReply(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff) Route->Timeout = 0; // Got Response - sscanf(&Buff->L4DATA[6], "%d", &OrigTime); - RTT = (int)((GetTickCount() - INP3timeLoadedMS) / 10 - (OrigTime)); // We work internally in mS + sscanf(&Buff->L4DATA[6], "%u", &OrigTime); + RTT = GetTickCountINP3() - OrigTime; // We work internally in mS - if (RTT > 60000) + if (RTT > 60000 || RTT < 0) return; // Ignore if more than 60 secs (why ??) Route->RTT = RTT; @@ -890,8 +896,8 @@ VOID UpdateRoute(struct DEST_LIST * Dest, struct INP3_DEST_ROUTE_ENTRY * ROUTEPT VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len, int Port) { - int OtherRTT; - int Dummy; + uint32_t OtherRTT; + uint32_t Dummy; char * ptr; struct _RTTMSG * RTTMsg = (struct _RTTMSG *)&Buff->L4DATA[0]; char Normcall[10]; @@ -920,18 +926,28 @@ VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len return; // We don't want to use INP3 } - // Extract other end's SRTT + // Basic Validation - look for spaces in the right place - // Get SWVERSION to see if other end is old (Buggy) BPQ - - if (memcmp(RTTMsg->SWVERSION, "BPQ32001 ", 9) == 0) - Route->OldBPQ = 1; + if ((RTTMsg->Space1 | RTTMsg->Space2 | RTTMsg->Space3 | RTTMsg->Space4 | RTTMsg->Space5) != ' ') + { + Debugprintf("Corrupt INP3 RTT Message %s", &Buff->L4DATA[0]); + } else - Route->OldBPQ = 0; + { + // Extract other end's SRTT - sscanf(&Buff->L4DATA[6], "%d %d", &Dummy, &OtherRTT); + // Get SWVERSION to see if other end is old (Buggy) BPQ - Route->NeighbourSRTT = OtherRTT; + if (memcmp(RTTMsg->SWVERSION, "BPQ32001 ", 9) == 0) + Route->OldBPQ = 1; + else + Route->OldBPQ = 0; + + sscanf(&Buff->L4DATA[6], "%u %u", &Dummy, &OtherRTT); + + if (OtherRTT < 60000) // Don't save suspect values + Route->NeighbourSRTT = OtherRTT; + } // Look for $M and $H (MAXRTT MAXHOPS) @@ -945,6 +961,8 @@ VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len if (ptr) Route->RemoteMAXHOPS = atoi(ptr + 2); + + // Echo Back to sender SendNetFrame(Route, Buff); @@ -965,7 +983,8 @@ VOID SendRTTMsg(struct ROUTE * Route) char Stamp[50]; char Normcall[10]; unsigned char temp[256]; - uint64_t sendTime; + uint32_t sendTime; + int n; Normcall[ConvFromAX25(Route->NEIGHBOUR_CALL, Normcall)] = 0; @@ -985,14 +1004,21 @@ 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. + // Windows GetTickCount wraps every 54 days or so. INP3 doesn't care, so long as the edge + // case where timer wraps between sending msg and getting response is ignored + // For platform independence use GetTickCountINP3() and map as appropriate - sendTime = ((uint64_t)GetTickCount() - INP3timeLoadedMS) / 10; // 10mS units + sendTime = GetTickCountINP3(); // 10mS units - if (sendTime > 9999999999) - sendTime = INP3timeLoadedMS = 0; + sprintf(Stamp, "%10u %10d %10d %10d ", sendTime, Route->SRTT, Route->RTT, RTTID++); - sprintf(Stamp, "%10llu %10d %10d %10d ", sendTime, Route->SRTT, Route->RTT, 0); + n = strlen(Stamp); + + if (n != 44) + { + Debugprintf("Trying to send corrupt RTT message %s", Stamp); + return; + } memcpy(RTTMsg.TXTIME, Stamp, 44); @@ -1209,6 +1235,7 @@ int SendRIPTimer() } L2SETUPCROSSLINKEX(Route, 2); // Only try SABM twice + Route->NeighbourSRTT = 0; // just in case! Route->LastConnectAttempt = REALTIMETICKS; diff --git a/Bpq32.c b/Bpq32.c index e49bd8b..23f53e9 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1300,6 +1300,12 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Fix FRMR caused by sending SREJ when no frames outstanding (8) // Fix some issues with NetromX connects and Route Selection when running INP3 and NODES routing (9) // Fix connecting to a netrom node with c p node command (10) +<<<<<<< Updated upstream +||||||| Stash base +======= +// Add validation of INP3 RTT messages and various INP3 fixes (12) +// Change NetromX connect syntax to Service@Node to fix passing commands to local applications (12) +>>>>>>> Stashed changes #define CKernel @@ -1540,7 +1546,6 @@ extern char ReportDest[7]; extern UCHAR ConfigDirectory[260]; -extern uint64_t INP3timeLoadedMS; VOID __cdecl Debugprintf(const char * format, ...); VOID __cdecl Consoleprintf(const char * format, ...); @@ -2481,8 +2486,6 @@ FirstInit() EnumProcessesPtr = (FARPROCX)GetProcAddress(ExtDriver,"EnumProcesses"); } - INP3timeLoadedMS = GetTickCount(); - srand(time(NULL)); INITIALISEPORTS(); diff --git a/Cmd.c b/Cmd.c index 42869d5..21ced5f 100644 --- a/Cmd.c +++ b/Cmd.c @@ -838,13 +838,14 @@ BOOL cATTACHTOBBS(TRANSPORTENTRY * Session, UINT Mask, int Paclen, int * AnySess return FALSE; } -void ConnecttoService(TRANSPORTENTRY * Session, char * Bufferptr, int ServiceIndex, char * Node, int Stay) +void ConnecttoService(TRANSPORTENTRY * Session, char * Bufferptr, int Service, char * Node, int Stay) { struct DEST_LIST * Dest = DESTS; int n = MAXDESTS; int gotDest = 0; unsigned char axcall[7]; - int Service = -1; + char cmdName[80]; + int i; // Make Sure Node is Known @@ -889,9 +890,20 @@ void ConnecttoService(TRANSPORTENTRY * Session, char * Bufferptr, int ServiceInd Session->STAYFLAG = Stay; - Service = SERVICES[ServiceIndex].ServiceNo; + // Get command name if a named command - Bufferptr = Cmdprintf(Session, Bufferptr, "Connecting to Service %s on Node %s \r", SERVICES[ServiceIndex].ServiceName, Node); + sprintf(cmdName, "%d", Service); // default to number + + for (i = 0; i < NUMBEROFSSERVICES; i++) + { + if (SERVICES[i].ServiceNo == Service) + { + strcpy(cmdName, SERVICES[i].ServiceName); + break; + } + } + + Bufferptr = Cmdprintf(Session, Bufferptr, "Connecting to Service %s on Node %s \r", cmdName, Node); DoNetromConnect(Session, Bufferptr, Dest, 0, Service); @@ -930,7 +942,7 @@ int checkifService(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, s { if (strcmp(APPName, SERVICES[i].ServiceName) == 0) { - ConnecttoService(Session, Bufferptr, i, ptr, Stay); + ConnecttoService(Session, Bufferptr, SERVICES[i].ServiceNo, ptr, Stay); return 1; } } @@ -948,7 +960,6 @@ VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct char * ptr1, *ptr2; int n = 12; BOOL Stay = FALSE; - char * ptr, *Context; // Copy Appl and Null Terminate @@ -967,14 +978,17 @@ VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct return; } - ptr = strtok_s(CmdTail, " ", &Context); - // ptr is first param. Context is rest of string; + if (CmdTail[0] == 'S') + Stay = TRUE; + // could be Node for NETROMX connect or S flag + + // We now use service@node, so can't get here + +/* if (ptr) { - // could be Node for NETROMX connect or S flag - int i; if (strlen(ptr) > 1) @@ -983,6 +997,8 @@ VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct Session->STAYFLAG = Stay; // See if APPL is one of Paula's service + + for (i = 0; i < NUMBEROFSSERVICES; i++) { @@ -1003,7 +1019,7 @@ VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct else if (ptr[0] == 'S') Session->STAYFLAG = Stay; } - +*/ memcpy(Session->APPL, CMD->String, 12); // SEE IF THERE IS AN ALIAS DEFINDED FOR THIS COMMAND @@ -2572,6 +2588,56 @@ VOID CMDC00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct C return; } + // See if NETROMX connect c service@node + + if (strchr(ptr, '@')) + { + // We now use service@node, unlike xr + + char * Context1; + + char * Cmd = strtok_s(ptr, "@", &Context1); + char * Node = strtok_s(NULL, " ", &Context1); + int i; + int Stay = 0; + + if (Context1 && Context1[0] == 'S') + Session->STAYFLAG = Stay; + + for (i = 0; i < NUMBEROFSSERVICES; i++) + { + if (strcmp(Cmd, SERVICES[i].ServiceName) == 0) + { + if (Node) + { + ConnecttoService(Session, Bufferptr, SERVICES[i].ServiceNo, Node, Stay); + return; + } + } + } + + // May be numeric service + + for (i = 0; i < strlen(Cmd); i++) + { + if (!isdigit(Cmd[i])) + break; + } + + if (i == strlen(Cmd)) + { + if (Node) + { + ConnecttoService(Session, Bufferptr, atoi(Cmd), Node, Stay); + return; + } + } + + Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid NetromX command\r"); + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + Port = atoi(ptr); if (Port) @@ -2671,7 +2737,12 @@ NoPort: // SEE IF CALL TO ANY OF OUR HOST SESSIONS - UNLESS DIGIS SPECIFIED +<<<<<<< Updated upstream // if (axcalls[7] == 0 && axcalls[9]) +||||||| Stash base + if (axcalls[7] == 0 && axcalls[9] ) +======= +>>>>>>> Stashed changes if (axcalls[7] == 0) { // If this connect is as a result of a command alias, don't check appls or we will loop @@ -2723,6 +2794,7 @@ NoPort: } } +<<<<<<< Updated upstream // if no digis see if connect to known node. // But now could have a single numeric param as a service number (Paula's Netromx) @@ -2750,6 +2822,32 @@ NoPort: } if (axcalls[7] == 0 || haveService) +||||||| Stash base + // if no digis see if connect to known node. But now could have a single numeric param as a service number (Paula's Netromx) + // cmdCopy is command tail (after call) + + // Make sure field is numeric + + i = 0; + + while (cmdCopy[i] >= '0' && cmdCopy[i]<= '9') + i++; + + if (cmdCopy[i] != ' ') + goto Downlink; + else + { + if (i > 0) // Some digits + { + haveService = 1; + Service = atoi(cmdCopy); + } + } + + if (axcalls[7] == 0 || haveService) +======= + if (axcalls[7] == 0) +>>>>>>> Stashed changes { // SEE IF CALL TO ANOTHER NODE @@ -2792,9 +2890,6 @@ Downlink: // L2 NEEDS PORT NUMBER Bufferptr = Cmdprintf(Session, Bufferptr, "Downlink connect needs port number - C P CALLSIGN\r"); - - // Send Port List - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); return; } @@ -5082,6 +5177,7 @@ VOID DoTheCommand(TRANSPORTENTRY * Session) int n; int i, Service = -1; char * Cmd, *Node, *Context; + int Stay = 0; ptr1 = &COMMANDBUFFER[0]; // @@ -5176,28 +5272,47 @@ VOID DoTheCommand(TRANSPORTENTRY * Session) // See if a NETROMX Service - Cmd = strtok_s(ptr1, " ", &Context); - Node = strtok_s(NULL, " ", &Context); - - for (i = 0; i < NUMBEROFSSERVICES; i++) + // We now use service@node, unlike xr + + if (strchr(ptr1, '@')) { - if (strcmp(Cmd, SERVICES[i].ServiceName) == 0) + Cmd = strtok_s(ptr1, "@", &Context); + Node = strtok_s(NULL, " ", &Context); + + if (Cmd && Node) { - int Stay = 0; - if (Context && Context[0] == 'S') Session->STAYFLAG = Stay; - if (Node) + for (i = 0; i < NUMBEROFSSERVICES; i++) { - ConnecttoService(Session, ReplyPointer, i, Node, Stay); + if (strcmp(Cmd, SERVICES[i].ServiceName) == 0) + { + ConnecttoService(Session, ReplyPointer, SERVICES[i].ServiceNo, Node, Stay); + return; + } + } + + // May be numeric service + + for (i = 0; i < strlen(Cmd); i++) + { + if (!isdigit(Cmd[i])) + break; + } + + if (i == strlen(Cmd)) + { + ConnecttoService(Session, ReplyPointer, atoi(Cmd), Node, Stay); return; } - - // Connecting to service on local node - msy be possible sometime } - } + ReplyPointer = Cmdprintf(Session, ReplyPointer, "Invalid NetromX command\r"); + SendCommandReply(Session, REPLYBUFFER, (int)(ReplyPointer - (char *)REPLYBUFFER)); + return; + + } Session->BADCOMMANDS++; if (Session->BADCOMMANDS > 6) // TOO MANY ERRORS @@ -5214,19 +5329,19 @@ VOID DoTheCommand(TRANSPORTENTRY * Session) ptr1 += CMDERRLEN; SendCommandReply(Session, Buffer, (int)(ptr1 - (char *)Buffer)); -} + } -VOID StatsTimer() -{ - struct PORTCONTROL * PORT = PORTTABLE; - uint64_t sum, sum2; - - // Interval is 60 secs - - while(PORT) + VOID StatsTimer() { - int index = PORT->StatsPointer++; + struct PORTCONTROL * PORT = PORTTABLE; + uint64_t sum, sum2; + + // Interval is 60 secs + + while(PORT) + { + int index = PORT->StatsPointer++; if (index == 1439) PORT->StatsPointer = 0; // Cyclic through 24 hours (1440 Mins) diff --git a/Events.c b/Events.c index bb2a8ef..8e63cfe 100644 --- a/Events.c +++ b/Events.c @@ -944,9 +944,9 @@ void APIL2Trace(struct _MESSAGE * Message, char * Dirn) // supervisory if (PF[0]) - udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, ", \"pf\": \"%s\", \"rseq\": %d, \"tseq\": %d", PF, NR, NS); + udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, ", \"pf\": \"%s\", \"rseq\": %d", PF, NR); else - udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, ", \"rseq\": %d, \"tseq\": %d", NR, NS); + udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, ", \"rseq\": %d", NR); } diff --git a/L4Code.c b/L4Code.c index a319504..9a37668 100644 --- a/L4Code.c +++ b/L4Code.c @@ -1929,19 +1929,34 @@ void L3SWAPADDRESSES(L3MESSAGEBUFFER * L3MSG) void SendConNAK(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) { + struct TNCINFO * TNC; + L3MSG->L4FLAGS = L4CACK | L4BUSY; // REJECT L3MSG->L4DATA[0] = 0; // WINDOW L3SWAPADDRESSES(L3MSG); L3MSG->L3TTL = L3LIVES; - C_Q_ADD(&LINK->TX_Q, L3MSG); + TNC = LINK->LINKPORT->TNC; + + if (LINK->NEIGHBOUR && LINK->NEIGHBOUR->TCPPort) + { + TCPNETROMSend(LINK->NEIGHBOUR, L3MSG); + ReleaseBuffer(L3MSG); + } + else if (TNC && TNC->NetRomMode) + SendVARANetromMsg(TNC, L3MSG); + else + C_Q_ADD(&LINK->TX_Q, L3MSG); + } VOID SendL4RESET(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) { // Paula's extension + struct TNCINFO * TNC; + L3MSG->L4RXNO = L3MSG->L4ID; L3MSG->L4TXNO = L3MSG->L4INDEX; @@ -1951,7 +1966,19 @@ VOID SendL4RESET(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) L3MSG->L3TTL = L3LIVES; L3MSG->LENGTH = (int)(&L3MSG->L4DATA[0] - (UCHAR *)L3MSG); - C_Q_ADD(&LINK->TX_Q, L3MSG); + + TNC = LINK->LINKPORT->TNC; + + if (LINK->NEIGHBOUR && LINK->NEIGHBOUR->TCPPort) + { + TCPNETROMSend(LINK->NEIGHBOUR, L3MSG); + ReleaseBuffer(L3MSG); + } + else if (TNC && TNC->NetRomMode) + SendVARANetromMsg(TNC, L3MSG); + else + C_Q_ADD(&LINK->TX_Q, L3MSG); + } diff --git a/LinBPQ.c b/LinBPQ.c index ad749d0..03af5a4 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -86,8 +86,14 @@ void SendBBSDataToPktMap(); void CloseAllLinks(); void hookNodeClosing(char * Reason); void NETROMTCPResolve(); +<<<<<<< Updated upstream extern uint64_t INP3timeLoadedMS; +||||||| Stash base + +extern uint64_t INP3timeLoadedMS; +======= +>>>>>>> Stashed changes BOOL IncludesMail = FALSE; BOOL IncludesChat = FALSE; @@ -861,8 +867,6 @@ int main(int argc, char * argv[]) if (!isatty(STDOUT_FILENO) || !isatty(STDIN_FILENO)) Redirected = 1; - INP3timeLoadedMS = GetTickCount(); - #endif printf("G8BPQ AX25 Packet Switch System Version %s %s\n", TextVerstring, Datestring); diff --git a/NETROMTCP.c b/NETROMTCP.c index f756621..e1d9fec 100644 --- a/NETROMTCP.c +++ b/NETROMTCP.c @@ -110,6 +110,7 @@ struct ConnectionInfo * AllocateNRTCPRec() sockptr->SocketActive = TRUE; sockptr->ConnectTime = sockptr->LastSendTime = time(NULL); +<<<<<<< Updated upstream Debugprintf("NRTCP Allocated %d", i); return sockptr; } @@ -593,6 +594,1049 @@ void NETROMConnectionLost(struct ConnectionInfo * sockptr) Route->TCPSession = 0; Info->Call[0] = 0; +||||||| Stash base +/* +Copyright 2001-2022 John Wiseman G8BPQ + +This file is part of LinBPQ/BPQ32. + +LinBPQ/BPQ32 is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +LinBPQ/BPQ32 is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses +*/ + +/* +Netrom over TCP Support + +This is intended for operation over radio links with an IP interface, eg New Packet Radio or possibly microwave links + +To simplify interface to the rest of the oode dummy LINK and PORT records are created + +Packet Format is Length (2 byte little endian) Call (10 bytes ASCII) NETROM L3/4 Packet, starting 0xcf (to detect framing errors). + +A TCP message can contain multiple packets and/or partial packets + +It uses the Telnet Server, with port defined in NETROMPORT + +ROUTE definitions have an extra field, the TCP Port Number + +*/ + +//#pragma data_seg("_BPQDATA") + + +#define _CRT_SECURE_NO_DEPRECATE + +#include "time.h" +#include "stdio.h" +#include +//#include "vmm.h" + +#include "cheaders.h" +#include "asmstrucs.h" +#include "telnetserver.h" + +#define NETROM_PID 0xCF + +void NETROMConnectionLost(struct ConnectionInfo * sockptr); +int DataSocket_ReadNETROM(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info, int portNo); +int NETROMTCPConnect(struct ROUTE * Route, struct ConnectionInfo * sockptr); +void NETROMConnected(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info); +VOID SendRTTMsg(struct ROUTE * Route); +BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE); +VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG); +int BPQTRACE(MESSAGE * Msg, BOOL TOAPRS); +VOID L3LINKCLOSED(struct _LINKTABLE * LINK, int Reason); + +struct NRTCPMsg +{ + short Length; + char Call[10]; + unsigned char PID; + char Packet[1024]; +}; + +struct NRTCPSTRUCT +{ + struct ConnectionInfo * sockptr; + struct _LINKTABLE * LINK; // Dummy Link Record for this ROUTE + struct ROUTE * Route; // May need backlink + char Call[10]; +}; + +struct NRTCPSTRUCT * NRTCPInfo[256] = {0}; + +// Do we want to use normal TCP server connections, which are limited, or our own. Let's try our own for now + +struct ConnectionInfo * AllocateNRTCPRec() +{ + struct ConnectionInfo * sockptr = 0; + struct NRTCPSTRUCT * Info; + int i; + + for (i = 0; i < 255; i++) + { + if (NRTCPInfo[i] == 0) + { + // only allocate as many as needed + + Info = NRTCPInfo[i] = (struct NRTCPSTRUCT *)zalloc(sizeof(struct NRTCPSTRUCT)); + Info->sockptr = (struct ConnectionInfo *)zalloc(sizeof(struct ConnectionInfo)); + Info->LINK = (struct _LINKTABLE *)zalloc(sizeof(struct _LINKTABLE)); + Info->sockptr->Number = i; + } + else + Info = NRTCPInfo[i]; + + sockptr = Info->sockptr; + + if (sockptr->SocketActive == FALSE) + { + sockptr->SocketActive = TRUE; + sockptr->ConnectTime = sockptr->LastSendTime = time(NULL); + + Debugprintf("NRTCP Allocated %d", i); + return sockptr; + } + } + return 0; +} + +void checkNRTCPSockets(int portNo) +{ + SOCKET sock; + int Active = 0; + SOCKET maxsock; + int retval; + int i; + + struct timeval timeout; + fd_set readfd, writefd, exceptfd; + + struct ConnectionInfo * sockptr; + + timeout.tv_sec = 0; + timeout.tv_usec = 0; // poll + + maxsock = 0; + + FD_ZERO(&readfd); + FD_ZERO(&writefd); + FD_ZERO(&exceptfd); + + for (i = 0; i < 255; i++) + { + if (NRTCPInfo[i] == 0) + break; // only as many as have been used + + sockptr = NRTCPInfo[i]->sockptr; + + if (sockptr->SocketActive == 0) + continue; + + if (sockptr->Connecting) + { + // look for complete or failed + + FD_SET(sockptr->socket, &writefd); + FD_SET(sockptr->socket, &exceptfd); + } + else + { + FD_SET(sockptr->socket, &readfd); + FD_SET(sockptr->socket, &exceptfd); + } + + Active++; + + if (sockptr->socket > maxsock) + maxsock = sockptr->socket; + } + + if (Active) + { + retval = select((int)maxsock + 1, &readfd, &writefd, &exceptfd, &timeout); + + if (retval == -1) + { + perror("data select"); + Debugprintf("NRTCP Select Error %d Active %d", WSAGetLastError(), Active); + } + else + { + if (retval) + { + // see who has data + + for (i = 0; i < 255; i++) + { + if (NRTCPInfo[i] == 0) + break; + + sockptr = NRTCPInfo[i]->sockptr; + + if (sockptr->SocketActive == 0) + continue; + + sock = sockptr->socket; + + if (FD_ISSET(sock, &writefd)) + NETROMConnected(sockptr, sock, NRTCPInfo[i]); + + if (FD_ISSET(sock, &readfd)) + DataSocket_ReadNETROM(sockptr, sock, NRTCPInfo[i], portNo); + + if (FD_ISSET(sock, &exceptfd)) + NETROMConnectionLost(sockptr); + } + } + } + } +} + +int NETROMOpenConnection(struct ROUTE * Route) +{ + struct NRTCPSTRUCT * Info; + struct ConnectionInfo * sockptr; + + Debugprintf("Opening NRTCP Connection"); + + if (Route->TCPSession) + { + // SESSION ALREADY EXISTS + + sockptr = Route->TCPSession->sockptr; + + if (sockptr->Connected || sockptr->Connecting) + return TRUE; + + // previous connect failed + } + else + { + sockptr = AllocateNRTCPRec(); + + if (sockptr == NULL) + return 0; + + Info = Route->TCPSession = NRTCPInfo[sockptr->Number]; + memcpy(Info->Call, MYNETROMCALL, 10); + Route->NEIGHBOUR_LINK = Info->LINK; + + Info->Route = Route; + Info->LINK->NEIGHBOUR = Route; + Info->LINK->LINKPORT = GetPortTableEntryFromPortNum(Route->NEIGHBOUR_PORT); + } + + return NETROMTCPConnect(Route, sockptr); + +} + +int NETROMTCPConnect(struct ROUTE * Route, struct ConnectionInfo * sockptr) +{ + int err; + u_long param=1; + BOOL bcopt=TRUE; + SOCKET sock; + struct sockaddr_in sinx; + int addrlen=sizeof(sinx); + char PortString[20]; + struct addrinfo hints, *res = 0, *saveres; + int Port = Route->TCPPort; + + sprintf(PortString, "%d", Port); + + // get host info, make socket, and connect it + + memset(&hints, 0, sizeof hints); + + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + + hints.ai_socktype = SOCK_STREAM; + getaddrinfo(Route->TCPHost, PortString, &hints, &res); + + if (!res) + { + err = WSAGetLastError(); + Debugprintf("Resolve HostName %s Failed - Error %d", Route->TCPHost, err); + return FALSE; // Resolve failed + } + + // Step thorough the list of hosts + + saveres = res; // Save for free + + sock = sockptr->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + + if (sock == INVALID_SOCKET) + { + Debugprintf, ("Netrom over TCP Create Socket Failed"); + return FALSE; + } + + ioctl(sock, FIONBIO, ¶m); + + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); + + + if (connect(sock, res->ai_addr, (int)res->ai_addrlen) == 0) + { + // + // Connected successful + // + + sockptr->Connected = TRUE; + freeaddrinfo(saveres); + + return TRUE; + } + else + { + freeaddrinfo(saveres); + + err=WSAGetLastError(); + + if (err == 10035 || err == 115 || err == 36) //EWOULDBLOCK + { + // Connect in Progress + + sockptr->Connecting = TRUE; + return TRUE; + } + else + { + // Connect failed + + closesocket(sockptr->socket); + + return FALSE; + } + } + + return FALSE; +} + + + + +void NETROMConnectionAccepted(struct ConnectionInfo * sockptr) +{ + // Not sure we can do much here until first message arrives with callsign + + sockptr->Connected = TRUE; + Debugprintf("NRTCP Connection Accepted"); +} + +void NETROMConnected(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info) +{ + // Connection Complete + + Debugprintf("NRTCP Connected"); + + sockptr->Connecting = FALSE; + sockptr->Connected = TRUE; + + Info->LINK->L2STATE = 5; + + if (Info->Route->INP3Node) + SendRTTMsg(Info->Route); +} + +int DataSocket_ReadNETROM(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info, int portNo) +{ + int len=0, maxlen; + struct NRTCPMsg * Msg; + struct _L3MESSAGEBUFFER * L3Msg; + struct ROUTE * Route; + UCHAR axCall[7]; + PMESSAGE Buffer; + + ioctl(sock,FIONREAD,&len); + + maxlen = InputBufferLen - sockptr->InputLen; + + if (len > maxlen) len = maxlen; + + len = recv(sock, &sockptr->InputBuffer[sockptr->InputLen], len, 0); + + if (len == SOCKET_ERROR || len == 0) + { + // Failed or closed - clear connection + + NETROMConnectionLost(sockptr); + return 0; + } + + sockptr->InputLen += len; + + // Process data + +checkLen: + + // See if we have a whole packet + + Msg = (struct NRTCPMsg *)&sockptr->InputBuffer[0]; + + if (Msg->Length > sockptr->InputLen) // if not got whole frame wait + return 0; + + if (Info->Call[0] == 0) + { + // first packet - do we need to do anything? + + // This must be an incoming connection as Call is set before calling so need to find route record and set things up. + + memcpy(Info->Call, Msg->Call, 10); + + ConvToAX25(Msg->Call, axCall); + + if (FindNeighbour(axCall, portNo, &Route)) + { + Info->Route = Route; + Route->NEIGHBOUR_LINK = Info->LINK; + Info->LINK->NEIGHBOUR = Route; + Info->LINK->LINKPORT = GetPortTableEntryFromPortNum(Route->NEIGHBOUR_PORT); + Route->TCPSession = Info; + Info->LINK->L2STATE = 5; + + if (Info->Route->INP3Node) + SendRTTMsg(Info->Route); + } + else + goto seeifMore; // Should we kill connection? + } + + + if (memcmp(Info->Call, Msg->Call, 10) != 0) + { + // something wrong - maybe connection reused + } + + // Format as if come from an ax.25 link + + L3Msg = GetBuff(); + + if (L3Msg == 0) + goto seeifMore; + + L3Msg->LENGTH = (Msg->Length - 12) + MSGHDDRLEN; + L3Msg->Next = 0; + L3Msg->Port = 0; + L3Msg->L3PID = NETROM_PID; + memcpy(&L3Msg->L3SRCE, Msg->Packet, Msg->Length - 13); + + // Create a dummy L2 message so we can trace it + + Buffer = GetBuff(); + + if (Buffer) + { + Buffer->CHAIN = 0; + Buffer->CTL = 0; + Buffer->PORT = portNo; + + ConvToAX25(Info->Call, Buffer->ORIGIN); + ConvToAX25(MYNETROMCALL, Buffer->DEST); + + memcpy(Buffer->L2DATA, &L3Msg->L3SRCE[0], Msg->Length - 13); + Buffer->ORIGIN[6] |= 1; // Set end of calls + Buffer->PID = NETROM_PID; + Buffer->LENGTH = Msg->Length + 10; + time(&Buffer->Timestamp); + + BPQTRACE(Buffer, FALSE); + ReleaseBuffer(Buffer); + } + + NETROMMSG(Info->LINK, L3Msg); + +seeifMore: + + sockptr->InputLen -= Msg->Length; + + if (sockptr->InputLen > 0) + { + memmove(sockptr->InputBuffer, &sockptr->InputBuffer[Msg->Length], sockptr->InputLen); + goto checkLen; + } + + return 0; +} + +VOID TCPNETROMSend(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame) +{ + struct NRTCPMsg Msg; + unsigned char * Data = (unsigned char *)&Frame->L3SRCE[0]; + int DataLen = Frame->LENGTH - (MSGHDDRLEN + 1); // Not including PID + int Ret; + PMESSAGE Buffer; + + Msg.Length = DataLen + 13; // include PID + memcpy(Msg.Call, MYNETROMCALL, 10); + Msg.PID = NETROM_PID; + memcpy(Msg.Packet, Data, DataLen); + + if (Route->TCPSession == 0) + return; + + Ret = send(Route->TCPSession->sockptr->socket, (char *)&Msg, DataLen + 13, 0); + + // Create a dummy L2 message so we can trace it + + Buffer = GetBuff(); + + if (Buffer) + { + Buffer->CHAIN = 0; + Buffer->CTL = 0; + Buffer->PORT = Route->NEIGHBOUR_PORT | 128; // TX Flag + + ConvToAX25(Route->TCPSession->Call, Buffer->DEST); + ConvToAX25(MYNETROMCALL, Buffer->ORIGIN); + + memcpy(Buffer->L2DATA, &Frame->L3SRCE[0], DataLen); + Buffer->ORIGIN[6] |= 1; // Set end of calls + Buffer->PID = NETROM_PID; + Buffer->LENGTH = DataLen + 15 + MSGHDDRLEN; + time(&Buffer->Timestamp); + + BPQTRACE(Buffer, FALSE); + ReleaseBuffer(Buffer); + } + +} + + +void NETROMConnectionLost(struct ConnectionInfo * sockptr) +{ + struct NRTCPSTRUCT * Info = NRTCPInfo[sockptr->Number]; + struct ROUTE * Route; + + closesocket(sockptr->socket); + + // If there is an attached route (there should be) clear all connections + + if (Info) + { + Route = Info->Route; + + if (sockptr->Connected) + L3LINKCLOSED(Info->LINK, LINKLOST); + + if (sockptr->Connecting) + L3LINKCLOSED(Info->LINK, SETUPFAILED); + + Route->TCPSession = 0; + + Info->Call[0] = 0; + } + + sockptr->SocketActive = FALSE; + + memset(sockptr, 0, sizeof(struct ConnectionInfo)); +} + +======= +// Debugprintf("NRTCP Allocated %d", i); + return sockptr; + } + } + return 0; +} + +void checkNRTCPSockets(int portNo) +{ + SOCKET sock; + int Active = 0; + SOCKET maxsock; + int retval; + int i; + + struct timeval timeout; + fd_set readfd, writefd, exceptfd; + + struct ConnectionInfo * sockptr; + + timeout.tv_sec = 0; + timeout.tv_usec = 0; // poll + + maxsock = 0; + + FD_ZERO(&readfd); + FD_ZERO(&writefd); + FD_ZERO(&exceptfd); + + for (i = 0; i < 255; i++) + { + if (NRTCPInfo[i] == 0) + break; // only as many as have been used + + sockptr = NRTCPInfo[i]->sockptr; + + if (sockptr->SocketActive == 0) + continue; + + if (sockptr->Connecting) + { + // look for complete or failed + + FD_SET(sockptr->socket, &writefd); + FD_SET(sockptr->socket, &exceptfd); + } + else + { + FD_SET(sockptr->socket, &readfd); + FD_SET(sockptr->socket, &exceptfd); + } + + Active++; + + if (sockptr->socket > maxsock) + maxsock = sockptr->socket; + } + + if (Active) + { + retval = select((int)maxsock + 1, &readfd, &writefd, &exceptfd, &timeout); + + if (retval == -1) + { + perror("data select"); + Debugprintf("NRTCP Select Error %d Active %d", WSAGetLastError(), Active); + } + else + { + if (retval) + { + // see who has data + + for (i = 0; i < 255; i++) + { + if (NRTCPInfo[i] == 0) + break; + + sockptr = NRTCPInfo[i]->sockptr; + + if (sockptr->SocketActive == 0) + continue; + + sock = sockptr->socket; + + if (FD_ISSET(sock, &writefd)) + NETROMConnected(sockptr, sock, NRTCPInfo[i]); + + if (FD_ISSET(sock, &readfd)) + DataSocket_ReadNETROM(sockptr, sock, NRTCPInfo[i], portNo); + + if (FD_ISSET(sock, &exceptfd)) + NETROMConnectionLost(sockptr); + } + } + } + } +} + +int NETROMOpenConnection(struct ROUTE * Route) +{ + struct NRTCPSTRUCT * Info; + struct ConnectionInfo * sockptr; + char farCall[10]; + + farCall[ConvFromAX25(Route->NEIGHBOUR_CALL, farCall)] = 0; + +// Debugprintf("Opening NRTCP Connection to %s", farCall); + + if (Route->TCPSession) + { + // SESSION ALREADY EXISTS + + sockptr = Route->TCPSession->sockptr; + + if (sockptr->Connected || sockptr->Connecting) + return TRUE; + + // previous connect failed + } + else + { + sockptr = AllocateNRTCPRec(); + + if (sockptr == NULL) + return 0; + + Info = Route->TCPSession = NRTCPInfo[sockptr->Number]; + memcpy(Info->Call, farCall, 10); + Route->NEIGHBOUR_LINK = Info->LINK; + + Info->Route = Route; + Info->LINK->NEIGHBOUR = Route; + Info->LINK->LINKPORT = GetPortTableEntryFromPortNum(Route->NEIGHBOUR_PORT); + } + + return NETROMTCPConnect(Route, sockptr); + +} + +void NETROMTCPResolve() +{ + struct ROUTE * Route = NEIGHBOURS; + int n = MAXNEIGHBOURS; + struct addrinfo hints, *res = 0; + char PortString[20]; + int err; + + while (n--) + { + if (Route->TCPAddress) + { + // try to resolve host + + sprintf(PortString, "%d", Route->TCPPort); + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + getaddrinfo(Route->TCPHost, PortString, &hints, &res); + + err = WSAGetLastError(); + + if (res) + { + Route->TCPAddress->ai_family = res->ai_family; + Route->TCPAddress->ai_socktype = res->ai_socktype; + Route->TCPAddress->ai_protocol = res->ai_protocol; + Route->TCPAddress->ai_addrlen = res->ai_addrlen; + memcpy(Route->TCPAddress->ai_addr, res->ai_addr, sizeof(struct sockaddr)); + freeaddrinfo(res); + } + } + + Route++; + } +} + +int NETROMTCPConnect(struct ROUTE * Route, struct ConnectionInfo * sockptr) +{ + int err; + u_long param=1; + BOOL bcopt=TRUE; + SOCKET sock; + struct sockaddr_in sinx; + int addrlen=sizeof(sinx); + char PortString[20]; + struct addrinfo * res = Route->TCPAddress; + int Port = Route->TCPPort; + + sprintf(PortString, "%d", Port); + + // get host info, make socket, and connect it + + if (res->ai_family == 0) + { +// err = WSAGetLastError(); +// Debugprintf("Resolve HostName %s Failed - Error %d", Route->TCPHost, err); + return FALSE; // Resolve failed + } + + sock = sockptr->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + if (sock == INVALID_SOCKET) + { + Debugprintf, ("Netrom over TCP Create Socket Failed"); + return FALSE; + } + + ioctl(sock, FIONBIO, ¶m); + + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); + + + if (connect(sock, res->ai_addr, (int)res->ai_addrlen) == 0) + { + // + // Connected successful + // + + sockptr->Connected = TRUE; + return TRUE; + } + else + { + err=WSAGetLastError(); + + if (err == 10035 || err == 115 || err == 36) //EWOULDBLOCK + { + // Connect in Progress + + sockptr->Connecting = TRUE; + return TRUE; + } + else + { + // Connect failed + + closesocket(sockptr->socket); + + return FALSE; + } + } + + return FALSE; +} + + + + +void NETROMConnectionAccepted(struct ConnectionInfo * sockptr) +{ + // Not sure we can do much here until first message arrives with callsign + + sockptr->Connected = TRUE; +// Debugprintf("NRTCP Connection Accepted"); +} + +void NETROMConnected(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info) +{ + // Connection Complete + +// Debugprintf("NRTCP Connected"); + + sockptr->Connecting = FALSE; + sockptr->Connected = TRUE; + + Info->LINK->L2STATE = 5; + + if (Info->Route->INP3Node) + SendRTTMsg(Info->Route); +} + +int DataSocket_ReadNETROM(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info, int portNo) +{ + int len=0, maxlen; + struct NRTCPMsg * Msg; + struct _L3MESSAGEBUFFER * L3Msg; + struct ROUTE * Route; + UCHAR axCall[7]; + PMESSAGE Buffer; + + ioctl(sock,FIONREAD,&len); + + maxlen = InputBufferLen - sockptr->InputLen; + + if (len > maxlen) len = maxlen; + + len = recv(sock, &sockptr->InputBuffer[sockptr->InputLen], len, 0); + + if (len == SOCKET_ERROR || len == 0) + { + // Failed or closed - clear connection + + NETROMConnectionLost(sockptr); + return 0; + } + + sockptr->InputLen += len; + + // Process data + +checkLen: + + // See if we have a whole packet + + Msg = (struct NRTCPMsg *)&sockptr->InputBuffer[0]; + + if (Msg->Length > sockptr->InputLen) // if not got whole frame wait + return 0; + + if (Info->Call[0] == 0) + { + // first packet - do we need to do anything? + + // This must be an incoming connection as Call is set before calling so need to find route record and set things up. + +// Debugprintf("New NRTCP Connection from %s", Msg->Call); + + memcpy(Info->Call, Msg->Call, 10); + + ConvToAX25(Msg->Call, axCall); + + if (FindNeighbour(axCall, portNo, &Route)) + { + Info->Route = Route; + Route->NEIGHBOUR_LINK = Info->LINK; + Route->NEIGHBOUR_PORT = portNo; + Info->LINK->NEIGHBOUR = Route; + Info->LINK->LINKPORT = GetPortTableEntryFromPortNum(portNo); + Route->TCPSession = Info; + Info->LINK->L2STATE = 5; + + if (Info->Route->INP3Node) + SendRTTMsg(Info->Route); + } + else + { + Debugprintf("Neighbour %s port %d not found - closing connection", Msg->Call, portNo); + closesocket(sockptr->socket); + sockptr->SocketActive = FALSE; + memset(sockptr, 0, sizeof(struct ConnectionInfo)); + Info->Call[0] = 0; + return 0; + } + } + + + if (memcmp(Info->Call, Msg->Call, 10) != 0) + { + Debugprintf("NRTCP Mismatch - closing connection"); + + closesocket(sockptr->socket); + sockptr->SocketActive = FALSE; + memset(sockptr, 0, sizeof(struct ConnectionInfo)); + Info->Call[0] = 0; + return 0; + } + + // Format as if come from an ax.25 link + + L3Msg = GetBuff(); + + if (L3Msg == 0) + goto seeifMore; + + L3Msg->LENGTH = (Msg->Length - 12) + MSGHDDRLEN; + L3Msg->Next = 0; + L3Msg->Port = portNo; + L3Msg->L3PID = NETROM_PID; + memcpy(&L3Msg->L3SRCE, Msg->Packet, Msg->Length - 13); + + // Create a dummy L2 message so we can trace it + + Buffer = GetBuff(); + + if (Buffer) + { + Buffer->CHAIN = 0; + Buffer->CTL = 0; + Buffer->PORT = portNo; + + ConvToAX25(Info->Call, Buffer->ORIGIN); + ConvToAX25(MYNETROMCALL, Buffer->DEST); + + memcpy(Buffer->L2DATA, &L3Msg->L3SRCE[0], Msg->Length - 13); + Buffer->ORIGIN[6] |= 1; // Set end of calls + Buffer->PID = NETROM_PID; + Buffer->LENGTH = Msg->Length + 10; + time(&Buffer->Timestamp); + + BPQTRACE(Buffer, FALSE); + + if(NodeAPISocket) + NetromTCPTrace(Buffer, "rcvd"); + + ReleaseBuffer(Buffer); + } + + NETROMMSG(Info->LINK, L3Msg); + +seeifMore: + + sockptr->InputLen -= Msg->Length; + + if (sockptr->InputLen > 0) + { + memmove(sockptr->InputBuffer, &sockptr->InputBuffer[Msg->Length], sockptr->InputLen); + goto checkLen; + } + + return 0; +} + +VOID TCPNETROMSend(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame) +{ + struct NRTCPMsg Msg; + unsigned char * Data = (unsigned char *)&Frame->L3SRCE[0]; + int DataLen = Frame->LENGTH - (MSGHDDRLEN + 1); // Not including PID + int Ret; + PMESSAGE Buffer; + + Msg.Length = DataLen + 13; // include PID + memcpy(Msg.Call, MYNETROMCALL, 10); + Msg.PID = NETROM_PID; + memcpy(Msg.Packet, Data, DataLen); + + if (Route->TCPSession == 0) + return; + + Ret = send(Route->TCPSession->sockptr->socket, (char *)&Msg, DataLen + 13, 0); + + // Create a dummy L2 message so we can trace it + + Buffer = GetBuff(); + + if (Buffer) + { + Buffer->CHAIN = 0; + Buffer->CTL = 0; + Buffer->PORT = Route->NEIGHBOUR_PORT; + + ConvToAX25(Route->TCPSession->Call, Buffer->DEST); + ConvToAX25(MYNETROMCALL, Buffer->ORIGIN); + + memcpy(Buffer->L2DATA, &Frame->L3SRCE[0], DataLen); + Buffer->ORIGIN[6] |= 1; // Set end of calls + Buffer->PID = NETROM_PID; + Buffer->LENGTH = DataLen + 15 + MSGHDDRLEN; + time(&Buffer->Timestamp); + + if(NodeAPISocket) + NetromTCPTrace(Buffer, "sent"); + + Buffer->PORT = Route->NEIGHBOUR_PORT | 128; // TX Flag + BPQTRACE(Buffer, FALSE); + + + ReleaseBuffer(Buffer); + } + +} + + +void NETROMConnectionLost(struct ConnectionInfo * sockptr) +{ + struct NRTCPSTRUCT * Info = NRTCPInfo[sockptr->Number]; + struct ROUTE * Route; + + closesocket(sockptr->socket); + + // If there is an attached route (there should be) clear all connections + + if (Info) + { + Route = Info->Route; + + if (sockptr->Connected) + L3LINKCLOSED(Info->LINK, LINKLOST); + + if (sockptr->Connecting) + L3LINKCLOSED(Info->LINK, SETUPFAILED); + + if (Route) + Route->TCPSession = 0; + + Info->Call[0] = 0; + Info->LINK->L2STATE = 0; +>>>>>>> Stashed changes } sockptr->SocketActive = FALSE; diff --git a/Versions.h b/Versions.h index a988953..79b7aea 100644 --- a/Versions.h +++ b/Versions.h @@ -10,8 +10,16 @@ #endif +<<<<<<< Updated upstream #define KVers 6,0,25,11 #define KVerstring "6.0.25.11\0" +||||||| Stash base +#define KVers 6,0,25,8 +#define KVerstring "6.0.25.8\0" +======= +#define KVers 6,0,25,12 +#define KVerstring "6.0.25.12\0" +>>>>>>> Stashed changes #ifdef CKernel diff --git a/compatbits.c b/compatbits.c index f93b2e5..a6ce8f5 100644 --- a/compatbits.c +++ b/compatbits.c @@ -25,6 +25,8 @@ Stuff to make compiling on WINDOWS and LINUX easier #ifdef WIN32 +#include + typedef unsigned int uint32_t; #define pthread_t uint32_t @@ -41,6 +43,7 @@ int pthread_equal(pthread_t T1, pthread_t T2) #include #include #include +#include #define BOOL int @@ -188,3 +191,27 @@ void closesocket(int sock) } #endif + +#ifdef WIN32 + +uint32_t GetTickCountINP3() +{ + // Returns system uptime in 10 mS, lower 20 bits only + + return (GetTickCount() / 10) & 0xfffff; +} +#else + +uint64_t GetTickCount(); + +uint32_t GetTickCountINP3() +{ + uint64_t Ticks = GetTickCount(); + + // Returns system uptime in 10 mS, lower 20 bits only + + return (Ticks / 10) & 0xfffff; +} + +#endif + diff --git a/compatbits.h b/compatbits.h index 9707771..1642af9 100644 --- a/compatbits.h +++ b/compatbits.h @@ -24,6 +24,7 @@ Stuff to make compiling on WINDOWS and LINUX easier #define strtoll _strtoi64 + #ifdef _WIN64 #include "stdint.h" #else @@ -219,7 +220,7 @@ typedef struct tagRECT #endif - +uint32_t GetTickCountINP3(); #ifdef LINBPQ