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..1f80282 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1300,6 +1300,8 @@ 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) +// 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) #define CKernel @@ -1540,7 +1542,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 +2482,6 @@ FirstInit() EnumProcessesPtr = (FARPROCX)GetProcAddress(ExtDriver,"EnumProcesses"); } - INP3timeLoadedMS = GetTickCount(); - srand(time(NULL)); INITIALISEPORTS(); diff --git a/Cmd.c b/Cmd.c index 42869d5..3e6c0eb 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,6 @@ NoPort: // SEE IF CALL TO ANY OF OUR HOST SESSIONS - UNLESS DIGIS SPECIFIED -// if (axcalls[7] == 0 && axcalls[9]) if (axcalls[7] == 0) { // If this connect is as a result of a command alias, don't check appls or we will loop @@ -2723,33 +2788,7 @@ NoPort: } } - // 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 - - if (cmdCopy[0] != ' ') - { - i = 0; - - while (cmdCopy[i] >= '0' && cmdCopy[i]<= '9') - i++; - - if (i && cmdCopy[i] != ' ') // have an all digit param = probably a service - goto Downlink; - else - { - if (i > 0) // Some digits - { - haveService = 1; - Service = atoi(cmdCopy); - } - } - } - - if (axcalls[7] == 0 || haveService) + if (axcalls[7] == 0) { // SEE IF CALL TO ANOTHER NODE @@ -2792,9 +2831,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 +5118,7 @@ VOID DoTheCommand(TRANSPORTENTRY * Session) int n; int i, Service = -1; char * Cmd, *Node, *Context; + int Stay = 0; ptr1 = &COMMANDBUFFER[0]; // @@ -5176,28 +5213,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 +5270,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..dd9bdf6 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -87,8 +87,6 @@ void CloseAllLinks(); void hookNodeClosing(char * Reason); void NETROMTCPResolve(); -extern uint64_t INP3timeLoadedMS; - BOOL IncludesMail = FALSE; BOOL IncludesChat = FALSE; @@ -861,8 +859,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..0710f73 100644 --- a/NETROMTCP.c +++ b/NETROMTCP.c @@ -110,7 +110,7 @@ struct ConnectionInfo * AllocateNRTCPRec() sockptr->SocketActive = TRUE; sockptr->ConnectTime = sockptr->LastSendTime = time(NULL); - Debugprintf("NRTCP Allocated %d", i); +// Debugprintf("NRTCP Allocated %d", i); return sockptr; } } @@ -217,7 +217,7 @@ int NETROMOpenConnection(struct ROUTE * Route) farCall[ConvFromAX25(Route->NEIGHBOUR_CALL, farCall)] = 0; - Debugprintf("Opening NRTCP Connection to %s", farCall); +// Debugprintf("Opening NRTCP Connection to %s", farCall); if (Route->TCPSession) { @@ -366,14 +366,14 @@ 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"); +// Debugprintf("NRTCP Connection Accepted"); } void NETROMConnected(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info) { // Connection Complete - Debugprintf("NRTCP Connected"); +// Debugprintf("NRTCP Connected"); sockptr->Connecting = FALSE; sockptr->Connected = TRUE; @@ -428,7 +428,7 @@ checkLen: // 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); +// Debugprintf("New NRTCP Connection from %s", Msg->Call); memcpy(Info->Call, Msg->Call, 10); @@ -461,8 +461,13 @@ checkLen: if (memcmp(Info->Call, Msg->Call, 10) != 0) { - Debugprintf("Mismatch"); - // something wrong - maybe connection reused + 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 @@ -593,6 +598,7 @@ void NETROMConnectionLost(struct ConnectionInfo * sockptr) Route->TCPSession = 0; Info->Call[0] = 0; + Info->LINK->L2STATE = 0; } sockptr->SocketActive = FALSE; diff --git a/Versions.h b/Versions.h index a988953..25ed90e 100644 --- a/Versions.h +++ b/Versions.h @@ -10,8 +10,8 @@ #endif -#define KVers 6,0,25,11 -#define KVerstring "6.0.25.11\0" +#define KVers 6,0,25,12 +#define KVerstring "6.0.25.12\0" #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