diff --git a/.rej b/.rej new file mode 100644 index 0000000..1137117 --- /dev/null +++ b/.rej @@ -0,0 +1,139 @@ +--- APRSCode.c ++++ APRSCode.c +@@ -3674,7 +3674,7 @@ + if (ptr1) + *ptr1 = 0; + +-// Debugprintf("Duplicate Message supressed %s", Msg); ++// Debugprintf("Duplicate Message suppressed %s", Msg); + return TRUE; // Duplicate + } + } +--- BPQChat.rc ++++ BPQChat.rc +@@ -162,7 +162,7 @@ + WS_VSCROLL + DEFPUSHBUTTON "Save Welcome Message",SAVEWELCOME,140,296,91,14, + BS_CENTER | BS_VCENTER +- LTEXT " If the node is not directly connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands seperared by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT", ++ LTEXT " If the node is not directly connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands separated by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT", + IDC_STATIC,9,52,355,24 + END + +--- BPQMail.rc ++++ BPQMail.rc +@@ -1045,7 +1045,7 @@ + CONTROL "Delete Log and Message Files to Recycle Bin", + IDC_DELETETORECYCLE,"Button",BS_AUTOCHECKBOX | + BS_LEFTTEXT | BS_MULTILINE | WS_TABSTOP,5,142,115,20 +- CONTROL "Supress Mailing of Housekeeping Results", ++ CONTROL "Suppress Mailing of Housekeeping Results", + IDC_MAINTNOMAIL,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | + BS_MULTILINE | WS_TABSTOP,5,182,115,20 + CONTROL "Generate Traffic Report",IDC_MAINTTRAFFIC,"Button", +--- HanksRT.c ++++ HanksRT.c +@@ -1186,7 +1186,7 @@ + // Duplicate, so discard, but save time + + DupInfo[i].DupTime = Now; +- Logprintf(LOG_CHAT, circuit, '?', "Duplicate Message From %s %s supressed", Call, Msg); ++ Logprintf(LOG_CHAT, circuit, '?', "Duplicate Message From %s %s suppressed", Call, Msg); + + return TRUE; // Duplicate + } +--- RigControl.c ++++ RigControl.c +@@ -8385,7 +8385,7 @@ + + switch (Msg[0]) + { +- case 'f': // Get Freqency ++ case 'f': // Get Frequency + + HLGetFreq(Sock, RIG, sep); + return 0; +--- UZ7HODrv.c ++++ UZ7HODrv.c +@@ -374,7 +374,7 @@ + { + // Read Freq + +- buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "UZ7HO} Modem Freqency %d\r", AGW->CenterFreq); ++ buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "UZ7HO} Modem Frequency %d\r", AGW->CenterFreq); + return 1; + } + +@@ -382,7 +382,7 @@ + + if (AGW->CenterFreq == 0) + { +- buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "UZ7HO} Invalid Modem Freqency\r"); ++ buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "UZ7HO} Invalid Modem Frequency\r"); + return 1; + } + +--- WinRPRHelper.c ++++ WinRPRHelper.c +@@ -111,7 +111,7 @@ + + if (argc < 3) + { +- printf ("Missing paramters - you need COM port and IP Address and rigctl port of BPQ, eg \r\n" ++ printf ("Missing parameters - you need COM port and IP Address and rigctl port of BPQ, eg \r\n" + " WinRPRHelper com10 192.168.1.64:4532\r\n\r\n" + "Press any key to exit\r\n"); + +--- config.c ++++ config.c +@@ -649,7 +649,7 @@ + if (LOCATOR[0] == 0 && LocSpecified == 0 && RFOnly == 0) + { + Consoleprintf(""); +- Consoleprintf("Please enter a LOCATOR statment in your BPQ32.cfg"); ++ Consoleprintf("Please enter a LOCATOR statement in your BPQ32.cfg"); + Consoleprintf("If you really don't want to be on the Node Map you can enter LOCATOR=NONE"); + Consoleprintf(""); + +--- kiss.c ++++ kiss.c +@@ -1485,7 +1485,7 @@ + } + } + else +- Debugprintf("Polled KISS - response from wrong address - Polled %d Reponse %d", ++ Debugprintf("Polled KISS - response from wrong address - Polled %d Response %d", + KISS->POLLPOINTER->OURCTRL, (Port->RXMSG[0] & 0xf0)); + + goto SeeifMore; // SEE IF ANYTHING ELSE +--- templatedefs.c ++++ templatedefs.c +@@ -1165,7 +1165,7 @@ + "Send Non-delivery Notifications
\r\n" + "for P and T messages
\r\n" + "
\r\n" +- "Supress Mailing of
\r\n" ++ "Suppress Mailing of
\r\n" + "Housekeeping Result

\r\n" + "Generate Traffic Report

\r\n" + "
\r\n" +@@ -1454,7 +1454,7 @@ + "
The Nodes to link to box defines which other Chat Nodes should be connected to, or from which " + "connections may be accepted. The format is ALIAS:CALL, eg BPQCHT:G8BPQ-4. If the node is not directly " + "connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands " +- "seperared by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT" ++ "separated by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT" + + "

The Callsign of the Chat Node is not defined here - it is obtained from the bpq32.cfg APPLICATION line corresponding to the Chat Appl Number.
\r\n" + "
\n" +--- WebMail.c ++++ WebMail.c +@@ -2020,7 +2020,7 @@ + "document.getElementById('myform').action = '/WebMail/QuoteOriginal' + '?%s';" + " document.getElementById('myform').submit();}" + ""; ++ "value='Include Original Msg'>"; + + char Temp[1024]; + char ReplyAddr[128]; diff --git a/AGWAPI.c b/AGWAPI.c index 80c1ce4..462fe86 100644 --- a/AGWAPI.c +++ b/AGWAPI.c @@ -128,7 +128,7 @@ int DataSocket_Write(struct AGWSocketConnectionInfo * sockptr, SOCKET sock); int AGWGetSessionKey(char * key, struct AGWSocketConnectionInfo * sockptr); int ProcessAGWCommand(struct AGWSocketConnectionInfo * sockptr); int SendDataToAppl(int Stream, byte * Buffer, int Length); -int InternalAGWDecodeFrame(char * msg, char * buffer, int Stamp, int * FrameType, int useLocalTime, int doNodes); +int InternalAGWDecodeFrame(char * msg, char * buffer, time_t Stamp, int * FrameType, int useLocalTime, int doNodes); int AGWDataSocket_Disconnect( struct AGWSocketConnectionInfo * sockptr); int SendRawPacket(struct AGWSocketConnectionInfo * sockptr, char *txmsg, int Length); int ShowApps(); @@ -402,7 +402,7 @@ int SetUpHostSessions() extern struct DATAMESSAGE * REPLYBUFFER; extern BOOL AGWActive; -VOID SHOWAGW(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID SHOWAGW(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // DISPLAY AGW Session Status diff --git a/AGWMoncode.c b/AGWMoncode.c index 84f4fe3..bd5a7e8 100644 --- a/AGWMoncode.c +++ b/AGWMoncode.c @@ -61,7 +61,6 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #define NODES_SIG 0xFF -char * strlop(char * buf, char delim); UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, int msglen); static UCHAR * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen, int DoNodes); diff --git a/AISCommon.c b/AISCommon.c index a193d2f..d33f25a 100644 --- a/AISCommon.c +++ b/AISCommon.c @@ -832,6 +832,7 @@ void SaveNavAidDataBase() char FN[256]; struct NAVAIDRECORD * navptr; + if (BPQDirectory[0] == 0) { strcpy(FN, "AIS_NavAids.txt"); @@ -2372,6 +2373,8 @@ void ProcessAISNavAidMessage() NavAidCount++; ProcessAISNavAidMessage(); + NavAidDBChanged = 1; + return; diff --git a/APRSCode.c b/APRSCode.c index b8f02f0..497ea74 100644 --- a/APRSCode.c +++ b/APRSCode.c @@ -22,7 +22,6 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // First Version, November 2011 #pragma data_seg("_BPQDATA") - #define _CRT_SECURE_NO_DEPRECATE #include @@ -63,7 +62,6 @@ VOID __cdecl Debugprintf(const char * format, ...); VOID __cdecl Consoleprintf(const char * format, ...); BOOL APIENTRY Send_AX(PMESSAGE Block, DWORD Len, UCHAR Port); VOID Send_AX_Datagram(PDIGIMESSAGE Block, DWORD Len, UCHAR Port); -char * strlop(char * buf, char delim); int APRSDecodeFrame(char * msg, char * buffer, time_t Stamp, uint64_t Mask); // Unsemaphored DecodeFrame APRSHEARDRECORD * UpdateHeard(UCHAR * Call, int Port); BOOL CheckforDups(char * Call, char * Msg, int Len); @@ -349,7 +347,7 @@ APRSHEARDRECORD MHTABLE[MAXHEARD] = {0}; APRSHEARDRECORD * MHDATA = &MHTABLE[0]; -static SOCKET sock = (SOCKET)0; +static SOCKET sock = 0; //Duplicate suppression Code @@ -3114,7 +3112,7 @@ VOID APRSISThread(void * Report) BOOL bcopt=TRUE; char Buffer[1000]; int InputLen = 1; // Non-zero - char errmsg[100]; + char errmsg[300]; char * ptr; size_t inptr = 0; char APRSinMsg[1000]; @@ -3675,7 +3673,7 @@ BOOL CheckforDups(char * Call, char * Msg, int Len) if (ptr1) *ptr1 = 0; -// Debugprintf("Duplicate Message supressed %s", Msg); +// Debugprintf("Duplicate Message suppressed %s", Msg); return TRUE; // Duplicate } } @@ -7667,7 +7665,7 @@ VOID APRSProcessHTTPMessage(SOCKET sock, char * MsgPtr, BOOL LOCAL, BOOL COOKIE) } - OutputLen += sprintf(&OutBuffer[OutputLen], WebTrailer); + OutputLen += sprintf(&OutBuffer[OutputLen], "%s", WebTrailer); HeaderLen = sprintf(Header, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); sendandcheck(sock, Header, HeaderLen); @@ -7712,7 +7710,7 @@ VOID APRSProcessHTTPMessage(SOCKET sock, char * MsgPtr, BOOL LOCAL, BOOL COOKIE) } - OutputLen += sprintf(&OutBuffer[OutputLen], WebTrailer); + OutputLen += sprintf(&OutBuffer[OutputLen], "%s", WebTrailer); HeaderLen = sprintf(Header, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); sendandcheck(sock, Header, HeaderLen); @@ -8114,7 +8112,7 @@ extern char OrigCmdBuffer[81]; BOOL isSYSOP(TRANSPORTENTRY * Session, char * Bufferptr); -VOID APRSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID APRSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // APRS Subcommands. Default for compatibility is APRSMH @@ -9179,7 +9177,7 @@ void GetSavedAPRSMessages() if ((file = fopen(FN, "r")) == NULL) return ; - while (fgets(Line, 512, file)) + while (fgets(Line, sizeof(Line), file)) { Stamp = Line; From = strlop(Stamp, ' '); diff --git a/APRSCode.c.orig b/APRSCode.c.orig new file mode 100644 index 0000000..b4ed594 --- /dev/null +++ b/APRSCode.c.orig @@ -0,0 +1,9223 @@ +/* +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 +*/ + +// Module to implement APRS "New Paradigm" Digipeater and APRS-IS Gateway + +// First Version, November 2011 + +#pragma data_seg("_BPQDATA") + +#define _CRT_SECURE_NO_DEPRECATE + +#include +#include "CHeaders.h" +#include "bpq32.h" +#include +#include "kernelresource.h" + +#include "tncinfo.h" + +#include "bpqaprs.h" + +#ifndef WIN32 + +#include +#include +#include + +int sfd; +struct sockaddr_un my_addr, peer_addr; +socklen_t peer_addr_size; + + +#endif + + +#define MAXAGE 3600 * 12 // 12 Hours +#define MAXCALLS 20 // Max Flood, Trace and Digi +#define GATETIMELIMIT 40 * 60 // Don't gate to RF if station not heard for this time (40 mins) + +static BOOL APIENTRY GETSENDNETFRAMEADDR(); +static VOID DoSecTimer(); +static VOID DoMinTimer(); +static int APRSProcessLine(char * buf); +static BOOL APRSReadConfigFile(); +VOID APRSISThread(void * Report); +VOID __cdecl Debugprintf(const char * format, ...); +VOID __cdecl Consoleprintf(const char * format, ...); +BOOL APIENTRY Send_AX(PMESSAGE Block, DWORD Len, UCHAR Port); +VOID Send_AX_Datagram(PDIGIMESSAGE Block, DWORD Len, UCHAR Port); +int APRSDecodeFrame(char * msg, char * buffer, time_t Stamp, uint64_t Mask); // Unsemaphored DecodeFrame +APRSHEARDRECORD * UpdateHeard(UCHAR * Call, int Port); +BOOL CheckforDups(char * Call, char * Msg, int Len); +VOID ProcessQuery(char * Query); +VOID ProcessSpecificQuery(char * Query, int Port, char * Origin, char * DestPlusDigis); +VOID CheckandDigi(DIGIMESSAGE * Msg, int Port, int FirstUnused, int Digis, int Len); +VOID SendBeacon(int toPort, char * Msg, BOOL SendISStatus, BOOL SendSOGCOG); +Dll BOOL APIENTRY PutAPRSMessage(char * Frame, int Len); +VOID ProcessAPRSISMsg(char * APRSMsg); +static VOID SendtoDigiPorts(PDIGIMESSAGE Block, DWORD Len, UCHAR Port); +APRSHEARDRECORD * FindStationInMH(char * call); +BOOL OpenGPSPort(); +void PollGPSIn(); +int CountLocalStations(); +BOOL SendAPPLAPRSMessage(char * Frame); +VOID SendAPRSMessage(char * Message, int toPort); +static VOID TCPConnect(void * unuxed); +struct STATIONRECORD * DecodeAPRSISMsg(char * msg); +struct STATIONRECORD * ProcessRFFrame(char * buffer, int len, int * ourMessage); +VOID APRSSecTimer(); +double myDistance(double laa, double loa, BOOL KM); +struct STATIONRECORD * FindStation(char * Call, BOOL AddIfNotFound); +int DecodeAPRSPayload(char * Payload, struct STATIONRECORD * Station); +BOOL KillOldTNC(char * Path); + +BOOL ToLOC(double Lat, double Lon , char * Locator); +BOOL InternalSendAPRSMessage(char * Text, char * Call); +void UndoTransparency(char * input); +char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char * format, ...); +char * GetStandardPage(char * FN, int * Len); +VOID WriteMiniDump(); +BOOL ProcessConfig(); +int ProcessAISMessage(char * msg, int len); +int read_png(unsigned char *bytes); +VOID sendandcheck(SOCKET sock, const char * Buffer, int Len); +void SaveAPRSMessage(struct APRSMESSAGE * ptr); +void ClearSavedMessages(); +void GetSavedAPRSMessages(); +static VOID GPSDConnect(void * unused); +int CanPortDigi(int Port); +int FromLOC(char * Locator, double * pLat, double * pLon); + +extern int SemHeldByAPI; +extern int APRSMONDECODE(); +extern struct ConsoleInfo MonWindow; +extern char VersionString[]; + +BOOL SaveAPRSMsgs = 0; + +BOOL LogAPRSIS = FALSE; + +// All data should be initialised to force into shared segment + +static char ConfigClassName[]="CONFIG"; + +extern BPQVECSTRUC * APRSMONVECPTR; + +extern int MONDECODE(); +extern VOID * zalloc(int len); +extern BOOL StartMinimized; + +extern char TextVerstring[]; + +extern HWND hConsWnd; +extern HKEY REGTREE; + +extern char LOCATOR[80]; +extern char LOC[7]; + +static int SecTimer = 10; +static int MinTimer = 60; + +BOOL APRSApplConnected = FALSE; +BOOL APRSWeb = FALSE; + +void * APPL_Q = 0; // Queue of frames for APRS Appl +void * APPLTX_Q = 0; // Queue of frames from APRS Appl +uint64_t APRSPortMask = 0; + +char APRSCall[10] = ""; +char APRSDest[10] = "APBPQ1"; + +char WXCall[10]; + +UCHAR AXCall[7] = ""; + +char CallPadded[10] = " "; + +char GPSPort[80] = ""; +int GPSSpeed = 0; +char GPSRelay[80] = ""; + +BOOL GateLocal = FALSE; +double GateLocalDistance = 0.0; + +int MaxDigisforIS = 7; // Dont send to IS if more digis uued to reach us + +char WXFileName[MAX_PATH]; +char WXComment[80]; +BOOL SendWX = FALSE; +int WXInterval = 30; +int WXCounter = 29 * 60; + +char APRSCall[10]; +char LoppedAPRSCall[10]; + +BOOL WXPort[MaxBPQPortNo + 1]; // Ports to send WX to + +BOOL GPSOK = 0; + +char LAT[] = "0000.00N"; // in standard APRS Format +char LON[] = "00000.00W"; //in standard APRS Format + +char HostName[80]; // for BlueNMEA +int HostPort = 4352; + +char GPSDHost[80]; +int GPSDPort = 2947; + + +extern int ADSBPort; +extern char ADSBHost[]; + +BOOL BlueNMEAOK = FALSE; +int BlueNMEATimer = 0; + +BOOL GPSDOK = FALSE; +int GPSDTimer = 0; + + +BOOL GPSSetsLocator = 0; // Update Map Location from GPS + +double SOG, COG; // From GPS + +double Lat = 0.0; +double Lon = 0.0; + +BOOL PosnSet = FALSE; +/* +The null position should be include the \. symbol (unknown/indeterminate +position). For example, a Position Report for a station with unknown position +will contain the coordinates …0000.00N\00000.00W.… +*/ +char * FloodCalls = 0; // Calls to relay using N-n without tracing +char * TraceCalls = 0; // Calls to relay using N-n with tracing +char * DigiCalls = 0; // Calls for normal relaying + +UCHAR FloodAX[MAXCALLS][7] = {0}; +UCHAR TraceAX[MAXCALLS][7] = {0}; +UCHAR DigiAX[MAXCALLS][7] = {0}; + +int FloodLen[MAXCALLS]; +int TraceLen[MAXCALLS]; +int DigiLen[MAXCALLS]; + +int ISPort = 0; +char ISHost[256] = ""; +int ISPasscode = 0; +char NodeFilter[1000] = "m/50"; // Filter when the isn't an application +char ISFilter[1000] = "m/50"; // Current Filter +char APPLFilter[1000] = ""; // Filter when an Applcation is running + +extern BOOL IGateEnabled; + +char StatusMsg[256] = ""; // Must be in shared segment +int StatusMsgLen = 0; + +char * BeaconPath[65] = {0}; + +char CrossPortMap[65][65] = {0}; +char APRSBridgeMap[65][65] = {0}; + +UCHAR BeaconHeader[65][10][7] = {""}; // Dest, Source and up to 8 digis +int BeaconHddrLen[65] = {0}; // Actual Length used + +UCHAR GatedHeader[65][10][7] = {""}; // Dest, Source and up to 8 digis for messages gated from IS +int GatedHddrLen[65] = {0}; // Actual Length used + + +char CFGSYMBOL = 'a'; +char CFGSYMSET = 'B'; + +char SYMBOL = '='; // Unknown Locaton +char SYMSET = '/'; + +char * PHG = 0; // Optional PHG (Power-Height-Gain) string for beacon + +BOOL TraceDigi = FALSE; // Add Trace to packets relayed on Digi Calls +BOOL SATGate = FALSE; // Delay Gating to IS directly heard packets +BOOL RXOnly = FALSE; // Run as RX only IGATE, ie don't gate anything to RF + +BOOL DefaultLocalTime = FALSE; +BOOL DefaultDistKM = FALSE; + +int multiple = 0; // Allows multiple copies of LinBPQ/APRS on one machine + +extern BOOL needAIS; + +extern unsigned long long IconData[]; // Symbols as a png image. + +typedef struct _ISDELAY +{ + struct _ISDELAY * Next; + char * ISMSG; + time_t SendTIme; +} ISDELAY; + +ISDELAY * SatISQueue = NULL; + +int MaxTraceHops = 2; +int MaxFloodHops = 2; + +int BeaconInterval = 0; +int MobileBeaconInterval = 0; +time_t LastMobileBeacon = 0; +int BeaconCounter = 0; +int IStatusCounter = 3600; // Used to send ?ISTATUS? Responses +//int StatusCounter = 0; // Used to send Status Messages + +char RunProgram[128] = ""; // Program to start + +BOOL APRSISOpen = FALSE; +BOOL BeacontoIS = TRUE; + +int ISDelayTimer = 0; // Time before trying to reopen APRS-IS link + +char APRSDESTS[][7] = {"AIR*", "ALL*", "AP*", "BEACON", "CQ*", "GPS*", "DF*", "DGPS*", "DRILL*", + "DX*", "ID*", "JAVA*", "MAIL*", "MICE*", "QST*", "QTH*", "RTCM*", "SKY*", + "SPACE*", "SPC*", "SYM*", "TEL*", "TEST*", "TLM*", "WX*", "ZIP"}; + +UCHAR AXDESTS[30][7] = {""}; +int AXDESTLEN[30] = {0}; + +UCHAR axTCPIP[7]; +UCHAR axRFONLY[7]; +UCHAR axNOGATE[7]; + +int MessageCount = 0; + +struct PortInfo +{ + int Index; + int ComPort; + char PortType[2]; + BOOL NewVCOM; // Using User Mode Virtual COM Driver + int ReopenTimer; // Retry if open failed delay + int RTS; + int CTS; + int DCD; + int DTR; + int DSR; + char Params[20]; // Init Params (eg 9600,n,8) + char PortLabel[20]; + HANDLE hDevice; + BOOL Created; + BOOL PortEnabled; + int FLOWCTRL; + int gpsinptr; +#ifdef WIN32 + OVERLAPPED Overlapped; + OVERLAPPED OverlappedRead; +#endif + char GPSinMsg[160]; + int GPSTypeFlag; // GPS Source flags + BOOL RMCOnly; // Only send RMC msgs to this port +}; + + + +struct PortInfo InPorts[1] = {0}; + +// Heard Station info + +#define MAXHEARD 1000 + +int HEARDENTRIES = 0; +int MAXHEARDENTRIES = 0; +int MHLEN = sizeof(APRSHEARDRECORD); + +// Area is allocated as needed + +APRSHEARDRECORD MHTABLE[MAXHEARD] = {0}; + +APRSHEARDRECORD * MHDATA = &MHTABLE[0]; + +static SOCKET sock = (SOCKET)0; + +//Duplicate suppression Code + +#define MAXDUPS 100 // Number to keep +#define DUPSECONDS 28 // Time to Keep + +struct DUPINFO +{ + time_t DupTime; + int DupLen; + char DupUser[8]; // Call in ax.35 format + char DupText[100]; +}; + +struct DUPINFO DupInfo[MAXDUPS]; + +struct OBJECT +{ + struct OBJECT * Next; + UCHAR Path[10][7]; // Dest, Source and up to 8 digis + int PathLen; // Actual Length used + char Message[81]; + char PortMap[MaxBPQPortNo + 1]; + int Interval; + int Timer; +}; + +struct OBJECT * ObjectList; // List of objects to send; + +int ObjectCount = 0; + +#include + +#define M_PI 3.14159265358979323846 + +int RetryCount = 4; +int RetryTimer = 45; +int ExpireTime = 120; +int TrackExpireTime = 1440; +BOOL SuppressNullPosn = FALSE; +BOOL DefaultNoTracks = FALSE; + +int MaxStations = 1000; + +int SharedMemorySize = 0; + + +RECT Rect, MsgRect, StnRect; + +char Key[80]; + +// function prototypes + +VOID RefreshMessages(); + +// a few global variables + +char APRSDir[MAX_PATH] = "BPQAPRS"; +char DF[MAX_PATH]; + +#define FEND 0xC0 // KISS CONTROL CODES +#define FESC 0xDB +#define TFEND 0xDC +#define TFESC 0xDD + +int StationCount = 0; + +UCHAR NextSeq = 1; + +// Stationrecords are stored in a shared memory segment. based at APRSStationMemory (normally 0x43000000) + +// A pointer to the first is placed at the start of this + +struct STATIONRECORD ** StationRecords = NULL; +struct STATIONRECORD * StationRecordPool = NULL; +struct APRSMESSAGE * MessageRecordPool = NULL; + +struct SharedMem * SMEM; + +UCHAR * Shared; +UCHAR * StnRecordBase; + +VOID SendObject(struct OBJECT * Object); +VOID MonitorAPRSIS(char * Msg, int MsgLen, BOOL TX); + +#ifndef WIN32 +#define WSAEWOULDBLOCK 11 +#endif + +HANDLE hMapFile; + +// Logging + +static int LogAge = 14; + +#ifdef WIN32 + +int DeleteAPRSLogFiles() +{ + WIN32_FIND_DATA ffd; + + char szDir[MAX_PATH]; + char File[MAX_PATH]; + HANDLE hFind = INVALID_HANDLE_VALUE; + DWORD dwError=0; + LARGE_INTEGER ft; + time_t now = time(NULL); + int Age; + + // Prepare string for use with FindFile functions. First, copy the + // string to a buffer, then append '\*' to the directory name. + + strcpy(szDir, GetLogDirectory()); + strcat(szDir, "/logs/APRS*.log"); + + // Find the first file in the directory. + + hFind = FindFirstFile(szDir, &ffd); + + if (INVALID_HANDLE_VALUE == hFind) + return dwError; + + // Walk directory + + do + { + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + OutputDebugString(ffd.cFileName); + } + else + { + ft.HighPart = ffd.ftCreationTime.dwHighDateTime; + ft.LowPart = ffd.ftCreationTime.dwLowDateTime; + + ft.QuadPart -= 116444736000000000; + ft.QuadPart /= 10000000; + + Age = (int)((now - ft.LowPart) / 86400); + + if (Age > LogAge) + { + sprintf(File, "%s/logs/%s%c", GetLogDirectory(), ffd.cFileName, 0); + Debugprintf("Deleting %s", File); + DeleteFile(File); + } + } + } + while (FindNextFile(hFind, &ffd) != 0); + + FindClose(hFind); + return dwError; +} + +#else + +#include + +int APRSFilter(const struct dirent * dir) +{ + return (memcmp(dir->d_name, "APRS", 4) == 0 && strstr(dir->d_name, ".log")); +} + +int DeleteAPRSLogFiles() +{ + struct dirent **namelist; + int n; + struct stat STAT; + time_t now = time(NULL); + int Age = 0, res; + char FN[256]; + + n = scandir("logs", &namelist, APRSFilter, alphasort); + + if (n < 0) + perror("scandir"); + else + { + while(n--) + { + sprintf(FN, "logs/%s", namelist[n]->d_name); + if (stat(FN, &STAT) == 0) + { + Age = (now - STAT.st_mtime) / 86400; + + if (Age > LogAge) + { + Debugprintf("Deleting %s\n", FN); + unlink(FN); + } + } + free(namelist[n]); + } + free(namelist); + } + return 0; +} +#endif + +int APRSWriteLog(char * msg) +{ + FILE *file; + UCHAR Value[MAX_PATH]; + time_t T; + struct tm * tm; + + if (LogAPRSIS == 0) + return 0; + + if (strchr(msg, '\n') == 0) + strcat(msg, "\r\n"); + + T = time(NULL); + tm = gmtime(&T); + + if (GetLogDirectory()[0] == 0) + { + strcpy(Value, "logs/APRS_"); + } + else + { + strcpy(Value, GetLogDirectory()); + strcat(Value, "/"); + strcat(Value, "logs/APRS_"); + } + + sprintf(Value, "%s%02d%02d%02d.log", Value, + tm->tm_year - 100, tm->tm_mon+1, tm->tm_mday); + + if ((file = fopen(Value, "ab")) == NULL) + return FALSE; + + fputs(msg, file); + fclose(file); + return 0; +} + + +int ISSend(SOCKET sock, char * Msg, int Len, int flags) +{ + int Loops = 0; + int Sent; + + MonitorAPRSIS(Msg, Len, TRUE); + + Sent = send(sock, Msg, Len, flags); + + while (Sent != Len && Loops++ < 300) // 10 secs max + { + if ((Sent == SOCKET_ERROR) && (WSAGetLastError() != WSAEWOULDBLOCK)) + return SOCKET_ERROR; + + if (Sent > 0) // something sent + { + Len -= Sent; + memmove(Msg, &Msg[Sent], Len); + } + + Sleep(30); + Sent = send(sock, Msg, Len, flags); + } + + return Sent; +} + +void * endofStations; + +Dll BOOL APIENTRY Init_APRS() +{ + int i; + char * DCall; + +#ifdef WIN32 + HKEY hKey=0; + int retCode, Vallen, Type; +#else + int fd; + char RX_SOCK_PATH[] = "BPQAPRSrxsock"; + char TX_SOCK_PATH[] = "BPQAPRStxsock"; + char SharedName[256]; + char * ptr1; +#endif + struct STATIONRECORD * Stn1, * Stn2; + struct APRSMESSAGE * Msg1, * Msg2; + + // Clear tables in case a restart + + StationRecords = NULL; + + StationCount = 0; + HEARDENTRIES = 0; + MAXHEARDENTRIES = 0; + MobileBeaconInterval = 0; + BeaconInterval = 0; + + DeleteAPRSLogFiles(); + + memset(MHTABLE, 0, sizeof(MHTABLE)); + + ConvToAX25(MYNODECALL, MYCALL); + + ConvToAX25("TCPIP", axTCPIP); + ConvToAX25("RFONLY", axRFONLY); + ConvToAX25("NOGATE", axNOGATE); + + memset(&FloodAX[0][0], 0, sizeof(FloodAX)); + memset(&TraceAX[0][0], 0, sizeof(TraceAX)); + memset(&DigiAX[0][0], 0, sizeof(DigiAX)); + + APRSPortMask = 0; + + memset(BeaconPath, sizeof(BeaconPath), 0); + + memset(&CrossPortMap[0][0], 0, sizeof(CrossPortMap)); + memset(&APRSBridgeMap[0][0], 0, sizeof(APRSBridgeMap)); + + for (i = 1; i <= MaxBPQPortNo; i++) + { + if (CanPortDigi(i)) + CrossPortMap[i][i] = TRUE; // Set Defaults - Same Port + CrossPortMap[i][0] = TRUE; // and APRS-IS + } + + PosnSet = 0; + ObjectList = NULL; + ObjectCount = 0; + + ISPort = ISHost[0] = ISPasscode = 0; + + if (APRSReadConfigFile() == 0) + return FALSE; + + if (APRSCall[0] == 0) + { + strcpy(APRSCall, MYNODECALL); + strlop(APRSCall, ' '); + strcpy(LoppedAPRSCall, APRSCall); + memcpy(CallPadded, APRSCall, (int)strlen(APRSCall)); // Call Padded to 9 chars for APRS Messaging + ConvToAX25(APRSCall, AXCall); + } + + if (WXCall[0] == 0) + strcpy(WXCall, APRSCall); + + // Caluclate size of Shared Segment + + SharedMemorySize = sizeof(struct STATIONRECORD) * (MaxStations + 4) + + sizeof(struct APRSMESSAGE) * (MAXMESSAGES + 4) + 32; // 32 for header + + +#ifndef WIN32 + + // Create a Shared Memory Object + + Shared = NULL; + + // Append last bit of current directory to shared name + + ptr1 = BPQDirectory; + + while (strchr(ptr1, '/')) + { + ptr1 = strchr(ptr1, '/'); + ptr1++; + } + + if (multiple) + sprintf(SharedName, "/BPQAPRSSharedMem%s", ptr1); + else + strcpy(SharedName, "/BPQAPRSSharedMem"); + + printf("Using Shared Memory %s\n", SharedName); + +#ifndef WIN32 + + fd = shm_open(SharedName, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (fd == -1) + { + perror("Create Shared Memory"); + printf("Create APRS Shared Memory Failed\n"); + } + else + { + if (ftruncate(fd, SharedMemorySize)) + { + perror("Extend Shared Memory"); + printf("Extend APRS Shared Memory Failed\n"); + } + else + { + // Map shared memory object + + Shared = mmap((void *)APRSSHAREDMEMORYBASE, + SharedMemorySize, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (Shared == MAP_FAILED) + { + perror("Map Shared Memory"); + printf("Map APRS Shared Memory Failed\n"); + Shared = NULL; + } + + if (Shared != (void *)APRSSHAREDMEMORYBASE) + { + printf("Map APRS Shared Memory Allocated at %x\n", Shared); + Shared = NULL; + } + + } + } + +#endif + + printf("Map APRS Shared Memory Allocated at %p\n", Shared); + + if (Shared == NULL) + { + printf("APRS not using shared memory\n"); + Shared = malloc(SharedMemorySize); + printf("APRS Non-Shared Memory Allocated at %x\n", Shared); + } + +#else + +#ifndef LINBPQ + + retCode = RegOpenKeyEx (REGTREE, + "SOFTWARE\\G8BPQ\\BPQ32", + 0, + KEY_QUERY_VALUE, + &hKey); + + if (retCode == ERROR_SUCCESS) + { + Vallen = 4; + retCode = RegQueryValueEx(hKey, "IGateEnabled", 0, &Type, (UCHAR *)&IGateEnabled, &Vallen); + } + +#endif + + // Create Memory Mapping for Station List + + hMapFile = CreateFileMapping( + INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // maximum object size (high-order DWORD) + SharedMemorySize, // maximum object size (low-order DWORD) + "BPQAPRSStationsMappingObject");// name of mapping object + + if (hMapFile == NULL) + { + Consoleprintf("Could not create file mapping object (%d).\n", GetLastError()); + return 0; + } + + UnmapViewOfFile((void *)APRSSHAREDMEMORYBASE); + + + Shared = (LPTSTR) MapViewOfFileEx(hMapFile, // handle to map object + FILE_MAP_ALL_ACCESS, // read/write permission + 0, + 0, + SharedMemorySize, + (void *)APRSSHAREDMEMORYBASE); + + if (Shared == NULL) + { + Consoleprintf("Could not map view of file (%d).\n", GetLastError()); + CloseHandle(hMapFile); + return 0; + } + +#endif + + // First record has pointer to table + + memset(Shared, 0, SharedMemorySize); + + StnRecordBase = Shared + 32; + SMEM = (struct SharedMem *)Shared; + + SMEM->Version = 1; + SMEM->SharedMemLen = SharedMemorySize; + SMEM->NeedRefresh = TRUE; + SMEM->Arch = sizeof(void *); + SMEM->SubVersion = 1; + + Stn1 = (struct STATIONRECORD *)StnRecordBase; + + StationRecords = (struct STATIONRECORD **)Stn1; + + Stn1++; + + StationRecordPool = Stn1; + + for (i = 1; i < MaxStations; i++) // Already have first + { + Stn2 = Stn1; + Stn2++; + Stn1->Next = Stn2; + + Stn1 = Stn2; + } + + Debugprintf("End of Stations %p", Stn1); + endofStations = Stn1; + + Stn1 += 2; // Try to fix corruption of messages. + + // Build Message Record Pool + + Msg1 = (struct APRSMESSAGE *)Stn1; + + MessageRecordPool = Msg1; + + for (i = 1; i < MAXMESSAGES; i++) // Already have first + { + Msg2 = Msg1; + Msg2++; + Msg1->Next = Msg2; + + Msg1 = Msg2; + } + + if (PosnSet == 0) + { + SYMBOL = '.'; + SYMSET = '\\'; // Undefined Posn Symbol + } + else + { + // Convert posn to floating degrees + + char LatDeg[3], LonDeg[4]; + memcpy(LatDeg, LAT, 2); + LatDeg[2]=0; + Lat=atof(LatDeg) + (atof(LAT+2)/60); + + if (LAT[7] == 'S') Lat=-Lat; + + memcpy(LonDeg, LON, 3); + LonDeg[3]=0; + Lon=atof(LonDeg) + (atof(LON+3)/60); + + if (LON[8]== 'W') Lon=-Lon; + + SYMBOL = CFGSYMBOL; + SYMSET = CFGSYMSET; + } + + // First record has control info for APRS Mapping App + + Stn1 = (struct STATIONRECORD *)StnRecordBase; + memcpy(Stn1->Callsign, APRSCall, 10); + Stn1->Lat = Lat; + Stn1->Lon = Lon; + Stn1->LastPort = MaxStations; + +#ifndef WIN32 + + // Open unix socket for messaging app + + sfd = socket(AF_UNIX, SOCK_DGRAM, 0); + + if (sfd == -1) + { + perror("Socket"); + } + else + { + u_long param=1; + ioctl(sfd, FIONBIO, ¶m); // Set non-blocking + + memset(&my_addr, 0, sizeof(struct sockaddr_un)); + my_addr.sun_family = AF_UNIX; + strncpy(my_addr.sun_path, TX_SOCK_PATH, sizeof(my_addr.sun_path) - 1); + + memset(&peer_addr, 0, sizeof(struct sockaddr_un)); + peer_addr.sun_family = AF_UNIX; + strncpy(peer_addr.sun_path, RX_SOCK_PATH, sizeof(peer_addr.sun_path) - 1); + + unlink(TX_SOCK_PATH); + + if (bind(sfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr_un)) == -1) + perror("bind"); + } +#endif + + // Convert Dest ADDRS to AX.25 + + for (i = 0; i < 26; i++) + { + DCall = &APRSDESTS[i][0]; + if (strchr(DCall, '*')) + AXDESTLEN[i] = (int)strlen(DCall) - 1; + else + AXDESTLEN[i] = 6; + + ConvToAX25(DCall, &AXDESTS[i][0]); + } + + // Process any Object Definitions + + // Setup Heard Data Area + + HEARDENTRIES = 0; + MAXHEARDENTRIES = MAXHEARD; + + APRSMONVECPTR->HOSTAPPLFLAGS = 0x80; // Request Monitoring + + if (ISPort && IGateEnabled) + { + _beginthread(APRSISThread, 0, (VOID *) TRUE); + } + + if (GPSPort[0]) + OpenGPSPort(); + + WritetoConsole("APRS Digi/Gateway Enabled\n"); + + APRSWeb = TRUE; + + read_png((unsigned char *)IconData); + + // Reload saved messages + + if (SaveAPRSMsgs) + GetSavedAPRSMessages(); + + // If a Run parameter was supplied, run the program + + if (RunProgram[0] == 0) + return TRUE; + + #ifndef WIN32 + { + char * arg_list[] = {NULL, NULL}; + pid_t child_pid; + + signal(SIGCHLD, SIG_IGN); // Silently (and portably) reap children. + + // Fork and Exec program + + printf("Trying to start %s\n", RunProgram); + + arg_list[0] = RunProgram; + + // Duplicate this process. + + child_pid = fork (); + + if (child_pid == -1) + { + printf ("APRS fork() Failed\n"); + return 0; + } + + if (child_pid == 0) + { + execvp (arg_list[0], arg_list); + + // The execvp function returns only if an error occurs. + + printf ("Failed to run %s\n", RunProgram); + exit(0); // Kill the new process + } + } +#else + { + int n = 0; + + STARTUPINFO SInfo; // pointer to STARTUPINFO + PROCESS_INFORMATION PInfo; // pointer to PROCESS_INFORMATION + + SInfo.cb=sizeof(SInfo); + SInfo.lpReserved=NULL; + SInfo.lpDesktop=NULL; + SInfo.lpTitle=NULL; + SInfo.dwFlags=0; + SInfo.cbReserved2=0; + SInfo.lpReserved2=NULL; + + while (KillOldTNC(RunProgram) && n++ < 100) + { + Sleep(100); + } + + if (!CreateProcess(RunProgram, NULL, NULL, NULL, FALSE,0 ,NULL ,NULL, &SInfo, &PInfo)) + Debugprintf("Failed to Start %s Error %d ", RunProgram, GetLastError()); + } +#endif + + return TRUE; +} + +#define SD_RECEIVE 0x00 +#define SD_SEND 0x01 +#define SD_BOTH 0x02 + +BOOL APRSActive; + +VOID APRSClose() +{ + APRSActive = FALSE; + + if (sock) + { + shutdown(sock, SD_BOTH); + Sleep(50); + + closesocket(sock); + } +#ifdef WIN32 + if (InPorts[0].hDevice) + CloseHandle(InPorts[0].hDevice); +#endif +} + +time_t lastSecTimer = 0; + + +Dll VOID APIENTRY Poll_APRS() +{ + time_t Now = time(NULL); + + if (lastSecTimer != Now) + { + lastSecTimer = Now; + + DoSecTimer(); + + MinTimer--; + + if (MinTimer == 0) + { + MinTimer = 60; + DoMinTimer(); + } + } + + if (SMEM->ClearRX) + { + // Clear Received Messages request from GUI + + struct APRSMESSAGE * ptr = SMEM->Messages; + + // Move Message Queue to Free Queue + + if (ptr) + { + while (ptr->Next) // Find end of chain + { + ptr = ptr->Next; + } + + // ptr is end of chain - chain free pool to it + + ptr->Next = MessageRecordPool; + + MessageRecordPool = SMEM->Messages; + MessageCount = 0; + } + + SMEM->Messages = NULL; + SMEM->ClearRX = 0; + SMEM->NeedRefresh = TRUE; + + ClearSavedMessages(); + } + + if (SMEM->ClearTX) + { + // Clear Sent Messages )request from GUI + + struct APRSMESSAGE * ptr = SMEM->OutstandingMsgs; + + // Move Message Queue to Free Queue + + if (ptr) + { + while (ptr->Next) // Find end of chain + { + ptr = ptr->Next; + } + + // ptr is end of chain - chain free pool to it + + ptr->Next = MessageRecordPool; + + MessageRecordPool = SMEM->OutstandingMsgs; + MessageCount = 0; + } + + SMEM->OutstandingMsgs = NULL; + SMEM->ClearTX = 0; + SMEM->NeedRefresh = TRUE; + } +#ifdef LINBPQ +#ifndef WIN32 + { + char Msg[256]; + int numBytes; + + // Look for messages from App + + numBytes = recvfrom(sfd, Msg, 256, 0, NULL, NULL); + + if (numBytes > 0) + { + InternalSendAPRSMessage(&Msg[10], &Msg[0]); + } + } +#endif +#endif + + if (GPSPort[0]) + PollGPSIn(); + + if (APPLTX_Q) + { + PMSGWITHLEN buffptr = Q_REM(&APPLTX_Q); + + InternalSendAPRSMessage(&buffptr->Data[10], &buffptr->Data[0]); + ReleaseBuffer(buffptr); + } + + while (APRSMONVECPTR->HOSTTRACEQ) + { + time_t stamp; + int len; + BOOL MonitorNODES = FALSE; + PMESSAGE monbuff; + UCHAR * monchars; + MESSAGE * Orig; + int Digis = 0; + MESSAGE * AdjBuff; // Adjusted for digis + BOOL FirstUnused = FALSE; + int DigisUsed = 0; // Digis used to reach us + DIGIMESSAGE Msg = {0}; + int Port; + unsigned char buffer[1024]; + char ISMsg[500]; + char * ptr1; + char * Payload; + char * ptr3; + char * ptr4; + BOOL ThirdParty = FALSE; + BOOL NoGate = FALSE; + APRSHEARDRECORD * MH; + char MsgCopy[500]; + int toPort; + struct STATIONRECORD * Station; + int ourMessage = 0; + +#ifdef WIN32 + struct _EXCEPTION_POINTERS exinfo; + char EXCEPTMSG[80] = ""; +#endif + monbuff = Q_REM((VOID **)&APRSMONVECPTR->HOSTTRACEQ); + + monchars = (UCHAR *)monbuff; + AdjBuff = Orig = (MESSAGE *)monchars; // Adjusted for digis + + Port = Orig->PORT; + + if (Port & 0x80) // TX + { + ReleaseBuffer(monbuff); + continue; + } + + if ((APRSPortMask & ((uint64_t)1 << (Port - 1))) == 0)// Port in use for APRS? + { + ReleaseBuffer(monbuff); + continue; + } + + stamp = monbuff->Timestamp; + + if ((UCHAR)monchars[4] & 0x80) // TX + { + ReleaseBuffer(monbuff); + continue; + } + + // See if digipeaters present. + + while ((AdjBuff->ORIGIN[6] & 1) == 0 && Digis < 9) + { + UCHAR * temp = (UCHAR *)AdjBuff; + temp += 7; + AdjBuff = (MESSAGE *)temp; + + // If we have already digi'ed it or if we sent it, + // ignore (Dup Check my fail on slow links) + + if (AdjBuff->ORIGIN[6] & 0x80) + { + // Used Digi + + if (memcmp(AdjBuff->ORIGIN, AXCall, 7) == 0) + { + ReleaseBuffer(monbuff); + return; + } + DigisUsed++; + } + + if (memcmp(AdjBuff->ORIGIN, axTCPIP, 6) == 0) + ThirdParty = TRUE; + + Digis ++; + + if (FirstUnused == FALSE && (AdjBuff->ORIGIN[6] & 0x80) == 0) + { + // Unused Digi - see if we should digi it + + FirstUnused = Digis; + // CheckDigi(buff, AdjBuff->ORIGIN); + } + } + + if (Digis > 8) + { + ReleaseBuffer(monbuff); + continue; // Corrupt + } + + if (Digis) + { + if (memcmp(AdjBuff->ORIGIN, axNOGATE, 6) == 0 + || memcmp(AdjBuff->ORIGIN, axRFONLY, 6) == 0 + || DigisUsed > MaxDigisforIS) + + // Too many digis or Last digis is NOGATE or RFONLY - dont send to IS + + NoGate = TRUE; + } + if (AdjBuff->CTL != 3 || AdjBuff->PID != 0xf0) // Only UI + { + ReleaseBuffer(monbuff); + continue; + } + + // Bridge if requested + + for (toPort = 1; toPort <= MaxBPQPortNo; toPort++) + { + if (APRSBridgeMap[Port][toPort]) + { + MESSAGE * Buffer = GetBuff(); + struct PORTCONTROL * PORT; + + if (Buffer) + { + memcpy(Buffer, Orig, Orig->LENGTH); + Buffer->PORT = toPort; + PORT = GetPortTableEntryFromPortNum(toPort); + + if (PORT) + { + if (PORT->SmartIDInterval && PORT->SmartIDNeeded == 0) + { + // Using Smart ID, but none scheduled + + PORT->SmartIDNeeded = time(NULL) + PORT->SmartIDInterval; + } + PUT_ON_PORT_Q(PORT, Buffer); + } + else + ReleaseBuffer(Buffer); + } + } + } + + // Used to check for dups here but according to "Notes to iGate developers" IS should be sent dups, and dup + // check only applied to digi'ing + +// if (SATGate == 0) +// { +// if (CheckforDups(Orig->ORIGIN, AdjBuff->L2DATA, Orig->LENGTH - Digis * 7 - (19 + sizeof(void *))) +// { +// ReleaseBuffer(monbuff); +// continue; +// } +// } + // Decode Frame to TNC2 Monitor Format + + len = APRSDecodeFrame((char *)monchars, buffer, stamp, APRSPortMask); + + if (len == 0) + { + // Couldn't Decode + + ReleaseBuffer(monbuff); + Debugprintf("APRS discarded frame - decode failed\n"); + continue; + } + + buffer[len] = 0; + + memcpy(MsgCopy, buffer, len); + MsgCopy[len] = 0; + + // Do internal Decode + +#ifdef WIN32 + + strcpy(EXCEPTMSG, "ProcessRFFrame"); + + __try + { + + Station = ProcessRFFrame(MsgCopy, len, &ourMessage); + } + #include "StdExcept.c" + + } +#else + Station = ProcessRFFrame(MsgCopy, len, &ourMessage); +#endif + + if (Station == NULL) + { + ReleaseBuffer(monbuff); + continue; + } + + memcpy(MsgCopy, buffer, len); // Process RF Frame may have changed it + MsgCopy[len] = 0; + + buffer[len++] = 10; + buffer[len] = 0; + ptr1 = &buffer[10]; // Skip Timestamp + Payload = strchr(ptr1, ':') + 2; // Start of Payload + ptr3 = strchr(ptr1, ' '); // End of addresses + *ptr3 = 0; + + // We should send path to IS unchanged, so create IS + // message before chopping path. We won't decide if + // we will actually send it to IS till later + + len = sprintf(ISMsg, "%s,qAR,%s:%s", ptr1, APRSCall, Payload); + + + // if digis, remove any unactioned ones + + if (Digis) + { + ptr4 = strchr(ptr1, '*'); // Last Used Digi + + if (ptr4) + { + // We need header up to ptr4 + + *(ptr4) = 0; + } + else + { + // No digis actioned - remove them all + + ptr4 = strchr(ptr1, ','); // End of Dest + if (ptr4) + *ptr4 = 0; + } + } + + ptr4 = strchr(ptr1, '>'); // End of Source + *ptr4++ = 0; + + MH = UpdateHeard(ptr1, Port); + + MH->Station = Station; + + if (ThirdParty) + { +// Debugprintf("Setting Igate Flag - %s", MsgCopy); + MH->IGate = TRUE; // if we've seen msgs to TCPIP, it must be an Igate + } + + if (NoGate || RXOnly) + goto NoIS; + + // I think all PID F0 UI frames go to APRS-IS, + // Except General Queries, Frames Gated from IS to RF, and Messages Addressed to us + + // or should we process Query frames locally ?? + + if (Payload[0] == '}') + goto NoIS; + + if (Payload[0] == '?') + { + // General Query + + ProcessQuery(&Payload[1]); + + // ?? Should we pass addressed Queries to IS ?? + + goto NoIS; + } + + if (Payload[0] == ':' && memcmp(&Payload[1], CallPadded, 9) == 0) + { + // Message for us + + if (Payload[11] == '?') // Only queries - the node doesnt do messaging + ProcessSpecificQuery(&Payload[12], Port, ptr1, ptr4); + + goto NoIS; + } + + if (APRSISOpen && CrossPortMap[Port][0]) // No point if not open + { + // was done above len = sprintf(ISMsg, "%s>%s,qAR,%s:%s", ptr1, ptr4, APRSCall, Payload); + + if (BeacontoIS == 0) + { + // Don't send anything we've received as an echo + + char SaveCall[7]; + memcpy(SaveCall, &monbuff->ORIGIN, 7); + SaveCall[6] &= 0x7e; // Mask End of address bit + + if (memcmp(SaveCall, AXCall, 7) == 0) // We sent it + { + // Should we check for being received via digi? - not for now + + goto NoIS; + } + } + + if (SATGate && (DigisUsed == 0)) + { + // If in Satgate mode delay directly heard to IGate + + ISDELAY * SatISEntry = malloc(sizeof(ISDELAY)); + SatISEntry->Next = NULL; + SatISEntry->ISMSG = _strdup(ISMsg); + SatISEntry->SendTIme = time(NULL) + 10; // Delay 10 seconds + + if (SatISQueue) + SatISEntry->Next = SatISQueue; // Chain + + SatISQueue = SatISEntry; + goto NoIS; + } + + ISSend(sock, ISMsg, len, 0); + + ptr1 = strchr(ISMsg, 13); + if (ptr1) *ptr1 = 0; +// Debugprintf(">%s", ISMsg); + } + + NoIS: + + // We skipped DUP check for SATGate Mode, so apply it here + + // Now we don't dup check earlier so always check here + +// if (SATGate) +// { + if (CheckforDups(Orig->ORIGIN, AdjBuff->L2DATA, Orig->LENGTH - Digis * 7 - (19 + sizeof(void *)))) + { + ReleaseBuffer(monbuff); + continue; + } +// } + + // See if it is an APRS frame + + // If MIC-E, we need to process, whatever the destination + + // Now process any dest + +/* + DEST = &Orig->DEST[0]; + + for (i = 0; i < 26; i++) + { + if (memcmp(DEST, &AXDESTS[i][0], AXDESTLEN[i]) == 0) + goto OK; + } + + switch(AdjBuff->L2DATA[0]) + { + case '`': + case 0x27: // ' + case 0x1c: + case 0x1d: // MIC-E + + break; + // default: + + // Not to an APRS Destination + +// ReleaseBuffer(monbuff); +// continue; + } + +OK: +*/ + + // If there are unused digis, we may need to digi it. + + if (ourMessage) + { + // A message addressed to us, so no point in digi'ing it + + ReleaseBuffer(monbuff); + continue; + } + + if (Digis == 0 || FirstUnused == 0) + { + // No Digis, so finished + + ReleaseBuffer(monbuff); + continue; + } + + if (memcmp(monbuff->ORIGIN, AXCall, 7) == 0) // We sent it + { + ReleaseBuffer(monbuff); + continue; + } + + // Copy frame to a DIGIMessage Struct + + memcpy(&Msg, monbuff, MSGHDDRLEN + 14 + (7 * Digis)); // Header, Dest, Source, Addresses and Digis + + len = Msg.LENGTH - (MSGHDDRLEN + 14) - (7 * Digis); // Payload Length (including CTL and PID + + memcpy(&Msg.CTL, &AdjBuff->CTL, len); + + // Pass to Digi Code + + CheckandDigi(&Msg, Port, FirstUnused, Digis, len); // Digi if necessary + + ReleaseBuffer(monbuff); + } + + return; +} + +VOID CheckandDigi(DIGIMESSAGE * Msg, int Port, int FirstUnused, int Digis, int Len) +{ + UCHAR * Digi = &Msg->DIGIS[--FirstUnused][0]; + UCHAR * Call; + int Index = 0; + int SSID; + + // Check ordinary digi first + + Call = &DigiAX[0][0]; + SSID = Digi[6] & 0x1e; + + while (*Call) + { + if ((memcmp(Digi, Call, 6) == 0) && ((Call[6] & 0x1e) == SSID)) + { + // Trace Call if enabled + + if (TraceDigi) + memcpy(Digi, AXCall, 7); + + // mark as used; + + Digi[6] |= 0x80; // Used bit + + SendtoDigiPorts(Msg, Len, Port); + return; + } + Call += 7; + Index++; + } + + Call = &TraceAX[0][0]; + Index = 0; + + while (*Call) + { + if (memcmp(Digi, Call, TraceLen[Index]) == 0) + { + // if possible move calls along + // insert our call, set used + // decrement ssid, and if zero, mark as used; + + SSID = (Digi[6] & 0x1E) >> 1; + + if (SSID == 0) + return; // Shouldn't have SSID 0 for Rrace/Flood + + if (SSID > MaxTraceHops) + SSID = MaxTraceHops; // Enforce our limit + + SSID--; + + if (SSID ==0) // Finihed with it ? + Digi[6] = (SSID << 1) | 0xe0; // Used and Fixed bits + else + Digi[6] = (SSID << 1) | 0x60; // Fixed bits + + if (Digis < 8) + { + memmove(Digi + 7, Digi, (Digis - FirstUnused) * 7); + } + + memcpy(Digi, AXCall, 7); + Digi[6] |= 0x80; + + SendtoDigiPorts(Msg, Len, Port); + + return; + } + Call += 7; + Index++; + } + + Index = 0; + Call = &FloodAX[0][0]; + + while (*Call) + { + if (memcmp(Digi, Call, FloodLen[Index]) == 0) + { + // decrement ssid, and if zero, mark as used; + + SSID = (Digi[6] & 0x1E) >> 1; + + if (SSID == 0) + return; // Shouldn't have SSID 0 for Trace/Flood + + if (SSID > MaxFloodHops) + SSID = MaxFloodHops; // Enforce our limit + + SSID--; + + if (SSID ==0) // Finihed with it ? + Digi[6] = (SSID << 1) | 0xe0; // Used and Fixed bits + else + Digi[6] = (SSID << 1) | 0x60; // Fixed bits + + SendtoDigiPorts(Msg, Len, Port); + + return; + } + Call += 7; + Index++; + } +} + + + +static VOID SendtoDigiPorts(PDIGIMESSAGE Block, DWORD Len, UCHAR Port) +{ + // Can't use API SENDRAW, as that tries to get the semaphore, which we already have + // Len is the Payload Length (from CTL onwards) + // The message can contain DIGIS - The payload must be copied forwards if there are less than 8 + + // We send to all ports enabled in CrossPortMap + + UCHAR * EndofDigis = &Block->CTL; + int i = 0; + int toPort; + + while (Block->DIGIS[i][0] && i < 8) + { + i++; + } + + EndofDigis = &Block->DIGIS[i][0]; + *(EndofDigis -1) |= 1; // Set End of Address Bit + + if (i != 8) + memmove(EndofDigis, &Block->CTL, Len); + + Len = Len + (i * 7) + 14; // Include Source, Dest and Digis + +// Block->DEST[6] &= 0x7e; // Clear End of Call +// Block->ORIGIN[6] |= 1; // Set End of Call + +// Block->CTL = 3; //UI + + for (toPort = 1; toPort <= MaxBPQPortNo; toPort++) + { + if (CrossPortMap[Port][toPort]) + Send_AX((PMESSAGE)Block, Len, toPort); + } + return; + +} + +VOID Send_AX_Datagram(PDIGIMESSAGE Block, DWORD Len, UCHAR Port) +{ + // Can't use API SENDRAW, as that tries to get the semaphore, which we already have + + // Len is the Payload Length (CTL, PID, Data) + + // The message can contain DIGIS - The payload must be copied forwards if there are less than 8 + + UCHAR * EndofDigis = &Block->CTL; + + int i = 0; + + while (Block->DIGIS[i][0] && i < 8) + { + i++; + } + + EndofDigis = &Block->DIGIS[i][0]; + *(EndofDigis -1) |= 1; // Set End of Address Bit + + if (i != 8) + memmove(EndofDigis, &Block->CTL, Len); // Include PID + + Len = Len + (i * 7) + 14; // Include Source, Dest and Digis + + Send_AX((PMESSAGE)Block, Len, Port); + + return; + +} + +static BOOL APRSReadConfigFile() +{ + char * Config; + char * ptr1, * ptr2; + + char buf[256],errbuf[256]; + + Config = PortConfig[APRSConfigSlot]; // Config from bpq32.cfg + + sprintf(StatusMsg, "BPQ32 Igate V %s", VersionString); // Set Default Status Message + + if (Config) + { + // Using config from bpq32.cfg + + ptr1 = Config; + + ptr2 = strchr(ptr1, 13); + while(ptr2) + { + memcpy(buf, ptr1, ptr2 - ptr1); + buf[ptr2 - ptr1] = 0; + ptr1 = ptr2 + 2; + ptr2 = strchr(ptr1, 13); + + strcpy(errbuf,buf); // save in case of error + + if (!APRSProcessLine(buf)) + { + WritetoConsole("APRS Bad config record "); + strcat(errbuf, "\r\n"); + WritetoConsole(errbuf); + } + } + return TRUE; + } + return FALSE; +} + +BOOL ConvertCalls(char * DigiCalls, UCHAR * AX, int * Lens) +{ + int Index = 0; + char * ptr; + char * Context; + UCHAR Work[MAXCALLS][7] = {0}; + int Len[MAXCALLS] = {0}; + + ptr = strtok_s(DigiCalls, ", ", &Context); + + while(ptr) + { + if (Index == MAXCALLS) return FALSE; + + ConvToAX25(ptr, &Work[Index][0]); + Len[Index++] = (int)strlen(ptr); + ptr = strtok_s(NULL, ", ", &Context); + } + + memcpy(AX, Work, sizeof(Work)); + memcpy(Lens, Len, sizeof(Len)); + return TRUE; +} + + + +static int APRSProcessLine(char * buf) +{ + char * ptr, * p_value; + + ptr = strtok(buf, "= \t\n\r"); + + if(ptr == NULL) return (TRUE); + + if(*ptr =='#') return (TRUE); // comment + + if(*ptr ==';') return (TRUE); // comment + + +// OBJECT PATH=APRS,WIDE1-1 PORT=1,IS INTERVAL=30 TEXT=;444.80TRF*111111z4807.60N/09610.63Wr%156 R15m + + if (_stricmp(ptr, "OBJECT") == 0) + { + char * p_Path, * p_Port, * p_Text; + int Interval; + struct OBJECT * Object; + int Digi = 2; + char * Context; + int SendTo; + + p_value = strtok(NULL, "="); + if (p_value == NULL) return FALSE; + if (_stricmp(p_value, "PATH")) + return FALSE; + + p_Path = strtok(NULL, "\t\n\r "); + if (p_Path == NULL) return FALSE; + + p_value = strtok(NULL, "="); + if (p_value == NULL) return FALSE; + if (_stricmp(p_value, "PORT")) + return FALSE; + + p_Port = strtok(NULL, "\t\n\r "); + if (p_Port == NULL) return FALSE; + + p_value = strtok(NULL, "="); + if (p_value == NULL) return FALSE; + if (_stricmp(p_value, "INTERVAL")) + return FALSE; + + p_value = strtok(NULL, " \t"); + if (p_value == NULL) return FALSE; + + Interval = atoi(p_value); + + if (Interval == 0) + return FALSE; + + p_value = strtok(NULL, "="); + if (p_value == NULL) return FALSE; + if (_stricmp(p_value, "TEXT")) + return FALSE; + + p_Text = strtok(NULL, "\n\r"); + if (p_Text == NULL) return FALSE; + + Object = zalloc(sizeof(struct OBJECT)); + + if (Object == NULL) + return FALSE; + + Object->Next = ObjectList; + ObjectList = Object; + + if (Interval < 10) + Interval = 10; + + Object->Interval = Interval; + Object->Timer = (ObjectCount++) * 10 + 30; // Spread them out; + + // Convert Path to AX.25 + + ConvToAX25(APRSCall, &Object->Path[1][0]); + + ptr = strtok_s(p_Path, ",\t\n\r", &Context); + + if (_stricmp(ptr, "APRS") == 0) // First is Dest + ConvToAX25(APRSDest, &Object->Path[0][0]); + else if (_stricmp(ptr, "APRS-0") == 0) + ConvToAX25("APRS", &Object->Path[0][0]); + else + ConvToAX25(ptr, &Object->Path[0][0]); + + ptr = strtok_s(NULL, ",\t\n\r", &Context); + + while (ptr) + { + ConvToAX25(ptr, &Object->Path[Digi++][0]); + ptr = strtok_s(NULL, " ,\t\n\r", &Context); + } + + Object->PathLen = Digi * 7; + + // Process Port List + + ptr = strtok_s(p_Port, ",", &Context); + + while (ptr) + { + SendTo = atoi(ptr); // this gives zero for IS + + if (SendTo > MaxBPQPortNo) + return FALSE; + + Object->PortMap[SendTo] = TRUE; + ptr = strtok_s(NULL, " ,\t\n\r", &Context); + } + + if (strlen(p_Text) > 80) + p_Text[80] = 0; + + strcpy(Object->Message, p_Text); + return TRUE; + } + + if (_stricmp(ptr, "STATUSMSG") == 0) + { + p_value = strtok(NULL, ";\t\n\r"); + memcpy(StatusMsg, p_value, 128); // Just in case too long + StatusMsgLen = (int)strlen(p_value); + return TRUE; + } + + if (_stricmp(ptr, "WXFileName") == 0) + { + p_value = strtok(NULL, ";\t\n\r"); + strcpy(WXFileName, p_value); + SendWX = TRUE; + return TRUE; + } + if (_stricmp(ptr, "WXComment") == 0) + { + p_value = strtok(NULL, ";\t\n\r"); + + if (p_value == NULL) + return TRUE; + + if (strlen(p_value) > 79) + p_value[80] = 0; + + strcpy(WXComment, p_value); + return TRUE; + } + + + if (_stricmp(ptr, "ISFILTER") == 0) + { + p_value = strtok(NULL, ";\t\n\r"); + strcpy(ISFilter, p_value); + strcpy(NodeFilter, ISFilter); + return TRUE; + } + + if (_stricmp(ptr, "ReplaceDigiCalls") == 0) + { + TraceDigi = TRUE; + return TRUE; + } + + if (_stricmp(ptr, "Multiple") == 0) + { + multiple = TRUE; + return TRUE; + } + + if (_stricmp(ptr, "SATGate") == 0) + { + SATGate = TRUE; + return TRUE; + } + + if (_stricmp(ptr, "RXOnly") == 0) + { + RXOnly = TRUE; + return TRUE; + } + + if (_stricmp(ptr, "DISTKM") == 0) + { + DefaultDistKM = TRUE; + return TRUE; + } + + if (_stricmp(ptr, "LOCALTIME") == 0) + { + DefaultLocalTime = TRUE; + return TRUE; + } + + if (_stricmp(ptr, "LOGAPRSIS") == 0) + { + LogAPRSIS = TRUE; + return TRUE; + } + + if (_stricmp(ptr, "SaveAPRSMsgs") == 0) + { + SaveAPRSMsgs = TRUE; + return TRUE; + } + + p_value = strtok(NULL, " \t\n\r"); + + if (p_value == NULL) + return FALSE; + + if (_stricmp(ptr, "APRSCALL") == 0) + { + strcpy(APRSCall, p_value); + strcpy(LoppedAPRSCall, p_value); + memcpy(CallPadded, APRSCall, (int)strlen(APRSCall)); // Call Padded to 9 chars for APRS Messaging + + // Convert to ax.25 + + return ConvToAX25(APRSCall, AXCall); + } + + if (_stricmp(ptr, "WXCALL") == 0) + { + strcpy(WXCall, p_value); + return TRUE; + } + + if (_stricmp(ptr, "APRSPATH") == 0) + { + int Digi = 2; + int Port; + char * Context; + + p_value = strtok_s(p_value, "=\t\n\r", &Context); + + Port = atoi(p_value); + + if (GetPortTableEntryFromPortNum(Port) == NULL) + return FALSE; + + APRSPortMask |= (uint64_t)1 << (Port - 1); + + if (Context == NULL || Context[0] == 0) + return TRUE; // No dest - a receive-only port + + BeaconPath[Port] = _strdup(_strupr(Context)); + + ptr = strtok_s(NULL, ",\t\n\r", &Context); + + if (ptr == NULL) + return FALSE; + + ConvToAX25(APRSCall, &BeaconHeader[Port][1][0]); + + if (_stricmp(ptr, "APRS") == 0) // First is Dest + ConvToAX25(APRSDest, &BeaconHeader[Port][0][0]); + else if (_stricmp(ptr, "APRS-0") == 0) + ConvToAX25("APRS", &BeaconHeader[Port][0][0]); + else + ConvToAX25(ptr, &BeaconHeader[Port][0][0]); + + ptr = strtok_s(NULL, ",\t\n\r", &Context); + + while (ptr) + { + ConvToAX25(ptr, &BeaconHeader[Port][Digi++][0]); + ptr = strtok_s(NULL, " ,\t\n\r", &Context); + } + + BeaconHddrLen[Port] = Digi * 7; + + return TRUE; + } + + if (_stricmp(ptr, "GATEDPATH") == 0) + { + int Digi = 2; + int Port; + char * Context; + + p_value = strtok_s(p_value, "=\t\n\r", &Context); + + Port = atoi(p_value); + + if (GetPortTableEntryFromPortNum(Port) == NULL) + return FALSE; + +// APRSPortMask |= 1 << (Port - 1); + + if (Context == NULL || Context[0] == 0) + return TRUE; // No dest - a receive-only port + + BeaconPath[Port] = _strdup(_strupr(Context)); + + ptr = strtok_s(NULL, ",\t\n\r", &Context); + + if (ptr == NULL) + return FALSE; + + ConvToAX25(APRSCall, &GatedHeader[Port][1][0]); + + if (_stricmp(ptr, "APRS") == 0) // First is Dest + ConvToAX25(APRSDest, &GatedHeader[Port][0][0]); + else if (_stricmp(ptr, "APRS-0") == 0) + ConvToAX25("APRS", &GatedHeader[Port][0][0]); + else + ConvToAX25(ptr, &GatedHeader[Port][0][0]); + + ptr = strtok_s(NULL, ",\t\n\r", &Context); + + while (ptr) + { + ConvToAX25(ptr, &GatedHeader[Port][Digi++][0]); + ptr = strtok_s(NULL, " ,\t\n\r", &Context); + } + + GatedHddrLen[Port] = Digi * 7; + + return TRUE; + } + + + if (_stricmp(ptr, "DIGIMAP") == 0) + { + int DigiTo; + int Port; + char * Context; + + p_value = strtok_s(p_value, "=\t\n\r", &Context); + + Port = atoi(p_value); + + if (GetPortTableEntryFromPortNum(Port) == NULL) + return FALSE; + + // Check that port can digi (SCS Pactor can't set digi'd bit in calls) + + if (CanPortDigi(Port) == 0) + return FALSE; + + + CrossPortMap[Port][Port] = FALSE; // Cancel Default mapping + CrossPortMap[Port][0] = FALSE; // Cancel Default APRSIS + + if (Context == NULL || Context[0] == 0) + return TRUE; + + ptr = strtok_s(NULL, ",\t\n\r", &Context); + + while (ptr) + { + DigiTo = atoi(ptr); // this gives zero for IS + + if (DigiTo && GetPortTableEntryFromPortNum(DigiTo) == NULL) + return FALSE; + + CrossPortMap[Port][DigiTo] = TRUE; + ptr = strtok_s(NULL, " ,\t\n\r", &Context); + } + + return TRUE; + } + if (_stricmp(ptr, "BRIDGE") == 0) + { + int DigiTo; + int Port; + char * Context; + + p_value = strtok_s(p_value, "=\t\n\r", &Context); + + Port = atoi(p_value); + + if (GetPortTableEntryFromPortNum(Port) == NULL) + return FALSE; + + if (Context == NULL) + return FALSE; + + ptr = strtok_s(NULL, ",\t\n\r", &Context); + + while (ptr) + { + DigiTo = atoi(ptr); // this gives zero for IS + + if (DigiTo > MaxBPQPortNo) + return FALSE; + + APRSBridgeMap[Port][DigiTo] = TRUE; + ptr = strtok_s(NULL, " ,\t\n\r", &Context); + } + + return TRUE; + } + + + if (_stricmp(ptr, "BeaconInterval") == 0) + { + BeaconInterval = atoi(p_value); + + if (BeaconInterval < 5) + BeaconInterval = 5; + + if (BeaconInterval) + BeaconCounter = 30; // Send first after 30 secs + + return TRUE; + } + + if (_stricmp(ptr, "MobileBeaconInterval") == 0) + { + MobileBeaconInterval = atoi(p_value) * 60; + return TRUE; + } + if (_stricmp(ptr, "MobileBeaconIntervalSecs") == 0) + { + MobileBeaconInterval = atoi(p_value); + if (MobileBeaconInterval < 10) + MobileBeaconInterval = 10; + + return TRUE; + } + + if (_stricmp(ptr, "BeacontoIS") == 0) + { + BeacontoIS = atoi(p_value); + return TRUE; + } + + + if (_stricmp(ptr, "TRACECALLS") == 0) + { + TraceCalls = _strdup(_strupr(p_value)); + ConvertCalls(TraceCalls, &TraceAX[0][0], &TraceLen[0]); + return TRUE; + } + + if (_stricmp(ptr, "FLOODCALLS") == 0) + { + FloodCalls = _strdup(_strupr(p_value)); + ConvertCalls(FloodCalls, &FloodAX[0][0], &FloodLen[0]); + return TRUE; + } + + if (_stricmp(ptr, "DIGICALLS") == 0) + { + char AllCalls[1024]; + + DigiCalls = _strdup(_strupr(p_value)); + strcpy(AllCalls, APRSCall); + strcat(AllCalls, ","); + strcat(AllCalls, DigiCalls); + ConvertCalls(AllCalls, &DigiAX[0][0], &DigiLen[0]); + return TRUE; + } + + if (_stricmp(ptr, "MaxStations") == 0) + { + MaxStations = atoi(p_value); + + if (MaxStations > 10000) + MaxStations = 10000; + + return TRUE; + } + + if (_stricmp(ptr, "MaxAge") == 0) + { + ExpireTime = atoi(p_value); + return TRUE; + } + + if (_stricmp(ptr, "GPSPort") == 0) + { + if (strcmp(p_value, "0") != 0) + strcpy(GPSPort, p_value); + return TRUE; + } + + if (_stricmp(ptr, "GPSSpeed") == 0) + { + GPSSpeed = atoi(p_value); + return TRUE; + } + + if (_stricmp(ptr, "GPSRelay") == 0) + { + if (strlen(p_value) > 79) + return FALSE; + + strcpy(GPSRelay, p_value); + return TRUE; + } + + if (_stricmp(ptr, "BlueNMEA") == 0 || _stricmp(ptr, "TCPHost") == 0 || _stricmp(ptr, "AISHost") == 0) + { + if (strlen(p_value) > 70) + return FALSE; + + strcpy(HostName, p_value); + return TRUE; + } + + if (_stricmp(ptr, "TCPPort") == 0 || _stricmp(ptr, "AISPort") == 0) + { + HostPort = atoi(p_value); + return TRUE; + } + + if (_stricmp(ptr, "GPSDHost") == 0) + { + if (strlen(p_value) > 70) + return FALSE; + + strcpy(GPSDHost, p_value); + return TRUE; + } + + if (_stricmp(ptr, "GPSDPort") == 0) + { + GPSDPort = atoi(p_value); + return TRUE; + } + + if (_stricmp(ptr, "ADSBHost") == 0) + { + if (strlen(p_value) > 70) + return FALSE; + + strcpy(ADSBHost, p_value); + return TRUE; + } + + if (_stricmp(ptr, "ADSBPort") == 0) + { + ADSBPort = atoi(p_value); + return TRUE; + } + + + + if (_stricmp(ptr, "GPSSetsLocator") == 0) + { + GPSSetsLocator = atoi(p_value); + return TRUE; + } + + if (_stricmp(ptr, "LAT") == 0) + { + if (strlen(p_value) != 8) + return FALSE; + + memcpy(LAT, _strupr(p_value), 8); + PosnSet = TRUE; + return TRUE; + } + + if (_stricmp(ptr, "LON") == 0) + { + if (strlen(p_value) != 9) + return FALSE; + + memcpy(LON, _strupr(p_value), 9); + PosnSet = TRUE; + return TRUE; + } + + if (_stricmp(ptr, "SYMBOL") == 0) + { + if (p_value[0] > ' ' && p_value[0] < 0x7f) + CFGSYMBOL = p_value[0]; + + return TRUE; + } + + if (_stricmp(ptr, "SYMSET") == 0) + { + CFGSYMSET = p_value[0]; + return TRUE; + } + + if (_stricmp(ptr, "PHG") == 0) + { + PHG = _strdup(p_value); + return TRUE; + } + + if (_stricmp(ptr, "MaxTraceHops") == 0) + { + MaxTraceHops = atoi(p_value); + return TRUE; + } + + if (_stricmp(ptr, "MaxFloodHops") == 0) + { + MaxFloodHops = atoi(p_value); + return TRUE; + } + + if (_stricmp(ptr, "ISHOST") == 0) + { + strncpy(ISHost, p_value, 250); + return TRUE; + } + + if (_stricmp(ptr, "ISPORT") == 0) + { + ISPort = atoi(p_value); + return TRUE; + } + + if (_stricmp(ptr, "ISPASSCODE") == 0) + { + ISPasscode = atoi(p_value); + return TRUE; + } + + if (_stricmp(ptr, "MaxDigisforIS") == 0) + { + MaxDigisforIS = atoi(p_value); + return TRUE; + } + + if (_stricmp(ptr, "GateLocalDistance") == 0) + { + GateLocalDistance = atoi(p_value); + if (GateLocalDistance > 0.0) + GateLocal = TRUE; + + return TRUE; + } + + if (_stricmp(ptr, "WXInterval") == 0) + { + WXInterval = atoi(p_value); + WXCounter = (WXInterval - 1) * 60; + return TRUE; + } + + if (_stricmp(ptr, "WXPortList") == 0) + { + char ParamCopy[80]; + char * Context; + int Port; + char * ptr; + int index = 0; + + for (index = 0; index < MaxBPQPortNo; index++) + WXPort[index] = FALSE; + + if (strlen(p_value) > 79) + p_value[80] = 0; + + strcpy(ParamCopy, p_value); + + ptr = strtok_s(ParamCopy, " ,\t\n\r", &Context); + + while (ptr) + { + Port = atoi(ptr); // this gives zero for IS + + WXPort[Port] = TRUE; + + ptr = strtok_s(NULL, " ,\t\n\r", &Context); + } + return TRUE; + } + + if (_stricmp(ptr, "Run") == 0) + { + strcpy(RunProgram, p_value); + return TRUE; + } + + // + // Bad line + // + return (FALSE); +} + +VOID SendAPRSMessageEx(char * Message, int toPort, char * FromCall, int Gated); + + +VOID SendAPRSMessage(char * Message, int toPort) +{ + SendAPRSMessageEx(Message, toPort, APRSCall, 0); +} + +// Ex allows setting source call (For WX Messages) + + +VOID SendAPRSMessageEx(char * Message, int toPort, char * FromCall, int Gated) +{ + int Port; + DIGIMESSAGE Msg; + + int Len; + + // toPort = -1 means all tadio ports. 0 = IS + + if (toPort == -1) + { + for (Port = 1; Port <= MaxBPQPortNo; Port++) + { + if (Gated && GatedHddrLen[Port]) + memcpy(Msg.DEST, &GatedHeader[Port][0][0], 10 * 7); + else if (BeaconHddrLen[Port]) // Only send to ports with a DEST defined + memcpy(Msg.DEST, &BeaconHeader[Port][0][0], 10 * 7); + else + continue; + + Msg.DEST[6] |= 0x80; // set Command Bit + + ConvToAX25(FromCall, Msg.ORIGIN); + Msg.PID = 0xf0; + Msg.CTL = 3; + Len = sprintf(Msg.L2DATA, "%s", Message); + Send_AX_Datagram(&Msg, Len + 2, Port); + } + + return; + } + + if (toPort == 0 && APRSISOpen) + { + char ISMsg[300]; + + Len = sprintf(ISMsg, "%s>%s,TCPIP*:%s\r\n", FromCall, APRSDest, Message); + ISSend(sock, ISMsg, Len, 0); + } + + if (toPort == 0) + return; + + if (Gated && GatedHddrLen[toPort]) + memcpy(Msg.DEST, &GatedHeader[toPort][0][0], 10 * 7); + else if (BeaconHddrLen[toPort]) // Only send to ports with a DEST defined + memcpy(Msg.DEST, &BeaconHeader[toPort][0][0], 10 * 7); + else + return; + + Msg.DEST[6] |= 0x80; // set Command Bit + + ConvToAX25(FromCall, Msg.ORIGIN); + Msg.PID = 0xf0; + Msg.CTL = 3; + Len = sprintf(Msg.L2DATA, "%s", Message); + Send_AX_Datagram(&Msg, Len + 2, toPort); + + return; +} + + +VOID ProcessSpecificQuery(char * Query, int Port, char * Origin, char * DestPlusDigis) +{ + if (_memicmp(Query, "APRSS", 5) == 0) + { + char Message[255]; + + sprintf(Message, ":%-9s:%s", Origin, StatusMsg); + SendAPRSMessage(Message, Port); + + return; + } + + if (_memicmp(Query, "APRST", 5) == 0 || _memicmp(Query, "PING?", 5) == 0) + { + // Trace Route + //:KH2ZV :?APRST :N8UR :KH2Z>APRS,DIGI1,WIDE*: + //:G8BPQ-14 :Path - G8BPQ-14>APU25N + + char Message[255]; + + sprintf(Message, ":%-9s:Path - %s>%s", Origin, Origin, DestPlusDigis); + SendAPRSMessage(Message, Port); + + return; + } +} + +VOID ProcessQuery(char * Query) +{ + if (memcmp(Query, "IGATE?", 6) == 0) + { + IStatusCounter = (rand() & 31) + 5; // 5 - 36 secs delay + return; + } + + if (memcmp(Query, "APRS?", 5) == 0) + { + BeaconCounter = (rand() & 31) + 5; // 5 - 36 secs delay + return; + } +} +Dll VOID APIENTRY APISendBeacon() +{ + BeaconCounter = 2; +} + +typedef struct _BeaconParams +{ + int toPort; + char * BeaconText; + BOOL SendStatus; + BOOL SendSOGCOG; +} Params; + + +Params BeaconParams; + +void SendBeaconThread(void * Params); + +VOID SendBeacon(int toPort, char * BeaconText, BOOL SendStatus, BOOL SendSOGCOG) +{ + // Send to IS if needed then start a thread to send to radio ports + + if (PosnSet == FALSE) + return; + + if (APRSISOpen && toPort == 0 && BeacontoIS) + { + char SOGCOG[10] = ""; + char ISMsg[300]; + int Len; + + Debugprintf("Sending APRS Beacon to APRS-IS"); + + if (SendSOGCOG | (COG != 0.0)) + sprintf(SOGCOG, "%03.0f/%03.0f", COG, SOG); + + if (PHG) // Send PHG instead of SOG COG + Len = sprintf(ISMsg, "%s>%s,TCPIP*:%c%s%c%s%c%s%s\r\n", APRSCall, APRSDest, + (APRSApplConnected) ? '=' : '!', LAT, SYMSET, LON, SYMBOL, PHG, BeaconText); + else + Len = sprintf(ISMsg, "%s>%s,TCPIP*:%c%s%c%s%c%s%s\r\n", APRSCall, APRSDest, + (APRSApplConnected) ? '=' : '!', LAT, SYMSET, LON, SYMBOL, SOGCOG, BeaconText); + + ISSend(sock, ISMsg, Len, 0); + Debugprintf(">%s", ISMsg); + } + + BeaconParams.toPort = toPort; + BeaconParams.BeaconText = BeaconText; + BeaconParams.SendStatus = SendStatus; + BeaconParams.SendSOGCOG = SendSOGCOG; + + _beginthread(SendBeaconThread, 0, (VOID *) &BeaconParams); +} + +void SendBeaconThread(void * Param) +{ + // runs as a thread so we can sleep() between calls + + // Params are passed via a param block + + Params * BeaconParams = (Params *)Param; + + int toPort = BeaconParams->toPort; + char * BeaconText = BeaconParams->BeaconText; + BOOL SendStatus = BeaconParams->SendStatus; + BOOL SendSOGCOG = BeaconParams->SendSOGCOG; + + int Port; + DIGIMESSAGE Msg; + int Len; + char SOGCOG[256] = ""; + struct STATIONRECORD * Station; + struct PORTCONTROL * PORT; + + if (PosnSet == FALSE) + return; + + if (PHG) // Send PHG instead of SOG COG + strcpy(SOGCOG, PHG); + else + if (SendSOGCOG | (COG != 0.0)) + sprintf(SOGCOG, "%03.0f/%03.0f", COG, SOG); + + BeaconCounter = BeaconInterval * 60; + + if (ISPort && IGateEnabled) + Len = sprintf(Msg.L2DATA, "%c%s%c%s%c%s%s", (APRSApplConnected) ? '=' : '!', + LAT, SYMSET, LON, SYMBOL, SOGCOG, BeaconText); + else + Len = sprintf(Msg.L2DATA, "%c%s%c%s%c%s%s", (APRSApplConnected) ? '=' : '!', + LAT, SYMSET, LON, SYMBOL, SOGCOG, BeaconText); + + Msg.PID = 0xf0; + Msg.CTL = 3; + + // Add to dup check list, so we won't digi it if we hear it back + // Should we drop it if we've sent it recently ?? + + if (CheckforDups(APRSCall, Msg.L2DATA, Len - (19 + sizeof(void *)))) + return; + + // Add to our station list + + Station = FindStation(APRSCall, TRUE); + + if (Station == NULL) + return; + + + strcpy(Station->Path, "APBPQ1"); + strcpy(Station->LastPacket, Msg.L2DATA); +// Station->LastPort = Port; + + DecodeAPRSPayload(Msg.L2DATA, Station); + Station->TimeLastUpdated = time(NULL); + + if (toPort) + { + if (BeaconHddrLen[toPort] == 0) + return; + + Debugprintf("Sending APRS Beacon to port %d", toPort); + + memcpy(Msg.DEST, &BeaconHeader[toPort][0][0], 10 * 7); // Clear unused digis + Msg.DEST[6] |= 0x80; // set Command Bit + + GetSemaphore(&Semaphore, 12); + Send_AX_Datagram(&Msg, Len + 2, toPort); + FreeSemaphore(&Semaphore); + + return; + } + + for (Port = 1; Port <= MaxBPQPortNo; Port++) // Check all ports + { + if (BeaconHddrLen[Port]) // Only send to ports with a DEST defined + { + Debugprintf("Sending APRS Beacon to port %d", Port); + + if (ISPort && IGateEnabled) + Len = sprintf(Msg.L2DATA, "%c%s%c%s%c%s%s", (APRSApplConnected) ? '=' : '!', + LAT, SYMSET, LON, SYMBOL, SOGCOG, BeaconText); + else + Len = sprintf(Msg.L2DATA, "%c%s%c%s%c%s%s", (APRSApplConnected) ? '=' : '!', + LAT, SYMSET, LON, SYMBOL, SOGCOG, BeaconText); + Msg.PID = 0xf0; + Msg.CTL = 3; + + memcpy(Msg.DEST, &BeaconHeader[Port][0][0], 10 * 7); + Msg.DEST[6] |= 0x80; // set Command Bit + + GetSemaphore(&Semaphore, 12); + Send_AX_Datagram(&Msg, Len + 2, Port); + FreeSemaphore(&Semaphore); + + // if Port has interlock set pause before next + + PORT = GetPortTableEntryFromPortNum(Port); + + // Just pause for all ports + +// if (PORT && PORT->PORTINTERLOCK) + Sleep(20000); + } + } + return ; +} + +VOID SendObject(struct OBJECT * Object) +{ + int Port; + DIGIMESSAGE Msg; + int Len; + + // Add to dup list in case we get it back + + CheckforDups(APRSCall, Object->Message, (int)strlen(Object->Message)); + + for (Port = 1; Port <= MaxBPQPortNo; Port++) + { + if (Object->PortMap[Port]) + { + Msg.PID = 0xf0; + Msg.CTL = 3; + Len = sprintf(Msg.L2DATA, "%s", Object->Message); + memcpy(Msg.DEST, &Object->Path[0][0], Object->PathLen + 1); + Msg.DEST[6] |= 0x80; // set Command Bit + + Send_AX_Datagram(&Msg, Len + 2, Port); + } + } + + // Also send to APRS-IS if connected + + if (APRSISOpen && Object->PortMap[0]) + { + char ISMsg[300]; + Len = sprintf(ISMsg, "%s>%s,TCPIP*:%s\r\n", APRSCall, APRSDest, Object->Message); + ISSend(sock, ISMsg, Len, 0); + } +} + + +/* +VOID SendStatus(char * StatusText) +{ + int Port; + DIGIMESSAGE Msg; + int Len; + + if (APRSISOpen) + { + Msg.PID = 0xf0; + Msg.CTL = 3; + + Len = sprintf(Msg.L2DATA, ">%s", StatusText); + + for (Port = 1; Port <= NUMBEROFPORTS; Port++) + { + if (BeaconHddrLen[Port]) // Only send to ports with a DEST defined + { + memcpy(Msg.DEST, &BeaconHeader[Port][0][0], 10 * 7); + Send_AX_Datagram(&Msg, Len + 2, Port); + } + } + + Len = sprintf(Msg.L2DATA, "%s>%s,TCPIP*:>%s\r\n", APRSCall, APRSDest, StatusText); + ISSend(sock, Msg.L2DATA, Len, 0); +// Debugprintf(">%s", Msg.L2DATA); + } +} + + +*/ +VOID SendIStatus() +{ + int Port; + DIGIMESSAGE Msg; + int Len; + + IStatusCounter = 3600; // One per hour + + if (APRSISOpen && BeacontoIS && RXOnly == 0) + { + Msg.PID = 0xf0; + Msg.CTL = 3; + + Len = sprintf(Msg.L2DATA, "%s,TCPIP*:%s", Msg.L2DATA); + } + +} + + +VOID DoSecTimer() +{ + struct OBJECT * Object = ObjectList; + + while (Object) + { + Object->Timer--; + + if (Object->Timer == 0) + { + Object->Timer = 60 * Object->Interval; + SendObject(Object); + } + Object = Object->Next; + } + + // Check SatGate Mode delay Q + + if (SatISQueue) + { + time_t NOW = time(NULL); + ISDELAY * SatISEntry = SatISQueue; + ISDELAY * Prev = NULL; + + while (SatISEntry) + { + if (SatISEntry->SendTIme < NOW) + { + // Send it + + ISSend(sock, SatISEntry->ISMSG, (int)strlen(SatISEntry->ISMSG), 0); + free(SatISEntry->ISMSG); + + if (Prev) + Prev->Next = SatISEntry->Next; + else + SatISQueue = SatISEntry->Next; + + free(SatISEntry); + return; // unlinkely to get 2 in sam esecond and doesn;t matter if we delay a bit more + } + + Prev = SatISEntry; + SatISEntry = SatISEntry->Next; + } + } + + if (ISPort && APRSISOpen == 0 && IGateEnabled) + { + ISDelayTimer++; + + if (ISDelayTimer > 60) + { + ISDelayTimer = 0; + _beginthread(APRSISThread, 0, (VOID *) TRUE); + } + } + + if (HostName[0]) + { + if (BlueNMEAOK == 0) + { + BlueNMEATimer++; + if (BlueNMEATimer > 15) + { + BlueNMEATimer = 0; + _beginthread(TCPConnect, 0, 0); + } + } + } + + if (GPSDHost[0]) + { + if (GPSDOK == 0) + { + GPSDTimer++; + if (GPSDTimer > 15) + { + GPSDTimer = 0; + _beginthread(GPSDConnect, 0, 0); + } + } + } + + if (BeaconCounter) + { + BeaconCounter--; + + if (BeaconCounter == 0) + { + BeaconCounter = BeaconInterval * 60; + SendBeacon(0, StatusMsg, TRUE, FALSE); + } + } + + if (IStatusCounter) + { + IStatusCounter--; + + if (IStatusCounter == 0) + { + SendIStatus(); + } + } + + if (GPSOK) + { + GPSOK--; + + if (GPSOK == 0) +#ifdef LINBPQ + Debugprintf("GPS Lost"); +#else + SetDlgItemText(hConsWnd, IDC_GPS, "No GPS"); +#endif + } + + APRSSecTimer(); // Code from APRS APPL +} + +int CountPool() +{ + struct STATIONRECORD * ptr = StationRecordPool; + int n = 0; + + while (ptr) + { + n++; + ptr = ptr->Next; + } + return n; +} + +static VOID DoMinTimer() +{ + struct STATIONRECORD * ptr = *StationRecords; + struct STATIONRECORD * last = NULL; + time_t AgeLimit = time(NULL ) - (ExpireTime * 60); + int i = 0; + + // Remove old records + + while (ptr) + { + if (ptr->TimeLastUpdated < AgeLimit) + { + StationCount--; + + if (last) + { + last->Next = ptr->Next; + + // Put on front of free chain + + ptr->Next = StationRecordPool; + StationRecordPool = ptr; + + ptr = last->Next; + } + else + { + // First in list + + *StationRecords = ptr->Next; + + // Put on front of free chain + + ptr->Next = StationRecordPool; + StationRecordPool = ptr; + + if (*StationRecords) + { + ptr = *StationRecords; + } + else + { + ptr = NULL; + } + } + } + else + { + last = ptr; + ptr = ptr->Next; + } + } +} + +char APRSMsg[300]; + +int ISHostIndex = 0; +char RealISHost[256]; + +VOID APRSISThread(void * Report) +{ + // Receive from core server + + char Signon[500]; + unsigned char work[4]; + + struct sockaddr_in sinx; + int addrlen=sizeof(sinx); + struct addrinfo hints, *res = 0, *saveres; + size_t len; + int err; + u_long param=1; + BOOL bcopt=TRUE; + char Buffer[1000]; + int InputLen = 1; // Non-zero + char errmsg[100]; + char * ptr; + size_t inptr = 0; + char APRSinMsg[1000]; + char PortString[20]; + char serv[256]; + + Debugprintf("BPQ32 APRS IS Thread"); +#ifndef LINBPQ + SetDlgItemText(hConsWnd, IGATESTATE, "IGate State: Connecting"); +#endif + + if (ISFilter[0]) + sprintf(Signon, "user %s pass %d vers BPQ32 %s filter %s\r\n", + APRSCall, ISPasscode, TextVerstring, ISFilter); + else + sprintf(Signon, "user %s pass %d vers BPQ32 %s\r\n", + APRSCall, ISPasscode, TextVerstring); + + + sprintf(PortString, "%d", ISPort); + + // 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(ISHost, PortString, &hints, &res); + + InputLen = sprintf(errmsg, "Connecting to APRS Host %s\r\n", ISHost); + MonitorAPRSIS(errmsg, InputLen, FALSE); + + if (!res) + { + err = WSAGetLastError(); + InputLen = sprintf(errmsg, "APRS IS Resolve %s Failed Error %d\r\n", ISHost, err); + MonitorAPRSIS(errmsg, InputLen, FALSE); + + return; // Resolve failed + + } + + // Step thorough the list of hosts + + saveres = res; // Save for free + + if (res->ai_next) // More than one + { + int n = ISHostIndex; + + while (n && res->ai_next) + { + res = res->ai_next; + n--; + } + + if (n) + { + // We have run off the end of the list + + ISHostIndex = 0; // Back to start + res = saveres; + } + else + ISHostIndex++; + + } + + getnameinfo(res->ai_addr, (int)res->ai_addrlen, RealISHost, 256, serv, 256, 0); + + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + if (sock == INVALID_SOCKET) + return; + + setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); + + memcpy(work, res->ai_addr->sa_data, 4); + + Debugprintf("Trying APRSIS Host %d.%d.%d.%d (%d) %s", work[0], work[1], work[2], work[3], ISHostIndex, RealISHost); + + if (connect(sock, res->ai_addr, (int)res->ai_addrlen)) + { + err=WSAGetLastError(); + + // + // Connect failed + // + +#ifndef LINBPQ + MySetWindowText(GetDlgItem(hConsWnd, IGATESTATE), "IGate State: Connect Failed"); +#else + printf("APRS Igate connect failed\n"); +#endif + err=WSAGetLastError(); + InputLen = sprintf(errmsg, "Connect Failed %s af %d Error %d \r\n", RealISHost, res->ai_family, err); + MonitorAPRSIS(errmsg, InputLen, FALSE); + + freeaddrinfo(res); + return; + } + + freeaddrinfo(saveres); + + APRSISOpen = TRUE; + +#ifndef LINBPQ + MySetWindowText(GetDlgItem(hConsWnd, IGATESTATE), "IGate State: Connected"); +#endif + + InputLen=recv(sock, Buffer, 500, 0); + + if (InputLen > 0) + { + Buffer[InputLen] = 0; + Debugprintf(Buffer); + MonitorAPRSIS(Buffer, InputLen, FALSE); + } + + ISSend(sock, Signon, (int)strlen(Signon), 0); +/* + InputLen=recv(sock, Buffer, 500, 0); + + if (InputLen > 0) + { + Buffer[InputLen] = 0; + Debugprintf(Buffer); + MonitorAPRSIS(Buffer, InputLen, FALSE); + } + + InputLen=recv(sock, Buffer, 500, 0); + + if (InputLen > 0) + { + Buffer[InputLen] = 0; + Debugprintf(Buffer); + MonitorAPRSIS(Buffer, InputLen, FALSE); + } +*/ + while (InputLen > 0 && IGateEnabled) + { + InputLen = recv(sock, &APRSinMsg[inptr], (int)(500 - inptr), 0); + + if (InputLen > 0) + { + inptr += InputLen; + + ptr = memchr(APRSinMsg, 0x0a, inptr); + + while (ptr != NULL) + { + ptr++; // include lf + len = ptr-(char *)APRSinMsg; + + inptr -= len; // bytes left + + // UIView server has a null before crlf + + if (*(ptr - 3) == 0) + { + *(ptr - 3) = 13; + *(ptr - 2) = 10; + *(ptr - 1) = 0; + + len --; + } + + if (len > 10 && len < 300) // Ignore if way too long or too short + { + memcpy(&APRSMsg, APRSinMsg, len); + MonitorAPRSIS(APRSMsg, (int)len, FALSE); + if (APRSMsg[len - 2] == 13) + APRSMsg[len - 2] = 0; + else + APRSMsg[len - 1] = 0; + +// Debugprintf("%s", APRSMsg); + + ProcessAPRSISMsg(APRSMsg); + } + + if (inptr > 0) + { + memmove(APRSinMsg, ptr, inptr); + ptr = memchr(APRSinMsg, 0x0a, inptr); + } + else + ptr = 0; + + if (inptr < 0) + break; + } + } + } + + closesocket(sock); + + APRSISOpen = FALSE; + + Debugprintf("BPQ32 APRS IS Thread Exited"); + +#ifndef LINBPQ + if (IGateEnabled) + SetDlgItemText(hConsWnd, IGATESTATE, "IGate State: Disconnected"); + else + SetDlgItemText(hConsWnd, IGATESTATE, "IGate State: Disabled"); +#endif + ISDelayTimer = 30; // Retry pretty quickly + return; +} + +VOID ProcessAPRSISMsg(char * APRSMsg) +{ + char * Payload; + char * Source; + char * Dest; + char IGateCall[10] = " "; + char * ptr; + char Message[255]; + PAPRSHEARDRECORD MH; + time_t NOW = time(NULL); + char ISCopy[1024]; + struct STATIONRECORD * Station = NULL; +#ifdef WIN32 + struct _EXCEPTION_POINTERS exinfo; + char EXCEPTMSG[80] = ""; +#endif + + if (APRSMsg[0] == '#') // Comment + return; + + // if APRS Appl is atttached, queue message to it + + strcpy(ISCopy, APRSMsg); + + GetSemaphore(&Semaphore, 12); + +#ifdef WIN32 + + strcpy(EXCEPTMSG, "ProcessAPRSISMsg"); + + __try + { + + Station = DecodeAPRSISMsg(ISCopy); + + } + #include "StdExcept.c" + Debugprintf(APRSMsg); + } +#else + Station = DecodeAPRSISMsg(ISCopy); +#endif + + FreeSemaphore(&Semaphore); + +//}WB4APR-14>APRS,RELAY,TCPIP,G9RXG*::G3NRWVVVV:Hi Ian{001 +//KE7XO-2>hg,TCPIP*,qAC,T2USASW::G8BPQ-14 :Path - G8BPQ-14>APU25N +//IGATECALL>APRS,GATEPATH}FROMCALL>TOCALL,TCPIP,IGATECALL*:original packet data + + Payload = strchr(APRSMsg, ':'); + + // Get call of originating Igate + + ptr = Payload; + + if (Payload == NULL) + return; + + *(Payload++) = 0; + + while (ptr[0] != ',') + ptr--; + + ptr++; + + if (strlen(ptr) > 9) + return; + + memcpy(IGateCall, ptr, (int)strlen(ptr)); + + if (strstr(APRSMsg, ",qAS,") == 0) // Findu generates invalid q construct + { + MH = FindStationInMH(IGateCall); + if (MH) + { +// Debugprintf("Setting Igate Flag - %s:%s", APRSMsg, Payload); + MH->IGate = TRUE; // If we have seen this station on RF, set it as an Igate + } + } + Source = APRSMsg; + Dest = strchr(APRSMsg, '>'); + + if (Dest == NULL) + return; + + *(Dest++) = 0; // Termainate Source + ptr = strchr(Dest, ','); + + if (ptr) + *ptr = 0; + + MH = UpdateHeard(Source, 0); + + MH->Station = Station; + + // See if we should gate to RF. + + // Have we heard dest recently? (use the message dest (not ax.25 dest) - does this mean we only gate Messages? + // Not if it is an Igate (it will get a copy direct) + // Have we recently sent a message from this call - if so, we gate the next Position + +/* + + From http://www.aprs-is.net/IGateDetails.aspx + + Gate message packets and associated posits to RF if all of the following are true: + + the receiving station has been heard within range within a predefined time period (range defined + as digi hops, distance, or both). + + the sending station has not been heard via RF within a predefined time period (packets gated + from the Internet by other stations are excluded from this test). + + the sending station does not have TCPXX, NOGATE, or RFONLY in the header. + + the receiving station has not been heard via the Internet within a predefined time period. + + A station is said to be heard via the Internet if packets from the station contain TCPIP* or + TCPXX* in the header or if gated (3rd-party) packets are seen on RF gated by the station + and containing TCPIP or TCPXX in the 3rd-party header (in other words, the station is seen on RF + as being an IGate). + +*/ + + if (Payload[0] == ':') // Message + { + char MsgDest[10]; + APRSHEARDRECORD * STN; + + if (strlen(Payload) > 100) // I don't think any valid APRS msgs are more than this + return; + + memcpy(MsgDest, &Payload[1], 9); + MsgDest[9] = 0; + + if (strcmp(MsgDest, CallPadded) == 0) // to us + return; + + // Check that the sending station has not been heard via RF recently + + if (MH->rfPort && (NOW - MH->MHTIME) < GATETIMELIMIT) + return; + + STN = FindStationInMH(MsgDest); + + // Shouldn't we check DUP list, in case we have digi'ed this message directly? + + if (CheckforDups(Source, Payload, (int)strlen(Payload))) + return; + + // has the receiving station has been heard on RF and is not an IGate + + if (STN && STN->rfPort && !STN->IGate && (NOW - STN->MHTIME) < GATETIMELIMIT) + { + sprintf(Message, "}%s>%s,TCPIP,%s*:%s", Source, Dest, APRSCall, Payload); + + GetSemaphore(&Semaphore, 12); + SendAPRSMessageEx(Message, STN->rfPort, APRSCall, 1); // Set gated to IS flag + FreeSemaphore(&Semaphore); + + MessageCount++; + MH->LASTMSG = NOW; + + return; + } + } + + // Not a message. If it is a position report gate if have sent a message recently + + if (Payload[0] == '!' || Payload[0] == '/' || Payload[0] == '=' || Payload[0] == '@') // Posn Reports + { + if ((NOW - MH->LASTMSG) < 900 && MH->rfPort) + { + sprintf(Message, "}%s>%s,TCPIP,%s*:%s", Source, Dest, APRSCall, Payload); + + GetSemaphore(&Semaphore, 12); + SendAPRSMessageEx(Message, MH->rfPort, APRSCall, 1); // Set gated to IS flag + FreeSemaphore(&Semaphore); + + return; + } + } + + // If Gate Local to RF is defined, and station is in range, Gate it + + if (GateLocal && Station) + { + if (Station->Object) + Station = Station->Object; // If Object Report, base distance on Object, not station + + if (Station->Lat != 0.0 && Station->Lon != 0.0 && myDistance(Station->Lat, Station->Lon, 0) < GateLocalDistance) + { + sprintf(Message, "}%s>%s,TCPIP,%s*:%s", Source, Dest, APRSCall, Payload); + GetSemaphore(&Semaphore, 12); + SendAPRSMessage(Message, -1); // Send to all APRS Ports + FreeSemaphore(&Semaphore); + + return; + } + } +} + +APRSHEARDRECORD * FindStationInMH(char * Call) +{ + APRSHEARDRECORD * MH = MHDATA; + int i; + + // We keep call in ascii format, as that is what we get from APRS-IS, and we have it in that form + + for (i = 0; i < HEARDENTRIES; i++) + { + if (memcmp(Call, MH->MHCALL, 9) == 0) + return MH; + + MH++; + } + + return NULL; +} + +APRSHEARDRECORD * UpdateHeard(UCHAR * Call, int Port) +{ + APRSHEARDRECORD * MH = MHDATA; + APRSHEARDRECORD * MHBASE = MH; + int i; + time_t NOW = time(NULL); + time_t OLDEST = NOW - MAXAGE; + char CallPadded[10] = " "; + BOOL SaveIGate = FALSE; + time_t SaveLastMsg = 0; + int SaveheardViaIS = 0; + + // We keep call in ascii format, space padded, as that is what we get from APRS-IS, and we have it in that form + + // Make Sure Space Padded + + memcpy(CallPadded, Call, (int)strlen(Call)); + + for (i = 0; i < MAXHEARDENTRIES; i++) + { + if (memcmp(CallPadded, MH->MHCALL, 10) == 0) + { + // if from APRS-IS, only update if record hasn't been heard via RF + + if (Port == 0) + MH->heardViaIS = 1; // Flag heard via IS + + if (Port == 0 && MH->rfPort) + return MH; // Don't update RF with IS + + if (Port == MH->rfPort) + { + SaveIGate = MH->IGate; + SaveLastMsg = MH->LASTMSG; + SaveheardViaIS = MH->heardViaIS; + goto DoMove; + } + } + + if (MH->MHCALL[0] == 0 || MH->MHTIME < OLDEST) // Spare entry + goto DoMove; + + MH++; + } + + // TABLE FULL AND ENTRY NOT FOUND - MOVE DOWN ONE, AND ADD TO TOP + + i = MAXHEARDENTRIES - 1; + + // Move others down and add at front +DoMove: + if (i != 0) // First + memmove(MHBASE + 1, MHBASE, i * sizeof(APRSHEARDRECORD)); + + if (i >= HEARDENTRIES) + { + char Status[80]; + + HEARDENTRIES = i + 1; + + sprintf(Status, "IGATE Stats: Msgs %d Local Stns %d", MessageCount , CountLocalStations()); +#ifndef LINBPQ + SetDlgItemText(hConsWnd, IGATESTATS, Status); +#endif + } + + memcpy (MHBASE->MHCALL, CallPadded, 10); + MHBASE->rfPort = Port; + MHBASE->MHTIME = NOW; + MHBASE->IGate = SaveIGate; + MHBASE->LASTMSG = SaveLastMsg; + MHBASE->heardViaIS = SaveheardViaIS; + + return MHBASE; +} + +int CountLocalStations() +{ + APRSHEARDRECORD * MH = MHDATA; + int i, n = 0; + + for (i = 0; i < HEARDENTRIES; i++) + { + if (MH->rfPort) // DOn't count IS Stations + n++; + + MH++; + } + return n; +} + + +BOOL CheckforDups(char * Call, char * Msg, int Len) +{ + // Primitive duplicate suppression - see if same call and text reeived in last few seconds + + time_t Now = time(NULL); + time_t DupCheck = Now - DUPSECONDS; + int i, saveindex = -1; + char * ptr1; + + if (Len < 1) + return TRUE; + + for (i = 0; i < MAXDUPS; i++) + { + if (DupInfo[i].DupTime < DupCheck) + { + // too old - use first if we need to save it + + if (saveindex == -1) + { + saveindex = i; + } + + if (DupInfo[i].DupTime == 0) // Off end of used area + break; + + continue; + } + + if ((Len == DupInfo[i].DupLen || (DupInfo[i].DupLen == 99 && Len > 99)) && memcmp(Call, DupInfo[i].DupUser, 7) == 0 && (memcmp(Msg, DupInfo[i].DupText, DupInfo[i].DupLen) == 0)) + { + // Duplicate, so discard + + Msg[Len] = 0; + ptr1 = strchr(Msg, 13); + if (ptr1) + *ptr1 = 0; + +// Debugprintf("Duplicate Message supressed %s", Msg); + return TRUE; // Duplicate + } + } + + // Not in list + + if (saveindex == -1) // List is full + saveindex = MAXDUPS - 1; // Stick on end + + DupInfo[saveindex].DupTime = Now; + memcpy(DupInfo[saveindex].DupUser, Call, 7); + + if (Len > 99) Len = 99; + + DupInfo[saveindex].DupLen = Len; + memcpy(DupInfo[saveindex].DupText, Msg, Len); + + return FALSE; +} + +char * FormatAPRSMH(APRSHEARDRECORD * MH) + { + // Called from CMD.ASM + + struct tm * TM; + static char MHLine[50]; + time_t szClock = MH->MHTIME; + + szClock = (time(NULL) - szClock); + TM = gmtime(&szClock); + + sprintf(MHLine, "%-10s %d %.2d:%.2d:%.2d:%.2d %s\r", + MH->MHCALL, MH->rfPort, TM->tm_yday, TM->tm_hour, TM->tm_min, TM->tm_sec, (MH->IGate) ? "IGATE" : ""); + + return MHLine; + } + +// GPS Handling Code + +void SelectSource(BOOL Recovering); +void DecodeRMC(char * msg, size_t len); + +void PollGPSIn(); + + +UINT GPSType = 0xffff; // Source of Postion info - 1 = Phillips 2 = AIT1000. ffff = not posn message + +int RecoveryTimer; // Serial Port recovery + +double PI = 3.1415926535; +double P2 = 3.1415926535 / 180; + +double Latitude, Longtitude, SOG, COG, LatIncrement, LongIncrement; +double LastSOG = -1.0; + +BOOL Check0183CheckSum(char * msg, size_t len) +{ + BOOL retcode=TRUE; + char * ptr; + UCHAR sum,xsum1,xsum2; + + sum=0; + ptr=++msg; // Skip $ + +loop: + + if (*(ptr)=='*') goto eom; + + sum ^=*(ptr++); + + len--; + + if (len > 0) goto loop; + + return TRUE; // No Checksum + +eom: + _strupr(ptr); + + xsum1=*(++ptr); + xsum1-=0x30; + if (xsum1 > 9) xsum1-=7; + + xsum2=*(++ptr); + xsum2-=0x30; + if (xsum2 > 9) xsum2-=7; + + xsum1=xsum1<<4; + xsum1+=xsum2; + + return (xsum1==sum); +} + +BOOL OpenGPSPort() +{ + struct PortInfo * portptr = &InPorts[0]; + + // open COMM device + + if (strlen(GPSPort) < 4) + { + int port = atoi(GPSPort); +#ifdef WIN32 + sprintf(GPSPort, "COM%d", port); +#else + sprintf(GPSPort, "com%d", port); +#endif + } + + portptr->hDevice = OpenCOMPort(GPSPort, GPSSpeed, TRUE, TRUE, FALSE, 0); + + if (portptr->hDevice == 0) + { + return FALSE; + } + + return TRUE; +} + +void PollGPSIn() +{ + size_t len; + char GPSMsg[2000] = "$GPRMC,061213.000,A,5151.5021,N,00056.8388,E,0.15,324.11,190414,,,A*6F"; + char * ptr; + struct PortInfo * portptr; + + portptr = &InPorts[0]; + + if (!portptr->hDevice) + return; + + getgpsin: + +// Comm Error - probably lost USB Port. Try closing and reopening after a delay + +// if (RecoveryTimer == 0) +// { +// RecoveryTimer = 100; // 10 Secs +// return; +// } +// } + + if (portptr->gpsinptr == 160) + portptr->gpsinptr = 0; + + len = ReadCOMBlock(portptr->hDevice, &portptr->GPSinMsg[portptr->gpsinptr], + 160 - portptr->gpsinptr); + + if (len > 0) + { + portptr->gpsinptr += (int)len; + + ptr = memchr(portptr->GPSinMsg, 0x0a, portptr->gpsinptr); + + while (ptr != NULL) + { + ptr++; // include lf + len=ptr-(char *)&portptr->GPSinMsg; + memcpy(&GPSMsg,portptr->GPSinMsg,len); + + GPSMsg[len] = 0; + + if (Check0183CheckSum(GPSMsg, len)) + if (memcmp(&GPSMsg[3], "RMC", 3) == 0) + DecodeRMC(GPSMsg, len); + + portptr->gpsinptr -= (int)len; // bytes left + + if (portptr->gpsinptr > 0 && *ptr == 0) + { + *ptr++; + portptr->gpsinptr--; + } + + if (portptr->gpsinptr > 0) + { + memmove(portptr->GPSinMsg,ptr, portptr->gpsinptr); + ptr = memchr(portptr->GPSinMsg, 0x0a, portptr->gpsinptr); + } + else + ptr=0; + } + + goto getgpsin; + } + return; +} + + +void ClosePorts() +{ + if (InPorts[0].hDevice) + { + CloseCOMPort(InPorts[0].hDevice); + InPorts[0].hDevice=0; + } + + return; +} + +void DecodeRMC(char * msg, size_t len) +{ + char * ptr1; + char * ptr2; + char TimHH[3], TimMM[3], TimSS[3]; + char OurSog[5], OurCog[4]; + char LatDeg[3], LonDeg[4]; + char NewLat[10] = "", NewLon[10] = ""; + struct STATIONRECORD * Stn1; + + char Day[3]; + + ptr1 = &msg[7]; + + len-=7; + + ptr2=(char *)memchr(ptr1,',',15); + + if (ptr2 == 0) return; // Duff + + *(ptr2++)=0; + + memcpy(TimHH,ptr1,2); + memcpy(TimMM,ptr1+2,2); + memcpy(TimSS,ptr1+4,2); + TimHH[2]=0; + TimMM[2]=0; + TimSS[2]=0; + + ptr1=ptr2; + + if (*(ptr1) != 'A') // ' Data Not Valid + { +#ifndef LINBPQ + SetDlgItemText(hConsWnd, IDC_GPS, "No GPS Fix"); +#endif + return; + } + + ptr1+=2; + + ptr2=(char *)memchr(ptr1,',',15); + + if (ptr2 == 0) return; // Duff + + *(ptr2++)=0; + + memcpy(NewLat, ptr1, 7); + memcpy(LatDeg, ptr1, 2); + LatDeg[2]=0; + Lat=atof(LatDeg) + (atof(ptr1+2)/60); + + if (*(ptr1+7) > '4') if (NewLat[6] < '9') NewLat[6]++; + + ptr1=ptr2; + + NewLat[7] = (*ptr1); + if ((*ptr1) == 'S') Lat=-Lat; + + ptr1+=2; + + ptr2=(char *)memchr(ptr1,',',15); + + if (ptr2 == 0) return; // Duff + *(ptr2++)=0; + + memcpy(NewLon, ptr1, 8); + + memcpy(LonDeg,ptr1,3); + LonDeg[3]=0; + Lon=atof(LonDeg) + (atof(ptr1+3)/60); + + if (*(ptr1+8) > '4') if (NewLon[7] < '9') NewLon[7]++; + + ptr1=ptr2; + + NewLon[8] = (*ptr1); + if ((*ptr1) == 'W') Lon=-Lon; + + // Now have a valid posn, so stop sending Undefined LOC Sysbol + + SYMBOL = CFGSYMBOL; + SYMSET = CFGSYMSET; + + PosnSet = TRUE; + + Stn1 = (struct STATIONRECORD *)StnRecordBase; // Pass to App + Stn1->Lat = Lat; + Stn1->Lon = Lon; + + if (GPSOK == 0) + { +#ifdef LINBPQ + Debugprintf("GPS OK"); + printf("GPS OK\n"); +#else + SetDlgItemText(hConsWnd, IDC_GPS, "GPS OK"); +#endif + } + + GPSOK = 30; + + ptr1+=2; + + ptr2 = (char *)memchr(ptr1,',',30); + + if (ptr2 == 0) return; // Duff + + *(ptr2++)=0; + + memcpy(OurSog, ptr1, 4); + OurSog[4] = 0; + + ptr1=ptr2; + + ptr2 = (char *)memchr(ptr1,',',15); + + if (ptr2 == 0) return; // Duff + + *(ptr2++)=0; + + memcpy(OurCog, ptr1, 3); + OurCog[3] = 0; + + memcpy(Day,ptr2,2); + Day[2]=0; + + SOG = atof(OurSog); + COG = atof(OurCog); + + if (strcmp(NewLat, LAT) || strcmp(NewLon, LON)) + { + if (MobileBeaconInterval) + { + time_t NOW = time(NULL); + + if ((NOW - LastMobileBeacon) > MobileBeaconInterval) + { + LastMobileBeacon = NOW; + SendBeacon(0, StatusMsg, FALSE, TRUE); + } + } + if (GPSSetsLocator) + { + ToLOC(Lat, Lon, LOC); + sprintf(LOCATOR, "%f:%f", Lat, Lon); + } + } + + strcpy(LAT, NewLat); + strcpy(LON, NewLon); +} + +Dll VOID APIENTRY APRSConnect(char * Call, char * Filter) +{ + // Request APRS Data from Switch (called by APRS Applications) + + APRSApplConnected = TRUE; + APRSWeb = TRUE; + + strcpy(APPLFilter, Filter); + + if (APPLFilter[0]) + { + // This is called in APPL context so must queue the message + + char Msg[2000]; + PMSGWITHLEN buffptr; + + sprintf(Msg, "filter %s", Filter); + + if (strlen(Msg) > 240) + Msg[240] = 0; + + + GetSemaphore(&Semaphore, 11); + + buffptr = GetBuff(); + + if (buffptr) + { + buffptr->Len = 0; + strcpy(&buffptr->Data[0], "SERVER"); + strcpy(&buffptr->Data[10], Msg); + C_Q_ADD(&APPLTX_Q, buffptr); + } + + buffptr = GetBuff(); + + if (buffptr) + { + buffptr->Len = 0; + strcpy(&buffptr->Data[0], "SERVER"); + strcpy(&buffptr->Data[10], "filter?"); + C_Q_ADD(&APPLTX_Q, buffptr); + } + FreeSemaphore(&Semaphore); + } + strcpy(Call, CallPadded); +} + +Dll VOID APIENTRY APRSDisconnect() +{ + // Stop requesting APRS Data from Switch (called by APRS Applications) + + char Msg[2000]; + PMSGWITHLEN buffptr; + + strcpy(ISFilter, NodeFilter); + sprintf(Msg, "filter %s", NodeFilter); + + APRSApplConnected = FALSE; + APRSWeb = FALSE; + + GetSemaphore(&Semaphore, 11); + + buffptr = GetBuff(); + + if (buffptr) + { + buffptr->Len = 0; + strcpy(&buffptr->Data[0], "SERVER"); + strcpy(&buffptr->Data[10], Msg); + C_Q_ADD(&APPLTX_Q, buffptr); + } + + buffptr = GetBuff(); + + if (buffptr) + { + buffptr->Len = 0; + strcpy(&buffptr->Data[0], "SERVER"); + strcpy(&buffptr->Data[10], "filter?"); + C_Q_ADD(&APPLTX_Q, buffptr); + } + + while (APPL_Q) + { + buffptr = Q_REM(&APPL_Q); + ReleaseBuffer(buffptr); + } + + FreeSemaphore(&Semaphore); +} + + +Dll char * APIENTRY APRSGetStatusMsgPtr() +{ + return StatusMsg; +} + + + +Dll BOOL APIENTRY GetAPRSFrame(char * Frame, char * Call) +{ + // Request APRS Data from Switch (called by APRS Applications) + + void ** buffptr; +#ifdef bpq32 + struct _EXCEPTION_POINTERS exinfo; +#endif + + GetSemaphore(&Semaphore, 10); + { + if (APPL_Q) + { + buffptr = Q_REM(&APPL_Q); + + memcpy(Call, (char *)&buffptr[2], 12); + strcpy(Frame, (char *)&buffptr[5]); + + ReleaseBuffer(buffptr); + FreeSemaphore(&Semaphore); + return TRUE; + } + } + + FreeSemaphore(&Semaphore); + + return FALSE; +} + +Dll BOOL APIENTRY PutAPRSFrame(char * Frame, int Len, int Port) +{ + // Called from BPQAPRS App + // Message has to be queued so it can be sent by Timer Process (IS sock is not valid in this context) + + PMSGWITHLEN buffptr; + + GetSemaphore(&Semaphore, 11); + + buffptr = GetBuff(); + + if (buffptr) + { + buffptr->Len = ++Len; // Len doesn't include Null + memcpy(&buffptr->Data[0], Frame, Len); + C_Q_ADD(&APPLTX_Q, buffptr); + } + +// buffptr-> = Port; // Pass to SendAPRSMessage(); + + FreeSemaphore(&Semaphore); + + return TRUE; +} + +Dll BOOL APIENTRY APISendAPRSMessage(char * Text, char * ToCall) +{ + // Called from BPQAPRS App or BPQMail + // Message has to be queued so it can be sent by Timer Process (IS sock is not valid in this context) + + PMSGWITHLEN buffptr; + + if (APRSActive == 0) + return FALSE; + + GetSemaphore(&Semaphore, 11); + + buffptr = GetBuff(); + + if (buffptr) + { + buffptr->Len = 0; + memcpy(&buffptr->Data[0], ToCall, 9); + buffptr->Data[9] = 0; + strcpy(&buffptr->Data[10], Text); + C_Q_ADD(&APPLTX_Q, buffptr); + } + + FreeSemaphore(&Semaphore); + + return TRUE; +} + +Dll BOOL APIENTRY GetAPRSLatLon(double * PLat, double * PLon) +{ + *PLat = Lat; + *PLon = Lon; + + return GPSOK; +} + +Dll BOOL APIENTRY GetAPRSLatLonString(char * PLat, char * PLon) +{ + strcpy(PLat, LAT); + strcpy(PLon, LON); + + return GPSOK; +} + +// Code to support getting GPS from Andriod Device running BlueNMEA + + +#define SD_BOTH 0x02 + +static VOID ProcessReceivedData(SOCKET TCPSock) +{ + char UDPMsg[8192]; + char Buffer[65536]; + + int len = recv(TCPSock, Buffer, 65500, 0); + + char * ptr; + char * Lastptr; + + if (len <= 0) + { + closesocket(TCPSock); + BlueNMEAOK = FALSE; + return; + } + + ptr = Lastptr = Buffer; + Buffer[len] = 0; + + while (len > 0) + { + ptr = strchr(Lastptr, 10); + + if (ptr) + { + size_t Len = ptr - Lastptr -1; + + if (Len > 8100) + return; + + memcpy(UDPMsg, Lastptr, Len); + UDPMsg[Len++] = 13; + UDPMsg[Len++] = 10; + UDPMsg[Len] = 0; + + if (!Check0183CheckSum(UDPMsg, Len)) + { + Debugprintf("Checksum Error %s", UDPMsg); + } + else + { + if (memcmp(&UDPMsg[3], "RMC", 3) == 0) + DecodeRMC(UDPMsg, Len); + + else if (memcmp(UDPMsg, "!AIVDM", 6) == 0) + ProcessAISMessage(UDPMsg, Len); + + } + Lastptr = ptr + 1; + len -= (int)Len; + } + else + return; + } +} + +static VOID TCPConnect(void * unused) +{ + int err, ret; + u_long param=1; + BOOL bcopt=TRUE; + fd_set readfs; + fd_set errorfs; + struct timeval timeout; + struct sockaddr_in destaddr; + SOCKET TCPSock; + + if (HostName[0] == 0) + return; + + destaddr.sin_addr.s_addr = inet_addr(HostName); + destaddr.sin_family = AF_INET; + destaddr.sin_port = htons(HostPort); + + if (destaddr.sin_addr.s_addr == INADDR_NONE) + { + // Resolve name to address + + struct hostent * HostEnt = gethostbyname(HostName); + + if (!HostEnt) + return; // Resolve failed + + memcpy(&destaddr.sin_addr.s_addr,HostEnt->h_addr,4); + } + + TCPSock = socket(AF_INET,SOCK_STREAM,0); + + if (TCPSock == INVALID_SOCKET) + { + return; + } + + setsockopt (TCPSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); + + BlueNMEAOK = TRUE; // So we don't try to reconnect while waiting + + if (connect(TCPSock,(LPSOCKADDR) &destaddr, sizeof(destaddr)) == 0) + { + // + // Connected successful + // + + ioctl(TCPSock, FIONBIO, ¶m); + } + else + { + err=WSAGetLastError(); +#ifdef LINBPQ + printf("Connect Failed for AIS socket - error code = %d\n", err); +#else + Debugprintf("Connect Failed for AIS socket - error code = %d", err); +#endif + closesocket(TCPSock); + BlueNMEAOK = FALSE; + + return; + } + + BlueNMEAOK = TRUE; + + while (TRUE) + { + FD_ZERO(&readfs); + FD_ZERO(&errorfs); + + FD_SET(TCPSock,&readfs); + FD_SET(TCPSock,&errorfs); + + timeout.tv_sec = 900; + timeout.tv_usec = 0; // We should get messages more frequently that this + + ret = select((int)TCPSock + 1, &readfs, NULL, &errorfs, &timeout); + + if (ret == SOCKET_ERROR) + { + goto Lost; + } + if (ret > 0) + { + // See what happened + + if (FD_ISSET(TCPSock, &readfs)) + { + ProcessReceivedData(TCPSock); + } + + if (FD_ISSET(TCPSock, &errorfs)) + { +Lost: +#ifdef LINBPQ + printf("AIS Connection lost\n"); +#endif + closesocket(TCPSock); + BlueNMEAOK = FALSE;; + return; + } + } + else + { + // 15 mins without data. Shouldn't happen + + shutdown(TCPSock, SD_BOTH); + Sleep(100); + + closesocket(TCPSock); + BlueNMEAOK = FALSE; + return; + } + } +} + +int GPSDAlerted = 0; + +static VOID GPSDConnect(void * unused) +{ + int err, ret; + u_long param=1; + BOOL bcopt=TRUE; + fd_set readfs; + fd_set errorfs; + struct timeval timeout; + struct sockaddr_in destaddr; + SOCKET TCPSock; + + if (GPSDHost[0] == 0) + return; + + destaddr.sin_addr.s_addr = inet_addr(GPSDHost); + destaddr.sin_family = AF_INET; + destaddr.sin_port = htons(GPSDPort); + + TCPSock = socket(AF_INET,SOCK_STREAM,0); + + if (TCPSock == INVALID_SOCKET) + { + return; + } + + setsockopt (TCPSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); + + GPSDOK = TRUE; // So we don't try to reconnect while waiting + + if (connect(TCPSock,(LPSOCKADDR) &destaddr, sizeof(destaddr)) == 0) + { + // + // Connected successful + // + +#ifdef LINBPQ + printf("GPSD Connected\n"); +#else + Debugprintf("GPSD Connected"); +#endif + GPSDAlerted = 0; + ioctl(TCPSock, FIONBIO, ¶m); + + // Request data + + send(TCPSock, "?WATCH={\"enable\":true,\"nmea\":true}\r\n", 36, 0); + } + else + { + err=WSAGetLastError(); + if (GPSDAlerted == 0) +#ifdef LINBPQ + printf("GPSD Connect Failed - error code = %d\n", err); +#else + Debugprintf("GPSD Connect Failed - error code = %d", err); +#endif + GPSDAlerted = 1; + closesocket(TCPSock); + GPSDOK = FALSE; + + return; + } + + while (TRUE) + { + FD_ZERO(&readfs); + FD_ZERO(&errorfs); + + FD_SET(TCPSock,&readfs); + FD_SET(TCPSock,&errorfs); + + timeout.tv_sec = 900; + timeout.tv_usec = 0; // We should get messages more frequently that this + + ret = select((int)TCPSock + 1, &readfs, NULL, &errorfs, &timeout); + + if (ret == SOCKET_ERROR) + { + goto Lost; + } + if (ret > 0) + { + // See what happened + + if (FD_ISSET(TCPSock, &readfs)) + { + char Buffer[65536]; + int len = recv(TCPSock, Buffer, 65500, 0); + char TCPMsg[8192]; + + char * ptr; + char * Lastptr; + + if (len == 0) + { + closesocket(TCPSock); + GPSDOK = FALSE;; + return; + } + + if (len < 9000) + { + Buffer[len] = 0; + + ptr = Lastptr = Buffer; + Buffer[len] = 0; + + while (len > 0) + { + ptr = strchr(Lastptr, 10); + + if (ptr) + { + size_t Len = ptr - Lastptr -1; + + if (Len > 8100) + return; + + memcpy(TCPMsg, Lastptr, Len); + TCPMsg[Len++] = 13; + TCPMsg[Len++] = 10; + TCPMsg[Len] = 0; + + if (!Check0183CheckSum(TCPMsg, Len)) + { + Debugprintf("Checksum Error %s", TCPMsg); + } + else + { + if (memcmp(&TCPMsg[3], "RMC", 3) == 0) + DecodeRMC(TCPMsg, Len); + } + Lastptr = ptr + 1; + len -= (int)Len; + } + else + return; + } + } + } + + if (FD_ISSET(TCPSock, &errorfs)) + { +Lost: +#ifdef LINBPQ + printf("GPSD Connection lost\n"); +#endif + closesocket(TCPSock); + GPSDOK = FALSE;; + return; + } + } + else + { + // 15 mins without data. Shouldn't happen + + shutdown(TCPSock, SD_BOTH); + Sleep(100); + + closesocket(TCPSock); + GPSDOK = FALSE; + return; + } + } +} + + + + + +// Code Moved from APRS Application + +// +// APRS Mapping and Messaging App for BPQ32 Switch. +// + + +VOID APIENTRY APRSConnect(char * Call, char * Filter); +VOID APIENTRY APRSDisconnect(); +BOOL APIENTRY GetAPRSFrame(char * Frame, char * Call); +BOOL APIENTRY PutAPRSFrame(char * Frame, int Len, int Port); +BOOL APIENTRY PutAPRSMessage(char * Frame, int Len); +BOOL APIENTRY GetAPRSLatLon(double * PLat, double * PLon); +BOOL APIENTRY GetAPRSLatLonString(char * PLat, char * PLon); +VOID APIENTRY APISendBeacon(); + + +int NewLine(HWND hWnd); +VOID ProcessBuff(HWND hWnd, MESSAGE * buff,int len,int stamp); +int TogglePort(HWND hWnd, int Item, int mask); +VOID SendFrame(UCHAR * buff, int txlen); +int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); +int KissDecode(UCHAR * inbuff, int len); +//void UpdateStation(char * Call, char * Path, char * Comment, double V_Lat, double V_Lon, double V_SOG, double V_COG, int iconRow, int iconCol); +VOID FindStationsByPixel(int MouseX, int MouseY); +void RefreshStation(struct STATIONRECORD * ptr); +void RefreshStationList(); +void RefreshStationMap(); +BOOL DecodeLocationString(UCHAR * Payload, struct STATIONRECORD * Station); +VOID Decode_MIC_E_Packet(char * Payload, struct STATIONRECORD * Station); +BOOL GetLocPixels(double Lat, double Lon, int * X, int * Y); +VOID APRSPoll(); +VOID OSMThread(); +VOID ResolveThread(); +VOID RefreshTile(char * FN, int Zoom, int x, int y); +int ProcessMessage(char * Payload, struct STATIONRECORD * Station); +VOID APRSSecTimer(); +double myBearing(double laa, double loa); + +BOOL CreatePipeThread(); + +VOID SendWeatherBeacon(); +VOID DecodeWXPortList(); + + +VOID DecodeWXReport(struct APRSConnectionInfo * sockptr, char * WX) +{ + UCHAR * ptr = strchr(WX, '_'); + char Type; + int Val; + + if (ptr == 0) + return; + + sockptr->WindDirn = atoi(++ptr); + ptr += 4; + sockptr->WindSpeed = atoi(ptr); + ptr += 3; +WXLoop: + + Type = *(ptr++); + + if (*ptr =='.') // Missing Value + { + while (*ptr == '.') + ptr++; + + goto WXLoop; + } + + Val = atoi(ptr); + + switch (Type) + { + case 'c': // = wind direction (in degrees). + + sockptr->WindDirn = Val; + break; + + case 's': // = sustained one-minute wind speed (in mph). + + sockptr->WindSpeed = Val; + break; + + case 'g': // = gust (peak wind speed in mph in the last 5 minutes). + + sockptr->WindGust = Val; + break; + + case 't': // = temperature (in degrees Fahrenheit). Temperatures below zero are expressed as -01 to -99. + + sockptr->Temp = Val; + break; + + case 'r': // = rainfall (in hundredths of an inch) in the last hour. + + sockptr->RainLastHour = Val; + break; + + case 'p': // = rainfall (in hundredths of an inch) in the last 24 hours. + + sockptr->RainLastDay = Val; + break; + + case 'P': // = rainfall (in hundredths of an inch) since midnight. + + sockptr->RainToday = Val; + break; + + case 'h': // = humidity (in %. 00 = 100%). + + sockptr->Humidity = Val; + break; + + case 'b': // = barometric pressure (in tenths of millibars/tenths of hPascal). + + sockptr->Pressure = Val; + break; + + default: + + return; + } + while(isdigit(*ptr)) + { + ptr++; + } + + if (*ptr != ' ') + goto WXLoop; +} + +static char HeaderTemplate[] = "Accept: */*\r\nHost: %s\r\nConnection: close\r\nContent-Length: 0\r\nUser-Agent: BPQ32(G8BPQ)\r\n\r\n"; +//char Header[] = "Accept: */*\r\nHost: tile.openstreetmap.org\r\nConnection: close\r\nContent-Length: 0\r\nUser-Agent: BPQ32(G8BPQ)\r\n\r\n"; + +char APRSMsg[300]; + +Dll struct STATIONRECORD * APIENTRY APPLFindStation(char * Call, BOOL AddIfNotFount) +{ + // Called from APRS Appl + + struct STATIONRECORD * Stn; + + GetSemaphore(&Semaphore, 12); + Stn = FindStation(Call, AddIfNotFount) ; + FreeSemaphore(&Semaphore); + + return Stn; +} + +Dll struct APRSMESSAGE * APIENTRY APRSGetMessageBuffer() +{ + struct APRSMESSAGE * ptr = MessageRecordPool; + + if (ptr == NULL) + { + // try getting oldest + + ptr = SMEM->Messages; + + if (ptr) + { + SMEM->Messages = ptr->Next; + memset(ptr, 0, sizeof(struct APRSMESSAGE)); + } + return ptr; + } + + if (ptr) + { + MessageRecordPool = ptr->Next; // Unchain + MessageCount++; + + ptr->Next = NULL; + + memset(ptr, 0, sizeof(struct APRSMESSAGE)); + } + + return ptr; +} + + +struct STATIONRECORD * FindStation(char * Call, BOOL AddIfNotFount) +{ + int i = 0; + struct STATIONRECORD * find; + struct STATIONRECORD * ptr; + struct STATIONRECORD * last = NULL; + int sum = 0; + + if (APRSActive == 0 || StationRecords == 0) + return FALSE; + + if (strlen(Call) > 9) + { + Debugprintf("APRS Call too long %s", Call); + Call[9] = 0; + } + + find = *StationRecords; + while(find) + { + if (strlen(find->Callsign) > 9) + { + Debugprintf("APRS Call in Station List too long %s", find->Callsign); + find->Callsign[9] = 0; + } + + if (strcmp(find->Callsign, Call) == 0) + return find; + + last = find; + find = find->Next; + i++; + } + + // Not found - add on end + + if (AddIfNotFount) + { + // Get first from station record pool + + ptr = StationRecordPool; + + if (ptr) + { + StationRecordPool = ptr->Next; // Unchain + StationCount++; + } + else + { + // Get First from Stations + + ptr = *StationRecords; + + if (ptr) + *StationRecords = ptr->Next; + } + + if (ptr == NULL) + return NULL; + + memset(ptr, 0, sizeof(struct STATIONRECORD)); + +// EnterCriticalSection(&Crit); + + if (*StationRecords == NULL) + *StationRecords = ptr; + else + last->Next = ptr; + +// LeaveCriticalSection(&Crit); + + // Debugprintf("APRS Add Stn %s Station Count = %d", Call, StationCount); + + strcpy(ptr->Callsign, Call); + ptr->TimeLastUpdated = ptr->TimeAdded = time(NULL); + ptr->Index = i; + ptr->NoTracks = DefaultNoTracks; + + for (i = 0; i < 9; i++) + sum += Call[i]; + + sum %= 20; + + ptr->TrackColour = sum; + ptr->Moved = TRUE; + + return ptr; + } + else + return NULL; +} + +struct STATIONRECORD * ProcessRFFrame(char * Msg, int len, int * ourMessage) +{ + char * Payload; + char * Path = NULL; + char * Comment = NULL; + char * Callsign; + char * ptr; + int Port = 0; + + struct STATIONRECORD * Station = NULL; + + Msg[len - 1] = 0; + +// Debugprintf("RF Frame %s", Msg); + + Msg += 10; // Skip Timestamp + + Payload = strchr(Msg, ':'); // End of Address String + + if (Payload == NULL) + { + Debugprintf("Invalid Msg %s", Msg); + return Station; + } + + ptr = strstr(Msg, "Port="); + + if (ptr) + Port = atoi(&ptr[5]); + + Payload++; + + if (*Payload != 0x0d) + return Station; + + *Payload++ = 0; + + Callsign = Msg; + + Path = strchr(Msg, '>'); + + if (Path == NULL) + { + Debugprintf("Invalid Header %s", Msg); + return Station; + } + + *Path++ = 0; + + ptr = strchr(Path, ' '); + + if (ptr) + *ptr = 0; + + // Look up station - create a new one if not found + + if (strcmp(Callsign, "AIS") == 0) + { + if (needAIS) + { + Payload += 3; + ProcessAISMessage(Payload, strlen(Payload)); + } + else + Debugprintf(Payload); + + return 0; + } + + Station = FindStation(Callsign, TRUE); + + strcpy(Station->Path, Path); + strcpy(Station->LastPacket, Payload); + Station->LastPort = Port; + + *ourMessage = DecodeAPRSPayload(Payload, Station); + Station->TimeLastUpdated = time(NULL); + + return Station; +} + + +/* +2E0AYY>APU25N,TCPIP*,qAC,AHUBSWE2:=5105.18N/00108.19E-Paul in Folkestone Kent {UIV32N} +G0AVP-12>APT310,MB7UC*,WIDE3-2,qAR,G3PWJ:!5047.19N\00108.45Wk074/000/Paul mobile +G0CJM-12>CQ,TCPIP*,qAC,AHUBSWE2:=/3&Rio94sg +M0HFC>APRS,WIDE2-1,qAR,G0MNI:!5342.83N/00013.79W# Humber Fortress ARC Look us up on QRZ +G8WVW-3>APTT4,WIDE1-1,WIDE2-1,qAS,G8WVW:T#063,123,036,000,000,000,00000000 +*/ + + +struct STATIONRECORD * DecodeAPRSISMsg(char * Msg) +{ + char * Payload; + char * Path = NULL; + char * Comment = NULL; + char * Callsign; + struct STATIONRECORD * Station = NULL; + +// Debugprintf(Msg); + + Payload = strchr(Msg, ':'); // End of Address String + + if (Payload == NULL) + { + Debugprintf("Invalid Msg %s", Msg); + return Station; + } + + *Payload++ = 0; + + Callsign = Msg; + + Path = strchr(Msg, '>'); + + if (Path == NULL) + { + Debugprintf("Invalid Msg %s", Msg); + return Station; + } + + *Path++ = 0; + + // Look up station - create a new one if not found + + if (strlen(Callsign) > 11) + { + Debugprintf("Invalid Msg %s", Msg); + return Station; + } + + Station = FindStation(Callsign, TRUE); + + strcpy(Station->Path, Path); + strcpy(Station->LastPacket, Payload); + Station->LastPort = 0; + + DecodeAPRSPayload(Payload, Station); + Station->TimeLastUpdated = time(NULL); + + return Station; +} + +double Cube91 = 91.0 * 91.0 * 91.0; +double Square91 = 91.0 * 91.0; + +BOOL DecodeLocationString(UCHAR * Payload, struct STATIONRECORD * Station) +{ + UCHAR SymChar; + char SymSet; + char NS; + char EW; + double NewLat, NewLon; + char LatDeg[3], LonDeg[4]; + char save; + + // Compressed has first character not a digit (it is symbol table) + + // /YYYYXXXX$csT + + if (Payload[0] == '!') + return FALSE; // Ultimeter 2000 Weather Station + + if (!isdigit(*Payload)) + { + int C, S; + + SymSet = *Payload; + SymChar = Payload[9]; + + NewLat = 90.0 - ((Payload[1] - 33) * Cube91 + (Payload[2] - 33) * Square91 + + (Payload[3] - 33) * 91.0 + (Payload[4] - 33)) / 380926.0; + + Payload += 4; + + NewLon = -180.0 + ((Payload[1] - 33) * Cube91 + (Payload[2] - 33) * Square91 + + (Payload[3] - 33) * 91.0 + (Payload[4] - 33)) / 190463.0; + + C = Payload[6] - 33; + + if (C >= 0 && C < 90 ) + { + S = Payload[7] - 33; + + Station->Course = C * 4; + Station->Speed = (pow(1.08, S) - 1) * 1.15077945; // MPH; + } + + + + } + else + { + // Standard format ddmm.mmN/dddmm.mmE? + + NS = Payload[7] & 0xdf; // Mask Lower Case Bit + EW = Payload[17] & 0xdf; + + SymSet = Payload[8]; + SymChar = Payload[18]; + + if (SymChar == '_') // WX + { + if (strlen(Payload) > 30) + strcpy(Station->LastWXPacket, Payload); + } + + memcpy(LatDeg, Payload,2); + LatDeg[2]=0; + NewLat = atof(LatDeg) + (atof(Payload+2) / 60); + + if (NS == 'S') + NewLat = -NewLat; + else + if (NS != 'N') + return FALSE; + + memcpy(LonDeg,Payload + 9, 3); + + if (SymChar != '_' && Payload[22] == '/') // not if WX + { + Station->Course = atoi(Payload + 19); + Station->Speed = atoi(Payload + 23); + } + + LonDeg[3]=0; + + save = Payload[17]; + Payload[17] = 0; + NewLon = atof(LonDeg) + (atof(Payload+12) / 60); + Payload[17] = save; + + if (EW == 'W') + NewLon = -NewLon; + else + if (EW != 'E') + return FALSE; + } + + Station->Symbol = SymChar; + + if (SymChar > ' ' && SymChar < 0x7f) + SymChar -= '!'; + else + SymChar = 0; + + Station->IconOverlay = 0; + + if ((SymSet >= '0' && SymSet <= '9') || (SymSet >= 'A' && SymSet <= 'Z')) + { + SymChar += 96; + Station->IconOverlay = SymSet; + } + else + if (SymSet == '\\') + SymChar += 96; + + Station->iconRow = SymChar >> 4; + Station->iconCol = SymChar & 15; + + if (NewLat > 90 || NewLat < -90 || NewLon > 180 || NewLon < -180) + return TRUE; + + if (Station->Lat != NewLat || Station->Lon != NewLon) + { + time_t NOW = time(NULL); + time_t Age = NOW - Station->TimeLastTracked; + + if (Age > 15) // Don't update too often + { + // Add to track + + Station->TimeLastTracked = NOW; + +// if (memcmp(Station->Callsign, "ISS ", 4) == 0) +// Debugprintf("%s %s %s ",Station->Callsign, Station->Path, Station->LastPacket); + + Station->LatTrack[Station->Trackptr] = NewLat; + Station->LonTrack[Station->Trackptr] = NewLon; + Station->TrackTime[Station->Trackptr] = NOW; + + Station->Trackptr++; + Station->Moved = TRUE; + + if (Station->Trackptr == TRACKPOINTS) + Station->Trackptr = 0; + } + + Station->Lat = NewLat; + Station->Lon = NewLon; + Station->Approx = 0; + } + + + return TRUE; +} + +int DecodeAPRSPayload(char * Payload, struct STATIONRECORD * Station) +{ + char * TimeStamp; + char * ObjName; + char ObjState; + struct STATIONRECORD * Object; + BOOL Item = FALSE; + char * ptr; + char * Callsign; + char * Path; + char * Msg; + char * context; + struct STATIONRECORD * TPStation; + + Station->Object = NULL; + + if (strcmp(Station->Callsign, "LA1ZDA-2") == 0) + { + int i = 1; + } + switch(*Payload) + { + case '`': + case 0x27: // ' + case 0x1c: + case 0x1d: // MIC-E + + Decode_MIC_E_Packet(Payload, Station); + return 0; + + case '$': // NMEA + Debugprintf(Payload); + break; + + case ')': // Item + +// Debugprintf("%s %s %s", Station->Callsign, Station->Path, Payload); + + Item = TRUE; + ObjName = ptr = Payload + 1; + + while (TRUE) + { + ObjState = *ptr; + if (ObjState == 0) + return 0; // Corrupt + + if (ObjState == '!' || ObjState == '_') // Item Terminator + break; + + ptr++; + } + + *ptr = 0; // Terminate Name + + Object = FindStation(ObjName, TRUE); + Object->ObjState = *ptr++ = ObjState; + + strcpy(Object->Path, Station->Callsign); + strcat(Object->Path, ">"); + if (Object == Station) + { + char Temp[256]; + strcpy(Temp, Station->Path); + strcat(Object->Path, Temp); + Debugprintf("item is station %s", Payload); + } + else + strcat(Object->Path, Station->Path); + + strcpy(Object->LastPacket, Payload); + + if (ObjState != '_') // Deleted Objects may have odd positions + DecodeLocationString(ptr, Object); + + Object->TimeLastUpdated = time(NULL); + Station->Object = Object; + return 0; + + + case ';': // Object + + ObjName = Payload + 1; + ObjState = Payload[10]; // * Live, _Killed + + Payload[10] = 0; + Object = FindStation(ObjName, TRUE); + Object->ObjState = Payload[10] = ObjState; + + strcpy(Object->Path, Station->Callsign); + strcat(Object->Path, ">"); + if (Object == Station) + { + char Temp[256]; + strcpy(Temp, Station->Path); + strcat(Object->Path, Temp); + Debugprintf("Object is station %s", Payload); + } + else + strcat(Object->Path, Station->Path); + + + strcpy(Object->LastPacket, Payload); + + TimeStamp = Payload + 11; + + if (ObjState != '_') // Deleted Objects may have odd positions + DecodeLocationString(Payload + 18, Object); + + Object->TimeLastUpdated = time(NULL); + Object->LastPort = Station->LastPort; + Station->Object = Object; + return 0; + + case '@': + case '/': // Timestamp, No Messaging + + TimeStamp = ++Payload; + Payload += 6; + + case '=': + case '!': + + Payload++; + + DecodeLocationString(Payload, Station); + + return 0; + + case '>': // Status + + strcpy(Station->Status, &Payload[1]); + + case '<': // Capabilities + case '_': // Weather + case 'T': // Telemetry + + break; + + case ':': // Message + + return ProcessMessage(Payload, Station); + + case '}': // Third Party Header + + // Process Payload as a new message + + // }GM7HHB-9>APDR12,TCPIP,MM1AVR*:=5556.62N/00303.55W>204/000/A=000213 http://www.dstartv.com + + Callsign = Msg = &Payload[1]; + Path = strchr(Msg, '>'); + + if (Path == NULL) + return 0; + + *Path++ = 0; + + Payload = strchr(Path, ':'); + + if (Payload == NULL) + return 0; + + *(Payload++) = 0; + + // Check Dup Filter + + if (CheckforDups(Callsign, Payload, (int)strlen(Payload))) + return 0; + + // Look up station - create a new one if not found + + TPStation = FindStation(Callsign, TRUE); + + strcpy(TPStation->Path, Path); + strcpy(TPStation->LastPacket, Payload); + TPStation->LastPort = 0; // Heard on RF, but info is from IS + + DecodeAPRSPayload(Payload, TPStation); + TPStation->TimeLastUpdated = time(NULL); + + return 0; + + default: + + // Non - APRS Message. If Payload contains a valid 6 char locator derive a position from it + + if (Station->Lat != 0.0 || Station->Lon != 0.0) + return 0; // already have position + + ptr = strtok_s(Payload, ",[](){} \n", &context); + + while (ptr && ptr[0]) + { + if (strlen(ptr) == 6) // could be locator + { + double Lat = 0.0, Lon = 0.0; + + if (FromLOC(ptr, &Lat, &Lon)) + { + if (Lat != 0.0 && Lon != 0.0) + { + // Randomise in locator square. + + Lat = Lat + ((rand() / 24.0) / RAND_MAX); + Lon = Lon + ((rand() / 12.0) / RAND_MAX); + Station->Lat = Lat; + Station->Lon = Lon; + Station->Approx = 1; + Debugprintf("%s %s %s", Station->Callsign, Station->Path, Payload); + } + } + } + + ptr = strtok_s(NULL, ",[](){} \n", &context); + } + + return 0; + } + return 0; +} + +// Convert MIC-E Char to Lat Digit (offset by 0x30) +// 0123456789 @ABCDEFGHIJKLMNOPQRSTUVWXYZ +char MicELat[] = "0123456789???????0123456789 ???0123456789 " ; + +char MicECode[]= "0000000000???????111111111110???22222222222" ; + + +VOID Decode_MIC_E_Packet(char * Payload, struct STATIONRECORD * Station) +{ + // Info is encoded in the Dest Addr (in Station->Path) as well as Payload. + // See APRS Spec for full details + + char Lat[10]; // DDMMHH + char LatDeg[3]; + char * ptr; + char c; + int i, n; + int LonDeg, LonMin; + BOOL LonOffset = FALSE; + char NS = 'S'; + char EW = 'E'; + UCHAR SymChar, SymSet; + double NewLat, NewLon; + int SP, DC, SE; // Course/Speed Encoded + int Course, Speed; + + // Make sure packet is long enough to have an valid address + + if (strlen(Payload) < 9) + return; + + ptr = &Station->Path[0]; + + for (i = 0; i < 6; i++) + { + n = (*(ptr++)) - 0x30; + c = MicELat[n]; + + if (c == '?') // Illegal + return; + + if (c == ' ') + c = '0'; // Limited Precision + + Lat[i] = c; + + } + + Lat[6] = 0; + + if (Station->Path[3] > 'O') + NS = 'N'; + + if (Station->Path[5] > 'O') + EW = 'W'; + + if (Station->Path[4] > 'O') + LonOffset = TRUE; + + n = Payload[1] - 28; // Lon Degrees S9PU0T,WIDE1-1,WIDE2-2,qAR,WB9TLH-15:`rB0oII>/]"6W}44 + + if (LonOffset) + n += 100; + + if (n > 179 && n < 190) + n -= 80; + else + if (n > 189 && n < 200) + n -= 190; + + LonDeg = n; + +/* + To decode the longitude degrees value: +1. subtract 28 from the d+28 value to obtain d. +2. if the longitude offset is +100 degrees, add 100 to d. +3. subtract 80 if 180 ˜ d ˜ 189 +(i.e. the longitude is in the range 100–109 degrees). +4. or, subtract 190 if 190 ˜ d ˜ 199. +(i.e. the longitude is in the range 0–9 degrees). +*/ + + n = Payload[2] - 28; // Lon Mins + + if (n > 59) + n -= 60; + + LonMin = n; + + n = Payload[3] - 28; // Lon Mins/100; + +//1. subtract 28 from the m+28 value to obtain m. +//2. subtract 60 if m ™ 60. +//(i.e. the longitude minutes is in the range 0–9). + + + memcpy(LatDeg, Lat, 2); + LatDeg[2]=0; + + NewLat = atof(LatDeg) + (atof(Lat+2) / 6000.0); + + if (NS == 'S') + NewLat = -NewLat; + + NewLon = LonDeg + LonMin / 60.0 + n / 6000.0; + + if (EW == 'W') // West + NewLon = -NewLon; + + + SP = Payload[4] - 28; + DC = Payload[5] - 28; + SE = Payload[6] - 28; // Course 100 and 10 degs + + Speed = DC / 10; // Quotient = Speed Units + Course = DC - (Speed * 10); // Remainder = Course Deg/100 + + Course = SE + (Course * 100); + + Speed += SP * 10; + + if (Speed >= 800) + Speed -= 800; + + if (Course >= 400) + Course -= 400; + + Station->Course = Course; + Station->Speed = Speed * 1.15077945; // MPH + +// Debugprintf("MIC-E Course/Speed %s %d %d", Station->Callsign, Course, Speed); + + SymChar = Payload[7]; // Symbol + SymSet = Payload[8]; // Symbol + + SymChar -= '!'; + + Station->IconOverlay = 0; + + if ((SymSet >= '0' && SymSet <= '9') || (SymSet >= 'A' && SymSet <= 'Z')) + { + SymChar += 96; + Station->IconOverlay = SymSet; + } + else + if (SymSet == '\\') + SymChar += 96; + + Station->iconRow = SymChar >> 4; + Station->iconCol = SymChar & 15; + + if (NewLat > 90 || NewLat < -90 || NewLon > 180 || NewLon < -180) + return; + + if (Station->Lat != NewLat || Station->Lon != NewLon) + { + time_t NOW = time(NULL); + time_t Age = NOW - Station->TimeLastUpdated; + + if (Age > 15) // Don't update too often + { + // Add to track + +// if (memcmp(Station->Callsign, "ISS ", 4) == 0) +// Debugprintf("%s %s %s ",Station->Callsign, Station->Path, Station->LastPacket); + + Station->LatTrack[Station->Trackptr] = NewLat; + Station->LonTrack[Station->Trackptr] = NewLon; + Station->TrackTime[Station->Trackptr] = NOW; + + Station->Trackptr++; + Station->Moved = TRUE; + + if (Station->Trackptr == TRACKPOINTS) + Station->Trackptr = 0; + } + + Station->Lat = NewLat; + Station->Lon = NewLon; + Station->Approx = 0; + } + + return; + +} + +/* + +INT_PTR CALLBACK ChildDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ +// This processes messages from controls on the tab subpages + int Command; + +// int retCode, disp; +// char Key[80]; +// HKEY hKey; +// BOOL OK; +// OPENFILENAME ofn; +// char Digis[100]; + + int Port = PortNum[CurrentPage]; + + switch (message) + { + case WM_NOTIFY: + + switch (((LPNMHDR)lParam)->code) + { + case TCN_SELCHANGE: + OnSelChanged(hDlg); + return TRUE; + // More cases on WM_NOTIFY switch. + case NM_CHAR: + return TRUE; + } + + break; + case WM_INITDIALOG: + OnChildDialogInit( hDlg); + return (INT_PTR)TRUE; + + case WM_CTLCOLORDLG: + + return (LONG)bgBrush; + + case WM_CTLCOLORSTATIC: + { + HDC hdcStatic = (HDC)wParam; + SetTextColor(hdcStatic, RGB(0, 0, 0)); + SetBkMode(hdcStatic, TRANSPARENT); + return (LONG)bgBrush; + } + + + case WM_COMMAND: + + Command = LOWORD(wParam); + + if (Command == 2002) + return TRUE; + + switch (Command) + { +/* case IDC_FILE: + + memset(&ofn, 0, sizeof (OPENFILENAME)); + ofn.lStructSize = sizeof (OPENFILENAME); + ofn.hwndOwner = hDlg; + ofn.lpstrFile = &FN[Port][0]; + ofn.nMaxFile = 250; + ofn.lpstrTitle = "File to send as beacon"; + ofn.lpstrInitialDir = GetBPQDirectory(); + + if (GetOpenFileName(&ofn)) + SetDlgItemText(hDlg, IDC_FILENAME, &FN[Port][0]); + + break; + + + case IDOK: + + GetDlgItemText(hDlg, IDC_UIDEST, &UIDEST[Port][0], 10); + + if (UIDigi[Port]) + { + free(UIDigi[Port]); + UIDigi[Port] = NULL; + } + + if (UIDigiAX[Port]) + { + free(UIDigiAX[Port]); + UIDigiAX[Port] = NULL; + } + + GetDlgItemText(hDlg, IDC_UIDIGIS, Digis, 99); + + UIDigi[Port] = _strdup(Digis); + + GetDlgItemText(hDlg, IDC_FILENAME, &FN[Port][0], 255); + GetDlgItemText(hDlg, IDC_MESSAGE, &Message[Port][0], 1000); + + Interval[Port] = GetDlgItemInt(hDlg, IDC_INTERVAL, &OK, FALSE); + + MinCounter[Port] = Interval[Port]; + + SendFromFile[Port] = IsDlgButtonChecked(hDlg, IDC_FROMFILE); + + sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\UIUtil\\UIPort%d", PortNum[CurrentPage]); + + retCode = RegCreateKeyEx(REGTREE, + Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); + + if (retCode == ERROR_SUCCESS) + { + retCode = RegSetValueEx(hKey, "UIDEST", 0, REG_SZ,(BYTE *)&UIDEST[Port][0], strlen(&UIDEST[Port][0])); + retCode = RegSetValueEx(hKey, "FileName", 0, REG_SZ,(BYTE *)&FN[Port][0], strlen(&FN[Port][0])); + retCode = RegSetValueEx(hKey, "Message", 0, REG_SZ,(BYTE *)&Message[Port][0], strlen(&Message[Port][0])); + retCode = RegSetValueEx(hKey, "Interval", 0, REG_DWORD,(BYTE *)&Interval[Port], 4); + retCode = RegSetValueEx(hKey, "SendFromFile", 0, REG_DWORD,(BYTE *)&SendFromFile[Port], 4); + retCode = RegSetValueEx(hKey, "Enabled", 0, REG_DWORD,(BYTE *)&UIEnabled[Port], 4); + retCode = RegSetValueEx(hKey, "Digis",0, REG_SZ, Digis, strlen(Digis)); + + RegCloseKey(hKey); + } + + SetupUI(Port); + + return (INT_PTR)TRUE; + + + case IDCANCEL: + + EndDialog(hDlg, LOWORD(wParam)); + return (INT_PTR)TRUE; + + case ID_TEST: + + SendBeacon(Port); + return TRUE; + + + + + } + break; + + } + return (INT_PTR)FALSE; +} + + + + +VOID WINAPI OnTabbedDialogInit(HWND hDlg) +{ + DLGHDR *pHdr = (DLGHDR *) LocalAlloc(LPTR, sizeof(DLGHDR)); + DWORD dwDlgBase = GetDialogBaseUnits(); + int cxMargin = LOWORD(dwDlgBase) / 4; + int cyMargin = HIWORD(dwDlgBase) / 8; + + TC_ITEM tie; + RECT rcTab; + + int i, pos, tab = 0; + INITCOMMONCONTROLSEX init; + + char PortNo[60]; + struct _EXTPORTDATA * PORTVEC; + + hwndDlg = hDlg; // Save Window Handle + + // Save a pointer to the DLGHDR structure. + + SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) pHdr); + + // Create the tab control. + + + init.dwICC = ICC_STANDARD_CLASSES; + init.dwSize=sizeof(init); + i=InitCommonControlsEx(&init); + + pHdr->hwndTab = CreateWindow(WC_TABCONTROL, "", WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, + 0, 0, 100, 100, hwndDlg, NULL, hInst, NULL); + + if (pHdr->hwndTab == NULL) { + + // handle error + + } + + // Add a tab for each of the child dialog boxes. + + tie.mask = TCIF_TEXT | TCIF_IMAGE; + + tie.iImage = -1; + + for (i = 1; i <= GetNumberofPorts(); i++) + { + // Only allow UI on ax.25 ports + + PORTVEC = (struct _EXTPORTDATA * )GetPortTableEntry(i); + + if (PORTVEC->PORTCONTROL.PORTTYPE == 16) // EXTERNAL + if (PORTVEC->PORTCONTROL.PROTOCOL == 10) // Pactor/WINMOR + continue; + + sprintf(PortNo, "Port %2d", GetPortNumber(i)); + PortNum[tab] = GetPortNumber(i); + + tie.pszText = PortNo; + TabCtrl_InsertItem(pHdr->hwndTab, tab, &tie); + + pHdr->apRes[tab++] = DoLockDlgRes("PORTPAGE"); + + } + + PageCount = tab; + + // Determine the bounding rectangle for all child dialog boxes. + + SetRectEmpty(&rcTab); + + for (i = 0; i < PageCount; i++) + { + if (pHdr->apRes[i]->cx > rcTab.right) + rcTab.right = pHdr->apRes[i]->cx; + + if (pHdr->apRes[i]->cy > rcTab.bottom) + rcTab.bottom = pHdr->apRes[i]->cy; + + } + + MapDialogRect(hwndDlg, &rcTab); + +// rcTab.right = rcTab.right * LOWORD(dwDlgBase) / 4; + +// rcTab.bottom = rcTab.bottom * HIWORD(dwDlgBase) / 8; + + // Calculate how large to make the tab control, so + + // the display area can accomodate all the child dialog boxes. + + TabCtrl_AdjustRect(pHdr->hwndTab, TRUE, &rcTab); + + OffsetRect(&rcTab, cxMargin - rcTab.left, cyMargin - rcTab.top); + + // Calculate the display rectangle. + + CopyRect(&pHdr->rcDisplay, &rcTab); + + TabCtrl_AdjustRect(pHdr->hwndTab, FALSE, &pHdr->rcDisplay); + + // Set the size and position of the tab control, buttons, + + // and dialog box. + + SetWindowPos(pHdr->hwndTab, NULL, rcTab.left, rcTab.top, rcTab.right - rcTab.left, rcTab.bottom - rcTab.top, SWP_NOZORDER); + + // Move the Buttons to bottom of page + + pos=rcTab.left+cxMargin; + + + // Size the dialog box. + + SetWindowPos(hwndDlg, NULL, 0, 0, rcTab.right + cyMargin + 2 * GetSystemMetrics(SM_CXDLGFRAME), + rcTab.bottom + 2 * cyMargin + 2 * GetSystemMetrics(SM_CYDLGFRAME) + GetSystemMetrics(SM_CYCAPTION), + SWP_NOMOVE | SWP_NOZORDER); + + // Simulate selection of the first item. + + OnSelChanged(hwndDlg); + +} + +// DoLockDlgRes - loads and locks a dialog template resource. + +// Returns a pointer to the locked resource. + +// lpszResName - name of the resource + +DLGTEMPLATE * WINAPI DoLockDlgRes(LPCSTR lpszResName) +{ + HRSRC hrsrc = FindResource(NULL, lpszResName, RT_DIALOG); + HGLOBAL hglb = LoadResource(hInst, hrsrc); + + return (DLGTEMPLATE *) LockResource(hglb); +} + +//The following function processes the TCN_SELCHANGE notification message for the main dialog box. The function destroys the dialog box for the outgoing page, if any. Then it uses the CreateDialogIndirect function to create a modeless dialog box for the incoming page. + +// OnSelChanged - processes the TCN_SELCHANGE notification. + +// hwndDlg - handle of the parent dialog box + +VOID WINAPI OnSelChanged(HWND hwndDlg) +{ + char PortDesc[40]; + int Port; + + DLGHDR *pHdr = (DLGHDR *) GetWindowLong(hwndDlg, GWL_USERDATA); + + CurrentPage = TabCtrl_GetCurSel(pHdr->hwndTab); + + // Destroy the current child dialog box, if any. + + if (pHdr->hwndDisplay != NULL) + + DestroyWindow(pHdr->hwndDisplay); + + // Create the new child dialog box. + + pHdr->hwndDisplay = CreateDialogIndirect(hInst, pHdr->apRes[CurrentPage], hwndDlg, ChildDialogProc); + + hwndDisplay = pHdr->hwndDisplay; // Save + + Port = PortNum[CurrentPage]; + // Fill in the controls + + GetPortDescription(PortNum[CurrentPage], PortDesc); + + SetDlgItemText(hwndDisplay, IDC_PORTNAME, PortDesc); + +// CheckDlgButton(hwndDisplay, IDC_FROMFILE, SendFromFile[Port]); + +// SetDlgItemInt(hwndDisplay, IDC_INTERVAL, Interval[Port], FALSE); + + SetDlgItemText(hwndDisplay, IDC_UIDEST, &UIDEST[Port][0]); + SetDlgItemText(hwndDisplay, IDC_UIDIGIS, UIDigi[Port]); + + + +// SetDlgItemText(hwndDisplay, IDC_FILENAME, &FN[Port][0]); +// SetDlgItemText(hwndDisplay, IDC_MESSAGE, &Message[Port][0]); + + ShowWindow(pHdr->hwndDisplay, SW_SHOWNORMAL); + +} + +//The following function processes the WM_INITDIALOG message for each of the child dialog boxes. You cannot specify the position of a dialog box created using the CreateDialogIndirect function. This function uses the SetWindowPos function to position the child dialog within the tab control's display area. + +// OnChildDialogInit - Positions the child dialog box to fall + +// within the display area of the tab control. + +VOID WINAPI OnChildDialogInit(HWND hwndDlg) +{ + HWND hwndParent = GetParent(hwndDlg); + DLGHDR *pHdr = (DLGHDR *) GetWindowLong(hwndParent, GWL_USERDATA); + + SetWindowPos(hwndDlg, HWND_TOP, pHdr->rcDisplay.left, pHdr->rcDisplay.top, 0, 0, SWP_NOSIZE); +} + + +*/ + + +/* +VOID ProcessMessage(char * Payload, struct STATIONRECORD * Station) +{ + char MsgDest[10]; + struct APRSMESSAGE * Message; + struct APRSMESSAGE * ptr = Messages; + char * TextPtr = &Payload[11]; + char * SeqPtr; + int n = 0; + char FromCall[10] = " "; + struct tm * TM; + time_t NOW; + + memcpy(FromCall, Station->Callsign, (int)strlen(Station->Callsign)); + memcpy(MsgDest, &Payload[1], 9); + MsgDest[9] = 0; + + SeqPtr = strchr(TextPtr, '{'); + + if (SeqPtr) + { + *(SeqPtr++) = 0; + if(strlen(SeqPtr) > 6) + SeqPtr[7] = 0; + } + + if (_memicmp(TextPtr, "ack", 3) == 0) + { + // Message Ack. See if for one of our messages + + ptr = OutstandingMsgs; + + if (ptr == 0) + return; + + do + { + if (strcmp(ptr->FromCall, MsgDest) == 0 + && strcmp(ptr->ToCall, FromCall) == 0 + && strcmp(ptr->Seq, &TextPtr[3]) == 0) + { + // Message is acked + + ptr->Retries = 0; + ptr->Acked = TRUE; +// if (hMsgsOut) +// UpdateTXMessageLine(hMsgsOut, n, ptr); + + return; + } + ptr = ptr->Next; + n++; + + } while (ptr); + + return; + } + + Message = malloc(sizeof(struct APRSMESSAGE)); + memset(Message, 0, sizeof(struct APRSMESSAGE)); + strcpy(Message->FromCall, Station->Callsign); + strcpy(Message->ToCall, MsgDest); + + if (SeqPtr) + { + strcpy(Message->Seq, SeqPtr); + + // If a REPLY-ACK Seg, copy to LastRXSeq, and see if it acks a message + + if (SeqPtr[2] == '}') + { + struct APRSMESSAGE * ptr1; + int nn = 0; + + strcpy(Station->LastRXSeq, SeqPtr); + + ptr1 = OutstandingMsgs; + + while (ptr1) + { + if (strcmp(ptr1->FromCall, MsgDest) == 0 + && strcmp(ptr1->ToCall, FromCall) == 0 + && memcmp(&ptr1->Seq, &SeqPtr[3], 2) == 0) + { + // Message is acked + + ptr1->Acked = TRUE; + ptr1->Retries = 0; +// if (hMsgsOut) +// UpdateTXMessageLine(hMsgsOut, nn, ptr); + + break; + } + ptr1 = ptr1->Next; + nn++; + } + } + else + { + // Station is not using reply-ack - set to send simple numeric sequence (workround for bug in APRS Messanger + + Station->SimpleNumericSeq = TRUE; + } + } + + if (strlen(TextPtr) > 100) + TextPtr[100] = 0; + + strcpy(Message->Text, TextPtr); + + NOW = time(NULL); + + if (DefaultLocalTime) + TM = localtime(&NOW); + else + TM = gmtime(&NOW); + + sprintf(Message->Time, "%.2d:%.2d", TM->tm_hour, TM->tm_min); + + if (_stricmp(MsgDest, APRSCall) == 0 && SeqPtr) // ack it if it has a sequence + { + // For us - send an Ack + + char ack[30]; + + int n = sprintf(ack, ":%-9s:ack%s", Message->FromCall, Message->Seq); + PutAPRSMessage(ack, n); + } + + if (ptr == NULL) + { + Messages = Message; + } + else + { + n++; + while(ptr->Next) + { + ptr = ptr->Next; + n++; + } + ptr->Next = Message; + } + + if (strcmp(MsgDest, APRSCall) == 0) // to me? + { + } +} + +*/ + +VOID APRSSecTimer() +{ + + // Check Message Retries + + struct APRSMESSAGE * ptr = SMEM->OutstandingMsgs; + int n = 0; + + if (SendWX) + SendWeatherBeacon(); + + + while (ptr) + { + if (ptr->Acked == FALSE) + { + if (ptr->Retries) + { + ptr->RetryTimer--; + + if (ptr->RetryTimer == 0) + { + ptr->Retries--; + + if (ptr->Retries) + { + // Send Again + + char Msg[255]; + APRSHEARDRECORD * STN; + + sprintf(Msg, ":%-9s:%s{%s", ptr->ToCall, ptr->Text, ptr->Seq); + + STN = FindStationInMH(ptr->ToCall); + + if (STN) + SendAPRSMessage(Msg, STN->rfPort); + else + { + if (memcmp(ptr->ToCall, "SERVER ", 9)) + SendAPRSMessage(Msg, -1); // All RF ports unless to SERVER + SendAPRSMessage(Msg, 0); // IS + } + ptr->RetryTimer = RetryTimer; + } + } + } + } + + ptr = ptr->Next; + n++; + } +} + +double radians(double Degrees) +{ + return M_PI * Degrees / 180; +} +double degrees(double Radians) +{ + return Radians * 180 / M_PI; +} + +double Distance(double laa, double loa, double lah, double loh, BOOL KM) +{ + +/* + +'Great Circle Calculations. + +'dif = longitute home - longitute away + + +' (this should be within -180 to +180 degrees) +' (Hint: This number should be non-zero, programs should check for +' this and make dif=0.0001 as a minimum) +'lah = latitude of home +'laa = latitude of away + +'dis = ArcCOS(Sin(lah) * Sin(laa) + Cos(lah) * Cos(laa) * Cos(dif)) +'distance = dis / 180 * pi * ERAD +'angle = ArcCOS((Sin(laa) - Sin(lah) * Cos(dis)) / (Cos(lah) * Sin(dis))) + +'p1 = 3.1415926535: P2 = p1 / 180: Rem -- PI, Deg =>= Radians +*/ + + loh = radians(loh); lah = radians(lah); + loa = radians(loa); laa = radians(laa); + + loh = 60*degrees(acos(sin(lah) * sin(laa) + cos(lah) * cos(laa) * cos(loa-loh))) * 1.15077945; + + if (KM) + loh *= 1.60934; + + return loh; +} + + +double myDistance(double laa, double loa, BOOL KM) +{ + double lah, loh; + + GetAPRSLatLon(&lah, &loh); + + return Distance(laa, loa, lah, loh, KM); +} + +/* + +'Great Circle Calculations. + +'dif = longitute home - longitute away + + +' (this should be within -180 to +180 degrees) +' (Hint: This number should be non-zero, programs should check for +' this and make dif=0.0001 as a minimum) +'lah = latitude of home +'laa = latitude of away + +'dis = ArcCOS(Sin(lah) * Sin(laa) + Cos(lah) * Cos(laa) * Cos(dif)) +'distance = dis / 180 * pi * ERAD +'angle = ArcCOS((Sin(laa) - Sin(lah) * Cos(dis)) / (Cos(lah) * Sin(dis))) + +'p1 = 3.1415926535: P2 = p1 / 180: Rem -- PI, Deg =>= Radians + + + loh = radians(loh); lah = radians(lah); + loa = radians(loa); laa = radians(laa); + + loh = 60*degrees(acos(sin(lah) * sin(laa) + cos(lah) * cos(laa) * cos(loa-loh))) * 1.15077945; + + if (KM) + loh *= 1.60934; + + return loh; +} +*/ + +double Bearing(double lat2, double lon2, double lat1, double lon1) +{ + double dlat, dlon, TC1; + + lat1 = radians(lat1); + lat2 = radians(lat2); + lon1 = radians(lon1); + lon2 = radians(lon2); + + dlat = lat2 - lat1; + dlon = lon2 - lon1; + + if (dlat == 0 || dlon == 0) return 0; + + TC1 = atan((sin(lon1 - lon2) * cos(lat2)) / (cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon1 - lon2))); + TC1 = degrees(TC1); + + if (fabs(TC1) > 89.5) if (dlon > 0) return 90; else return 270; + + if (dlat > 0) + { + if (dlon > 0) return -TC1; + if (dlon < 0) return 360 - TC1; + return 0; + } + + if (dlat < 0) + { + if (dlon > 0) return TC1 = 180 - TC1; + if (dlon < 0) return TC1 = 180 - TC1; // 'ok? + return 180; + } + + return 0; +} + + +double myBearing(double lat2, double lon2) +{ + double lat1, lon1; + + GetAPRSLatLon(&lat1, &lon1); + + return Bearing(lat2, lon2, lat1, lon1); +} +/* + + + + + lat1 = radians(lat1); + lat2 = radians(lat2); + lon1 = radians(lon1); + lon2 = radians(lon2); + + dlat = lat2 - lat1; + dlon = lon2 - lon1; + + if (dlat == 0 || dlon == 0) return 0; + + TC1 = atan((sin(lon1 - lon2) * cos(lat2)) / (cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon1 - lon2))); + TC1 = degrees(TC1); + + if (fabs(TC1) > 89.5) if (dlon > 0) return 90; else return 270; + + if (dlat > 0) + { + if (dlon > 0) return -TC1; + if (dlon < 0) return 360 - TC1; + return 0; + } + + if (dlat < 0) + { + if (dlon > 0) return TC1 = 180 - TC1; + if (dlon < 0) return TC1 = 180 - TC1; // 'ok? + return 180; + } + + return 0; +} +*/ + +// Weather Data + +static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +VOID SendWeatherBeacon() +{ + char Msg[256]; + char DD[3]=""; + char HH[3]=""; + char MM[3]=""; + char Lat[10], Lon[10]; + size_t Len; + int index; + char WXMessage[1024]; + char * WXptr; + char * WXend; + time_t WXTime; + time_t now = time(NULL); + FILE * hFile; + struct tm * TM; + struct stat STAT; + + WXCounter++; + + if (WXCounter < WXInterval * 60) + return; + + WXCounter = 0; + +// Debugprintf("BPQAPRS - Trying to open WX file %s", WXFileName); + + if (stat(WXFileName, &STAT)) + { + Debugprintf("APRS WX File %s stat() failed %d", WXFileName, GetLastError()); + return; + } + + WXTime = (now - STAT.st_mtime) /60; // Minutes + + if (WXTime > (3 * WXInterval)) + { + Debugprintf("APRS Send WX File %s too old - %d minutes", WXFileName, WXTime); + return; + } + + hFile = fopen(WXFileName, "rb"); + + if (hFile) + Len = fread(WXMessage, 1, 1024, hFile); + else + { + Debugprintf("APRS WX File %s open() failed %d", WXFileName, GetLastError()); + return; + } + + + if (Len < 30) + { + Debugprintf("BPQAPRS - WX file %s is too short - %d Chars", WXFileName, Len); + fclose(hFile); + return; + } + + WXMessage[Len] = 0; + + // see if wview format + +//04-09-13, 2245 +//TempIn 23 +//TempEx 18 +//WindHi 0 +//WindAv 0 +//WindDr 200 +//BarmPs 30167 +//HumdIn 56 +//HumdEx 100 +//RnFall 0.00 +//DailyRnFall 0.00 + + if (strstr(WXMessage, "TempIn")) + { + int Wind = 0; + int Gust = 0; + int Temp = 0; + int Winddir = 0; + int Humidity = 0; + int Raintoday = 0; + int Rain24hrs = 0; + int Pressure = 0; + + char * ptr; + + ptr = strstr(WXMessage, "TempEx"); + if (ptr) + Temp = (int)(atof(ptr + 7) * 1.8) + 32; + + ptr = strstr(WXMessage, "WindHi"); + if (ptr) + Gust = atoi(ptr + 7); + + ptr = strstr(WXMessage, "WindAv"); + if (ptr) + Wind = atoi(ptr + 7); + + ptr = strstr(WXMessage, "WindDr"); + if (ptr) + Winddir = atoi(ptr + 7); + + ptr = strstr(WXMessage, "BarmPs"); + if (ptr) + Pressure = (int)(atof(ptr + 7) * 0.338638866667); // Inches to 1/10 millbars + + ptr = strstr(WXMessage, "HumdEx"); + if (ptr) + Humidity = atoi(ptr + 7); + + ptr = strstr(WXMessage, "RnFall"); + if (ptr) + Rain24hrs = (int)(atof(ptr + 7) * 100.0); + + ptr = strstr(WXMessage, "DailyRnFall"); + if (ptr) + Raintoday = (int)(atof(ptr + 12) * 100.0); + + if (Humidity > 99) + Humidity = 99; + + sprintf(WXMessage, "%03d/%03dg%03dt%03dr%03dP%03dp%03dh%02db%05d", + Winddir, Wind, Gust, Temp, 0, Raintoday, Rain24hrs, Humidity, Pressure); + + } + + WXptr = strchr(WXMessage, 10); + + if (WXptr) + { + WXend = strchr(++WXptr, 13); + if (WXend == 0) + WXend = strchr(WXptr, 10); + if (WXend) + *WXend = 0; + } + else + WXptr = &WXMessage[0]; + + // Get DDHHMM from Filetime + + TM = gmtime(&STAT.st_mtime); + + sprintf(DD, "%02d", TM->tm_mday); + sprintf(HH, "%02d", TM->tm_hour); + sprintf(MM, "%02d", TM->tm_min); + + GetAPRSLatLonString(Lat, Lon); + + Len = sprintf(Msg, "@%s%s%sz%s/%s_%s%s", DD, HH, MM, Lat, Lon, WXptr, WXComment); + + Debugprintf(Msg); + + for (index = 0; index < MaxBPQPortNo; index++) + { + if (WXPort[index]) + SendAPRSMessageEx(Msg, index, WXCall, FALSE); + } + + fclose(hFile); +} + + +/* +Jan 22 2012 14:10 +123/005g011t031r000P000p000h00b10161 + +/MITWXN Mitchell IN weather Station N9LYA-3 {UIV32} +< previous + +@221452z3844.42N/08628.33W_203/006g007t032r000P000p000h00b10171 +Complete Weather Report Format — with Lat/Long position, no Timestamp +! or = Lat Sym Table ID Long Symbol Code _ Wind Directn/ Speed Weather Data APRS Software WX Unit uuuu + 1 8 1 9 1 7 n 1 2-4 +Examples +!4903.50N/07201.75W_220/004g005t077r000p000P000h50b09900wRSW +!4903.50N/07201.75W_220/004g005t077r000p000P000h50b.....wRSW + +*/ + +// Web Server Code + +// The actual HTTP socket code is in bpq32.dll. Any requests for APRS data are passed in +// using a Named Pipe. The request looks exactly like one from a local socket, and the respone is +// a fully pormatted HTTP packet + + +#define InputBufferLen 1000 + + +#define MaxSessions 100 + + +HANDLE PipeHandle; + +int HTTPPort = 80; +BOOL IPV6 = TRUE; + +#define MAX_PENDING_CONNECTS 5 + +BOOL OpenSockets6(); + +char HTDocs[MAX_PATH] = "HTML"; +char SpecialDocs[MAX_PATH] = "Special Pages"; + +char SymbolText[192][20] = { + +"Police Stn", "No Symbol", "Digi", "Phone", "DX Cluster", "HF Gateway", "Plane sm", "Mob Sat Stn", +"WheelChair", "Snowmobile", "Red Cross", "Boy Scout", "Home", "X", "Red Dot", "Circle (0)", +"Circle (1)", "Circle (2)", "Circle (3)", "Circle (4)", "Circle (5)", "Circle (6)", "Circle (7)", "Circle (8)", +"Circle (9)", "Fire", "Campground", "Motorcycle", "Rail Eng.", "Car", "File svr", "HC Future", + +"Aid Stn", "BBS", "Canoe", "No Symbol", "Eyeball", "Tractor", "Grid Squ.", "Hotel", +"Tcp/ip", "No Symbol", "School", "Usr Log-ON", "MacAPRS", "NTS Stn", "Balloon", "Police", +"TBD", "Rec Veh'le", "Shuttle", "SSTV", "Bus", "ATV", "WX Service", "Helo", +"Yacht", "WinAPRS", "Jogger", "Triangle", "PBBS", "Plane lrge", "WX Station", "Dish Ant.", + +"Ambulance", "Bike", "ICP", "Fire Station", "Horse", "Fire Truck", "Glider", "Hospital", +"IOTA", "Jeep", "Truck", "Laptop", "Mic-E Rptr", "Node", "EOC", "Rover", +"Grid squ.", "Antenna", "Power Boat", "Truck Stop", "Truck 18wh", "Van", "Water Stn", "XAPRS", +"Yagi", "Shelter", "No Symbol", "No Symbol", "No Symbol", "No Symbol", "", "", + +"Emergency", "No Symbol", "No. Digi", "Bank", "No Symbol", "No. Diam'd", "Crash site", "Cloudy", +"MEO", "Snow", "Church", "Girl Scout", "Home (HF)", "UnknownPos", "Destination", "No. Circle", +"No Symbol", "No Symbol", "No Symbol", "No Symbol", "No Symbol", "No Symbol", "No Symbol", "No Symbol", +"Petrol Stn", "Hail", "Park", "Gale Fl", "No Symbol", "No. Car", "Info Kiosk", "Hurricane", + +"No. Box", "Snow blwng", "Coast G'rd", "Drizzle", "Smoke", "Fr'ze Rain", "Snow Shwr", "Haze", +"Rain Shwr", "Lightning", "Kenwood", "Lighthouse", "No Symbol", "Nav Buoy", "Rocket", "Parking ", +"Quake", "Restaurant", "Sat/Pacsat", "T'storm", "Sunny", "VORTAC", "No. WXS", "Pharmacy", +"No Symbol", "No Symbol", "Wall Cloud", "No Symbol", "No Symbol", "No. Plane", "No. WX Stn", "Rain", + +"No. Diamond", "Dust blwng", "No. CivDef", "DX Spot", "Sleet", "Funnel Cld", "Gale", "HAM store", +"No. Blk Box", "WorkZone", "SUV", "Area Locns", "Milepost", "No. Triang", "Circle sm", "Part Cloud", +"No Symbol", "Restrooms", "No. Boat", "Tornado", "No. Truck", "No. Van", "Flooding", "No Symbol", +"Sky Warn", "No Symbol", "Fog", "No Symbol", "No Symbol", "No Symbol", "", ""}; + +// All Calls (8 per line) + +//EI7IG-1 +//G7TKK-1 +//GB7GL-B +//GM1TCN +//GM8BPQ +//GM8BPQ-14 +//LA2VPA-9 +//LA3FIA-10 +//LA6JF-2LD4STM0CHK-7M0OZH-7MB7UFO-1MB7UNMM0DXE-15PA2AYX-9 +//PA3AQW-5PD1CPD5LWD-2PI1ECO + + +char * DoSummaryLine(struct STATIONRECORD * ptr, int n, int Width) +{ + static char Line2[80]; + int x; + char XCall[256]; + char * ptr1 = ptr->Callsign; + char * ptr2 = XCall; + + // Object Names can contain spaces + + while(*ptr1) + { + if (*ptr1 == ' ') + { + memcpy(ptr2, "%20", 3); + ptr2 += 3; + } + else + *(ptr2++) = *ptr1; + + ptr1++; + } + + *ptr2 = 0; + + + // Object Names can contain spaces + + + sprintf(Line2, "%s", + XCall, ptr->Callsign); + + x = ++n/Width; + x = x * Width; + + if (x == n) + strcat(Line2, ""); + + return Line2; +} + +char * DoDetailLine(struct STATIONRECORD * ptr, BOOL LocalTime, BOOL KM) +{ + static char Line[512]; + double Lat = ptr->Lat; + double Lon = ptr->Lon; + char NS='N', EW='E'; + + char LatString[20], LongString[20], DistString[20], BearingString[20]; + int Degrees; + double Minutes; + char Time[80]; + struct tm * TM; + char XCall[256]; + + char * ptr1 = ptr->Callsign; + char * ptr2 = XCall; + + // Object Names can contain spaces + + while(*ptr1) + { + if (*ptr1 == ' ') + { + memcpy(ptr2, "%20", 3); + ptr2 += 3; + } + else + *(ptr2++) = *ptr1; + + ptr1++; + } + + *ptr2 = 0; + + +// if (ptr->ObjState == '_') // Killed Object +// return; + + if (LocalTime) + TM = localtime(&ptr->TimeLastUpdated); + else + TM = gmtime(&ptr->TimeLastUpdated); + + sprintf(Time, "%.2d:%.2d:%.2d", TM->tm_hour, TM->tm_min, TM->tm_sec); + + if (ptr->Lat < 0) + { + NS = 'S'; + Lat=-Lat; + } + if (Lon < 0) + { + EW = 'W'; + Lon=-Lon; + } + +#pragma warning(push) +#pragma warning(disable:4244) + + Degrees = Lat; + Minutes = Lat * 60.0 - (60 * Degrees); + + sprintf(LatString,"%2d°%05.2f'%c", Degrees, Minutes, NS); + + Degrees = Lon; + +#pragma warning(pop) + + Minutes = Lon * 60 - 60 * Degrees; + + sprintf(LongString, "%3d°%05.2f'%c",Degrees, Minutes, EW); + + sprintf(DistString, "%6.1f", myDistance(ptr->Lat, ptr->Lon, KM)); + sprintf(BearingString, "%3.0f", myBearing(ptr->Lat, ptr->Lon)); + + sprintf(Line, " %s%s%s%s %s%s%s%s\r\n", + XCall, ptr->Callsign, + (strchr(ptr->Path, '*'))? "*": "", &SymbolText[ptr->iconRow << 4 | ptr->iconCol][0], LatString, LongString, DistString, BearingString, Time); + + return Line; +} + + +int CompareFN(const void *a, const void *b) +{ + const struct STATIONRECORD * x = a; + const struct STATIONRECORD * y = b; + + x = x->Next; + y = y->Next; + + return strcmp(x->Callsign, y->Callsign); + + /* strcmp functions works exactly as expected from + comparison function */ +} + + + +char * CreateStationList(BOOL RFOnly, BOOL WX, BOOL Mobile, char Objects, int * Count, char * Param, BOOL KM) +{ + char * Line = malloc(100000); + struct STATIONRECORD * ptr = *StationRecords; + int n = 0, i; + struct STATIONRECORD * List[1000]; + int TableWidth = 8; + BOOL LocalTime = DefaultLocalTime; + + if (strstr(Param, "time=local")) + LocalTime = TRUE; + else if (strstr(Param, "time=utc")) + LocalTime = FALSE; + + Line[0] = 0; + + if (Param && Param[0]) + { + char * Key, *Context; + + Key = strtok_s(Param, "=", &Context); + + if (_stricmp(Key, "width") == 0) + TableWidth = atoi(Context); + + if (TableWidth == 0) + TableWidth = 8; + } + + // Build list of calls + + while (ptr) + { + if (ptr->ObjState == Objects && ptr->Lat != 0.0 && ptr->Lon != 0.0) + { + if ((WX && (ptr->LastWXPacket[0] == 0)) || (RFOnly && (ptr->LastPort == 0)) || + (Mobile && ((ptr->Speed < 0.1) || ptr->LastWXPacket[0] != 0))) + { + ptr = ptr->Next; + continue; + } + + List[n++] = ptr; + + if (n > 999) + break; + + } + ptr = ptr->Next; + } + + if (n > 1) + qsort(List, n, sizeof(void *), CompareFN); + + for (i = 0; i < n; i++) + { + if (RFOnly) + strcat(Line, DoDetailLine(List[i], LocalTime, KM)); + else + strcat(Line, DoSummaryLine(List[i], i, TableWidth)); + } + + *Count = n; + + return Line; + +} + +char * APRSLookupKey(struct APRSConnectionInfo * sockptr, char * Key, BOOL KM) +{ + struct STATIONRECORD * stn = sockptr->SelCall; + + if (strcmp(Key, "##MY_CALLSIGN##") == 0) + return _strdup(LoppedAPRSCall); + + if (strcmp(Key, "##CALLSIGN##") == 0) + return _strdup(sockptr->Callsign); + + if (strcmp(Key, "##CALLSIGN_NOSSID##") == 0) + { + char * Call = _strdup(sockptr->Callsign); + char * ptr = strchr(Call, '-'); + if (ptr) + *ptr = 0; + return Call; + } + + if (strcmp(Key, "##MY_WX_CALLSIGN##") == 0) + return _strdup(LoppedAPRSCall); + + if (strcmp(Key, "##MY_BEACON_COMMENT##") == 0) + return _strdup(StatusMsg); + + if (strcmp(Key, "##MY_WX_BEACON_COMMENT##") == 0) + return _strdup(WXComment); + + if (strcmp(Key, "##MILES_KM##") == 0) + if (KM) + return _strdup("KM"); + else + return _strdup("Miles"); + + if (strcmp(Key, "##EXPIRE_TIME##") == 0) + { + char val[80]; + sprintf(val, "%d", ExpireTime); + return _strdup(val); + } + + if (strcmp(Key, "##LOCATION##") == 0) + { + char val[80]; + double Lat = sockptr->SelCall->Lat; + double Lon = sockptr->SelCall->Lon; + char NS='N', EW='E'; + char LatString[20]; + int Degrees; + double Minutes; + + if (Lat < 0) + { + NS = 'S'; + Lat=-Lat; + } + if (Lon < 0) + { + EW = 'W'; + Lon=-Lon; + } + +#pragma warning(push) +#pragma warning(disable:4244) + + Degrees = Lat; + Minutes = Lat * 60.0 - (60 * Degrees); + + sprintf(LatString,"%2d°%05.2f'%c",Degrees, Minutes, NS); + + Degrees = Lon; + +#pragma warning(pop) + + Minutes = Lon * 60 - 60 * Degrees; + + sprintf(val,"%s %3d°%05.2f'%c", LatString, Degrees, Minutes, EW); + + return _strdup(val); + } + + if (strcmp(Key, "##LOCDDMMSS##") == 0) + { + char val[80]; + double Lat = sockptr->SelCall->Lat; + double Lon = sockptr->SelCall->Lon; + char NS='N', EW='E'; + char LatString[20]; + int Degrees; + double Minutes; + + // 48.45.18N, 002.18.37E + + if (Lat < 0) + { + NS = 'S'; + Lat=-Lat; + } + if (Lon < 0) + { + EW = 'W'; + Lon=-Lon; + } + +#pragma warning(push) +#pragma warning(disable:4244) + + Degrees = Lat; + Minutes = Lat * 60.0 - (60 * Degrees); +// IntMins = Minutes; +// Seconds = Minutes * 60.0 - (60 * IntMins); + + sprintf(LatString,"%2d.%05.2f%c",Degrees, Minutes, NS); + + Degrees = Lon; + Minutes = Lon * 60.0 - 60 * Degrees; +// IntMins = Minutes; +// Seconds = Minutes * 60.0 - (60 * IntMins); + +#pragma warning(pop) + + sprintf(val,"%s, %03d.%05.2f%c", LatString, Degrees, Minutes, EW); + + return _strdup(val); + } + + if (strcmp(Key, "##LATLON##") == 0) + { + char val[80]; + double Lat = sockptr->SelCall->Lat; + double Lon = sockptr->SelCall->Lon; + char NS='N', EW='E'; + + // 58.5, -6.2 + + sprintf(val,"%f, %f", Lat, Lon); + return _strdup(val); + } + + if (strcmp(Key, "##STATUS_TEXT##") == 0) + return _strdup(stn->Status); + + if (strcmp(Key, "##LASTPACKET##") == 0) + return _strdup(stn->LastPacket); + + + if (strcmp(Key, "##LAST_HEARD##") == 0) + { + char Time[80]; + struct tm * TM; + time_t Age = time(NULL) - stn->TimeLastUpdated; + + TM = gmtime(&Age); + + sprintf(Time, "%.2d:%.2d:%.2d", TM->tm_hour, TM->tm_min, TM->tm_sec); + + return _strdup(Time); + } + + if (strcmp(Key, "##FRAME_HEADER##") == 0) + return _strdup(stn->Path); + + if (strcmp(Key, "##FRAME_INFO##") == 0) + return _strdup(stn->LastWXPacket); + + if (strcmp(Key, "##BEARING##") == 0) + { + char val[80]; + + sprintf(val, "%03.0f", myBearing(sockptr->SelCall->Lat, sockptr->SelCall->Lon)); + return _strdup(val); + } + + if (strcmp(Key, "##COURSE##") == 0) + { + char val[80]; + + sprintf(val, "%03.0f", stn->Course); + return _strdup(val); + } + + if (strcmp(Key, "##SPEED_MPH##") == 0) + { + char val[80]; + + sprintf(val, "%5.1f", stn->Speed); + return _strdup(val); + } + + if (strcmp(Key, "##DISTANCE##") == 0) + { + char val[80]; + + sprintf(val, "%5.1f", myDistance(sockptr->SelCall->Lat, sockptr->SelCall->Lon, KM)); + return _strdup(val); + } + + + + if (strcmp(Key, "##WIND_DIRECTION##") == 0) + { + char val[80]; + + sprintf(val, "%03d", sockptr->WindDirn); + return _strdup(val); + } + + if (strcmp(Key, "##WIND_SPEED_MPH##") == 0) + { + char val[80]; + + sprintf(val, "%d", sockptr->WindSpeed); + return _strdup(val); + } + + if (strcmp(Key, "##WIND_GUST_MPH##") == 0) + { + char val[80]; + + sprintf(val, "%d", sockptr->WindGust); + return _strdup(val); + } + + if (strcmp(Key, "##TEMPERATURE_F##") == 0) + { + char val[80]; + + sprintf(val, "%d", sockptr->Temp); + return _strdup(val); + } + + if (strcmp(Key, "##HUMIDITY##") == 0) + { + char val[80]; + + sprintf(val, "%d", sockptr->Humidity); + return _strdup(val); + } + + if (strcmp(Key, "##PRESSURE_HPA##") == 0) + { + char val[80]; + + sprintf(val, "%05.1f", sockptr->Pressure /10.0); + return _strdup(val); + } + + if (strcmp(Key, "##RAIN_TODAY_IN##") == 0) + { + char val[80]; + + sprintf(val, "%5.2f", sockptr->RainToday /100.0); + return _strdup(val); + } + + + if (strcmp(Key, "##RAIN_24_IN##") == 0) + { + char val[80]; + + sprintf(val, "%5.2f", sockptr->RainLastDay /100.0); + return _strdup(val); + } + + + if (strcmp(Key, "##RAIN_HOUR_IN##") == 0) + { + char val[80]; + + sprintf(val, "%5.2f", sockptr->RainLastHour /100.0); + return _strdup(val); + } + + if (strcmp(Key, "##MAP_LAT_LON##") == 0) + { + char val[256]; + + sprintf(val, "%f,%f", stn->Lat, stn->Lon); + return _strdup(val); + } + + if (strcmp(Key, "##SYMBOL_DESCRIPTION##") == 0) + return _strdup(&SymbolText[stn->iconRow << 4 | stn->iconCol][0]); + + +/* +##WIND_SPEED_MS## - wind speed metres/sec +##WIND_SPEED_KMH## - wind speed km/hour +##WIND_GUST_MPH## - wind gust miles/hour +##WIND_GUST_MS## - wind gust metres/sec +##WIND_GUST_KMH## - wind gust km/hour +##WIND_CHILL_F## - wind chill F +##WIND_CHILL_C## - wind chill C +##TEMPERATURE_C## - temperature C +##DEWPOINT_F## - dew point temperature F +##DEWPOINT_C## - dew point temperature C +##PRESSURE_IN## - pressure inches of mercury +##PRESSURE_HPA## - pressure hPa (mb) +##RAIN_HOUR_MM## - rain in last hour mm +##RAIN_TODAY_MM## - rain today mm +##RAIN_24_MM## - rain in last 24 hours mm +##FRAME_HEADER## - frame header of the last posit heard from the station +##FRAME_INFO## - information field of the last posit heard from the station +##MAP_LARGE_SCALE##" - URL of a suitable large scale map on www.vicinity.com +##MEDIUM_LARGE_SCALE##" - URL of a suitable medium scale map on www.vicinity.com +##MAP_SMALL_SCALE##" - URL of a suitable small scale map on www.vicinity.com +##MY_LOCATION## - 'Latitude', 'Longitude' in 'Station Setup' +##MY_STATUS_TEXT## - status text configured in 'Status Text' +##MY_SYMBOL_DESCRIPTION## - 'Symbol' that would be shown for our station in 'Station List' +##HIT_COUNTER## - The number of times the page has been accessed +##DOCUMENT_LAST_CHANGED## - The date/time the page was last edited + +##FRAME_HEADER## - frame header of the last posit heard from the station +##FRAME_INFO## - information field of the last posit heard from the station + +*/ + return NULL; +} + +VOID APRSProcessSpecialPage(struct APRSConnectionInfo * sockptr, char * Buffer, int FileSize, char * StationTable, int Count, BOOL WX, BOOL KM) +{ + // replaces ##xxx### constructs with the requested data + + char * NewMessage = malloc(250000); + char * ptr1 = Buffer, * ptr2, * ptr3, * ptr4, * NewPtr = NewMessage; + size_t PrevLen; + size_t BytesLeft = FileSize; + size_t NewFileSize = FileSize; + char * StripPtr = ptr1; + int HeaderLen; + char Header[256]; + + if (WX && sockptr->SelCall && sockptr->SelCall->LastWXPacket) + { + DecodeWXReport(sockptr, sockptr->SelCall->LastWXPacket); + } + + // strip comments blocks + + while (ptr4 = strstr(ptr1, ""); + if (ptr2) + { + PrevLen = (ptr4 - ptr1); + memcpy(StripPtr, ptr1, PrevLen); + StripPtr += PrevLen; + ptr1 = ptr2 + 3; + BytesLeft = FileSize - (ptr1 - Buffer); + } + } + + + memcpy(StripPtr, ptr1, BytesLeft); + StripPtr += BytesLeft; + + BytesLeft = StripPtr - Buffer; + + FileSize = (int)BytesLeft; + NewFileSize = FileSize; + ptr1 = Buffer; + ptr1[FileSize] = 0; + +loop: + ptr2 = strstr(ptr1, "##"); + + if (ptr2) + { + PrevLen = (ptr2 - ptr1); // Bytes before special text + + ptr3 = strstr(ptr2+2, "##"); + + if (ptr3) + { + char Key[80] = ""; + size_t KeyLen; + char * NewText; + size_t NewTextLen; + + ptr3 += 2; + KeyLen = ptr3 - ptr2; + + if (KeyLen < 80) + memcpy(Key, ptr2, KeyLen); + + if (strcmp(Key, "##STATION_TABLE##") == 0) + { + NewText = _strdup(StationTable); + } + else + { + if (strcmp(Key, "##TABLE_COUNT##") == 0) + { + char val[80]; + sprintf(val, "%d", Count); + NewText = _strdup(val); + } + else + NewText = APRSLookupKey(sockptr, Key, KM); + } + + if (NewText) + { + NewTextLen = strlen(NewText); + NewFileSize = NewFileSize + NewTextLen - KeyLen; + // NewMessage = realloc(NewMessage, NewFileSize); + + memcpy(NewPtr, ptr1, PrevLen); + NewPtr += PrevLen; + memcpy(NewPtr, NewText, NewTextLen); + NewPtr += NewTextLen; + + free(NewText); + NewText = NULL; + } + else + { + // Key not found, so just leave + + memcpy(NewPtr, ptr1, PrevLen + KeyLen); + NewPtr += (PrevLen + KeyLen); + } + + ptr1 = ptr3; // Continue scan from here + BytesLeft = Buffer + FileSize - ptr3; + } + else // Unmatched ## + { + memcpy(NewPtr, ptr1, PrevLen + 2); + NewPtr += (PrevLen + 2); + ptr1 = ptr2 + 2; + } + goto loop; + } + + // Copy Rest + + memcpy(NewPtr, ptr1, BytesLeft); + + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", (int)NewFileSize); + send(sockptr->sock, Header, HeaderLen, 0); + send(sockptr->sock, NewMessage, (int)NewFileSize, 0); + + free (NewMessage); + free(StationTable); + + return; +} + +VOID APRSSendMessageFile(struct APRSConnectionInfo * sockptr, char * FN) +{ + int FileSize = 0; + char * MsgBytes = 0; + char * SaveMsgBytes = 0; + + char MsgFile[MAX_PATH]; + FILE * hFile; + BOOL Special = FALSE; + int HeaderLen; + char Header[256]; + char * Param = 0; + struct stat STAT; + int Sent; + char * ptr; + + if (strchr(FN, '?')) + strtok_s(FN, "?", &Param); + + UndoTransparency(FN); + + if (strstr(FN, "..")) + { + FN[0] = '/'; + FN[1] = 0; + } + + if (strcmp(FN, "/") == 0) + sprintf_s(MsgFile, sizeof(MsgFile), "%s/%s/%s/index.html", BPQDirectory, APRSDir, SpecialDocs); + else + sprintf_s(MsgFile, sizeof(MsgFile), "%s/%s/%s%s", BPQDirectory, APRSDir, SpecialDocs, &FN[5]); + + hFile = fopen(MsgFile, "rb"); + + if (hFile == NULL) + { + // Try normal pages + + + if (strcmp(FN, "/") == 0) + sprintf_s(MsgFile, sizeof(MsgFile), "%s/%s/%s/index.html", BPQDirectory, APRSDir, HTDocs); + else + sprintf_s(MsgFile, sizeof(MsgFile), "%s/%s/%s%s", BPQDirectory,APRSDir, HTDocs, &FN[5]); + + // My standard page set is now hard coded + + + + MsgBytes = SaveMsgBytes = GetStandardPage(&FN[6], &FileSize); + + if (MsgBytes) + { + if (FileSize == 0) + FileSize = strlen(MsgBytes); + } + else + { + hFile = fopen(MsgFile, "rb"); + + if (hFile == NULL) + { + HeaderLen = sprintf(Header, "HTTP/1.1 404 Not Found\r\nContent-Length: 16\r\n\r\nPage not found\r\n"); + send(sockptr->sock, Header, HeaderLen, 0); + return; + } + } + } + else + Special = TRUE; + + if (FileSize == 0) // Not from internal template + { + if (stat(MsgFile, &STAT) == 0) + FileSize = STAT.st_size; + + MsgBytes = SaveMsgBytes = malloc(FileSize+1); + + fread(MsgBytes, 1, FileSize, hFile); + + fclose(hFile); + } + + // if HTML file, look for ##...## substitutions + + if ((strstr(FN, "htm" ) || strstr(FN, "HTM")) && strstr(MsgBytes, "##" )) + { + // Build Station list, depending on URL + + int Count = 0; + BOOL RFOnly = !(strstr(_strlwr(FN), "rf") == NULL); // Leaves FN in lower case + BOOL WX =!(strstr(FN, "wx") == NULL); + BOOL Mobile = !(strstr(FN, "mobile") == NULL); + char Objects = (strstr(FN, "obj"))? '*' :0; + char * StationList; + BOOL KM = DefaultDistKM; + + if (Param == 0) + Param =""; + else + _strlwr(Param); + + if (strstr(Param, "dist=km")) + KM = TRUE; + else if (strstr(Param, "dist=miles")) + KM = FALSE; + + + StationList = CreateStationList(RFOnly, WX, Mobile, Objects, &Count, Param, KM); + + APRSProcessSpecialPage(sockptr, MsgBytes, FileSize, StationList, Count, WX, KM); + free (MsgBytes); + return; // ProcessSpecial has sent the reply + } + + ptr = FN; + + while (strchr(ptr, '.')) + { + ptr = strchr(ptr, '.'); + ++ptr; + } + + if (_stricmp(ptr, "jpg") == 0 || _stricmp(ptr, "jpeg") == 0 || _stricmp(ptr, "png") == 0 || _stricmp(ptr, "gif") == 0 || _stricmp(ptr, "ico") == 0) + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: image\r\n\r\n", FileSize); + else + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", FileSize); + + send(sockptr->sock, Header, HeaderLen, 0); + + Sent = send(sockptr->sock, MsgBytes, FileSize, 0); +// printf("Send %d %d\n", FileSize, Sent); + + while (Sent < FileSize) + { + FileSize -= Sent; + MsgBytes += Sent; + Sent = send(sockptr->sock, MsgBytes, FileSize, 0); +// printf("Send %d %d\n", FileSize, Sent); + if (Sent == -1) + { + Sleep(10); + Sent = 0; + } + } + + free (SaveMsgBytes); +} + +char WebHeader[] = "" + "" + "APRS Messaging" + "" + "" + "" + "" + "" + "" + "" + "" + "
APRS MapReceived MessagesSent MessagesSend MessageStation PagesReturn to Node Pages
" + "

%s's Messages

" + ""; + +char WebTXHeader[] = "" + "" + "APRS Messaging" + "" + "
FromToSeqTime Message
" + "" + "" + "" + "" + "" + "" + "
APRS MapReceived MessagesSent MessagesSend MessageStation PagesReturn to Node Pages
" + "

Message Sent by %s

" + ""; + +char WebLine[] = ""; + +char WebTXLine[] = "" + ""; + + +char WebTrailer[] = "
ToSeqTimeStatemessage
%s %s %s %s" + "Reply %s
%s %s %s %s %s
"; + +char SendMsgPage[] = "BPQ32 APRS Messaging" + "

APRS Message Input

" + "
" + "" + "" + "
To
Message
" + "

"; + +char APRSIndexPage[] = "BPQ32 Web Server APRS Pages" + "

" + "

BPQ32 APRS Server

" + "" + "" + "" + "" + "" + "" + "" + "
APRS MapReceived MessagesSent MessagesSend MessageStation PagesReturn to Node Pages
%s"; + +extern char Tail[]; + +VOID APRSProcessHTTPMessage(SOCKET sock, char * MsgPtr, BOOL LOCAL, BOOL COOKIE) +{ + int InputLen = 0; + int OutputLen = 0; + char * URL; + char * ptr; + struct APRSConnectionInfo CI; + struct APRSConnectionInfo * sockptr = &CI; + char Key[12] = ""; + char OutBuffer[100000]; + char Header[1024]; + int HeaderLen = 0; + + memset(&CI, 0, sizeof(CI)); + + sockptr->sock = sock; + + if (memcmp(MsgPtr, "POST" , 3) == 0) + { + char * To; + char * Msg = ""; + + URL = &MsgPtr[5]; + + ptr = strstr(URL, "\r\n\r\n"); + + if (ptr) + { + char * param, * context; + + UndoTransparency(ptr); + + param = strtok_s(ptr + 4, "&", &context); + + while (param) + { + char * val = strlop(param, '='); + + if (val) + { + if (_stricmp(param, "call") == 0) + To = _strupr(val); + else if (_stricmp(param, "message") == 0) + Msg = val; + else if (_stricmp(param, "Cancel") == 0) + { + + // Return APRS Index Page + + OutputLen = sprintf(OutBuffer, APRSIndexPage, "



Message Cancelled

"); + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); + send(sockptr->sock, Header, HeaderLen, 0); + send(sockptr->sock, OutBuffer, OutputLen, 0); + + return; + } + } + + param = strtok_s(NULL,"&", &context); + } + + strlop(To, ' '); + + if (strlen(To) < 2) + { + OutputLen = sprintf(OutBuffer, SendMsgPage, To); + OutputLen += sprintf(&OutBuffer[OutputLen], "

Invalid Callsign

"); + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); + send(sockptr->sock, Header, HeaderLen, 0); + send(sockptr->sock, OutBuffer, OutputLen, 0); + + return; + } + + if (Msg[0] == 0) + { + OutputLen = sprintf(OutBuffer, SendMsgPage, To); + OutputLen += sprintf(&OutBuffer[OutputLen], "

No Message

"); + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); + send(sockptr->sock, Header, HeaderLen, 0); + send(sockptr->sock, OutBuffer, OutputLen, 0); + + return; + } + + // Send APRS Messsage + + if (strlen(Msg) > 100) + Msg[100] = 0; + + InternalSendAPRSMessage(Msg, To); + + OutputLen = sprintf(OutBuffer, APRSIndexPage, "



Message Sent

"); + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); + send(sockptr->sock, Header, HeaderLen, 0); + send(sockptr->sock, OutBuffer, OutputLen, 0); + + return; + } + } + + URL = &MsgPtr[4]; + + ptr = strstr(URL, " HTTP"); + + if (ptr) + *ptr = 0; + + if (_stricmp(URL, "/APRS") == 0) + { + // Return APRS Index Page + + OutputLen = sprintf(OutBuffer, APRSIndexPage, ""); + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); + send(sockptr->sock, Header, HeaderLen, 0); + send(sockptr->sock, OutBuffer, OutputLen, 0); + + return; + } + + + if (_memicmp(URL, "/aprs/msgs/entermsg", 19) == 0 || _memicmp(URL, "/aprs/entermsg", 14) == 0) + { + char * To = strchr(URL, '='); + + if (LOCAL == FALSE && COOKIE == FALSE) + { + // Send Not Authorized + + OutputLen = sprintf(OutBuffer, APRSIndexPage, "
Not authorized - please return to Node Menu and sign in"); + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", (int)(OutputLen + strlen(Tail))); + send(sock, Header, HeaderLen, 0); + send(sock, OutBuffer, OutputLen, 0); + send(sock, Tail, (int)strlen(Tail), 0); + return; + } + + + if (To) + { + To++; + UndoTransparency(To); + strlop(To, '&'); + } + else + To = ""; + + OutputLen = sprintf(OutBuffer, SendMsgPage, To); + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); + send(sockptr->sock, Header, HeaderLen, 0); + send(sockptr->sock, OutBuffer, OutputLen, 0); + + return; + + } + + else if (_memicmp(URL, "/aprs/msgs", 10) == 0) + { + // Return Messages Received Page + + struct APRSMESSAGE * ptr = SMEM->Messages; + int n = 0; + char BaseCall[10]; + char BaseFrom[10]; + char * MsgCall = LoppedAPRSCall; + BOOL OnlyMine = TRUE; + BOOL AllSSID = TRUE; + BOOL OnlySeq = FALSE; + BOOL ShowBulls = TRUE; + + // Parse parameters + + // ?call=g8bpq&bulls=true&seqonly=true&onlymine=true + + char * params = strchr(URL, '?'); + + if (params) + { + char * param, * context; + + param = strtok_s(++params, "&", &context); + + while (param) + { + char * val = strlop(param, '='); + + if (val) + { + strlop(val, ' '); + if (_stricmp(param, "call") == 0) + MsgCall = _strupr(val); + else if (_stricmp(param, "bulls") == 0) + ShowBulls = !_stricmp(val, "true"); + else if (_stricmp(param, "onlyseq") == 0) + OnlySeq = !_stricmp(val, "true"); + else if (_stricmp(param, "onlymine") == 0) + OnlyMine = !_stricmp(val, "true"); + else if (_stricmp(param, "AllSSID") == 0) + AllSSID = !_stricmp(val, "true"); + } + param = strtok_s(NULL,"&", &context); + } + } + if (AllSSID) + { + memcpy(BaseCall, MsgCall, 10); + strlop(BaseCall, '-'); + } + + OutputLen = sprintf(OutBuffer, WebHeader, MsgCall, MsgCall); + + while (ptr) + { + char ToLopped[11] = ""; + memcpy(ToLopped, ptr->ToCall, 10); + strlop(ToLopped, ' '); + + if (memcmp(ToLopped, "BLN", 3) == 0) + if (ShowBulls == TRUE) + goto wantit; + + if (strcmp(ToLopped, MsgCall) == 0) // to me? + goto wantit; + + if (strcmp(ptr->FromCall, MsgCall) == 0) // to me? + goto wantit; + + if (AllSSID) + { + memcpy(BaseFrom, ToLopped, 10); + strlop(BaseFrom, '-'); + + if (strcmp(BaseFrom, BaseCall) == 0) + goto wantit; + + memcpy(BaseFrom, ptr->FromCall, 10); + strlop(BaseFrom, '-'); + + if (strcmp(BaseFrom, BaseCall) == 0) + goto wantit; + + } + + if (OnlyMine == FALSE) // Want All + if (OnlySeq == FALSE || ptr->Seq[0] != 0) + goto wantit; + + // ignore + + ptr = ptr->Next; + continue; + wantit: + OutputLen += sprintf(&OutBuffer[OutputLen], WebLine, + ptr->FromCall, ptr->ToCall, ptr->Seq, ptr->Time, + ptr->FromCall, ptr->ToCall, ptr->Text); + + ptr = ptr->Next; + + if (OutputLen > 99000) + break; + + } + + OutputLen += sprintf(&OutBuffer[OutputLen], WebTrailer); + + HeaderLen = sprintf(Header, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); + sendandcheck(sock, Header, HeaderLen); + sendandcheck(sock, OutBuffer, OutputLen); + + return; + + } + + else if (_memicmp(URL, "/aprs/txmsgs", 12) == 0) + { + // Return Messages Received Page + + struct APRSMESSAGE * ptr = SMEM->OutstandingMsgs; + char * MsgCall = LoppedAPRSCall; + + char Retries[10]; + + + OutputLen = sprintf(OutBuffer, WebTXHeader, MsgCall, MsgCall); + + while (ptr) + { + char ToLopped[11] = ""; + + if (ptr->Acked) + strcpy(Retries, "A"); + else if (ptr->Retries == 0) + strcpy(Retries, "F"); + else + sprintf(Retries, "%d", ptr->Retries); + + memcpy(ToLopped, ptr->ToCall, 10); + strlop(ToLopped, ' '); + + OutputLen += sprintf(&OutBuffer[OutputLen], WebTXLine, + ptr->ToCall, ptr->Seq, ptr->Time, Retries, ptr->Text); + ptr = ptr->Next; + + if (OutputLen > 99000) + break; + + } + + OutputLen += sprintf(&OutBuffer[OutputLen], WebTrailer); + + HeaderLen = sprintf(Header, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); + sendandcheck(sock, Header, HeaderLen); + sendandcheck(sock, OutBuffer, OutputLen); + + return; + + } + + + if (_memicmp(URL, "/aprs/find.cgi?call=", 20) == 0) + { + // return Station details + + char * Call = &URL[20]; + BOOL RFOnly, WX, Mobile, Object = FALSE; + struct STATIONRECORD * stn; + char * Referrer = strstr(ptr + 1, "Referer:"); + + // Undo any % transparency in call + + char * ptr1 = Call; + char * ptr2 = Key; + char c; + + c = *(ptr1++); + + while (c) + { + if (c == '%') + { + int n; + int m = *(ptr1++) - '0'; + if (m > 9) m = m - 7; + n = *(ptr1++) - '0'; + if (n > 9) n = n - 7; + + *(ptr2++) = m * 16 + n; + } + else if (c == '+') + *(ptr2++) = ' '; + else + *(ptr2++) = c; + + c = *(ptr1++); + } + + *(ptr2++) = 0; + + if (Referrer) + { + ptr = strchr(Referrer, 13); + if (ptr) + { + *ptr = 0; + RFOnly = !(strstr(Referrer, "rf") == NULL); + WX = !(strstr(Referrer, "wx") == NULL); + Mobile = !(strstr(Referrer, "mobile") == NULL); + Object = !(strstr(Referrer, "obj") == NULL); + + if (WX) + strcpy(URL, "/aprs/infowx_call.html"); + else if (Mobile) + strcpy(URL, "/aprs/infomobile_call.html"); + else if (Object) + strcpy(URL, "/aprs/infoobj_call.html"); + else + strcpy(URL, "/aprs/info_call.html"); + } + } + + if (Object) + { + // Name is space padded, and could have embedded spaces + + int Keylen = (int)strlen(Key); + + if (Keylen < 9) + memset(&Key[Keylen], 32, 9 - Keylen); + } + + stn = FindStation(Key, FALSE); + + if (stn == NULL) + strcpy(URL, "/aprs/noinfo.html"); + else + sockptr->SelCall = stn; + } + + + strcpy(sockptr->Callsign, Key); + + APRSSendMessageFile(sockptr, URL); + + return; +} + +// Code for handling APRS messages within BPQ32/LinBPQ instead of GUI + + +int ProcessMessage(char * Payload, struct STATIONRECORD * Station) +{ + char MsgDest[10]; + struct APRSMESSAGE * Message; + struct APRSMESSAGE * ptr = SMEM->Messages; + char * TextPtr = &Payload[11]; + char * SeqPtr; + int n = 0; + char FromCall[10] = " "; + struct tm * TM; + time_t NOW; + char noSeq[] = ""; + int ourMessage = 0; + + memcpy(FromCall, Station->Callsign, strlen(Station->Callsign)); + memcpy(MsgDest, &Payload[1], 9); + MsgDest[9] = 0; + + if (strcmp(MsgDest, CallPadded) == 0) // to me? + { + SMEM->NeedRefresh = 255; // Flag to control Msg popup + ourMessage = 1; + } + else + SMEM->NeedRefresh = 1; + + SeqPtr = strchr(TextPtr, '{'); + + if (SeqPtr) + { + *(SeqPtr++) = 0; + if(strlen(SeqPtr) > 6) + SeqPtr[7] = 0; + } + else + SeqPtr = noSeq; + + if (_memicmp(TextPtr, "ack", 3) == 0) + { + // Message Ack. See if for one of our messages + + ptr = SMEM->OutstandingMsgs; + + if (ptr == 0) + return ourMessage; + + do + { + if (strcmp(ptr->FromCall, MsgDest) == 0 + && strcmp(ptr->ToCall, FromCall) == 0 + && strcmp(ptr->Seq, &TextPtr[3]) == 0) + { + // Message is acked + + ptr->Retries = 0; + ptr->Acked = TRUE; + + return ourMessage; + } + ptr = ptr->Next; + n++; + + } while (ptr); + + return ourMessage; + } + + // See if we already have this message + + ptr = SMEM->Messages; + + while(ptr) + { + if (strcmp(ptr->ToCall, MsgDest) == 0 + && strcmp(ptr->FromCall, FromCall) == 0 + && strcmp(ptr->Seq, SeqPtr) == 0 + && strcmp(ptr->Text, TextPtr) == 0) + + // Duplicate + + return ourMessage; + + ptr = ptr->Next; + } + + Message = APRSGetMessageBuffer(); + + if (Message == NULL) + return ourMessage; + + memset(Message, 0, sizeof(struct APRSMESSAGE)); + memset(Message->FromCall, ' ', 9); + memcpy(Message->FromCall, Station->Callsign, strlen(Station->Callsign)); + strcpy(Message->ToCall, MsgDest); + + if (SeqPtr) + { + strcpy(Message->Seq, SeqPtr); + + // If a REPLY-ACK Seg, copy to LastRXSeq, and see if it acks a message + + if (SeqPtr[2] == '}') + { + struct APRSMESSAGE * ptr1; + int nn = 0; + + strcpy(Station->LastRXSeq, SeqPtr); + + ptr1 = SMEM->OutstandingMsgs; + + while (ptr1) + { + if (strcmp(ptr1->FromCall, MsgDest) == 0 + && strcmp(ptr1->ToCall, FromCall) == 0 + && memcmp(&ptr1->Seq, &SeqPtr[3], 2) == 0) + { + // Message is acked + + ptr1->Acked = TRUE; + ptr1->Retries = 0; + + break; + } + ptr1 = ptr1->Next; + nn++; + } + } + else + { + // Station is not using reply-ack - set to send simple numeric sequence (workround for bug in APRS Messanges + + Station->SimpleNumericSeq = TRUE; + } + } + + if (strlen(TextPtr) > 100) + TextPtr[100] = 0; + + strcpy(Message->Text, TextPtr); + + NOW = time(NULL); + + if (DefaultLocalTime) + TM = localtime(&NOW); + else + TM = gmtime(&NOW); + + sprintf(Message->Time, "%.2d:%.2d", TM->tm_hour, TM->tm_min); + + if (_stricmp(MsgDest, CallPadded) == 0 && SeqPtr) // ack it if it has a sequence + { + // For us - send an Ack + + char ack[30]; + APRSHEARDRECORD * STN; + + sprintf(ack, ":%-9s:ack%s", Message->FromCall, Message->Seq); + + if (memcmp(Message->FromCall, "SERVER ", 9) == 0) + { + SendAPRSMessage(ack, 0); // IS + } + else + { + STN = FindStationInMH(Message->ToCall); + + if (STN) + SendAPRSMessage(ack, STN->rfPort); + else + { + SendAPRSMessage(ack, -1); // All RF ports + SendAPRSMessage(ack, 0); // IS + } + } + } + + if (SaveAPRSMsgs) + SaveAPRSMessage(Message); + + ptr = SMEM->Messages; + + if (ptr == NULL) + { + SMEM->Messages = Message; + } + else + { + n++; + while(ptr->Next) + { + ptr = ptr->Next; + n++; + } + ptr->Next = Message; + } + + return ourMessage; +} + +BOOL InternalSendAPRSMessage(char * Text, char * Call) +{ + char Msg[255]; + size_t len = strlen(Call); + APRSHEARDRECORD * STN; + struct tm * TM; + time_t NOW; + + struct APRSMESSAGE * Message; + struct APRSMESSAGE * ptr = SMEM->OutstandingMsgs; + + Message = APRSGetMessageBuffer(); + + if (Message == NULL) + return FALSE; + + memset(Message, 0, sizeof(struct APRSMESSAGE)); + strcpy(Message->FromCall, CallPadded); + + memset(Message->ToCall, ' ', 9); + memcpy(Message->ToCall, Call, len); + + Message->ToStation = FindStation(Call, TRUE); + + if (Message->ToStation == NULL) + return FALSE; + + SMEM->NeedRefresh = TRUE; + + if (Message->ToStation->LastRXSeq[0]) // Have we received a Reply-Ack message from him? + sprintf(Message->Seq, "%02X}%c%c", ++Message->ToStation->NextSeq, Message->ToStation->LastRXSeq[0], Message->ToStation->LastRXSeq[1]); + else + { + if (Message->ToStation->SimpleNumericSeq) + sprintf(Message->Seq, "%d", ++Message->ToStation->NextSeq); + else + sprintf(Message->Seq, "%02X}", ++Message->ToStation->NextSeq); // Don't know, so assume message-ack capable + } + + if (strlen(Text) > 100) + Text[100] = 0; + + strcpy(Message->Text, Text); + Message->Retries = RetryCount; + Message->RetryTimer = RetryTimer; + + NOW = time(NULL); + + if (DefaultLocalTime) + TM = localtime(&NOW); + else + TM = gmtime(&NOW); + + sprintf(Message->Time, "%.2d:%.2d", TM->tm_hour, TM->tm_min); + + + // Chain to Outstanding Queue + + if (ptr == NULL) + { + SMEM->OutstandingMsgs = Message; + } + else + { + while(ptr->Next) + { + ptr = ptr->Next; + } + ptr->Next = Message; + } + + sprintf(Msg, ":%-9s:%s{%s", Call, Text, Message->Seq); + + if (strcmp(Call, "SERVER") == 0) + { + SendAPRSMessage(Msg, 0); // IS + return TRUE; + } + + STN = FindStationInMH(Message->ToCall); + + if (STN && STN->MHTIME > (time(NULL) - 900)) // Heard in last 15 mins + SendAPRSMessage(Msg, STN->rfPort); + else + { + SendAPRSMessage(Msg, -1); // All RF ports + SendAPRSMessage(Msg, 0); // IS + } + return TRUE; +} + + + + + +extern BOOL APRSReconfigFlag; +extern struct DATAMESSAGE * REPLYBUFFER; +extern char COMMANDBUFFER[81]; +extern char OrigCmdBuffer[81]; + +BOOL isSYSOP(TRANSPORTENTRY * Session, char * Bufferptr); + +VOID APRSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +{ + // APRS Subcommands. Default for compatibility is APRSMH + + // Others are STATUS ENABLEIGATE DISABLEIGATE RECONFIG + + APRSHEARDRECORD * MH = MHDATA; + int n = MAXHEARDENTRIES; + char * ptr; + char * Pattern, * context; + int Port = -1; + char dummypattern[] =""; + + if (memcmp(CmdTail, "? ", 2) == 0) + { + Bufferptr = Cmdprintf(Session, Bufferptr, "APRS Subcommmands:\r"); + Bufferptr = Cmdprintf(Session, Bufferptr, "STATUS SEND MSGS SENT ENABLEIGATE DISABLEIGATE BEACON RECONFIG\r"); + Bufferptr = Cmdprintf(Session, Bufferptr, "Default is Station list - Params [Port] [Pattern]\r"); + + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + + if (memcmp(CmdTail, "RECONFIG ", 5) == 0) + { + if (isSYSOP(Session, Bufferptr) == FALSE) + return; + + if (!ProcessConfig()) + { + Bufferptr = Cmdprintf(Session, Bufferptr, "Configuration File check failed - will continue with old config"); + } + else + { + APRSReconfigFlag=TRUE; + Bufferptr = Cmdprintf(Session, Bufferptr, "Reconfiguration requested\r"); + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + } + + if (memcmp(CmdTail, "ENABLEIGATE ", 6) == 0) + { + if (isSYSOP(Session, Bufferptr) == FALSE) + return; + + IGateEnabled = TRUE; + Bufferptr = Cmdprintf(Session, Bufferptr, "IGate Enabled\r"); + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + + if (memcmp(CmdTail, "DISABLEIGATE ", 6) == 0) + { + if (isSYSOP(Session, Bufferptr) == FALSE) + return; + + IGateEnabled = FALSE; + Bufferptr = Cmdprintf(Session, Bufferptr, "IGate Disabled\r"); + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + + if (memcmp(CmdTail, "STATUS ", 7) == 0) + { + if (IGateEnabled == FALSE) + Bufferptr = Cmdprintf(Session, Bufferptr, "IGate Disabled\r"); + else + { + Bufferptr = Cmdprintf(Session, Bufferptr, "IGate Enabled "); + if (APRSISOpen) + Bufferptr = Cmdprintf(Session, Bufferptr, "and connected to %s\r", RealISHost); + else + Bufferptr = Cmdprintf(Session, Bufferptr, "but not connected\r"); + } + + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + + if (memcmp(CmdTail, "BEACON ", 7) == 0) + { + if (isSYSOP(Session, Bufferptr) == FALSE) + return; + + BeaconCounter = 2; + Bufferptr = Cmdprintf(Session, Bufferptr, "Beacons requested\r"); + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + + if (memcmp(CmdTail, "MSGS ", 5) == 0) + { + struct APRSMESSAGE * ptr = SMEM->Messages; + char Addrs[32]; + + Bufferptr = Cmdprintf(Session, Bufferptr, + "\rTime Calls Seq Text\r"); + + while (ptr) + { + char ToLopped[11] = ""; + + memcpy(ToLopped, ptr->ToCall, 10); + strlop(ToLopped, ' '); + + sprintf(Addrs, "%s>%s", ptr->FromCall, ToLopped); + + Bufferptr = Cmdprintf(Session, Bufferptr, "%s %-20s%-5s %s\r", + ptr->Time, Addrs, ptr->Seq, ptr->Text); + + ptr = ptr->Next; + } + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + + if (memcmp(CmdTail, "SENT ", 5) == 0) + { + struct APRSMESSAGE * ptr = SMEM->OutstandingMsgs; + char Addrs[32]; + + Bufferptr = Cmdprintf(Session, Bufferptr, + "\rTime Calls Seq State Text\r"); + + while (ptr) + { + char ToLopped[11] = ""; + char Retries[10]; + + if (ptr->Acked) + strcpy(Retries, "A"); + else if (ptr->Retries == 0) + strcpy(Retries, "F"); + else + sprintf(Retries, "%d", ptr->Retries); + + + memcpy(ToLopped, ptr->ToCall, 10); + strlop(ToLopped, ' '); + + sprintf(Addrs, "%s>%s", ptr->FromCall, ToLopped); + + Bufferptr = Cmdprintf(Session, Bufferptr, "%s %-20s%-5s %-2s %s\r", + ptr->Time, Addrs, ptr->Seq, Retries, ptr->Text); + + ptr = ptr->Next; + } + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + + if (memcmp(CmdTail, "SEND ", 5) == 0) + { + // Send Message. Params are Call and Message + + char * Call = strtok_s(&CmdTail[5], " \r", &context); + char * Text = strtok_s(NULL, " \r", &context); + int len = 0; + + if (isSYSOP(Session, Bufferptr) == FALSE) + return; + + if (Call) + len = (int)strlen(Call); + + if (len < 3 || len > 9) + { + Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Callsign\r"); + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + + if (Text == NULL) + { + Bufferptr = Cmdprintf(Session, Bufferptr, "No Message Text\r"); + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + // Replace command tail with original (before conversion to upper case + + Text = Text + (OrigCmdBuffer - COMMANDBUFFER); + + InternalSendAPRSMessage(Text, Call); + + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + + // DISPLAY APRS HEARD LIST + + // APRS [Port] [Pattern] + + Pattern = strtok_s(CmdTail, " \r", &context); + + if (Pattern && (int)strlen(Pattern) < 3) + { + // could be port number + + if (isdigit(Pattern[0]) && (Pattern[1] == 0 || isdigit(Pattern[1]))) + { + Port = atoi(Pattern); + Pattern = strtok_s(NULL, " \r", &context); + } + } + + // Param is a pattern to match + + if (Pattern == NULL) + Pattern = dummypattern; + + if (Pattern[0] == ' ') + { + // Prepare Pattern + + char * ptr1 = Pattern + 1; + char * ptr2 = Pattern; + char c; + + do + { + c = *ptr1++; + *(ptr2++) = c; + } + while (c != ' '); + + *(--ptr2) = 0; + } + + strlop(Pattern, ' '); + _strupr(Pattern); + + *(Bufferptr++) = 13; + + while (n--) + { + if (MH->MHCALL[0] == 0) + break; + + if ((Port > -1) && Port != MH->rfPort) + { + MH++; + continue; + } + + ptr = FormatAPRSMH(MH); + + MH++; + + if (ptr) + { + if (Pattern[0] && strstr(ptr, Pattern) == 0) + continue; + + Bufferptr = Cmdprintf(Session, Bufferptr, "%s", ptr); + } + } + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); +} + +int GetPosnFromAPRS(char * Call, double * Lat, double * Lon) +{ + struct STATIONRECORD * Station; + + Station = FindStation(Call, FALSE); + + if (Station) + { + *Lat = Station->Lat; + *Lon = Station->Lon; + + return 1; + } + + return 0; +} + +// Station Name Font + +const unsigned char ASCII[][5] = { +//const u08 ASCII[][5] = { + {0x00, 0x00, 0x00, 0x00, 0x00} // 20 + ,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 ! + ,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 " + ,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 # + ,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $ + ,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 % + ,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 & + ,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 ' + ,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 ( + ,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 ) + ,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a * + ,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b + + ,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c , + ,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d - + ,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e . + ,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f / + ,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0 + ,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1 + ,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2 + ,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3 + ,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4 + ,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5 + ,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6 + ,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7 + ,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8 + ,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9 + ,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a : + ,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ; + ,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c < + ,{0x14, 0x14, 0x14, 0x14, 0x14} // 3d = + ,{0x00, 0x41, 0x22, 0x14, 0x08} // 3e > + ,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ? + ,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @ + ,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A + ,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B + ,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C + ,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D + ,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E + ,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F + ,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G + ,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H + ,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I + ,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J + ,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K + ,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L + ,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M + ,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N + ,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O + ,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P + ,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q + ,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R + ,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S + ,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T + ,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U + ,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V + ,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W + ,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X + ,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y + ,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z + ,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [ + ,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c + ,{0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ] + ,{0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^ + ,{0x40, 0x40, 0x40, 0x40, 0x40} // 5f _ + ,{0x00, 0x01, 0x02, 0x04, 0x00} // 60 ` + ,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a + ,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b + ,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c + ,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d + ,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e + ,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f + ,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g + ,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h + ,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i + ,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j + ,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k + ,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l + ,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m + ,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n + ,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o + ,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p + ,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q + ,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r + ,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s + ,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t + ,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u + ,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v + ,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w + ,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x + ,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y + ,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z + ,{0x00, 0x08, 0x36, 0x41, 0x00} // 7b { + ,{0x00, 0x00, 0x7f, 0x00, 0x00} // 7c | + ,{0x00, 0x41, 0x36, 0x08, 0x00} // 7d } + ,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ~ + ,{0x78, 0x46, 0x41, 0x46, 0x78} // 7f DEL +}; + + +// APRS Web Map Code + +// Not sure yet what is best way to do station icons but for now build and cache any needed icons + +extern int IconDataLen; +extern unsigned long long IconData[]; // Symbols as a png image.& + +// IconData is a png image, so needs to be uncompressed to an RGB array + + +// Will key cached icons by IconRow, IconCol, Overlay Char - xxxxA + +int cachedIconCount = 0; + +// We need key, icon data, icon len for each. Maybe a simple linked list - we never remove any + +struct iconCacheEntry +{ + struct iconCacheEntry * Next; + char key[8]; + int pngimagelen; + int pngmalloclen; + unsigned char * pngimage; +}; + +struct iconCacheEntry * iconCache = NULL; + + +// Each icon has to be created as an RGB array, then converted to a png image, as +// Leaflet icons need a png file + +#include "mypng.h" + + +struct png_info_struct * info_ptr = NULL; + +unsigned char * PngEncode (png_byte *pDiData, int iWidth, int iHeight, struct iconCacheEntry * Icon); + +void createIcon(char * Key, int iconRow, int iconCol, char Overlay) +{ + int i, j, index, mask; + int row; + int col; // First row + unsigned char * rgbData = malloc(68 * 22); // 1323 + unsigned char * ptr = rgbData; + png_color colour = {0, 0, 0}; + int Pointer; + char c; + int bit; + struct iconCacheEntry * Icon = zalloc(sizeof(struct iconCacheEntry)); + + strcpy(Icon->key, Key); + + // icon data is in info_ptr->row_pointers (we have 255 of them) + + row = iconRow * 21; + col = iconCol * 21 * 3; + + for (j = 0; j < 22; j++) + { + memcpy(ptr, info_ptr->row_pointers[row + j] + col, 22 * 3); // One scan line + ptr += 68; // Rounded up to mod 4 + } + + + // This code seems to assume an icon is 16 pixels, but image is 22 x 22 ??? + +// j = ptr->iconRow * 21 * 337 * 3 + ptr->iconCol * 21 * 3 + 9 + 337 * 9; +// for (i = 0; i < 16; i++) +// { +// memcpy(nptr, &iconImage[j], 16 * 3); +// nptr += 6144; +// j += 337 * 3; +// } + + + // If an overlay is specified, add it + + if (Overlay) + { + Pointer = 68 * 7 + 7 * 3; // 7th row, 7th col + mask = 1; + + for (index = 0 ; index < 7 ; index++) + { + rgbData[Pointer++] = 255; // Blank line above chars + rgbData[Pointer++] = 255; + rgbData[Pointer++] = 255; + } + + Pointer = 68 * 8 + 7 * 3; // 8th row, 7th col + + for (i = 0; i < 7; i++) + { + rgbData[Pointer++] = 255; // Blank col + rgbData[Pointer++] = 255; + rgbData[Pointer++] = 255; + + for (index = 0 ; index < 5 ; index++) + { + c = ASCII[Overlay - 0x20][index]; // Font data + bit = c & mask; + + if (bit) + { + rgbData[Pointer++] = 0; + rgbData[Pointer++] = 0; + rgbData[Pointer++] = 0; + } + else + { + rgbData[Pointer++] = 255; + rgbData[Pointer++] = 255; + rgbData[Pointer++] = 255; + } + } + + rgbData[Pointer++] = 255; // Blank col + rgbData[Pointer++] = 255; + rgbData[Pointer++] = 255; + + mask <<= 1; + Pointer += 47; + } + for (index = 0 ; index < 7 ; index++) + { + rgbData[Pointer++] = 255; // Blank line above chars + rgbData[Pointer++] = 255; + rgbData[Pointer++] = 255; + } + } + + // Encode + + PngEncode(rgbData, 22, 22, Icon); + + if (iconCache) + Icon->Next = iconCache; + + iconCache = Icon; + +} + +int GetAPRSIcon(unsigned char * _REPLYBUFFER, char * NodeURL) +{ + char Key[8] = ""; + struct iconCacheEntry * Icon = iconCache; + + memcpy(Key, &NodeURL[5], 5); + + while (Icon) + { + if (strcmp(Icon->key, Key) == 0) // Have it + { + memcpy(_REPLYBUFFER, Icon->pngimage, Icon->pngimagelen); + return Icon->pngimagelen; + } + Icon = Icon->Next; + } + + return 0; +} + +char * doHTMLTransparency(char * string) +{ + // Make sure string doesn't contain forbidden XML chars (<>"'&) + + char * newstring = malloc(5 * strlen(string) + 1); // If len is zero still need null terminator + + char * in = string; + char * out = newstring; + char c; + + c = *(in++); + + while (c) + { + switch (c) + { + case '<': + + strcpy(out, "<"); + out += 4; + break; + + case '>': + + strcpy(out, ">"); + out += 4; + break; + + case '"': + + strcpy(out, """); + out += 6; + break; + + case '\'': + + strcpy(out, "'"); + out += 6; + break; + + case '&': + + strcpy(out, "&"); + out += 5; + break; + + case ',': + + strcpy(out, ","); + out += 5; + break; + + case '|': + + strcpy(out, "|"); + out += 5; + break; + + default: + + *(out++) = c; + } + c = *(in++); + } + + *(out++) = 0; + return newstring; +} + +int GetAPRSPageInfo(char * Buffer, double N, double S, double W, double E, int aprs, int ais, int adsb) +{ + struct STATIONRECORD * ptr = *StationRecords; + int n = 0, Len = 0; + struct tm * TM; + time_t NOW = time(NULL); + char popup[65536] = ""; + char Msg[2048]; + int LocalTime = 0; + int KM = DefaultDistKM; + char * ptr1; + + while (ptr && aprs && Len < 240000) + { + if (ptr->Lat != 0.0 && ptr->Lon != 0.0) + { + if (ptr->Lat > S && ptr->Lat < N && ptr->Lon > W && ptr->Lon < E) + { + // See if we have the Icon - if not build + + char IconKey[6]; + struct iconCacheEntry * Icon = iconCache; + + sprintf(IconKey, "%02X%02X ", ptr->iconRow, ptr->iconCol); + + if (ptr->IconOverlay) + IconKey[4] = ptr->IconOverlay; + else + IconKey[4] = '@'; + + while (Icon) + { + if (strcmp(Icon->key, IconKey) == 0) // Have it + break; + + Icon = Icon->Next; + } + + if (Icon == NULL) + createIcon(IconKey, ptr->iconRow, ptr->iconCol, ptr->IconOverlay); + + popup[0] = 0; + + if (ptr->Approx) + { + sprintf(Msg, "Approximate Position From Locator
"); + strcat(popup, Msg); + } + ptr1 = doHTMLTransparency(ptr->Path); + sprintf(Msg, "%s
", ptr1); + strcat(popup, Msg); + free(ptr1); + ptr1 = doHTMLTransparency(ptr->LastPacket); + sprintf(Msg, "%s
", ptr1); + strcat(popup, Msg); + free(ptr1); + ptr1 = doHTMLTransparency(ptr->Status); + sprintf(Msg, "%s
", ptr1); + strcat(popup, Msg); + free(ptr1); + if (LocalTime) + TM = localtime(&ptr->TimeLastUpdated); + else + TM = gmtime(&ptr->TimeLastUpdated); + + sprintf(Msg, "Last Heard: %.2d:%.2d:%.2d on Port %d
", + TM->tm_hour, TM->tm_min, TM->tm_sec, ptr->LastPort); + + strcat(popup, Msg); + + sprintf(Msg, "Distance %6.1f Bearing %3.0f Course %1.0f° Speed %3.1f
", + myDistance(ptr->Lat, ptr->Lon, KM), + myBearing(ptr->Lat, ptr->Lon), ptr->Course, ptr->Speed); + strcat(popup, Msg); + + if (ptr->LastWXPacket[0]) + { + //display wx info + + struct APRSConnectionInfo temp; + + memset(&temp, 0, sizeof(temp)); + + DecodeWXReport(&temp, ptr->LastWXPacket); + + sprintf(Msg, "Wind Speed %d MPH
", temp.WindSpeed); + strcat(popup, Msg); + + sprintf(Msg, "Wind Gust %d MPH
", temp.WindGust); + strcat(popup, Msg); + + sprintf(Msg, "Wind Direction %d\xC2\xB0
", temp.WindDirn); + strcat(popup, Msg); + + sprintf(Msg, "Temperature %d\xC2\xB0 F
", temp.Temp); + strcat(popup, Msg); + + sprintf(Msg, "Pressure %05.1f
", temp.Pressure / 10.0); + strcat(popup, Msg); + + sprintf(Msg, "Humidity %d%%
", temp.Humidity); + strcat(popup, Msg); + + sprintf(Msg, "Rainfall Last Hour/Last 24H/Today %5.2f, %5.2f, %5.2f (inches)", + temp.RainLastHour / 100.0, temp.RainLastDay / 100.0, temp.RainToday / 100.0); + + ptr1 = doHTMLTransparency(Msg); + sprintf(Msg, "%s
", ptr1); + strcat(popup, Msg); + free(ptr1); + } + + Len += sprintf(&Buffer[Len],"A,%.4f,%.4f,%s,%s,%s,%d\r\n|", + ptr->Lat, ptr->Lon, ptr->Callsign, popup, IconKey, + NOW - ptr->TimeLastUpdated); + + if (ptr->TrackTime[0] && ptr->TrackTime[1]) // Have trackpoints + { + int n = ptr->Trackptr; + int i; + double lastLat = 0; + + // We read from next track point (oldest) for TRACKPOINT records, ignoring zeros + + Len += sprintf(&Buffer[Len],"T,"); + + for (i = 0; i < TRACKPOINTS; i++) + { + if (ptr->TrackTime[n]) + { + Len += sprintf(&Buffer[Len],"%.4f,%.4f,", ptr->LatTrack[n], ptr->LonTrack[n]); + lastLat = ptr->LatTrack[n]; + } + + n++; + if (n == TRACKPOINTS) + n = 0; + } + if (lastLat != ptr->Lat) + Len += sprintf(&Buffer[Len],"%.4f,%.4f,\r\n|", ptr->Lat, ptr->Lon); //Add current position to end of track + else + Len += sprintf(&Buffer[Len],"\r\n|"); + } + } + } + + ptr = ptr->Next; + } + return Len; +} + + + + + /* The png_jmpbuf() macro, used in error handling, became available in + * libpng version 1.0.6. If you want to be able to run your code with older + * versions of libpng, you must define the macro yourself (but only if it + * is not already defined by libpng!). + */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->png_jmpbuf) +#endif +/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() + * returns zero if the image is a PNG and nonzero if it isn't a PNG. + * + * The function check_if_png() shown here, but not used, returns nonzero (true) + * if the file can be opened and is a PNG, 0 (false) otherwise. + * + * If this call is successful, and you are going to keep the file open, + * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once + * you have created the png_ptr, so that libpng knows your application + * has read that many bytes from the start of the file. Make sure you + * don't call png_set_sig_bytes() with more than 8 bytes read or give it + * an incorrect number of bytes read, or you will either have read too + * many bytes (your fault), or you are telling libpng to read the wrong + * number of magic bytes (also your fault). + * + * Many applications already read the first 2 or 4 bytes from the start + * of the image to determine the file type, so it would be easiest just + * to pass the bytes to png_sig_cmp() or even skip that if you know + * you have a PNG file, and call png_set_sig_bytes(). + */ + +unsigned char * user_io_ptr = 0; + +void __cdecl user_read_fn(png_struct * png, png_bytep Buffer, png_size_t Len) +{ + unsigned char ** ptr = png->io_ptr; + unsigned char * ptr1; + + ptr1 = ptr[0]; + + memcpy(Buffer, ptr1, Len); + ptr[0]+= Len; +} + + +// This is based on example https://www1.udel.edu/CIS/software/dist/libpng-1.2.8/example.c + +// This decodes a png encoded image from memory + +int read_png(unsigned char *bytes) +{ + png_structp png_ptr; + unsigned int sig_read = 0; + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also supply the + * the compiler header file version, so that we know if the application + * was compiled with a compatible version of the library. REQUIRED + */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (png_ptr == NULL) + { + return (0); + } + /* Allocate/initialize the memory for image information. REQUIRED. */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return (0); + } + /* Set error handling if you are using the setjmp/longjmp method (this is + * the normal method of doing things with libpng). REQUIRED unless you + * set up your own error handlers in the png_create_read_struct() earlier. + */ + + user_io_ptr = (unsigned char *)&IconData; + + png_set_read_fn(png_ptr, (void *)&user_io_ptr,(png_rw_ptr)user_read_fn); + + png_set_sig_bytes(png_ptr, sig_read); + + png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, NULL); + + // Data is in info->row_pointers. Can we use it from there ?? + +// printf("%d %d %d\n", info_ptr->width, info_ptr->height, info_ptr->valid); + + return TRUE; +} + +void Myabort() +{} + +// This is based on pngfile.c + +//------------------------------------- +// PNGFILE.C -- Image File Functions +//------------------------------------- + +// Copyright 2000, Willem van Schaik. For conditions of distribution and +// use, see the copyright/license/disclaimer notice in png.h + +// Encodes pDiData to png format in memory + + + +void my_png_write_data(struct png_struct_def * png_ptr, png_bytep data, png_size_t length) +{ + struct iconCacheEntry * Icon = png_ptr->io_ptr; + + if (Icon->pngimagelen + (int)length > Icon->pngmalloclen) + { + Icon->pngmalloclen += length; + Icon->pngimage = realloc(Icon->pngimage, Icon->pngmalloclen); + } + + memcpy(&Icon->pngimage[Icon->pngimagelen], data, length); + Icon->pngimagelen += length; +} + + // io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr)); + // Area png_uint_32 check; + + + +static void png_flush(png_structp png_ptr) +{ +} + +unsigned char * PngEncode (png_byte *pDiData, int iWidth, int iHeight, struct iconCacheEntry * Icon) +{ + const int ciBitDepth = 8; + const int ciChannels = 3; + png_structp png_ptr; + png_infop info_ptr = NULL; + png_uint_32 ulRowBytes; + static png_byte **ppbRowPointers = NULL; + int i; + + // Set up image array and pointer. First allocate a buffer as big as the original + // in the unlikely event of it being too small write_data will realloc it + + Icon->pngmalloclen = iWidth * iHeight * 3; + Icon->pngimage = malloc(Icon->pngmalloclen); + Icon->pngimagelen = 0; + + // prepare the standard PNG structures + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) + { + return FALSE; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + return FALSE; + } + + { + // initialize the png structure + + png_set_write_fn(png_ptr, Icon, my_png_write_data, png_flush); + + png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, ciBitDepth, + PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); + + // write the file header information + + png_write_info(png_ptr, info_ptr); + + // row_bytes is the width x number of channels + + ulRowBytes = iWidth * ciChannels; + + // we can allocate memory for an array of row-pointers + + if ((ppbRowPointers = (png_bytepp) malloc(iHeight * sizeof(png_bytep))) == NULL) + Debugprintf( "Visualpng: Out of memory"); + + // set the individual row-pointers to point at the correct offsets + + for (i = 0; i < iHeight; i++) + ppbRowPointers[i] = pDiData + i * (((ulRowBytes + 3) >> 2) << 2); + + // write out the entire image data in one call + + png_write_image (png_ptr, ppbRowPointers); + + // write the additional chunks to the PNG file (not really needed) + + png_write_end(png_ptr, info_ptr); + + // and we're done + + free (ppbRowPointers); + ppbRowPointers = NULL; + + // clean up after the write, and free any memory allocated + + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + + // yepp, done + } + + return Icon->pngimage; +} + +void SaveAPRSMessage(struct APRSMESSAGE * ptr) +{ + // Save messages in case of a restart + + char FN[250]; + FILE *file; + + // Set up filename + + if (BPQDirectory[0] == 0) + { + strcpy(FN,"APRSMsgs.dat"); + } + else + { + strcpy(FN,BPQDirectory); + strcat(FN,"/"); + strcat(FN,"APRSMsgs.dat"); + } + + if ((file = fopen(FN, "a")) == NULL) + return ; + + fprintf(file, "%d %s,%s,%s,%s,%s\n", time(NULL), ptr->FromCall, ptr->ToCall, ptr->Seq, ptr->Time, ptr->Text); + + fclose(file); +} + +void ClearSavedMessages() +{ + char FN[250]; + FILE *file; + + // Set up filename + + if (BPQDirectory[0] == 0) + { + strcpy(FN,"APRSMsgs.dat"); + } + else + { + strcpy(FN,BPQDirectory); + strcat(FN,"/"); + strcat(FN,"APRSMsgs.dat"); + } + + if ((file = fopen(FN, "w")) == NULL) + return ; + + fclose(file); +} + +void GetSavedAPRSMessages() +{ + // Get Saved messages + + // 1668768157 SERVER ,GM8BPQ-2 ,D7Yx,10:42,filter m/200 active + + char FN[250]; + FILE *file; + struct APRSMESSAGE * Message; + struct APRSMESSAGE * ptr; + char Line[512]; + char * Stamp = 0; + char * From = 0; + char * To = 0; + char * Seq = 0; + char * Time = 0; + char * Text = 0; + + // Set up filename + + if (BPQDirectory[0] == 0) + { + strcpy(FN,"APRSMsgs.dat"); + } + else + { + strcpy(FN,BPQDirectory); + strcat(FN,"/"); + strcat(FN,"APRSMsgs.dat"); + } + + if ((file = fopen(FN, "r")) == NULL) + return ; + + while (fgets(Line, 512, file)) + { + Stamp = Line; + From = strlop(Stamp, ' '); + To = strlop(From, ','); + Seq = strlop(To, ','); + Time = strlop(Seq, ','); + Text = strlop(Time, ','); + + if (Stamp && From && To && Seq && Time && Text) + { + Message = APRSGetMessageBuffer(); + + if (Message == NULL) + break; + + memset(Message, 0, sizeof(struct APRSMESSAGE)); + + strcpy(Message->FromCall, From); + strcpy(Message->ToCall, To); + strcpy(Message->Seq, Seq); + strcpy(Message->Time, Time); + strcpy(Message->Text, Text); + + ptr = SMEM->Messages; + + if (ptr == NULL) + { + SMEM->Messages = Message; + } + else + { + while(ptr->Next) + { + ptr = ptr->Next; + } + ptr->Next = Message; + } + + } + } + fclose(file); +} diff --git a/APRSCode.c.rej b/APRSCode.c.rej new file mode 100644 index 0000000..1137117 --- /dev/null +++ b/APRSCode.c.rej @@ -0,0 +1,139 @@ +--- APRSCode.c ++++ APRSCode.c +@@ -3674,7 +3674,7 @@ + if (ptr1) + *ptr1 = 0; + +-// Debugprintf("Duplicate Message supressed %s", Msg); ++// Debugprintf("Duplicate Message suppressed %s", Msg); + return TRUE; // Duplicate + } + } +--- BPQChat.rc ++++ BPQChat.rc +@@ -162,7 +162,7 @@ + WS_VSCROLL + DEFPUSHBUTTON "Save Welcome Message",SAVEWELCOME,140,296,91,14, + BS_CENTER | BS_VCENTER +- LTEXT " If the node is not directly connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands seperared by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT", ++ LTEXT " If the node is not directly connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands separated by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT", + IDC_STATIC,9,52,355,24 + END + +--- BPQMail.rc ++++ BPQMail.rc +@@ -1045,7 +1045,7 @@ + CONTROL "Delete Log and Message Files to Recycle Bin", + IDC_DELETETORECYCLE,"Button",BS_AUTOCHECKBOX | + BS_LEFTTEXT | BS_MULTILINE | WS_TABSTOP,5,142,115,20 +- CONTROL "Supress Mailing of Housekeeping Results", ++ CONTROL "Suppress Mailing of Housekeeping Results", + IDC_MAINTNOMAIL,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | + BS_MULTILINE | WS_TABSTOP,5,182,115,20 + CONTROL "Generate Traffic Report",IDC_MAINTTRAFFIC,"Button", +--- HanksRT.c ++++ HanksRT.c +@@ -1186,7 +1186,7 @@ + // Duplicate, so discard, but save time + + DupInfo[i].DupTime = Now; +- Logprintf(LOG_CHAT, circuit, '?', "Duplicate Message From %s %s supressed", Call, Msg); ++ Logprintf(LOG_CHAT, circuit, '?', "Duplicate Message From %s %s suppressed", Call, Msg); + + return TRUE; // Duplicate + } +--- RigControl.c ++++ RigControl.c +@@ -8385,7 +8385,7 @@ + + switch (Msg[0]) + { +- case 'f': // Get Freqency ++ case 'f': // Get Frequency + + HLGetFreq(Sock, RIG, sep); + return 0; +--- UZ7HODrv.c ++++ UZ7HODrv.c +@@ -374,7 +374,7 @@ + { + // Read Freq + +- buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "UZ7HO} Modem Freqency %d\r", AGW->CenterFreq); ++ buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "UZ7HO} Modem Frequency %d\r", AGW->CenterFreq); + return 1; + } + +@@ -382,7 +382,7 @@ + + if (AGW->CenterFreq == 0) + { +- buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "UZ7HO} Invalid Modem Freqency\r"); ++ buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "UZ7HO} Invalid Modem Frequency\r"); + return 1; + } + +--- WinRPRHelper.c ++++ WinRPRHelper.c +@@ -111,7 +111,7 @@ + + if (argc < 3) + { +- printf ("Missing paramters - you need COM port and IP Address and rigctl port of BPQ, eg \r\n" ++ printf ("Missing parameters - you need COM port and IP Address and rigctl port of BPQ, eg \r\n" + " WinRPRHelper com10 192.168.1.64:4532\r\n\r\n" + "Press any key to exit\r\n"); + +--- config.c ++++ config.c +@@ -649,7 +649,7 @@ + if (LOCATOR[0] == 0 && LocSpecified == 0 && RFOnly == 0) + { + Consoleprintf(""); +- Consoleprintf("Please enter a LOCATOR statment in your BPQ32.cfg"); ++ Consoleprintf("Please enter a LOCATOR statement in your BPQ32.cfg"); + Consoleprintf("If you really don't want to be on the Node Map you can enter LOCATOR=NONE"); + Consoleprintf(""); + +--- kiss.c ++++ kiss.c +@@ -1485,7 +1485,7 @@ + } + } + else +- Debugprintf("Polled KISS - response from wrong address - Polled %d Reponse %d", ++ Debugprintf("Polled KISS - response from wrong address - Polled %d Response %d", + KISS->POLLPOINTER->OURCTRL, (Port->RXMSG[0] & 0xf0)); + + goto SeeifMore; // SEE IF ANYTHING ELSE +--- templatedefs.c ++++ templatedefs.c +@@ -1165,7 +1165,7 @@ + "Send Non-delivery Notifications
\r\n" + "for P and T messages
\r\n" + "
\r\n" +- "Supress Mailing of
\r\n" ++ "Suppress Mailing of
\r\n" + "Housekeeping Result

\r\n" + "Generate Traffic Report

\r\n" + "
\r\n" +@@ -1454,7 +1454,7 @@ + "
The Nodes to link to box defines which other Chat Nodes should be connected to, or from which " + "connections may be accepted. The format is ALIAS:CALL, eg BPQCHT:G8BPQ-4. If the node is not directly " + "connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands " +- "seperared by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT" ++ "separated by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT" + + "

The Callsign of the Chat Node is not defined here - it is obtained from the bpq32.cfg APPLICATION line corresponding to the Chat Appl Number.
\r\n" + "
\n" +--- WebMail.c ++++ WebMail.c +@@ -2020,7 +2020,7 @@ + "document.getElementById('myform').action = '/WebMail/QuoteOriginal' + '?%s';" + " document.getElementById('myform').submit();}" + ""; ++ "value='Include Original Msg'>"; + + char Temp[1024]; + char ReplyAddr[128]; diff --git a/ARDOP.c b/ARDOP.c index ff3ce4e..704092f 100644 --- a/ARDOP.c +++ b/ARDOP.c @@ -562,7 +562,7 @@ static int ProcessLine(char * buf, int Port) void ARDOPThread(struct TNCINFO * TNC); VOID ARDOPProcessDataSocketData(int port); -int ConnecttoARDOP(); +int ConnecttoARDOP(struct TNCINFO * TNC); static VOID ARDOPProcessReceivedData(struct TNCINFO * TNC); static VOID ARDOPProcessReceivedControl(struct TNCINFO * TNC); int V4ProcessReceivedData(struct TNCINFO * TNC); @@ -3212,7 +3212,7 @@ VOID ARDOPProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 @@ -5063,7 +5063,7 @@ tcpHostFrame: { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // Make sure app is available diff --git a/BBSUtilities.c b/BBSUtilities.c index 56e08a0..50de210 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -51,6 +51,8 @@ extern struct ConsoleInfo BBSConsole; extern char LOC[7]; +extern BOOL MQTT; + //#define BBSIDLETIME 120 //#define USERIDLETIME 300 @@ -126,6 +128,7 @@ int32_t Encode(char * in, char * out, int32_t inlen, BOOL B1Protocol, int Compre int APIENTRY ChangeSessionCallsign(int Stream, unsigned char * AXCall); void SendMessageReadEvent(char * call, struct MsgInfo * Msg); void SendNewMessageEvent(char * call, struct MsgInfo * Msg); +void MQTTMessageEvent(struct MsgInfo * message); config_t cfg; config_setting_t * group; @@ -3452,6 +3455,11 @@ VOID FlagAsKilled(struct MsgInfo * Msg, BOOL SaveDB) if (SaveDB) SaveMessageDatabase(); RebuildNNTPList(); +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(Msg); +#endif + } void DoDeliveredCommand(CIRCUIT * conn, struct UserInfo * user, char * Cmd, char * Arg1, char * Context) @@ -4896,6 +4904,10 @@ sendEOM: Msg->datechanged=time(NULL); SaveMessageDatabase(); SendMessageReadEvent(user->Call, Msg); +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(Msg); +#endif } } } @@ -6457,6 +6469,10 @@ nextline: user = LookupCall(Msg->to); SendNewMessageEvent(user->Call, Msg); +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(Msg); +#endif if (EnableUI) #ifdef LINBPQ @@ -10141,7 +10157,6 @@ BOOL GetConfig(char * ConfigName) int i; char Size[80]; config_setting_t *setting; - const char * ptr; char * ptr1; char FBBString[8192]= ""; FBBFilter f; @@ -10264,8 +10279,7 @@ BOOL GetConfig(char * ConfigName) if (setting && setting->value.sval[0]) { - ptr = config_setting_get_string (setting); - WelcomeMsg = _strdup(ptr); + WelcomeMsg = _strdup(config_setting_get_string (setting)); } else WelcomeMsg = _strdup("Hello $I. Latest Message is $L, Last listed is $Z\r\n"); @@ -10274,10 +10288,7 @@ BOOL GetConfig(char * ConfigName) setting = config_setting_get_member (group, "NewUserWelcomeMsg"); if (setting && setting->value.sval[0]) - { - ptr = config_setting_get_string (setting); - NewWelcomeMsg = _strdup(ptr); - } + NewWelcomeMsg = _strdup(config_setting_get_string (setting)); else NewWelcomeMsg = _strdup("Hello $I. Latest Message is $L, Last listed is $Z\r\n"); @@ -10285,10 +10296,7 @@ BOOL GetConfig(char * ConfigName) setting = config_setting_get_member (group, "ExpertWelcomeMsg"); if (setting && setting->value.sval[0]) - { - ptr = config_setting_get_string (setting); - ExpertWelcomeMsg = _strdup(ptr); - } + ExpertWelcomeMsg = _strdup(config_setting_get_string (setting)); else ExpertWelcomeMsg = _strdup(""); @@ -10297,10 +10305,7 @@ BOOL GetConfig(char * ConfigName) setting = config_setting_get_member (group, "Prompt"); if (setting && setting->value.sval[0]) - { - ptr = config_setting_get_string (setting); - Prompt = _strdup(ptr); - } + Prompt = _strdup(config_setting_get_string (setting)); else { Prompt = malloc(20); @@ -10310,10 +10315,7 @@ BOOL GetConfig(char * ConfigName) setting = config_setting_get_member (group, "NewUserPrompt"); if (setting && setting->value.sval[0]) - { - ptr = config_setting_get_string (setting); - NewPrompt = _strdup(ptr); - } + NewPrompt = _strdup(config_setting_get_string (setting)); else { NewPrompt = malloc(20); @@ -10323,10 +10325,7 @@ BOOL GetConfig(char * ConfigName) setting = config_setting_get_member (group, "ExpertPrompt"); if (setting && setting->value.sval[0]) - { - ptr = config_setting_get_string (setting); - ExpertPrompt = _strdup(ptr); - } + ExpertPrompt = _strdup(config_setting_get_string (setting)); else { ExpertPrompt = malloc(20); @@ -10547,7 +10546,7 @@ int Connected(int Stream) char ConnectedMsg[] = "*** CONNECTED "; char Msg[100]; char Title[100]; - int Freq = 0; + int64_t Freq = 0; int Mode = 0; BPQVECSTRUC * SESS; TRANSPORTENTRY * Sess1 = NULL, * Sess2; @@ -11781,6 +11780,11 @@ VOID ProcessTextFwdLine(ConnectionInfo * conn, struct UserInfo * user, char * Bu SaveMessageDatabase(); +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(conn->FwdMsg); +#endif + conn->UserPointer->ForwardingInfo->MsgCount--; // See if any more to forward diff --git a/BPQChat.rc b/BPQChat.rc index 11b919a..528e943 100644 --- a/BPQChat.rc +++ b/BPQChat.rc @@ -162,7 +162,7 @@ BEGIN WS_VSCROLL DEFPUSHBUTTON "Save Welcome Message",SAVEWELCOME,140,296,91,14, BS_CENTER | BS_VCENTER - LTEXT " If the node is not directly connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands seperared by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT", + LTEXT " If the node is not directly connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands separared by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT", IDC_STATIC,9,52,355,24 END diff --git a/BPQINP3.c b/BPQINP3.c index bfe7cb0..dac41c4 100644 --- a/BPQINP3.c +++ b/BPQINP3.c @@ -64,7 +64,7 @@ typedef struct _RTTMSG } RTTMSG; -extern int COUNTNODES(); +int COUNTNODES(struct ROUTE * ROUTE); VOID __cdecl Debugprintf(const char * format, ...); diff --git a/BPQMail.c b/BPQMail.c index 4291daf..9f45d7a 100644 --- a/BPQMail.c +++ b/BPQMail.c @@ -2830,6 +2830,12 @@ gotAddr: EndDialog(hDlg, LOWORD(wParam)); +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(Msg); +#endif + + return TRUE; } @@ -3085,6 +3091,8 @@ BOOL Initialise() GetTimeZoneInformation(&TimeZoneInformation); + Debugprintf("%d", sizeof(struct MsgInfo)); + _tzset(); _MYTIMEZONE = timezone; _MYTIMEZONE = TimeZoneInformation.Bias * 60; diff --git a/BPQMail.rc b/BPQMail.rc index 440945c..88d1116 100644 --- a/BPQMail.rc +++ b/BPQMail.rc @@ -1045,7 +1045,7 @@ BEGIN CONTROL "Delete Log and Message Files to Recycle Bin", IDC_DELETETORECYCLE,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | WS_TABSTOP,5,142,115,20 - CONTROL "Supress Mailing of Housekeeping Results", + CONTROL "Suppress Mailing of Housekeeping Results", IDC_MAINTNOMAIL,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | WS_TABSTOP,5,182,115,20 CONTROL "Generate Traffic Report",IDC_MAINTTRAFFIC,"Button", diff --git a/BPQTermMDI.c b/BPQTermMDI.c index 447cde3..afdb4f5 100644 --- a/BPQTermMDI.c +++ b/BPQTermMDI.c @@ -214,7 +214,7 @@ LRESULT APIENTRY InputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; LRESULT APIENTRY MonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; -extern CMDX COMMANDS[]; +extern struct CMDX COMMANDS[]; extern int APPL1; static HMENU trayMenu; diff --git a/BPQtoAGW.c b/BPQtoAGW.c index 3c07458..b91a20c 100644 --- a/BPQtoAGW.c +++ b/BPQtoAGW.c @@ -87,7 +87,7 @@ void CreateMHWindow(); int Update_MH_List(struct in_addr ipad, char * call, char proto); static BOOL ReadConfigFile(int Port); -int ConnecttoAGW(); +int ConnecttoAGW(int port); int ProcessReceivedData(int bpqport); static int ProcessLine(char * buf, int Port, BOOL CheckPort); diff --git a/Bpq32.c b/Bpq32.c index 9589351..8311011 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1237,7 +1237,8 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Save MH and NODES every hour (51) // Fix handling long unix device names (now max 250 bytes) (52) // Fix error reporting in api update (53) -// Coding changes to remove some compiler warnings (53) +// Coding changes to remove some compiler warnings (53, 54) +// Add MQTT reporting o #define CKernel diff --git a/CHeaders.h b/CHeaders.h index aeef69c..c0af6d2 100644 --- a/CHeaders.h +++ b/CHeaders.h @@ -93,7 +93,7 @@ VOID DoTheCommand(TRANSPORTENTRY * Session); char * MOVEANDCHECK(TRANSPORTENTRY * Session, char * Bufferptr, char * Source, int Len); VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer); char * FormatUptime(int Uptime); -char * strlop(char * buf, char delim); +char * strlop(const char * buf, char delim); BOOL CompareCalls(UCHAR * c1, UCHAR * c2); VOID PostDataAvailable(TRANSPORTENTRY * Session); @@ -109,7 +109,7 @@ int cCOUNT_AT_L2(struct _LINKTABLE * LINK); VOID SENDL4CONNECT(TRANSPORTENTRY * Session); VOID CloseSessionPartner(TRANSPORTENTRY * Session); -int COUNTNODES(); +int COUNTNODES(struct ROUTE * ROUTE); int DecodeNodeName(char * NodeName, char * ptr);; VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer); int cCOUNT_AT_L2(struct _LINKTABLE * LINK); @@ -359,7 +359,7 @@ extern char * ConfigBuffer; extern char * WL2KReportLine[]; -extern CMDX COMMANDS[]; +extern struct CMDX COMMANDS[]; extern int QCOUNT, MAXBUFFS, MAXCIRCUITS, L4DEFAULTWINDOW, L4T1, CMDXLEN; extern char CMDALIAS[ALIASLEN][NumberofAppls]; diff --git a/CMSAuth.c b/CMSAuth.c index 902714e..e2fbd06 100644 --- a/CMSAuth.c +++ b/CMSAuth.c @@ -23,6 +23,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #ifdef LINBPQ #include "compatbits.h" +char * strlop(const char * buf, char delim); #define APIENTRY #define VOID void @@ -31,7 +32,6 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include #endif -char * strlop(char * buf, char delim); VOID APIENTRY md5 (char *arg, unsigned char * checksum); diff --git a/Cmd-skigdebian.c b/Cmd-skigdebian.c deleted file mode 100644 index 88189b1..0000000 --- a/Cmd-skigdebian.c +++ /dev/null @@ -1,5989 +0,0 @@ -/* -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. S"paclenee 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 -*/ - -// -// C replacement for cmd.asm -// -#define Kernel - -#define _CRT_SECURE_NO_DEPRECATE -#pragma data_seg("_BPQDATA") - -//#include "windows.h" -//#include "winerror.h" - - -#include "time.h" -#include "stdio.h" -#include -//#include "vmm.h" -//#include "SHELLAPI.H" - -#include "CHeaders.h" -#include "bpqaprs.h" -#include "kiss.h" - -#pragma pack() - -#include "tncinfo.h" -#include "telnetserver.h" - -//#include "GetVersion.h" - -//#define DllImport __declspec( dllimport ) -//#define DllExport __declspec( dllexport ) - -BOOL DecodeCallString(char * Calls, BOOL * Stay, BOOL * Spy, UCHAR *AXCalls); -VOID Send_AX_Datagram(PDIGIMESSAGE Block, DWORD Len, UCHAR Port); -int APIENTRY ClearNodes(); -VOID GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value); -VOID SendHTTPRequest(SOCKET sock, char * Host, int Port, char * Request, char * Params, int Len, char * Return); -SOCKET OpenWL2KHTTPSock(); -VOID FormatTime3(char * Time, time_t cTime); -VOID Format_Addr(unsigned char * Addr, char * Output, BOOL IPV6); -VOID Tel_Format_Addr(struct ConnectionInfo * sockptr, char * dst); -VOID FindLostBuffers(); -BOOL CheckCMS(struct TNCINFO * TNC); -VOID L2SENDXID(struct _LINKTABLE * LINK); -int CountBits(unsigned long in); -VOID SaveMH(); -BOOL RestartTNC(struct TNCINFO * TNC); -void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID WriteMiniDump(); -int CheckKissInterlock(struct PORTCONTROL * PORT, int Exclusive); -int seeifInterlockneeded(struct PORTCONTROL * PORT); - -extern VOID KISSTX(); - -char COMMANDBUFFER[81] = ""; // Command Hander input buffer -char OrigCmdBuffer[81] = ""; // Command Hander input buffer before toupper - -struct DATAMESSAGE * REPLYBUFFER = NULL; -UINT APPLMASK = 0; -UCHAR SAVEDAPPLFLAGS = 0; - -UCHAR ALIASINVOKED = 0; - - -VOID * CMDPTR = 0; - -short CMDPACLEN = 0; - -char OKMSG[] = "Ok\r"; - -char CMDERRMSG[] = "Invalid command - Enter ? for command list\r"; -#define CMDERRLEN sizeof(CMDERRMSG) - 1 - -char PASSWORDMSG[] = "Command requires SYSOP status - enter password\r"; -#define LPASSMSG sizeof(PASSWORDMSG) - 1 - -char CMDLIST[] = "CONNECT BYE INFO NODES PORTS ROUTES USERS MHEARD"; - -#define CMDLISTLEN sizeof(CMDLIST) - 1 - -char BADMSG[] = "Bad Parameter\r"; -char BADPORT[] = "Invalid Port Number\r"; -char NOTEXTPORT[] = "Only valid on EXT ports\r"; -char NOVALCALLS[] = "No Valid Calls defined on this port\r"; - -char BADVALUEMSG[] = "Invalid parameter\r"; - -char BADCONFIGMSG[] = "Configuration File check falled - will continue with old config\r"; -#ifdef LINBPQ -char REBOOTOK[] = "Rebooting\r"; -#else -char REBOOTOK[] = "Rebooting in 20 secs\r"; -#endif -char REBOOTFAILED[] = "Shutdown failed\r"; - -char RESTARTOK[] = "Restarting\r"; -char RESTARTFAILED[] = "Restart failed\r"; - -UCHAR ARDOP[7] = {'A'+'A','R'+'R','D'+'D','O'+'O','P'+'P',' '+' '}; // ARDOP IN AX25 -UCHAR VARA[7] = {'V'+'V','A'+'A','R'+'R','A'+'A',' '+' ',' '+' '}; // VARA IN AX25 - -int STATSTIME = 0; -int MAXBUFFS = 0; -int QCOUNT = 0; -int MINBUFFCOUNT = 65535; -int NOBUFFCOUNT = 0; -int BUFFERWAITS = 0; -int MAXDESTS = 0; -int NUMBEROFNODES = 0; -int L4CONNECTSOUT = 0; -int L4CONNECTSIN = 0; -int L4FRAMESTX = 0; -int L4FRAMESRX = 0; -int L4FRAMESRETRIED = 0; -int OLDFRAMES = 0; -int L3FRAMES = 0; - -VOID SENDSABM(); -VOID RESET2(); - -int APPL1 = 0; -int PASSCMD = 0; - -#pragma pack(1) - -struct _EXTPORTDATA DP; // Only way I can think of to get offets to port data into cmd table - -char CMDALIAS[ALIASLEN][NumberofAppls] = {0}; -char * ALIASPTR = &CMDALIAS[0][0]; - -extern int RigReconfigFlag; - -CMDX COMMANDS[]; - -int CMDXLEN = sizeof (CMDX); - -VOID SENDNODESMSG(); -VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STOPCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STARTCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STOPPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STARTPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID FINDBUFFS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID WL2KSYSOP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID AXRESOLVER(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID AXMHEARD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWTELNET(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWAGW(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWARP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWNAT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID PING(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWIPROUTE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID FLMSG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD); -void ListExcludedCalls(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID APRSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID RECONFIGTELNET (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID HELPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD); -VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD); -void hookL2SessionAttempt(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK); - - - -char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char * format, ...) -{ - // Send Command response checking PACLEN - - char Mess[4096]; - va_list(arglist); - int OldLen; - int MsgLen; - struct DATAMESSAGE * Buffer; - char * Messptr = Mess; - int Paclen = Session->SESSPACLEN; - - if (Paclen == 0) - Paclen = 255; - - va_start(arglist, format); - - MsgLen = vsprintf(Mess, format, arglist); - - OldLen = (int)(Bufferptr - (char *)REPLYBUFFER->L2DATA); - - while ((OldLen + MsgLen) > Paclen) - { - // Have to send Paclen then get a new buffer - - int ThisBit = Paclen - OldLen; // What we can send this time - - if (ThisBit < 0) - ThisBit = 0; // How can this happen?? - - memcpy(Bufferptr, Messptr, ThisBit); - Messptr += ThisBit; - MsgLen -= ThisBit; - - // QUEUE IT AND GET ANOTHER BUFFER - - Buffer = (struct DATAMESSAGE *)GetBuff(); - - if (Buffer == NULL) - - // No buffers, so just reuse the old one (better than crashing !!) - - Buffer = REPLYBUFFER; - else - SendCommandReply(Session, REPLYBUFFER, Paclen + (4 + sizeof(void *))); - - - REPLYBUFFER = Buffer; - Buffer->PID = 0xf0; - - Bufferptr = &Buffer->L2DATA[0]; - OldLen = 0; - } - - // Add last bit to buffer - - memcpy(Bufferptr, Messptr, MsgLen); - - return Bufferptr + MsgLen; -} - - -VOID SENDNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - SENDNODESMSG(); - - strcpy(Bufferptr, OKMSG); - Bufferptr += (int)strlen(OKMSG); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID SAVEMHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - SaveMH(); - - strcpy(Bufferptr, OKMSG); - Bufferptr += (int)strlen(OKMSG); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID SAVENODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - SaveNodes(); - - strcpy(Bufferptr, OKMSG); - Bufferptr += (int)strlen(OKMSG); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID DUMPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - WriteMiniDump(); - - strcpy(Bufferptr, OKMSG); - Bufferptr += (int)strlen(OKMSG); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID RIGRECONFIG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - if (!ProcessConfig()) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Configuration File check falled - will continue with old config"); - } - else - { - RigReconfigFlag = TRUE; - Bufferptr = Cmdprintf(Session, Bufferptr, "Rigcontrol Reconfig requested"); - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID REBOOT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - if (Reboot()) - { - strcpy(Bufferptr, REBOOTOK); - Bufferptr += (int)strlen(REBOOTOK); - } - else - { - strcpy(Bufferptr, REBOOTFAILED); - Bufferptr += (int)strlen(REBOOTFAILED); - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID RESTART(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - if (Restart()) - { - strcpy(Bufferptr, RESTARTOK); - Bufferptr += (int)strlen(RESTARTOK); - } - else - { - strcpy(Bufferptr, RESTARTFAILED); - Bufferptr += (int)strlen(RESTARTFAILED); - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID RESTARTTNC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char * ptr, *Context; - int portno; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - { - portno = atoi (ptr); - - if (portno && portno < 33) - { - struct TNCINFO * TNC = TNCInfo[portno]; - - if (TNC == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - } - else - { - if (TNC->ProgramPath) - { - if (RestartTNC(TNC)) - Bufferptr = Cmdprintf(Session, Bufferptr, "Restart %s Ok\r", TNC->ProgramPath); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Restart %s Failed\r", TNC->ProgramPath); - } - else - { - Bufferptr = Cmdprintf(Session, Bufferptr, "PATH not defined so can't restart TNC\r"); - } - } - } - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -UCHAR VALNODESFLAG = 0, EXTONLY = 0; - -VOID PORTVAL (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); - -VOID VALNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - VALNODESFLAG = 1; - PORTVAL(Session, Bufferptr, CmdTail, CMD); -} - -VOID EXTPORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - EXTONLY = 1; - PORTVAL(Session, Bufferptr, CmdTail, CMD); -} -VOID PORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // PROCESS PORT VALUE COMMANDS - - char * ptr, *Context, * ptr1; - int portno; - UCHAR oldvalue, newvalue; - struct PORTCONTROL * PORT = PORTTABLE; - int n = NUMBEROFPORTS; - UCHAR * valueptr; - - // Get port number - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - { - portno = atoi (ptr); - - if (portno) - { - while (n--) - { - if (PORT->PORTNUMBER == portno) - { - if (VALNODESFLAG) - { - char * VNPtr = PORT->PERMITTEDCALLS; - char Normcall[10]; - - VALNODESFLAG = 0; - - if (VNPtr) - { - while (VNPtr[0]) - { - Normcall[ConvFromAX25(VNPtr, Normcall)] = 0; - Bufferptr = Cmdprintf(Session, Bufferptr, "%s ", Normcall); - VNPtr += 7; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - } - else - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", NOVALCALLS); - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - - return; - - } - - if (EXTONLY) - { - // Make sure an Extenal Port - - EXTONLY = 0; - - if (PORT->PORTTYPE != 0x10) - { - strcpy(Bufferptr, NOTEXTPORT); - Bufferptr += (int)strlen(NOTEXTPORT); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - } - - valueptr = (UCHAR *)PORT + CMD->CMDFLAG; - oldvalue = *valueptr; - - // Display Param Namee - - ptr1 = &CMD->String[0]; - n = 12; - - while (*(ptr1) != ' ' && n--) - *(Bufferptr++) = *(ptr1++); - - // See if another param - if not, just display current value - - ptr = strtok_s(NULL, " ", &Context); - - if (ptr && ptr[0]) - { - // Get new value - - newvalue = atoi(ptr); - *valueptr = newvalue; - - Bufferptr = Cmdprintf(Session, Bufferptr, " was %d now %d\r", oldvalue, newvalue); - } - - else - Bufferptr = Cmdprintf(Session, Bufferptr, " %d\r", oldvalue); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - - } - PORT = PORT->PORTPOINTER; - } - } - } - - // Bad port - - strcpy(Bufferptr, BADPORT); - Bufferptr += (int)strlen(BADPORT); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - -} - -VOID SWITCHVAL (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // Update switch 8 bit value - - char * ptr, *Context, * ptr1; - UCHAR oldvalue, newvalue; - int n; - UCHAR * valueptr; - - valueptr = (UCHAR *)CMD->CMDFLAG; - - oldvalue = *valueptr; - - // Display Param Name - - ptr1 = &CMD->String[0]; - n = 12; - - while (*(ptr1) != ' ' && n--) - *(Bufferptr++) = *(ptr1++); - - // See if a param - if not, just display current value - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr && ptr[0]) - { - // Get new value - - newvalue = atoi(ptr); - *valueptr = newvalue; - - Bufferptr = Cmdprintf(Session, Bufferptr, " was %d now %d\r", oldvalue, newvalue); - - if (memcmp(CMD->String, "NODESINT ", 8) == 0) - L3TIMER = L3INTERVAL; - } - else - Bufferptr = Cmdprintf(Session, Bufferptr, " %d\r", oldvalue); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - -} - -VOID SWITCHVALW (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // Update switch 16 bit value - - char * ptr, *Context, * ptr1; - USHORT oldvalue, newvalue; - int n; - USHORT * valueptr; - - valueptr = (USHORT *)CMD->CMDFLAG; - - oldvalue = (USHORT)*valueptr; - - // Display Param Name - - ptr1 = &CMD->String[0]; - n = 12; - - while (*(ptr1) != ' ' && n--) - *(Bufferptr++) = *(ptr1++); - - // See if a param - if not, just display current value - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr && ptr[0]) - { - // Get new value - - newvalue = atoi(ptr); - *valueptr = newvalue; - - Bufferptr = Cmdprintf(Session, Bufferptr, " was %d now %d\r", oldvalue, newvalue); - } - else - Bufferptr = Cmdprintf(Session, Bufferptr, " %d\r", oldvalue); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - -} - -TRANSPORTENTRY * SetupSessionFromSession(TRANSPORTENTRY * Session, PBPQVECSTRUC HOSTSESS, UINT APPLMASK) -{ - // Create a Transport (L4) session linked to an incoming Session - - TRANSPORTENTRY * NewSess = L4TABLE; - int Index = 0; - - while (Index < MAXCIRCUITS) - { - if (NewSess->L4USER[0] == 0) - { - // Got One - - UCHAR * ourcall = &MYCALL[0]; - - Session->L4CROSSLINK = NewSess; - NewSess->L4CROSSLINK = Session; - - if (APPLMASK) - { - // Circuit for APPL - look for an APPLCALL - - APPLCALLS * APPL = APPLCALLTABLE; - - while ((APPLMASK & 1) == 0) - { - APPLMASK >>= 1; - APPL++; - } - if (APPL->APPLCALL[0] > 0x40) // We have an applcall - ourcall = &APPL->APPLCALL[0]; - } - - memcpy(NewSess->L4USER, ourcall, 7); - memcpy(NewSess->L4MYCALL, Session->L4MYCALL, 7); - - NewSess->CIRCUITINDEX = Index; //OUR INDEX - NewSess->CIRCUITID = NEXTID; - - NEXTID++; - if (NEXTID == 0) - NEXTID++; // kEEP nON-ZERO - - NewSess->SESSIONT1 = Session->SESSIONT1; - NewSess->L4WINDOW = (UCHAR)L4DEFAULTWINDOW; - NewSess->SESSPACLEN = PACLEN; // Default; - - NewSess->L4TARGET.HOST = HOSTSESS; - NewSess->L4STATE = 5; - return NewSess; - } - Index++; - NewSess++; - } - return NULL; -} - -extern int GETCONNECTIONINFO(); - - -BOOL cATTACHTOBBS(TRANSPORTENTRY * Session, UINT Mask, int Paclen, int * AnySessions) -{ - PBPQVECSTRUC HOSTSESS = BPQHOSTVECTOR; - TRANSPORTENTRY * NewSess; - int ApplNum; - int n = BPQHOSTSTREAMS; - int ConfigedPorts = 0; - - // LOOK FOR A FREE HOST SESSION - - while (n--) - { - if (HOSTSESS->HOSTAPPLMASK & Mask) - { - // Right appl - - ConfigedPorts++; - - if (HOSTSESS->HOSTSESSION == NULL && (HOSTSESS->HOSTFLAGS & 3) == 0) // Not attached and no report outstanding - { - // WEVE GOT A FREE BPQ HOST PORT - USE IT - - NewSess = SetupSessionFromSession(Session, HOSTSESS, Mask); - - if (NewSess == NULL) - return FALSE; // Appl not available - - HOSTSESS->HOSTSESSION = NewSess; - - // Convert APPLMASK to APPLNUM - - ApplNum = 1; - - while (APPLMASK && (APPLMASK & 1) == 0) - { - ApplNum++; - APPLMASK >>= 1; - } - - HOSTSESS->HOSTAPPLNUM = ApplNum; - - HOSTSESS->HOSTFLAGS |= 2; // Indicate State Change - - NewSess->L4CIRCUITTYPE = BPQHOST | DOWNLINK; - - PostStateChange(NewSess); - - NewSess->SESS_APPLFLAGS = HOSTSESS->HOSTAPPLFLAGS; - - NewSess->SESSPACLEN = Paclen; - - return TRUE; - } - } - HOSTSESS++; - } - - *AnySessions = ConfigedPorts; // to distinguish between none and all in use - return FALSE; -} - -VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - BOOL CONFAILED = 0; - UINT CONERROR ; - char APPName[13]; - char * ptr1, *ptr2; - int n = 12; - BOOL Stay = FALSE; - - // Copy Appl and Null Terminate - - ptr1 = &CMD->String[0]; - ptr2 = APPName; - - while (*(ptr1) != ' ' && n--) - *(ptr2++) = *(ptr1++); - - *(ptr2) = 0; - - if (Session->LISTEN) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Can't use %s while listening\r", APPName); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - - if (CmdTail[0] == 'S') - Stay = TRUE; - - Session->STAYFLAG = Stay; - - memcpy(Session->APPL, CMD->String, 12); - - // SEE IF THERE IS AN ALIAS DEFINDED FOR THIS COMMAND - - if (ALIASPTR[0] > ' ') - { - // COPY ALIAS TO COMMAND BUFFER, THEN REENTER COMMAND HANDLER - - int SaveSecure = Session->Secure_Session; - - memcpy(COMMANDBUFFER, ALIASPTR, ALIASLEN); - _strupr(COMMANDBUFFER); - memcpy(OrigCmdBuffer, ALIASPTR, ALIASLEN); // In case original case version needed - - ALIASINVOKED = 1; // To prevent Alias Loops - - // Set secure session for application alias in case telnet outward connect - - Session->Secure_Session = 1; - DoTheCommand(Session); - Session->Secure_Session = SaveSecure; - - return; - } - - if (cATTACHTOBBS(Session, APPLMASK, CMDPACLEN, &CONERROR) == 0) - { - // No Streams - - if (CONERROR) - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, All %s Ports are in use - Please try later\r", APPName); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, Application %s is not running - Please try later\r", APPName); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // IF CMD_TO_APPL SET IN APPLFLAGS, SEND INPUT MSG TO APPL - - if (Session->L4CROSSLINK->SESS_APPLFLAGS & CMD_TO_APPL) - { - struct DATAMESSAGE * Msg = (struct DATAMESSAGE *)GetBuff(); - TRANSPORTENTRY * XSession = Session->L4CROSSLINK; - - if (Msg) - { - COMMANDBUFFER[72] = 13; - memcpy(Msg->L2DATA, COMMANDBUFFER, 73); - Msg->LENGTH = 73 + 4 + sizeof(void *); - Msg->PID = 0xf0; - - C_Q_ADD(&XSession->L4TX_Q, (UINT *)Msg); - PostDataAvailable(XSession); - } - } - - if (Stay) - Session->L4CROSSLINK->L4TARGET.HOST->HOSTFLAGS |= 0x20; - - // IF MSG_TO_USER SET, SEND 'CONNECTED' MESSAGE TO USER - - Session->SESS_APPLFLAGS = Session->L4CROSSLINK->SESS_APPLFLAGS; - - if (Session->L4CROSSLINK->SESS_APPLFLAGS & MSG_TO_USER) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Connected to %s\r", APPName); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - - // DONT NEED BUFFER ANY MORE - - ReleaseBuffer((UINT *)REPLYBUFFER); - return; -} - - -VOID CMDI00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", INFOMSG); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID CMDV00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - if (sizeof(void *) == 4) - Bufferptr = Cmdprintf(Session, Bufferptr, "Version %s\r", VersionString); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Version %s (64 bit)\r", VersionString); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID BYECMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - CLOSECURRENTSESSION(Session); // Kills any crosslink, plus local link - ReleaseBuffer((UINT *)REPLYBUFFER); - return; -} - -VOID CMDPAC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // SET PACLEN FOR THIS SESSION - - char * ptr, *Context; - int newvalue; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr && ptr[0]) - { - // Get new value - - newvalue = atoi(ptr); - if (newvalue > 29 && newvalue < 256) - Session->SESSPACLEN = newvalue & 0xff; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "PACLEN - %d\r", Session->SESSPACLEN); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID CMDIDLE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // SET IDLETIME FOR THIS SESSION - - char * ptr, *Context; - int newvalue; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr && ptr[0]) - { - // Get new value - - newvalue = atoi(ptr); - if (newvalue > 59 && newvalue < 901) - Session->L4LIMIT = newvalue; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "IDLETIME - %d\r", Session->L4LIMIT); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - -} -VOID CMDT00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // SET L4 TIMEOUT FOR CONNECTS ON THIS SESSION - - char * ptr, *Context; - int newvalue; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr && ptr[0]) - { - // Get new value - - newvalue = atoi(ptr); - if (newvalue > 20) - Session->SESSIONT1 = newvalue; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "L4TIMEOUT - %d\r", Session->SESSIONT1); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -UCHAR PWLen; -char PWTEXT[80]; - -VOID PWDCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char * ptr, *Context; - USHORT pwsum = 0; - int n = 5, p1, p2, p3, p4, p5; - - if (Session->Secure_Session) // HOST - SET AUTHORISED REGARDLESS - { - Session->PASSWORD = 0xFFFF; // SET AUTHORISED - Session->Secure_Session = 1; - strcpy(Bufferptr, OKMSG); - Bufferptr += (int)strlen(OKMSG); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr && ptr[0]) - { - // Check Password - - n = 5; - - while (n--) - pwsum += *(ptr++); - - if (Session->PASSWORD == pwsum) - { - Session->PASSWORD = 0xFFFF; // SET AUTHORISED - Session->Secure_Session = 1; - strcpy(Bufferptr, OKMSG); - Bufferptr += (int)strlen(OKMSG); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - ReleaseBuffer((UINT *)REPLYBUFFER); - return; - } - - // SEND PASSWORD PROMPT - - if (PWLen == 0) - PWLen = 1; - - p1 = rand() % PWLen; - pwsum += PWTEXT[p1++]; - - p2 = rand() % PWLen; - pwsum += PWTEXT[p2++]; - - p3 = rand() % PWLen; - pwsum += PWTEXT[p3++]; - - p4 = rand() % PWLen; - pwsum += PWTEXT[p4++]; - - p5 = rand() % PWLen; - pwsum += PWTEXT[p5++]; - - Session->PASSWORD = pwsum; - - Bufferptr = Cmdprintf(Session, Bufferptr, "%d %d %d %d %d\r", p1, p2, p3, p4, p5); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - -VOID CMDSTATS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char * ptr, *Context; - int Port = 0, cols = NUMBEROFPORTS, i; - char * uptime; - struct PORTCONTROL * PORT = PORTTABLE; - struct PORTCONTROL * STARTPORT; - - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - // SEE IF ANY PARAM - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr && ptr[0]) - Port = atoi(ptr); - - // IF ASKING FOR PORT STATS, DONT DO SYSTEM ONES - - if (Port == 0) - { - uptime = FormatUptime(STATSTIME); - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", uptime); - - Bufferptr = Cmdprintf(Session, Bufferptr, "Semaphore Get-Rel/Clashes %9d%9d\r", - Semaphore.Gets - Semaphore.Rels, Semaphore.Clashes); - - Bufferptr = Cmdprintf(Session, Bufferptr, "Buffers:Max/Cur/Min/Out/Wait%9d%9d%9d%9d%9d\r", - MAXBUFFS, QCOUNT, MINBUFFCOUNT, NOBUFFCOUNT, BUFFERWAITS); - - Bufferptr = Cmdprintf(Session, Bufferptr, "Known Nodes/Max Nodes %9d%9d\r", - NUMBEROFNODES, MAXDESTS); - - Bufferptr = Cmdprintf(Session, Bufferptr, "L4 Connects Sent/Rxed %9d%9d\r", - L4CONNECTSOUT, L4CONNECTSIN); - - Bufferptr = Cmdprintf(Session, Bufferptr, "L4 Frames TX/RX/Resent/Reseq%9d%9d%9d%9d\r", - L4FRAMESTX, L4FRAMESRX, L4FRAMESRETRIED, OLDFRAMES); - - Bufferptr = Cmdprintf(Session, Bufferptr, "L3 Frames Relayed %9d\r", L3FRAMES); - - if (ptr && ptr[0] == 'S') - { - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - } - - // POSITION TO REQUESTED PORT - - if (Port) - { - while (PORT && PORT->PORTNUMBER != Port) - { - PORT = PORT->PORTPOINTER; - cols--; - } - } - - if (PORT == NULL) // REQUESTED PORT NOT FOUND - { - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - STARTPORT = PORT; - - if (cols > 7) - cols = 7; - - Bufferptr = Cmdprintf(Session, Bufferptr, " "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Port %02d ", PORT->PORTNUMBER); - PORT = PORT->PORTPOINTER; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Frames Digied"); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2DIGIED); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Frames Heard "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2FRAMES); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Frames Rxed "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2FRAMESFORUS); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Frames Sent "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2FRAMESSENT); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Timeouts "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2TIMEOUTS); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "REJ Frames Rxed "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2REJCOUNT); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "RX out of Seq "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2OUTOFSEQ); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Resequenced "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2RESEQ); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "Undrun/Poll T/o "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2URUNC); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "RX Overruns "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2ORUNC); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "RX CRC Errors "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->RXERRORS); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "FRMRs Sent "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2FRMRTX); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "FRMRs Received "); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2FRMRRX); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; - Bufferptr = Cmdprintf(Session, Bufferptr, "Frames abandoned"); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L1DISCARD); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - PORT = STARTPORT; -// Bufferptr = Cmdprintf(Session, Bufferptr, "Link Active %% "); - Bufferptr = Cmdprintf(Session, Bufferptr, "Active(TX/Busy) %%"); - - for (i = 0; i < cols; i++) - { - Bufferptr = Cmdprintf(Session, Bufferptr, " %2d %3d ", PORT->AVSENDING, PORT->AVACTIVE); - PORT = PORT->PORTPOINTER; - } - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID CMDL00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // PROCESS 'LINKS' MESSAGE - - struct _LINKTABLE * LINK = LINKS; - int n = MAXLINKS; - int len; - char Normcall[11] = ""; - - Bufferptr = Cmdprintf(Session, Bufferptr, "Links\r"); - - while (n--) - { - if (LINK->LINKCALL[0]) - { - len = ConvFromAX25(LINK->LINKCALL, Normcall); - - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", Normcall); - - len = ConvFromAX25(LINK->OURCALL, Normcall); - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", Normcall); - - if (LINK->Ver2point2) - Bufferptr = Cmdprintf(Session, Bufferptr, " S=%d P=%d T=%d V=2.2\r", - LINK->L2STATE, LINK->LINKPORT->PORTNUMBER, LINK->LINKTYPE); - else - Bufferptr = Cmdprintf(Session, Bufferptr, " S=%d P=%d T=%d V=%d\r", - LINK->L2STATE, LINK->LINKPORT->PORTNUMBER, LINK->LINKTYPE, 2 - LINK->VER1FLAG); - } - LINK++; - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - - -VOID CMDS00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // PROCESS 'USERS' - - int n = MAXCIRCUITS; - TRANSPORTENTRY * L4 = L4TABLE; - TRANSPORTENTRY * Partner; - int MaxLinks = MAXLINKS; - char State[12] = "", Type[12] = "Uplink"; - char LHS[50] = "", MID[10] = "", RHS[50] = ""; - char Line[100]; - - Bufferptr = Cmdprintf(Session, Bufferptr, "%s%d)\r", SESSIONHDDR, QCOUNT); - - while (n--) - { - if (L4->L4USER[0]) - { - RHS[0] = MID[0] = 0; - - if ((L4->L4CIRCUITTYPE & UPLINK) == 0) //SHORT CMDS10A ; YES - { - // IF DOWNLINK, ONLY DISPLAY IF NO CROSSLINK - - if (L4->L4CROSSLINK == 0) //jne CMDS60 ; WILL PROCESS FROM OTHER END - { - // ITS A DOWNLINK WITH NO PARTNER - MUST BE A CLOSING SESSION - // DISPLAY TO THE RIGHT FOR NOW - - strcpy(LHS, "(Closing) "); - DISPLAYCIRCUIT(L4, RHS); - goto CMDS50; - } - else - goto CMDS60; // WILL PROCESS FROM OTHER END - } - - if (L4->L4CROSSLINK == 0) - { - // Single Entry - - DISPLAYCIRCUIT(L4, LHS); - } - else - { - DISPLAYCIRCUIT(L4, LHS); - - Partner = L4->L4CROSSLINK; - - if (Partner->L4STATE == 5) - strcpy(MID, "<-->"); - else - strcpy(MID, "<~~>"); - - DISPLAYCIRCUIT(Partner, RHS); - } -CMDS50: - memset(Line, 32, 100); - memcpy(Line, LHS, (int)strlen(LHS)); - memcpy(&Line[35], MID, (int)strlen(MID)); - strcpy(&Line[40], RHS); - strcat(&Line[40], "\r"); - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", Line); - } -CMDS60: - L4++; - } - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -extern int MasterPort[MAXBPQPORTS+1]; // Pointer to first BPQ port for a specific MPSK or UZ7HO host - -VOID CMDP00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // Process PORTS Message - - // If extended show state of TNC (Open, Active, etc) - - struct PORTCONTROL * PORT = PORTTABLE; - char Extended = CmdTail[0]; - struct PORTCONTROL * SAVEPORT; - - Bufferptr = Cmdprintf(Session, Bufferptr, "Ports\r"); - - while (PORT) - { - char Status[32] = "???????"; - int Portno = PORT->PORTNUMBER; - - if (PORT->Hide) - { - PORT = PORT->PORTPOINTER; - continue; - } - - if (Extended != 'E') - { - Bufferptr = Cmdprintf(Session, Bufferptr, " %2d %s\r", PORT->PORTNUMBER, PORT->PORTDESCRIPTION); - - PORT = PORT->PORTPOINTER; - continue; - } - - // Try to get port status - may not be possible with some - - if (PORT->PortStopped) - { - strcpy(Status, "Stopped"); - Bufferptr = Cmdprintf(Session, Bufferptr, " %2d %-7s %s\r", PORT->PORTNUMBER, Status, PORT->PORTDESCRIPTION); - - PORT = PORT->PORTPOINTER; - continue; - } - - if (PORT->PORTTYPE == 0) - { - struct KISSINFO * KISS = (struct KISSINFO *)PORT; - NPASYINFO Port; - - SAVEPORT = PORT; - - if (KISS->FIRSTPORT && KISS->FIRSTPORT != KISS) - { - // Not first port on device - - PORT = (struct PORTCONTROL *)KISS->FIRSTPORT; - Port = KISSInfo[Portno]; - } - - Port = KISSInfo[PORT->PORTNUMBER]; - - if (Port) - { - // KISS like - see if connected - - if (PORT->PORTIPADDR.s_addr || PORT->KISSSLAVE) - { - // KISS over UDP or TCP - - if (PORT->KISSTCP) - { - if (Port->Connected) - strcpy(Status, "Open "); - else - if (PORT->KISSSLAVE) - strcpy(Status, "Listen"); - else - strcpy(Status, "Closed"); - } - else - strcpy(Status, "UDP"); - } - else - if (Port->idComDev) // Serial port Open - strcpy(Status, "Open "); - else - strcpy(Status, "Closed"); - - PORT = SAVEPORT; - } - } - else if (PORT->PORTTYPE == 14) // Loopback - strcpy(Status, "Open "); - - else if (PORT->PORTTYPE == 16) // External - { - if (PORT->PROTOCOL == 10) // 'HF' Port - { - struct TNCINFO * TNC = TNCInfo[Portno]; - - if (TNC == NULL) - { - PORT = PORT->PORTPOINTER; - continue; - } - - switch (TNC->Hardware) // Hardware Type - { - case H_SCS: - case H_KAM: - case H_AEA: - case H_HAL: - case H_TRK: - case H_SERIAL: - - // Serial - - if (TNC->hDevice) - strcpy(Status, "Open "); - else - strcpy(Status, "Closed"); - - break; - - case H_UZ7HO: - - if (TNCInfo[MasterPort[Portno]]->CONNECTED) - strcpy(Status, "Open "); - else - strcpy(Status, "Closed"); - - break; - - case H_WINMOR: - case H_V4: - - case H_MPSK: - case H_FLDIGI: - case H_UIARQ: - case H_ARDOP: - case H_VARA: - case H_KISSHF: - case H_WINRPR: - case H_FREEDATA: - - // TCP - - if (TNC->CONNECTED) - { - if (TNC->Streams[0].Attached) - strcpy(Status, "In Use"); - else - strcpy(Status, "Open "); - } - else - strcpy(Status, "Closed"); - - break; - - case H_TELNET: - - strcpy(Status, "Open "); - } - } - else - { - // External but not HF - AXIP, BPQETHER VKISS, ?? - - struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)PORT; - - strcpy(Status, "Open "); - } - } - - Bufferptr = Cmdprintf(Session, Bufferptr, " %2d %-7s %s\r", PORT->PORTNUMBER, Status, PORT->PORTDESCRIPTION); - - PORT = PORT->PORTPOINTER; - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -char * DisplayRoute(TRANSPORTENTRY * Session, char * Bufferptr, struct ROUTE * Routes, char Verbose) -{ - char Normcall[10]; - char locked[] = " ! "; - int NodeCount; - int Percent = 0; - char PercentString[20]; - int Iframes, Retries; - char Active[10]; - int Queued; - - int Port = 0; - - int len = ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall); - - Normcall[9]=0; - - if ((Routes->NEIGHBOUR_FLAG & 1) == 1) - strcpy(locked, "!"); - else - strcpy(locked, " "); - - NodeCount = COUNTNODES(Routes); - - if (Routes->NEIGHBOUR_LINK && Routes->NEIGHBOUR_LINK->L2STATE >= 5) - strcpy(Active, ">"); - else - strcpy(Active, " "); - - if (Verbose) - { - if (Routes->NEIGHBOUR_LINK) - Queued = COUNT_AT_L2(Routes->NEIGHBOUR_LINK); // SEE HOW MANY QUEUED - else - Queued = 0; - - Iframes = Routes->NBOUR_IFRAMES; - Retries = Routes->NBOUR_RETRIES; - - if (Iframes) - { - Percent = (Retries * 100) / Iframes; - sprintf(PercentString, "%3d%%", Percent); - } - else - strcpy(PercentString, " "); - - - Bufferptr = Cmdprintf(Session, Bufferptr, "%s%2d %s %3d %3d%s%4d %4d %s %d %d %02d:%02d %d %d", - Active, Routes->NEIGHBOUR_PORT, Normcall, - Routes->NEIGHBOUR_QUAL, NodeCount, locked, Iframes, Retries, PercentString, Routes->NBOUR_MAXFRAME, Routes->NBOUR_FRACK, - Routes->NEIGHBOUR_TIME >> 8, (Routes->NEIGHBOUR_TIME) & 0xff, Queued, Routes->OtherendsRouteQual); - - // IF INP3 DISPLAY SRTT - - if (Routes->INP3Node) // INP3 Enabled? - { - double srtt = Routes->SRTT/1000.0; - double nsrtt = Routes->NeighbourSRTT/1000.0; - - Bufferptr = Cmdprintf(Session, Bufferptr, " %4.2fs %4.2fs", srtt, nsrtt); - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - } - else - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%s %d %s %d %d%s\r", - Active, Routes->NEIGHBOUR_PORT, Normcall, Routes->NEIGHBOUR_QUAL, NodeCount, locked); - } - - return Bufferptr; -} - - -VOID CMDR00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - struct ROUTE * Routes = NEIGHBOURS; - int MaxRoutes = MAXNEIGHBOURS; - char locked[] = " ! "; - int Percent = 0; - char * ptr, * Context; - char Verbose = 0; - int Port = 0; - char AXCALL[7]; - BOOL Found; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr && (int)strlen(ptr) > 1) - { - // Route Update - - goto ROUTEUPDATE; - } - - if (ptr) - { - Verbose = ptr[0]; - ptr = strtok_s(NULL, " ", &Context); - if (ptr) - Port = atoi(ptr); - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "Routes\r"); - - while (MaxRoutes--) - { - if (Routes->NEIGHBOUR_CALL[0] != 0) - if (Port == 0 || Port == Routes->NEIGHBOUR_PORT) - Bufferptr = DisplayRoute(Session, Bufferptr, Routes, Verbose); - - Routes++; - } - goto SendReply; - -ROUTEUPDATE: - - if (Session->PASSWORD != 0xFFFF) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", PASSWORDMSG); - goto SendReply; - } - - // Line is - - // ROUTES G8BPQ-2 2 100 - Set quality to 100 - // ROUTES G8BPQ-2 2 ! - Toggle 'Locked Route' flag - // ROUTES G8BPQ-2 2 100 ! - Set quality and toggle 'locked' flag - - - ConvToAX25(ptr, AXCALL); - - ptr = strtok_s(NULL, " ", &Context); - - if (ptr) - Port = atoi(ptr); - - if (Port == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Port Number Missing \r"); - goto SendReply; - } - - Found = FindNeighbour(AXCALL, Port, &Routes); - - if (Context && Context[0] > 32) - { - // More Params - - ptr = strtok_s(NULL, " ", &Context); - - if (ptr) - { - // Adding - - memcpy(Routes->NEIGHBOUR_CALL, AXCALL, 7); // In case Add - Routes->NEIGHBOUR_PORT = Port; - Found = TRUE; - } - - if (strcmp(ptr, "!") == 0) - { - // Toggle Lock - - Routes->NEIGHBOUR_FLAG ^= 1; // FLIP LOCKED BIT - goto Displayit; - } - - if (strcmp(ptr, "Z") == 0) - { - // Clear Counts - - Routes->NBOUR_IFRAMES = 0; - Routes->NBOUR_RETRIES = 0; - goto Displayit; - } - - Routes->NEIGHBOUR_QUAL = atoi(ptr); - - if (Context && Context[0] == '!') - { - // Toggle Lock - - Routes->NEIGHBOUR_FLAG ^= 1; // FLIP LOCKED BIT - goto Displayit; - } - } - -Displayit: - - // Just display - - if (Found) - Bufferptr = DisplayRoute(Session, Bufferptr, Routes, 1); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Not Found\r"); - - - -/* MOV ROUTEDISP,1 - - CMP BYTE PTR [ESI],20H - JE SHORT JUSTDISPLAY - - MOV ZAPFLAG,0 - - CMP BYTE PTR [ESI],'Z' - JNE SHORT NOTZAP - - MOV ZAPFLAG,1 - JMP SHORT JUSTDISPLAY - - PUBLIC NOTZAP -NOTZAP: - - MOV ROUTEDISP,2 ; LOCK UPDATE - - CMP BYTE PTR [ESI],'!' - JE SHORT JUSTDISPLAY -; -; LOOK FOR V FOR ADDING A DIGI -; - CMP WORD PTR [ESI],' V' ; V [SPACE] - JE ADDDIGI - - CALL GETVALUE ; GET NUMBER, UP TO SPACE , CR OR OFFH - JC SHORT BADROUTECMD ; INVALID DIGITS - - MOV NEWROUTEVAL,AL - - MOV ROUTEDISP,0 - - CALL SCAN ; SEE IF ! - MOV AH,[ESI] - - - PUBLIC JUSTDISPLAY -JUSTDISPLAY: - - - MOV ESI,OFFSET32 AX25CALL - CALL _FINDNEIGHBOUR - JZ SHORT FOUNDROUTE ; IN LIST - OK - - CMP EBX,0 - JE SHORT BADROUTECMD ; TABLE FULL?? - - MOV ECX,7 - MOV EDI,EBX - REP MOVSB ; PUT IN CALL - - MOV AL,SAVEPORT - MOV NEIGHBOUR_PORT[EBX],AL - - JMP SHORT FOUNDROUTE - - - PUBLIC BADROUTECMD -BADROUTECMD: - - POP EDI - - JMP PBADVALUE - - PUBLIC FOUNDROUTE -FOUNDROUTE: - - CMP ZAPFLAG,1 - JNE SHORT NOTCLEARCOUNTS - - XOR AX,AX - MOV ES:WORD PTR NBOUR_IFRAMES[EDI],AX - MOV ES:WORD PTR NBOUR_IFRAMES+2[EDI],AX - MOV ES:WORD PTR NBOUR_RETRIES[EDI],AX - MOV ES:WORD PTR NBOUR_RETRIES+2[EDI],AX - - JMP SHORT NOUPDATE - - PUBLIC NOTCLEARCOUNTS -NOTCLEARCOUNTS: - - CMP ROUTEDISP,1 - JE SHORT NOUPDATE - - CMP ROUTEDISP,2 - JE SHORT LOCKUPDATE - - MOV AL,NEWROUTEVAL - MOV NEIGHBOUR_QUAL[EBX],AL - - CMP AH,'!' - JNE SHORT NOUPDATE - - PUBLIC LOCKUPDATE -LOCKUPDATE: - - XOR NEIGHBOUR_FLAG[EBX],1 ; FLIP LOCKED BIT - - PUBLIC NOUPDATE -NOUPDATE: - - MOV ESI,EBX - POP EDI - - POP EBX - CALL DISPLAYROUTE - - JMP SENDCOMMANDREPLY - - PUBLIC ADDDIGI -ADDDIGI: - - ADD ESI,2 - PUSH ESI ; SAVE INPUT BUFFER - - MOV ESI,OFFSET32 AX25CALL - CALL _FINDNEIGHBOUR - - POP ESI - - JZ SHORT ADD_FOUND ; IN LIST - OK - - JMP BADROUTECMD - - PUBLIC ADD_FOUND -ADD_FOUND: - - CALL CONVTOAX25 ; GET DIGI CALLSIGN - - PUSH ESI - - MOV ESI,OFFSET32 AX25CALL - LEA EDI,NEIGHBOUR_DIGI[EBX] - MOV ECX,7 - REP MOVSB - - POP ESI ; MSG BUFFER -; -; SEE IF ANOTHER DIGI -; - CMP BYTE PTR [ESI],20H - JE SHORT NOMORE - - CALL CONVTOAX25 ; GET DIGI CALLSIGN - MOV ESI,OFFSET32 AX25CALL - LEA EDI,NEIGHBOUR_DIGI+7[EBX] - MOV ECX,7 - REP MOVSB - - PUBLIC NOMORE -NOMORE: - - JMP NOUPDATE - - - -*/ - -SendReply: - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - - -VOID LISTENCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // PROCESS LISTEN COMMAND - - // for monitoring a remote ax.25 port - - int Port = 0, index =0; - uint64_t ListenMask = 0; - char * ptr, *Context; - struct PORTCONTROL * PORT = NULL; - char ListenPortList[128] = ""; - - ptr = strtok_s(CmdTail, " ,", &Context); - - // Now accepts a list of ports - - if (ptr == 0 || memcmp(ptr, "OFF", 3) == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Listening disabled\r"); - Session->LISTEN = 0; - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - while (ptr) - { - Port = atoi(ptr); - - if (Port == 0 && NUMBEROFPORTS == 1) - Port = 1; - - ptr = strtok_s(NULL, ", ", &Context); // Get port String - - if (Port) - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port %d\r", Port); - continue; - } - - if (PORT->PROTOCOL == 10 && PORT->UICAPABLE == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port %d is not an ax.25 port\r", Port); - continue; - } - - if (PORT->PORTL3FLAG) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port %d is for internode traffic only\r", Port); - continue; - } - - if (Session->L4CIRCUITTYPE == L2LINK + UPLINK) - { - if (Session->L4TARGET.LINK->LINKPORT->PORTNUMBER == Port) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "You can't Listen to the port you are connected on\r"); - continue; - } - } - - sprintf(ListenPortList, "%s %d", ListenPortList, Port); - - ListenMask |= ((uint64_t)1 << (Port - 1)); - } - - Session->LISTEN = ListenMask; - - if (ListenMask) - { - if (CountBits64(ListenMask) == 1) - Bufferptr = Cmdprintf(Session, Bufferptr, "Listening on port%s. Use CQ to send a beacon, LIS to disable\r", ListenPortList); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Listening on ports%s. Use LIS to disable\r", ListenPortList); - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - - -VOID UNPROTOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // PROCESS UNPROTO COMMAND - - int Port = 0, index =0; - char * ptr, *Context; - struct PORTCONTROL * PORT = NULL; - UCHAR axcalls[64]; - BOOL Stay, Spy; - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - Port = atoi(ptr); - - if (Port == 0 && NUMBEROFPORTS == 1) - Port = 1; - else - ptr = strtok_s(NULL, " ", &Context); // Get Unproto String - - if (Port) - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (ptr == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Destination missing\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - ptr[strlen(ptr)] = ' '; // Put param back together - - if (DecodeCallString(ptr, &Stay, &Spy, &axcalls[0]) == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Call\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (PORT->PROTOCOL == 10 && PORT->UICAPABLE == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is not an ax.25 port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (PORT->PORTL3FLAG) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is for internode traffic only\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // Copy Address Info to Session Record - - Session->UNPROTO = Port; - Session->UAddrLen = (int)strlen(axcalls); - memcpy(Session->UADDRESS, axcalls, 63); - - Bufferptr = Cmdprintf(Session, Bufferptr, "Unproto Mode - enter ctrl/z or /ex to exit\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - -VOID CALCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // PROCESS CAL COMMAND - - int Port = 0, index = 0, Count = 0; - char * ptr, *Context; - struct PORTCONTROL * PORT = NULL; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - Port = atoi(ptr); - - if (Port == 0 && NUMBEROFPORTS == 1) - Port = 1; - else - ptr = strtok_s(NULL, " ", &Context); // Get Unproto String - - if (Port) - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (PORT->PROTOCOL == 10 && PORT->UICAPABLE == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is not an ax.25 port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (ptr == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Count Missing\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - Count = atoi(ptr); - - ptr = strtok_s(NULL, " ", &Context); // Get Unproto String - - Bufferptr = Cmdprintf(Session, Bufferptr, "Ok\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - - - -VOID CQCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // Send a CQ Beacon on a radio port. Must be in LISTEN state - - DIGIMESSAGE Msg; - int Port = 0; - int OneBits = 0; - uint64_t MaskCopy = Session->LISTEN; - int Len; - UCHAR CQCALL[7]; - char Empty[] = ""; - char * ptr1 = &OrigCmdBuffer[3]; - UCHAR * axptr = &Msg.DIGIS[0][0]; - char * ptr2, *Context; - - while (MaskCopy) - { - if (MaskCopy & 1) - OneBits++; - - Port++; - MaskCopy = MaskCopy >> 1; - } - - if (OneBits == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "You must enter LISTEN before calling CQ\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (OneBits > 1) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "You can't call CQ if LISTENing on more than one port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - - Len = (int)strlen(OrigCmdBuffer) - 3; - - if (Len < 0) - Len = 0; - - memset(&Msg, 0, sizeof(Msg)); - - Msg.PORT = Port; - Msg.CTL = 3; // UI - - // see if a Via specified - - if (_memicmp(ptr1, "via ", 4) == 0) - { - ptr2 = strtok_s(ptr1 + 4, ",", &Context); - - while (ptr2) - { - if (ConvToAX25(ptr2, axptr) == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid via string\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - axptr += 7; - - if (axptr == &Msg.DIGIS[7][0]) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Too many digis\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - ptr1 = ptr2; - ptr2 = strtok_s(NULL, ",", &Context); - } - - // ptr1 is start of last digi call. We need to position to data - - ptr1 = strchr(ptr1, ' '); - - if (ptr1 == NULL) - ptr1 = Empty; - else - ptr1++ ; // to message - - Len = (int)strlen(ptr1); - - } - - ConvToAX25("CQ", CQCALL); - memcpy(Msg.DEST, CQCALL, 7); - Msg.DEST[6] |= 0x80; // set Command Bit - memcpy(Msg.ORIGIN, Session->L4USER, 7); - Msg.ORIGIN[6] ^= 0x1e; // Flip SSID - Msg.PID = 0xf0; // Data PID - memcpy(&Msg.L2DATA, ptr1, Len); - - Send_AX_Datagram(&Msg, Len + 2, Port); // Len is Payload ie CTL, PID and Data - - Bufferptr = Cmdprintf(Session, Bufferptr, "CQ sent\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - -} - - -TRANSPORTENTRY * SetupNewSession(TRANSPORTENTRY * Session, char * Bufferptr) -{ - TRANSPORTENTRY * NewSess = L4TABLE; - int Index = 0; - - while (Index < MAXCIRCUITS) - { - if (NewSess->L4USER[0] == 0) - { - // Got One - - Session->L4CROSSLINK = NewSess; - NewSess->L4CROSSLINK = Session; - - memcpy(NewSess->L4USER, Session->L4USER, 7); - memcpy(NewSess->L4MYCALL, Session->L4MYCALL, 7); - - - NewSess->CIRCUITINDEX = Index; //OUR INDEX - NewSess->CIRCUITID = NEXTID; - - NEXTID++; - if (NEXTID == 0) - NEXTID++; // kEEP nON-ZERO - - NewSess->SESSIONT1 = Session->SESSIONT1; - NewSess->L4WINDOW = (UCHAR)L4DEFAULTWINDOW; - - return NewSess; - } - Index++; - NewSess++; - } - - if (Bufferptr) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry - System Tables Full\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - } - - return NULL; -} - - -VOID DoNetromConnect(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIST * Dest, BOOL Spy) -{ - TRANSPORTENTRY * NewSess; - - NewSess = SetupNewSession(Session, Bufferptr); - - if (NewSess == NULL) - return; // Tables Full - - NewSess->L4CIRCUITTYPE = SESSION + DOWNLINK; - - NewSess->L4TARGET.DEST = Dest; - NewSess->L4STATE = 2; // CONNECTING - - NewSess->SPYFLAG = Spy; - - ReleaseBuffer((UINT *)REPLYBUFFER); - - SENDL4CONNECT(NewSess); - - L4CONNECTSOUT++; - - return; -} - -BOOL FindLink(UCHAR * LinkCall, UCHAR * OurCall, int Port, struct _LINKTABLE ** REQLINK) -{ - struct _LINKTABLE * LINK = LINKS; - struct _LINKTABLE * FIRSTSPARE = NULL; - int n = MAXLINKS; - - while (n--) - { - if (LINK->LINKCALL[0] == 0) // Spare - { - if (FIRSTSPARE == NULL) - FIRSTSPARE = LINK; - - LINK++; - continue; - } - - if ((LINK->LINKPORT->PORTNUMBER == Port) && CompareCalls(LINK->LINKCALL, LinkCall) && CompareCalls(LINK->OURCALL, OurCall)) - { - *REQLINK = LINK; - return TRUE; - } - - LINK++; - } - // ENTRY NOT FOUND - FIRSTSPARE HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL - - *REQLINK = FIRSTSPARE; - return FALSE; -} - -VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD); - -VOID CMDC00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // PROCESS CONNECT COMMAND - - TRANSPORTENTRY * NewSess; - - int CONNECTPORT, Port; - BOOL CallEvenIfInNodes = FALSE; - char * ptr, *Context; - UCHAR axcalls[64]; - UCHAR ourcall[7]; // Call we are using (may have SSID bits inverted - int ret; - struct PORTCONTROL * PORT = PORTTABLE; - struct _LINKTABLE * LINK; - int CQFLAG = 0; // NOT CQ CALL - BOOL Stay, Spy; - int n; - char TextCall[10]; - int TextCallLen; - char PortString[10]; - char cmdCopy[256]; - struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)PORT; - char toCall[12], fromCall[12]; - -#ifdef EXCLUDEBITS - - if (CheckExcludeList(Session->L4USER) == FALSE) - { - // CONNECTS FROM THIS STATION ARE NOT ALLOWED - - ReleaseBuffer((UINT *)REPLYBUFFER); - return; - } - -#endif - - if (Session->LISTEN) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Can't connect while listening\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - CONNECTPORT = 0; // NO PORT SPECIFIED - - ptr = strtok_s(CmdTail, " ", &Context); - - strcpy(cmdCopy, Context); // Save in case Telnet Connect - - if (ptr == 0) - { - // No param - - if (CFLAG) // C Command Disabled ? - { - // Convert to HOST (appl 32) command - - //MOV _CMDPTR,OFFSET32 _HOSTCMD - //MOV _ALIASPTR,OFFSET32 _HOSTCMD + 32 * 31 - - //MOV _APPLMASK, 80000000H ; Internal Term - - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Call\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - Port = atoi(ptr); - - if (Port) - { - // IF THERE IS NOTHING FOLLOWING THE NUMBER, ASSUME IT IS A - // NUMERIC ALIAS INSTEAD OF A PORT - - sprintf(PortString, "%d", Port); - - if (strlen(PortString) < (int)strlen(ptr)) - goto NoPort; - - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - EXTPORT = (struct _EXTPORTDATA *)PORT; - - ptr = strtok_s(NULL, " ", &Context); - - if (ptr == 0) - { - // No param - - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Call\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - CONNECTPORT = Port; - - if (strcmp(ptr, "CMS") == 0 || strcmp(ptr, "HOST") == 0) // In case someeone has CMS or HOST as an alias - goto Downlink; - - } - -NoPort: - - ptr[strlen(ptr)] = ' '; // Put param back together - - if (ptr[0] == '!') - { - CallEvenIfInNodes = TRUE; - ptr++; - } - - if (memcmp(ptr, "RELAY ", 5) == 0 || memcmp(ptr, "SYNC ", 5) == 0) - { - // c p relay with extra parms - - goto Downlink; - } - - // Skip call validation if using a ptc to allow 1:call, 2:call format - - if (Port && PORT->PROTOCOL == 10 && memcmp(EXTPORT->PORT_DLL_NAME, "SCSPACTOR", 9) == 0) - { - char * p; - - if (p = strstr(cmdCopy, " S ")) - { - Stay = TRUE; - p++; - *p = ' '; - } - - if (p = strstr(cmdCopy, " Z ")) - { - Spy = TRUE; - p++; - *p = ' '; - } - - goto Downlink; - } - else - { - if (DecodeCallString(ptr, &Stay, &Spy, &axcalls[0]) == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Call\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - } - - Session->STAYFLAG = Stay; - - TextCallLen = ConvFromAX25(axcalls, TextCall); - - if (CallEvenIfInNodes) - goto Downlink; - - // SEE IF CALL TO ANY OF OUR HOST SESSIONS - UNLESS DIGIS SPECIFIED - - if (axcalls[7] == 0) - { - // If this connect is as a result of a command alias, don't check appls or we will loop - - if (ALIASINVOKED == 0) - { - APPLCALLS * APPL = APPLCALLTABLE; - int n = NumberofAppls; - APPLMASK = 1; - - while (n--) - { - if (memcmp(axcalls, APPL->APPLALIAS, 6) == 0 || CompareCalls(axcalls, APPL->APPLCALL)) - { - // Call to an appl - - // Convert to an APPL command, so any alias is actioned - - // SEE IF THERE IS AN ALIAS DEFINDED FOR THIS COMMAND - - if (APPL->APPLHASALIAS && APPL->APPLALIASVAL[0] != 0x20) - { - // COPY ALIAS TO COMMAND _BUFFER, THEN REENTER COMMAND HANDLER - - memcpy(COMMANDBUFFER, APPL->APPLALIASVAL, ALIASLEN); - COMMANDBUFFER[80] = 0; - _strupr(COMMANDBUFFER); - memcpy(OrigCmdBuffer, APPL->APPLALIASVAL, ALIASLEN); // In case original case version needed - - ALIASINVOKED = TRUE; // To prevent Alias Loops - } - else - { - - // Copy Appl Command to Command Buffer. Ensure doesn't contain old command - - memset(COMMANDBUFFER, ' ', 72); - memcpy(COMMANDBUFFER, APPL->APPLCMD, 12); - } - DoTheCommand(Session); - return; - } - APPL++; - APPLMASK <<= 1; - } - } - } - - if (axcalls[7] == 0) - { - // SEE IF CALL TO ANOTHER NODE - - struct DEST_LIST * Dest = DESTS; - int n = MAXDESTS; - - if (axcalls[6] == 0x60) // if SSID, dont check aliases - { - while (n--) - { - if (memcmp(Dest->DEST_ALIAS, TextCall, 6) == 0) - { - DoNetromConnect(Session, Bufferptr, Dest, Spy); - return; - } - Dest++; - } - } - - Dest = DESTS; - n = MAXDESTS; - - while (n--) - { - if (CompareCalls(Dest->DEST_CALL, axcalls)) - { - DoNetromConnect(Session, Bufferptr, Dest, Spy); - return; - } - Dest++; - } - } - - // Must be Downlink Connect - -Downlink: - - if (CONNECTPORT == 0 && NUMBEROFPORTS > 1) - { - // 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; - } - - // ENSURE PORT IS AVAILABLE FOR L2 USE - - if (PORT->PROTOCOL >= 10) // Pactor=-style port? - { - int count; - - // if Via PACTOR ARDOP WINMOR or VARA, convert to attach and call = Digi's are in AX25STRING (+7) - - if (memcmp(&axcalls[7], &WINMOR[0], 6) == 0 || - memcmp(&axcalls[7], &ARDOP[0], 6) == 0 || - memcmp(&axcalls[7], &VARA[0], 6) == 0 || - memcmp(&axcalls[7], &PACTORCALL[0], 6) == 0) - { - char newcmd[80]; - - TextCall[TextCallLen] = 0; - sprintf(newcmd, "%s %s", CmdTail, TextCall); - - ATTACHCMD(Session, Bufferptr, newcmd, NULL); - return; - } - - // If on a KAM or SCS with ax.25 on port 2, do an Attach command, then pass on connect - - if (EXTPORT->MAXHOSTMODESESSIONS <= 1) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is not an ax.25 port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // Only Allow Attach VHF from Secure Applications or if PERMITGATEWAY is set - - if (EXTPORT->PERMITGATEWAY == 0 && Session->Secure_Session == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, you are not allowed to use this port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - count = EXTPORT->MAXHOSTMODESESSIONS; - count--; // First is Pactor Stream, count is now last ax.25 session - - while (count) - { - if (EXTPORT->ATTACHEDSESSIONS[count] == 0) - { - int Paclen, PortPaclen; - struct DATAMESSAGE * Buffer; - struct DATAMESSAGE Message = {0}; - char Callstring[80]; - int len; - - // Found a free one - use it - - // See if TNC is OK - - Message.PORT = count; - - ret = PORT->PORTTXCHECKCODE(PORT, Message.PORT); - - if ((ret & 0xff00) == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - TNC Not Ready\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // GET CIRCUIT TABLE ENTRY FOR OTHER END OF LINK - - NewSess = SetupNewSession(Session, Bufferptr); - if (NewSess == NULL) - return; - - // if a UZ7HO port, and the uplink is L2 or Uz7HO invert SSID bits - - // We only get here if multisession - - if (memcmp(EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0) - goto noFlip; - - if ((Session->L4CIRCUITTYPE & BPQHOST))// host - goto noFlip; - - if ((Session->L4CIRCUITTYPE & PACTOR)) - { - // incoming is Pactorlike - see if UZ7HO - - if (memcmp(Session->L4TARGET.EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0) - goto noFlip; - else - NewSess->L4USER[6] ^= 0x1e; // UZ7HO Uplink - flip - } - else - - // Must be L2 uplink - flip - - NewSess->L4USER[6] ^= 0x1e; // Flip SSID -noFlip: - EXTPORT->ATTACHEDSESSIONS[count] = NewSess; - - NewSess->KAMSESSION = count; - - // Set paclen to lower of incoming and outgoing - - Paclen = Session->SESSPACLEN; // Incoming PACLEN - - if (Paclen == 0) - Paclen = 256; // 0 = 256 - - PortPaclen = PORT->PORTPACLEN; - - if (PortPaclen == 0) - PortPaclen = 256; // 0 = 256 - - if (PortPaclen < Paclen) - Paclen = PortPaclen; - - NewSess->SESSPACLEN = Paclen; - Session->SESSPACLEN = Paclen; - - NewSess->L4STATE = 5; - NewSess->L4CIRCUITTYPE = DOWNLINK + PACTOR; - NewSess->L4TARGET.PORT = PORT; - - // Send the connect command to the TNC - - Buffer = REPLYBUFFER; - - Buffer->PORT = count; - Buffer->PID = 0xf0; - - // if on Telnet Port convert use original cmd tail - - // Why just on telnet - what not all ports?? - - if (memcmp(EXTPORT->PORT_DLL_NAME, "TELNET", 6) == 0 || memcmp(EXTPORT->PORT_DLL_NAME, "SCSPACTOR", 9) == 0) - { - NewSess->Secure_Session = Session->Secure_Session; - len = sprintf(Callstring,"C %s", cmdCopy); - } - else - { - TextCall[TextCallLen] = 0; - - len = sprintf(Callstring,"C %s", TextCall); - - if (axcalls[7]) - { - int digi = 7; - - // we have digis - - len += sprintf(&Callstring[len], " via"); - - while (axcalls[digi]) - { - TextCall[ConvFromAX25(&axcalls[digi], TextCall)] = 0; - len += sprintf(&Callstring[len], " %s", TextCall); - digi += 7; - } - } - } - Callstring[len++] = 13; - Callstring[len] = 0; - - Buffer->LENGTH = len + MSGHDDRLEN + 1; - memcpy(Buffer->L2DATA, Callstring, len); - C_Q_ADD(&PORT->PORTTX_Q, (UINT *)Buffer); - - return; - } - count--; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - No free streams on this port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if ((Session->L4CIRCUITTYPE & BPQHOST) == 0 && PORT->PORTL3FLAG) - { - //Port only for L3 - - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is for internode traffic only\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (PORT->PortUIONLY) - { - //Port only for UI - - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is for UI traffic only\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - ret = CheckKissInterlock(PORT, TRUE); - - if (ret) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, Interlocked port %d is in use\r", ret); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - - if (Session->L4USER[6] == 0x42 || Session->L4USER[6] == 0x44) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry - Can't make ax.25 calls with SSID of T or R\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // Get Session Entry for Downlink - - NewSess = SetupNewSession(Session, Bufferptr); - if (NewSess == NULL) - return; - - NewSess->L4CIRCUITTYPE = L2LINK + DOWNLINK; - - // FORMAT LINK TABLE ENTRY FOR THIS CONNECTION - - memcpy(ourcall, NewSess->L4USER, 7); - - // SSID SWAP TEST - LEAVE ALONE FOR HOST or Pactor like (unless UZ7HO) - - if ((Session->L4CIRCUITTYPE & BPQHOST))// host - goto noFlip3; - - if ((Session->L4CIRCUITTYPE & PACTOR)) - { - // incoming is Pactorlike - see if UZ7HO - - if (memcmp(Session->L4TARGET.EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0) - goto noFlip3; - - if (Session->L4TARGET.EXTPORT->MAXHOSTMODESESSIONS < 2) // Not multisession - goto noFlip3; - - ourcall[6] ^= 0x1e; // UZ7HO Uplink - flip - } - else - - // Must be L2 uplink - flip - - ourcall[6] ^= 0x1e; // Flip SSID - -noFlip3: - - // SET UP NEW SESSION (OR RESET EXISTING ONE) - - FindLink(axcalls, ourcall, Port, &LINK); - - if (LINK == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry - System Tables Full\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - - // Should release NewSess - - return; - } - - memcpy(LINK->LINKCALL, axcalls, 7); - memcpy(LINK->OURCALL, ourcall, 7); - - LINK->LINKPORT = PORT; - - LINK->L2TIME = PORT->PORTT1; - - // Copy Digis - - n = 7; - ptr = &LINK->DIGIS[0]; - - while (axcalls[n]) - { - memcpy(ptr, &axcalls[n], 7); - n += 7; - ptr += 7; - - LINK->L2TIME += 2 * PORT->PORTT1; // ADJUST TIMER VALUE FOR 1 DIGI - } - - LINK->LINKTYPE = 2; // DOWNLINK - LINK->LINKWINDOW = PORT->PORTWINDOW; - - RESET2(LINK); // RESET ALL FLAGS - - toCall[ConvFromAX25(LINK->LINKCALL, toCall)] = 0; - fromCall[ConvFromAX25(LINK->OURCALL, fromCall)] = 0; - - hookL2SessionAttempt(CONNECTPORT, fromCall, toCall, LINK); - - - if (CMD->String[0] == 'N' && SUPPORT2point2) - LINK->L2STATE = 1; // New (2.2) send XID - else - LINK->L2STATE = 2; // Send SABM - - LINK->CIRCUITPOINTER = NewSess; - - NewSess->L4TARGET.LINK = LINK; - - if (PORT->PORTPACLEN) - NewSess->SESSPACLEN = Session->SESSPACLEN = PORT->PORTPACLEN; - - if (CQFLAG == 0) // if a CQ CALL DONT SEND SABM - { - seeifInterlockneeded(PORT); - - if (LINK->L2STATE == 1) - L2SENDXID(LINK); - else - SENDSABM(LINK); - } - ReleaseBuffer((UINT *)REPLYBUFFER); - return; -} - -BOOL DecodeCallString(char * Calls, BOOL * Stay, BOOL * Spy, UCHAR * AXCalls) -{ - // CONVERT CALL + OPTIONAL DIGI STRING TO AX25, RETURN - // CONVERTED STRING IN AXCALLS. Return FALSE if invalied - - char * axptr = AXCalls; - char * ptr, *Context; - int CQFLAG = 0; // NOT CQ CALL - int n = 8; // Max digis - - *Stay = 0; - *Spy = 0; - - memset(AXCalls, 0, 64); - - ptr = strtok_s(Calls, " ,", &Context); - - if (ptr == NULL) - return FALSE; - - // First field is Call - - if (ConvToAX25(ptr, axptr) == 0) - return FALSE; - - axptr += 7; - - ptr = strtok_s(NULL, " ,", &Context); - - while (ptr && n--) - { - // NEXT FIELD = COULD BE CALLSIGN, VIA, OR S (FOR STAY) - - if (strcmp(ptr, "S") == 0) - *Stay = TRUE; - else if (strcmp(ptr, "Z") == 0) - *Spy = TRUE; - else if (memcmp(ptr, "VIA", (int)strlen(ptr)) == 0) - { - } //skip via - else - { - // Convert next digi - - if (ConvToAX25(ptr, axptr) == 0) - return FALSE; - - axptr += 7; - } - - ptr = strtok_s(NULL, " ,", &Context); - } - - return TRUE; -} - - -VOID LINKCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // PROCESS *** LINKED to CALLSIGN - - char * ptr, *Context; - UCHAR axcall[7]; - int ret; - - if (LINKEDFLAG == 'Y' || // UNCONDITIONAL? - (LINKEDFLAG == 'A' && - ((Session->L4CIRCUITTYPE & BPQHOST) || Session->Secure_Session || Session->PASSWORD == 0xffff))) - { - ptr = strtok_s(CmdTail, " ", &Context); - if (ptr) - ptr = strtok_s(NULL, " ", &Context); - - if (ptr) - { - ret = ConvToAX25Ex(ptr, axcall); - - if (ret) - { - memcpy(Session->L4USER, axcall, 7); - strcpy(Bufferptr, OKMSG); - Bufferptr += (int)strlen(OKMSG); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - } - - strcpy(Bufferptr, BADMSG); - Bufferptr += (int)strlen(BADMSG); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - memcpy(Bufferptr, PASSWORDMSG, LPASSMSG); - Bufferptr += LPASSMSG; - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -int CompareNode(const void *a, const void *b); -int CompareAlias(const void *a, const void *b); - -char * DoOneNode(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIST * Dest) -{ - char Normcall[10]; - char Alias[10]; - struct NR_DEST_ROUTE_ENTRY * NRRoute; - struct DEST_ROUTE_ENTRY * Route; - struct ROUTE * Neighbour; - int i, Active, len; - - Alias[6] = 0; - - memcpy(Alias, Dest->DEST_ALIAS, 6); - strlop(Alias, ' '); - - Normcall[ConvFromAX25(Dest->DEST_CALL, Normcall)] = 0; - - Bufferptr = Cmdprintf(Session, Bufferptr, "Routes to: %s:%s", Alias, Normcall); - - if (Dest->DEST_COUNT) - Bufferptr = Cmdprintf(Session, Bufferptr, " RTT=%4.2f FR=%d %c %.1d\r", - Dest->DEST_RTT /1000.0, Dest->DEST_COUNT, - (Dest->DEST_STATE & 0x40)? 'B':' ', (Dest->DEST_STATE & 63)); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - NRRoute = &Dest->NRROUTE[0]; - - Active = Dest->DEST_ROUTE; - - for (i = 1; i < 4; i++) - { - Neighbour = NRRoute->ROUT_NEIGHBOUR; - - if (Neighbour) - { - len = ConvFromAX25(Neighbour->NEIGHBOUR_CALL, Normcall); - Normcall[len] = 0; - - Bufferptr = Cmdprintf(Session, Bufferptr, "%c %d %d %d %s\r", - (Active == i)?'>':' ',NRRoute->ROUT_QUALITY, NRRoute->ROUT_OBSCOUNT, Neighbour->NEIGHBOUR_PORT, Normcall); - } - NRRoute++; - } - - // DISPLAY INP3 ROUTES - - Route = &Dest->ROUTE[0]; - - Active = Dest->DEST_ROUTE; - - for (i = 1; i < 4; i++) - { - Neighbour = Route->ROUT_NEIGHBOUR; - - if (Neighbour) - { - double srtt = Route->SRTT/1000.0; - - len = ConvFromAX25(Neighbour->NEIGHBOUR_CALL, Normcall); - Normcall[len] = 0; - - Bufferptr = Cmdprintf(Session, Bufferptr, "%c %d %4.2fs %d %s\r", - (Active == i + 3)?'>':' ',Route->Hops, srtt, Neighbour->NEIGHBOUR_PORT, Normcall); - } - Route++; - } - - return Bufferptr; -} - - -int DoViaEntry(struct DEST_LIST * Dest, int n, char * line, int cursor) -{ - char Portcall[10]; - int len; - - if (Dest->NRROUTE[n].ROUT_NEIGHBOUR != 0 && Dest->NRROUTE[n].ROUT_NEIGHBOUR->INP3Node == 0) - { - len=ConvFromAX25(Dest->NRROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Portcall); - Portcall[len]=0; - - len=sprintf(&line[cursor],"%s %d %d ", - Portcall, - Dest->NRROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, - Dest->NRROUTE[n].ROUT_QUALITY); - - cursor+=len; - - if (Dest->NRROUTE[n].ROUT_OBSCOUNT > 127) - { - len=sprintf(&line[cursor],"! "); - cursor+=len; - } - } - return cursor; -} - -int DoINP3ViaEntry(struct DEST_LIST * Dest, int n, char * line, int cursor) -{ - char Portcall[10]; - int len; - double srtt; - - if (Dest->ROUTE[n].ROUT_NEIGHBOUR != 0) - { - srtt = Dest->ROUTE[n].SRTT/1000.0; - - len=ConvFromAX25(Dest->ROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Portcall); - Portcall[len]=0; - - len=sprintf(&line[cursor],"%s %d %d %4.2fs ", - Portcall, - Dest->ROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, - Dest->ROUTE[n].Hops, srtt); - - cursor+=len; - - if (Dest->NRROUTE[n].ROUT_OBSCOUNT > 127) - { - len=sprintf(&line[cursor],"! "); - cursor+=len; - } - } - return cursor; -} - -int WildCmp(char * pattern, char * string) -{ - // Check if string is at end or not. - - if (*pattern == '\0') - return *string == '\0'; - - // Check for single character missing or match - - if (*pattern == '?' || *pattern == *string) - return *string != '\0' && WildCmp(pattern + 1, string + 1); - - if (*pattern == '*') - { - // Check for multiple character missing - - return WildCmp(pattern + 1, string) || (*string != '\0' && WildCmp(pattern, string + 1)); - } - - return 0; -} - -VOID CMDN00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - struct DEST_LIST * Dest = DESTS; - int count = MAXDESTS, i; - char Normcall[10]; - char Alias[10]; - int Width = 4; - int x = 0, n = 0; - struct DEST_LIST * List[1000]; - char Param = 0; - char * ptr, * param2,* Context; - char Nodeline[21]; - char AXCALL[7]; - char * Call; - char * Qualptr; - int Qual; - char line[160]; - int cursor, len; - UCHAR axcall[7]; - int SavedOBSINIT = OBSINIT; - struct ROUTE * ROUTE = NULL; - char Pattern[80] = ""; - char * firststar; - int minqual = 0; - - ptr = strtok_s(CmdTail, " ", &Context); - param2 = strtok_s(NULL, " ", &Context); - - if (ptr) - { - if (strcmp(ptr, "ADD") == 0) - goto NODE_ADD; - - if (strcmp(ptr, "DEL") == 0) - goto NODE_DEL; - - if (strcmp(ptr, "VIA") == 0) - goto NODE_VIA; - } - - if (ptr) - { - // Could be C or a pattern. Accept C pattern or pattern C - - if ((int)strlen(ptr) > 1) - { - strcpy(Pattern, ptr); - if (param2 && param2[0] == 'C') - Param = 'C'; - } - else - { - Param = ptr[0]; - if (param2) - strcpy(Pattern, param2); - } - } - - // Pattern >nnn selects nodes with at least that quality - - if (Pattern[0] == '>') - { - minqual = atoi(&Pattern[1]); - Pattern[0] = 0; - } - - // We need to pick out CALL or CALL* from other patterns (as call use detail display) - - firststar = strchr(Pattern, '*'); - - if ((firststar && *(firststar + 1) != 0)|| strchr(Pattern, '?')) //(* not on end) - - // definitely pattern - - goto DoNodePattern; - - // If it works as CALL*, process, else drop through - - if (Pattern[0]) - { - UCHAR AXCall[8]; - int count; - int paramlen = (int)strlen(ptr); - char parampadded[20]; - int n = 0; - - Alias[8] = 0; - strcpy(parampadded, Pattern); - strcat(parampadded, " "); - - ConvToAX25(Pattern, AXCall); - - // if * on end, list all ssids - - if (firststar) - { - AXCall[6] = 0; - - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - while (AXCall[6] < 32) - { - Dest = DESTS; - - for (count = 0; count < MAXDESTS; count++) - { - if (memcmp(Dest->DEST_ALIAS, parampadded, 6) == 0 || CompareCalls(Dest->DEST_CALL, AXCall)) - { - break; - } - Dest++; - } - - if (count < MAXDESTS) - { - Bufferptr = DoOneNode(Session, Bufferptr, Dest); - n++; - } - - AXCall[6] += 2; - } - - if (n) // Found Some - { - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - Dest = DESTS; // Reset - - // Drop through to try as pattern - } - else - { - // process as just call - - for (count = 0; count < MAXDESTS; count++) - { - if (memcmp(Dest->DEST_ALIAS, parampadded, 6) == 0 || CompareCalls(Dest->DEST_CALL, AXCall)) - { - break; - } - Dest++; - } - - if (count == MAXDESTS) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not found\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - Bufferptr = DoOneNode(Session, Bufferptr, Dest); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - } - -DoNodePattern: - - Bufferptr = Cmdprintf(Session, Bufferptr, "Nodes\r"); - - while (count--) - { - if (Dest->DEST_CALL[0] != 0) - { - if (Dest->NRROUTE->ROUT_QUALITY >= minqual) - if (Param != 'T' || Dest->DEST_COUNT) - List[n++] = Dest; - - if (n > 999) - break; - } - Dest++; - } - - if (Param == 'C') - qsort(List, n, sizeof(void *), CompareNode); - else - qsort(List, n, sizeof(void *), CompareAlias); - - - for (i = 0; i < n; i++) - { - int len = ConvFromAX25(List[i]->DEST_CALL, Normcall); - Normcall[len]=0; - - memcpy(Alias, List[i]->DEST_ALIAS, 6); - Alias[6] = 0; - strlop(Alias, ' '); - - if (strlen(Alias)) - strcat(Alias, ":"); - - if (Alias[0] == '#' && HIDENODES == 1 && Param != '*') // Hidden Node and not N * command - continue; - - if (Pattern[0]) - if (!WildCmp(Pattern, Normcall) && !WildCmp(Pattern, Alias)) - continue; - - if (Param == 'T') - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%s%s RTT=%4.2f Frames = %d %c %.1d\r", - Alias, Normcall, List[i]->DEST_RTT /1000.0, List[i]->DEST_COUNT, - (List[i]->DEST_STATE & 0x40)? 'B':' ', (List[i]->DEST_STATE & 63)); - } - else - { - len = sprintf(Nodeline, "%s%s", Alias, Normcall); - memset(&Nodeline[len], ' ', 20 - len); - Nodeline[20] = 0; - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", Nodeline); - - if (++x == Width) - { - x = 0; - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - } - } - } - - if (x) - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - goto SendReply; - - -NODE_VIA: - - // List Nodes reachable via a neighbour - - ptr = param2; - - if (ptr == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Missing Call\r"); - goto SendReply; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - ConvToAX25(ptr, AXCALL); - - Dest = DESTS; - - Dest-=1; - - for (count=0; countNRROUTE[0].ROUT_NEIGHBOUR == 0 && Dest->ROUTE[0].ROUT_NEIGHBOUR == 0) - continue; - - - if ((Dest->NRROUTE[0].ROUT_NEIGHBOUR && CompareCalls(Dest->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL)) - || (Dest->NRROUTE[1].ROUT_NEIGHBOUR && CompareCalls(Dest->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL)) - || (Dest->NRROUTE[2].ROUT_NEIGHBOUR && CompareCalls(Dest->NRROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL)) - - || (Dest->ROUTE[0].ROUT_NEIGHBOUR && CompareCalls(Dest->ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL)) - || (Dest->ROUTE[1].ROUT_NEIGHBOUR && CompareCalls(Dest->ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL)) - || (Dest->ROUTE[2].ROUT_NEIGHBOUR && CompareCalls(Dest->ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))) - { - len=ConvFromAX25(Dest->DEST_CALL,Normcall); - - Normcall[len]=0; - - memcpy(Alias,Dest->DEST_ALIAS,6); - - Alias[6]=0; - - for (i=0;i<6;i++) - { - if (Alias[i] == ' ') - Alias[i] = 0; - } - - cursor=sprintf(line,"%s:%s ", Alias,Normcall); - - cursor = DoViaEntry(Dest, 0, line, cursor); - cursor = DoViaEntry(Dest, 1, line, cursor); - cursor = DoViaEntry(Dest, 2, line, cursor); - cursor = DoINP3ViaEntry(Dest, 0, line, cursor); - cursor = DoINP3ViaEntry(Dest, 1, line, cursor); - cursor = DoINP3ViaEntry(Dest, 2, line, cursor); - - line[cursor++]='\r'; - line[cursor++]=0; - - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", line); - } - } - - - goto SendReply; - -NODE_ADD: - - // FORMAT IS NODE ADD ALIAS:CALL QUAL ROUTE PORT - - - if (Session->PASSWORD != 0xFFFF) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", PASSWORDMSG); - goto SendReply; - } - - ptr = param2; - - if (ptr == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Missing Alias:Call\r"); - goto SendReply; - } - - Call = strlop(ptr, ':'); - - if (Call == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Missing Alias:Call\r"); - goto SendReply; - } - - - ConvToAX25(Call, AXCALL); - - Qualptr = strtok_s(NULL, " ", &Context); - - if (Qualptr == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Quality missing\r"); - goto SendReply; - } - - Qual = atoi(Qualptr); - - if (Qual < MINQUAL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Quality is below MINQUAL\r"); - goto SendReply; - } - - if (FindDestination(AXCALL, &Dest)) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Node already in Table\r"); - goto SendReply; - } - - if (Dest == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Node Table Full\r"); - goto SendReply; - } - - memcpy(Dest->DEST_CALL, AXCALL, 7); - memcpy(Dest->DEST_ALIAS, ptr, 6); - - NUMBEROFNODES++; - - ptr = strtok_s(NULL, " ", &Context); - - if (ptr == NULL || ptr[0] == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Neighbour missing\r"); - goto SendReply; - } - - if (ConvToAX25(ptr, axcall) == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Neighbour\r"); - goto SendReply; - } - else - { - int Port; - - ptr = strtok_s(NULL, " ", &Context); - if (ptr == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Port missing\r"); - goto SendReply; - } - - Port = atoi(ptr); - - if (Context[0] == '!') - { - OBSINIT = 255; //; SPECIAL FOR LOCKED - } - - if (FindNeighbour(axcall, Port, &ROUTE)) - { - PROCROUTES(Dest, ROUTE, Qual); - } - - OBSINIT = SavedOBSINIT; - - Bufferptr = Cmdprintf(Session, Bufferptr, "Node Added\r"); - goto SendReply; - } - - - - -/* -PNODE48: - - -; GET NEIGHBOURS FOR THIS DESTINATION -; - CALL CONVTOAX25 - JNZ SHORT BADROUTE -; - CALL GETVALUE - MOV SAVEPORT,AL ; SET PORT FOR _FINDNEIGHBOUR - - CALL GETVALUE - MOV ROUTEQUAL,AL -; - MOV ESI,OFFSET32 AX25CALL - - PUSH EBX ; SAVE DEST - CALL _FINDNEIGHBOUR - MOV EAX,EBX ; ROUTE TO AX - POP EBX - - JZ SHORT NOTBADROUTE - - JMP SHORT BADROUTE - -NOTBADROUTE: -; -; UPDATE ROUTE LIST FOR THIS DEST -; - MOV ROUT1_NEIGHBOUR[EBX],EAX - MOV AL,ROUTEQUAL - MOV ROUT1_QUALITY[EBX],AL - MOV ROUT1_OBSCOUNT[EBX],255 ; LOCKED -; - POP EDI - POP EBX - - INC _NUMBEROFNODES - - JMP SENDOK - -BADROUTE: -; -; KILL IT -; - MOV ECX,TYPE DEST_LIST - MOV EDI,EBX - MOV AL,0 - REP STOSB - - JMP BADROUTECMD - -*/ - - goto SendReply; - - -NODE_DEL: - - if (Session->PASSWORD != 0xFFFF) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", PASSWORDMSG); - goto SendReply; - } - - ptr = param2; - - if (ptr == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Missing Call\r"); - goto SendReply; - } - - if (strcmp(ptr, "ALL") == 0) - { - struct DEST_LIST * DEST = DESTS; - int n = MAXDESTS; - - while (n--) - { - if (DEST->DEST_CALL[0] && ((DEST->DEST_STATE & 0x80) == 0)) // Don't delete appl node - REMOVENODE(DEST); - - DEST++; - } - - ClearNodes(); - - Bufferptr = Cmdprintf(Session, Bufferptr, "All Nodes Deleted\r"); - goto SendReply; - } - - ConvToAX25(ptr, AXCALL); - - if (FindDestination(AXCALL, &Dest) == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not Found\r"); - goto SendReply; - } - - if (Dest->DEST_STATE & 0x80) - Bufferptr = Cmdprintf(Session, Bufferptr, "APPL Node - Can't delete\r"); - else - { - REMOVENODE(Dest); - Bufferptr = Cmdprintf(Session, Bufferptr, "Node Deleted\r"); - } - Bufferptr = Cmdprintf(Session, Bufferptr, "Node Deleted\r"); - -SendReply: - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID CMDQUERY(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD) -{ - // DISPLAY AVAILABLE COMMANDS - - int n; - char * ptr; - char ApplList[2048]; - char * out = ApplList; - - CMDX * CMD = &COMMANDS[APPL1]; - - for (n = 0; n < NumberofAppls; n++) - { - ptr = &CMD->String[0]; - if (*(ptr) != '*') - { - while (*ptr != ' ') - { - *(out++) = *(ptr++); - } - *(out++) = ' '; - } - CMD++; - } - - *(out) = 0; - - n = CMDLISTLEN; - - if (NEEDMH == 0) - n -= 7; // Dont show MH - - Bufferptr = Cmdprintf(Session, Bufferptr, "%s%s\r", ApplList, CMDLIST); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -char * FormatMH(MHSTRUC * MH, char Format); - -VOID MHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // DISPLAY HEARD LIST - - int Port = 0, sess = 0; - char * ptr, *Context, *pattern; - struct PORTCONTROL * PORT = NULL; - MHSTRUC * MH; - int count = MHENTRIES; - int n; - char Normcall[20]; - char From[10]; - char DigiList[100]; - char * Output; - int len; - char Digi = 0; - - - // Note that the MHDIGIS field may contain rubbish. You have to check End of Address bit to find - // how many digis there are - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr == NULL || ptr[0] == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Port Number needed eg MH 1\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (ptr) - Port = atoi(ptr); - - if (Port) - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - pattern = strtok_s(NULL, " ", &Context); - - if (pattern) - _strupr(pattern); // Optional filter - - MH = PORT->PORTMHEARD; - - if (MH == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "MHEARD not enabled on that port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (pattern && strstr(pattern, "CLEAR")) - { - if (Session->Secure_Session) - { - memset(MH, 0, MHENTRIES * sizeof(MHSTRUC)); - SaveMH(); - Bufferptr = Cmdprintf(Session, Bufferptr, "Heard List for Port %d Cleared\r", Port); - } - else - { - Bufferptr = Cmdprintf(Session, Bufferptr, "MH Clear needs SYSOP status\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - } - else - { - if (CMD->String[2] == 'V') // MHV - { - Bufferptr = Cmdprintf(Session, Bufferptr, "MHeard List %s for Port %d\r", MYNODECALL, Port); - Bufferptr = Cmdprintf(Session, Bufferptr, "Callsign Last heard Pkts RX via Digi ;) \r"); - Bufferptr = Cmdprintf(Session, Bufferptr, "--------- ----------- ------- ------------------------------------------\r"); - } - else - if (pattern) - Bufferptr = Cmdprintf(Session, Bufferptr, "Heard List for Port %d filtered by %s\r", Port, pattern); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Heard List for Port %d\r", Port); - } - while (count--) - { - if (MH->MHCALL[0] == 0) - break; - - Digi = 0; - - len = ConvFromAX25(MH->MHCALL, Normcall); - - Normcall[len++] = MH->MHDIGI; - Normcall[len++] = 0; - - if (pattern && strstr(Normcall, pattern) == 0) - { - MH++; - continue; - } - - n = 8; // Max number of digi-peaters - - ptr = &MH->MHCALL[6]; // End of Address bit - - Output = &DigiList[0]; - - if ((*ptr & 1) == 0) - { - // at least one digi - - strcpy(Output, "via "); - Output += 4; - - while ((*ptr & 1) == 0) - { - // MORE TO COME - - From[ConvFromAX25(ptr + 1, From)] = 0; - Output += sprintf((char *)Output, "%s", From); - - ptr += 7; - n--; - - if (n == 0) - break; - - // See if digi actioned - put a * on last actioned - - if (*ptr & 0x80) - { - if (*ptr & 1) // if last address, must need * - { - *(Output++) = '*'; - Digi = '*'; - } - - else - if ((ptr[7] & 0x80) == 0) // Repeased by next? - { - *(Output++) = '*'; // No, so need * - Digi = '*'; - } - -} - *(Output++) = ','; - } - *(--Output) = 0; // remove last comma - } - else - *(Output) = 0; - - // if we used a digi set * on call and display via string - - - if (Digi) - Normcall[len++] = Digi; - else - DigiList[0] = 0; // Dont show list if not used - - Normcall[len++] = 0; - - - ptr = FormatMH(MH, CMD->String[2]); - - if (CMD->String[2] == 'V') // MHV - Bufferptr = Cmdprintf(Session, Bufferptr, "%-10s %-10s %-10d %-30s\r", - Normcall, ptr, MH->MHCOUNT, DigiList); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "%-10s %s %s\r", Normcall, ptr, DigiList); - - MH++; - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -int Rig_Command(TRANSPORTENTRY * Session, char * Command); - -VOID RADIOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD) -{ - char * ptr; - - if (Rig_Command(Session, CmdTail)) - { - ReleaseBuffer((UINT *)REPLYBUFFER); - return; - } - - // Error Message is in buffer - - ptr = strchr(CmdTail, 13); - - if (ptr) - { - int len = (int)(++ptr - CmdTail); - - memcpy(Bufferptr, CmdTail, len); - Bufferptr += len; - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - - -VOID SendNRRecordRoute(struct DEST_LIST * DEST, TRANSPORTENTRY * Session); - - -VOID NRRCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD) -{ - // PROCESS 'NRR - Netrom Record Route' COMMAND - - char * ptr, *Context; - struct DEST_LIST * Dest = DESTS; - int count = MAXDESTS; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - { - UCHAR AXCall[8]; - int count; - - ConvToAX25(ptr, AXCall); - strcat(ptr, " "); - - for (count = 0; count < MAXDESTS; count++) - { - if (memcmp(Dest->DEST_ALIAS, ptr, 6) == 0 || CompareCalls(Dest->DEST_CALL, AXCall)) - { - SendNRRecordRoute(Dest, Session); - memcpy(Bufferptr, OKMSG, 3); - Bufferptr += 3; - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - - return; - } - Dest++; - } - } - Bufferptr = Cmdprintf(Session, Bufferptr, "Not found\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - -int CHECKINTERLOCK(struct PORTCONTROL * OURPORT) -{ - // See if any Interlocked ports are Busy - - struct PORTCONTROL * PORT = PORTTABLE; - struct _EXTPORTDATA * EXTPORT; - - int n = NUMBEROFPORTS; - int ourgroup = OURPORT->PORTINTERLOCK; - - while (PORT) - { - if (PORT != OURPORT) - { - if (PORT->PORTINTERLOCK == ourgroup) - { - // Same Group - is it busy - - int i = 0; - - EXTPORT = (struct _EXTPORTDATA *)PORT; - - while (i < 27) - if (EXTPORT->ATTACHEDSESSIONS[i++]) - return PORT->PORTNUMBER; - } - } - PORT = PORT->PORTPOINTER; - } - - return 0; -} - -VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD) -{ - // ATTACH to a PACTOR or similar port - - TRANSPORTENTRY * NewSess; - struct _EXTPORTDATA * EXTPORT; - struct TNCINFO * TNC = 0; - - int Port = 0, sess = 0; - char * ptr, *Context; - int ret; - struct PORTCONTROL * PORT = NULL; - struct DATAMESSAGE Message = {0}; - int Paclen, PortPaclen; - struct DATAMESSAGE * Buffer; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - Port = atoi(ptr); - - if (Port) - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL || PORT->PROTOCOL < 10) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // If attach on telnet port, find a free stream - - EXTPORT = (struct _EXTPORTDATA *)PORT; - - if (strstr(EXTPORT->PORT_DLL_NAME, "TELNET")) - { - int count = EXTPORT->MAXHOSTMODESESSIONS; - count--; // First is Pactor Stream, count is now last ax.25 session - - while (count) - { - if (EXTPORT->ATTACHEDSESSIONS[count] == 0) - { - int Paclen, PortPaclen; - struct DATAMESSAGE Message = {0}; - - // Found a free one - use it - - // See if TNC is OK - - Message.PORT = count; - - ret = PORT->PORTTXCHECKCODE(PORT, Message.PORT); - - if ((ret & 0xff00) == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - TNC Not Ready\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // GET CIRCUIT TABLE ENTRY FOR OTHER END OF LINK - - NewSess = SetupNewSession(Session, Bufferptr); - - if (NewSess == NULL) - return; - - EXTPORT->ATTACHEDSESSIONS[count] = NewSess; - - NewSess->Secure_Session = Session->Secure_Session; - - NewSess->KAMSESSION = count; - - // Set paclen to lower of incoming and outgoing - - Paclen = Session->SESSPACLEN; // Incoming PACLEN - - if (Paclen == 0) - Paclen = 256; // 0 = 256 - - PortPaclen = PORT->PORTPACLEN; - - if (PortPaclen == 0) - PortPaclen = 256; // 0 = 256 - - if (PortPaclen < Paclen) - Paclen = PortPaclen; - - NewSess->SESSPACLEN = Paclen; - Session->SESSPACLEN = Paclen; - - NewSess->L4STATE = 5; - NewSess->L4CIRCUITTYPE = DOWNLINK + PACTOR; - NewSess->L4TARGET.PORT = PORT; - - ptr = strtok_s(NULL, " ", &Context); - sess = count; - - // Replace command tail with original (before conversion to upper case - - Context = Context + (OrigCmdBuffer - COMMANDBUFFER); - - goto checkattachandcall; - - - memcpy(Bufferptr, OKMSG, 3); - Bufferptr += 3; - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - - return; - } - count--; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - No free streams on this port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - Message.PORT = 0; - - ret = PORT->PORTTXCHECKCODE(PORT, Message.PORT); - - if ((ret & 0xff00) == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - TNC Not Ready\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // See if "Attach and Call" (for VHF ports) - - ptr = strtok_s(NULL, " ", &Context); - - if (ptr && strcmp(ptr, "S") == 0) - { - Session->STAYFLAG = TRUE; - ptr = strtok_s(NULL, " ", &Context); - } - - if (ptr) - { - // we have another param - - // if it is a single char it is a channel number for vhf attach - - if (strlen(ptr) == 1) - { - // Only Allow Attach VHF from Secure Applications or if PERMITGATEWAY is set - - if (EXTPORT->PERMITGATEWAY == 0 && Session->Secure_Session == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, you are not allowed to use this port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - sess = ptr[0] - '@'; - - if (sess < 1 || sess > EXTPORT->MAXHOSTMODESESSIONS) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Invalid Channel\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - ptr = strtok_s(NULL, " ", &Context); - - if (ptr && strcmp(ptr, "S") == 0) - { - Session->STAYFLAG = TRUE; - ptr = strtok_s(NULL, " ", &Context); - } - } - } - - if (ret & 0x8000) // Disconnecting - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port in use\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // Check Interlock. Only ports with a TNC record can be interlocked - - TNC = PORT->TNC; - - if (TNC) - { - // See if any interlocked ports are in use - - struct TNCINFO * OtherTNC; - int i; - int rxInterlock = TNC->RXRadio; - int txInterlock = TNC->TXRadio; - - if (rxInterlock || txInterlock) - { - for (i=1; i <= MAXBPQPORTS; i++) - { - OtherTNC = TNCInfo[i]; - - if (OtherTNC == NULL) - continue; - - if (OtherTNC == TNC) - continue; - - if (rxInterlock && rxInterlock == OtherTNC->RXRadio || txInterlock && txInterlock == OtherTNC->TXRadio) // Same Group - { - int n; - - for (n = 0; n <= 26; n++) - { - if (OtherTNC->PortRecord->ATTACHEDSESSIONS[n]) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, interlocked port %d is in use\r", i); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - } - } - } - } - } - - - - - if (EXTPORT->ATTACHEDSESSIONS[sess] || PORT->PortSuspended) - { - // In use - - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port in use\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - // GET CIRCUIT TABLE ENTRY FOR OTHER END OF LINK - - NewSess = SetupNewSession(Session, Bufferptr); - - if (NewSess == NULL) - return; - - // if a UZ7HO port, and the uplink is L2 or Uz7HO and multisession, - // invert SSID bits - - if (memcmp(EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0) - goto noFlip1; - - if (EXTPORT->MAXHOSTMODESESSIONS < 2) // Not multisession - goto noFlip1; - - if ((Session->L4CIRCUITTYPE & BPQHOST)) // host - goto noFlip1; - - if ((Session->L4CIRCUITTYPE & PACTOR)) - { - // incoming is Pactorlike - see if UZ7HO - - if (memcmp(Session->L4TARGET.EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0) - goto noFlip1; - else - NewSess->L4USER[6] ^= 0x1e; // UZ7HO Uplink - flip - } - else - - // Must be L2 uplink - flip - - NewSess->L4USER[6] ^= 0x1e; // Flip SSID -noFlip1: - - EXTPORT->ATTACHEDSESSIONS[sess] = NewSess; - - NewSess->KAMSESSION = sess; - - // Set paclen to lower of incoming and outgoing - - Paclen = Session->SESSPACLEN; // Incoming PACLEN - - if (Paclen == 0) - Paclen = 256; // 0 = 256 - - PortPaclen = PORT->PORTPACLEN; - - if (PortPaclen == 0) - PortPaclen = 256; // 0 = 256 - - if (PortPaclen < Paclen) - Paclen = PortPaclen; - - NewSess->SESSPACLEN = Paclen; - Session->SESSPACLEN = Paclen; - NewSess->L4STATE = 5; - NewSess->L4CIRCUITTYPE = DOWNLINK + PACTOR; - NewSess->L4TARGET.PORT = PORT; - -checkattachandcall: - - // If set freq on attach is defined, do it - - if (TNC && TNC->ActiveRXFreq && TNC->RXRadio) - { - char Msg[128]; - - sprintf(Msg, "R%d %f", TNC->RXRadio, TNC->ActiveRXFreq); - Rig_Command( (TRANSPORTENTRY *) -1, Msg); - } - - if (TNC && TNC->ActiveTXFreq && TNC->TXRadio && TNC->TXRadio != TNC->RXRadio) - { - char Msg[128]; - - sprintf(Msg, "R%d %f", TNC->TXRadio, TNC->ActiveTXFreq); - Rig_Command( (TRANSPORTENTRY *) -1, Msg); - } - - if (ptr) - { - // we have a call to connect to - - char Callstring[80]; - int len; - - Buffer = REPLYBUFFER; - Buffer->PORT = sess; - Buffer->PID = 0xf0; - - len = sprintf(Callstring,"C %s", ptr); - - ptr = strtok_s(NULL, " ", &Context); - - while (ptr) // if any other params (such as digis) copy them - { - if (strcmp(ptr, "S") == 0) - { - Session->STAYFLAG = TRUE; - } - else - len += sprintf(&Callstring[len], " %s", ptr); - - ptr = strtok_s(NULL, " ", &Context); - } - - Callstring[len++] = 13; - Callstring[len] = 0; - - Buffer->LENGTH = len + MSGHDDRLEN + 1; - memcpy(Buffer->L2DATA, Callstring, len); - C_Q_ADD(&PORT->PORTTX_Q, (UINT *)Buffer); - - return; - } - - memcpy(Bufferptr, OKMSG, 3); - Bufferptr += 3; - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - - return; -} - -// SYSOP COMMANDS - -CMDX COMMANDS[] = -{ - "SAVENODES ",8, SAVENODES, 0, - "TELRECONFIG ",4, RECONFIGTELNET, 0, - "SAVEMH ",6, SAVEMHCMD, 0, - "REBOOT ",6, REBOOT, 0, - "RIGRECONFIG ",8 , RIGRECONFIG, 0, - "RESTART ",7,RESTART,0, - "RESTARTTNC ",10,RESTARTTNC,0, - "SENDNODES ",8,SENDNODES,0, - "EXTRESTART ",10, EXTPORTVAL, offsetof(EXTPORTDATA, EXTRESTART), - "TXDELAY ",3, PORTVAL, offsetof(PORTCONTROLX, PORTTXDELAY), - "MAXFRAME ",3, PORTVAL, offsetof(PORTCONTROLX, PORTWINDOW), - "RETRIES ",3, PORTVAL, offsetof(PORTCONTROLX, PORTN2), - "FRACK ",3,PORTVAL, offsetof(PORTCONTROLX, PORTT1), - "RESPTIME ",3,PORTVAL, offsetof(PORTCONTROLX, PORTT2), - "PPACLEN ",3,PORTVAL, offsetof(PORTCONTROLX, PORTPACLEN), - "QUALITY ",3,PORTVAL, offsetof(PORTCONTROLX, PORTQUALITY), - "PERSIST ",2,PORTVAL, offsetof(PORTCONTROLX, PORTPERSISTANCE), - "TXTAIL ",3,PORTVAL, offsetof(PORTCONTROLX, PORTTAILTIME), - "XMITOFF ",7,PORTVAL, offsetof(PORTCONTROLX, PORTDISABLED), - "DIGIFLAG ",5,PORTVAL, offsetof(PORTCONTROLX, DIGIFLAG), - "DIGIPORT ",5,PORTVAL, offsetof(PORTCONTROLX, DIGIPORT), - "MAXUSERS ",4,PORTVAL, offsetof(PORTCONTROLX, USERS), - "L3ONLY ",6,PORTVAL, offsetof(PORTCONTROLX, PORTL3FLAG), - "BBSALIAS ",4,PORTVAL, offsetof(PORTCONTROLX, PORTBBSFLAG), - "VALIDCALLS ",5,VALNODES,0, - "WL2KSYSOP ",5,WL2KSYSOP,0, - "STOPPORT ",4,STOPPORT,0, - "STARTPORT ",5,STARTPORT,0, - "STOPCMS ",7,STOPCMS,0, - "STARTCMS ",8,STARTCMS,0, - - "FINDBUFFS ",4,FINDBUFFS,0, - "KISS ",4,KISSCMD,0, - "GETPORTCTEXT",9,GetPortCTEXT, 0, - -#ifdef EXCLUDEBITS - - "EXCLUDE ",4,ListExcludedCalls,0, - -#endif - - "FULLDUP ",4,PORTVAL, offsetof(PORTCONTROLX, FULLDUPLEX), - "SOFTDCD ",4,PORTVAL, offsetof(PORTCONTROLX, SOFTDCDFLAG), - "OBSINIT ",7,SWITCHVAL,(size_t)&OBSINIT, - "OBSMIN ",6,SWITCHVAL,(size_t)&OBSMIN, - "NODESINT ",8,SWITCHVAL,(size_t)&L3INTERVAL, - "L3TTL ",5,SWITCHVAL,(size_t)&L3LIVES, - "L4RETRIES ",5,SWITCHVAL,(size_t)&L4N2, - "L4TIMEOUT ",5,SWITCHVALW,(size_t)&L4T1, - "T3 ",2,SWITCHVALW,(size_t)&T3, - "NODEIDLETIME",8,SWITCHVALW,(size_t)&L4LIMIT, - "LINKEDFLAG ",10,SWITCHVAL,(size_t)&LINKEDFLAG, - "IDINTERVAL ",5,SWITCHVAL,(size_t)&IDINTERVAL, - "MINQUAL ",7,SWITCHVAL,(size_t)&MINQUAL, - "FULLCTEXT ",6,SWITCHVAL,(size_t)&FULL_CTEXT, - "HIDENODES ",8,SWITCHVAL,(size_t)&HIDENODES, - "L4DELAY ",7,SWITCHVAL,(size_t)&L4DELAY, - "L4WINDOW ",6,SWITCHVAL,(size_t)&L4DEFAULTWINDOW, - "BTINTERVAL ",5,SWITCHVAL,(size_t)&BTINTERVAL, - "PASSWORD ", 8, PWDCMD, 0, - - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, - "************", 12, APPLCMD, 0, // Apppl 32 is internal Terminal - "*** LINKED ",10,LINKCMD,0, - "CQ ",2,CQCMD,0, - "CONNECT ",1,CMDC00,0, - "NC ",2,CMDC00,0, - "BYE ",1,BYECMD,0, - "QUIT ",1,BYECMD,0, - "INFO ",1,CMDI00,0, - "HELP ",1,HELPCMD,0, - "VERSION ",1,CMDV00,0, - "NODES ",1,CMDN00,0, - "LINKS ",1,CMDL00,0, - "LISTEN ",3,LISTENCMD,0, - "L4T1 ",2,CMDT00,0, - "PORTS ",1,CMDP00,0, - "PACLEN ",3,CMDPAC,0, - "IDLETIME ",4,CMDIDLE,0, - "ROUTES ",1,CMDR00,0, - "STATS ",1,CMDSTATS,0, - "USERS ",1,CMDS00,0, - "UNPROTO ",2,UNPROTOCMD,0, - "? ",1,CMDQUERY,0, - "DUMP ",4,DUMPCMD,0, - "MHU ",3,MHCMD,0, // UTC Times - "MHL ",3,MHCMD,0, // Local Times - "MHV ",3,MHCMD,0, - "MHEARD ",1,MHCMD,0, - "APRS ",2,APRSCMD,0, - "ATTACH ",1,ATTACHCMD,0, - "RADIO ",3,RADIOCMD,0, - "AXRESOLVER ",3,AXRESOLVER,0, - "AXMHEARD ",3,AXMHEARD,0, - "TELSTATUS ",3,SHOWTELNET,0, - "NRR ",1,NRRCMD,0, - "PING ",2,PING,0, - "AGWSTATUS ",3,SHOWAGW,0, - "ARP ",3,SHOWARP,0, - "NAT ",3,SHOWNAT,0, - "IPROUTE ",3,SHOWIPROUTE,0, - "UZ7HO ",5,UZ7HOCMD,0, - "QTSM ",4,QTSMCMD,0, - - "..FLMSG ",7,FLMSG,0 -}; - -CMDX * CMD = NULL; - -int NUMBEROFCOMMANDS = sizeof(COMMANDS)/sizeof(CMDX); - -char * ReplyPointer; // Pointer into reply buffer - -int DecodeNodeName(char * NodeName, char * ptr) -{ - // NodeName is TABLE ENTRY WITH AX25 CALL AND ALIAS - - // Copyies 20 byte 20 DECODED NAME IN FORM ALIAS:CALL to ptr - // Returns significant length of string - - int len; - char Normcall[10]; - char * alias = &NodeName[7]; - int n = 6; - char * start = ptr; - - memset(ptr, ' ', 20); - - len = ConvFromAX25(NodeName, Normcall); - - if (*(alias) > ' ') // Does alias start with a null or a space ? - { - while (*(alias) > ' ' && n--) - { - *ptr++ = *alias++; - } - *ptr++ = ':'; - } - - memcpy(ptr, Normcall, len); - ptr += len; - - return (int)(ptr - start); -} - -char * SetupNodeHeader(struct DATAMESSAGE * Buffer) -{ - char Header[20]; - int len; - - char * ptr = &Buffer->L2DATA[0]; - - len = DecodeNodeName(MYCALLWITHALIAS, Header); - - memcpy (ptr, Header, len); - ptr += len; - - (*ptr++) = HEADERCHAR; - (*ptr++) = ' '; - - return ptr; -} - -VOID SendCommandReply(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer, int Len) -{ - if (Len == (4 + sizeof(void *))) // Null Packet - { - ReleaseBuffer((UINT *)Buffer); - return; - } - - Buffer->LENGTH = Len; - - C_Q_ADD(&Session->L4TX_Q, (UINT *)Buffer); - - PostDataAvailable(Session); -} - - -VOID CommandHandler(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer) -{ - // ignore frames with single NULL (Keepalive) - - if (Buffer->LENGTH == sizeof(void *) + 5 && Buffer->L2DATA[0] == 0) - { - ReleaseBuffer(Buffer); - return; - } - - if (Buffer->LENGTH > 100) - { -// Debugprintf("BPQ32 command too long %s", Buffer->L2DATA); - ReleaseBuffer(Buffer); - return; - } - -InnerLoop: - - InnerCommandHandler(Session, Buffer); - -// See if any more commands in buffer - - if (Session->PARTCMDBUFFER) - { - char * ptr1, * ptr2; - int len; - - Buffer = Session->PARTCMDBUFFER; - - // Check that message has a CR, if not save buffer and exit - - len = Buffer->LENGTH - (4 + sizeof(void *)); - ptr1 = &Buffer->L2DATA[0]; - - ptr2 = memchr(ptr1, 13, len); - - if (ptr2 == NULL) - return; - - Session->PARTCMDBUFFER = NULL; - - goto InnerLoop; - } -} - - -VOID InnerCommandHandler(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer) -{ - char * ptr1, * ptr2, *ptr3; - int len, oldlen, newlen, rest, n; - struct DATAMESSAGE * OldBuffer; - struct DATAMESSAGE * SaveBuffer; - char c; - - // If a partial command is stored, append this data to it. - - if (Session->PARTCMDBUFFER) - { - len = Buffer->LENGTH - (sizeof(void *) + 4); - ptr1 = &Buffer->L2DATA[0]; - - OldBuffer = Session->PARTCMDBUFFER; // Old Data - - if (OldBuffer == Buffer) - { - // something has gone horribly wrong - - Session->PARTCMDBUFFER = NULL; - return; - } - - oldlen = OldBuffer->LENGTH; - - newlen = len + oldlen; - - if (newlen > 200) - { - // Command far too long - ignore previous - - OldBuffer->LENGTH = oldlen = sizeof(void *) + 4; - } - - OldBuffer->LENGTH += len; - memcpy(&OldBuffer->L2DATA[oldlen - (sizeof(void *) + 4)], Buffer->L2DATA, len); - - ReleaseBuffer((UINT *)Buffer); - - Buffer = OldBuffer; - - Session->PARTCMDBUFFER = NULL; - } - - // Check that message has a CR, if not save buffer and exit - - len = Buffer->LENGTH - (sizeof(void *) + 4); - ptr1 = &Buffer->L2DATA[0]; - - // Check for sending YAPP to Node - - if (len == 2 && ptr1[0] == 5 && ptr1[1] == 1) - { - ptr1[0] = 0x15; // NAK - - ptr1[1] = sprintf(&ptr1[2], "Node doesn't support YAPP Transfers"); - - Buffer->LENGTH += ptr1[1]; - - C_Q_ADD(&Session->L4TX_Q, (UINT *)Buffer); - PostDataAvailable(Session); - return; - } - - - ptr2 = memchr(ptr1, ';', len); - - if (ptr2 == 0) - { - ptr2 = memchr(ptr1, 13, len); - - if (ptr2 == 0) - { - // No newline - - Session->PARTCMDBUFFER = Buffer; - return; - } - } - - ptr2++; - - rest = len - (int)(ptr2 - ptr1); - - if (rest) - { - // there are chars beyond the cr in the buffer - - // see if LF after CR - - if ((*ptr2) == 10) // LF - { - ptr2++; - rest--; - } - - if (rest) // May only have had LF - { - // Get a new buffer, and copy extra data to it. - - SaveBuffer = (struct DATAMESSAGE *)GetBuff(); - - if (SaveBuffer) //`Just ignore if no buffers - { - SaveBuffer->LENGTH = rest + MSGHDDRLEN + 1; - SaveBuffer->PID = 0xf0; - memcpy(&SaveBuffer->L2DATA[0], ptr2, rest); - Session->PARTCMDBUFFER = SaveBuffer; - } - } - } - - // GET PACLEN FOR THIS CONNECTION - - CMDPACLEN = Session->SESSPACLEN; - - if (CMDPACLEN == 0) - CMDPACLEN = PACLEN; // Use default if no Session PACLEN - - // If sesion is in UNPROTO Mode, send message as a UI message - - if (Session->UNPROTO) - { -// char LongMsg[512] = -// "VeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessage" -// "VeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessage"; - - DIGIMESSAGE Msg; - int Port = Session->UNPROTO; - int Len = Buffer->LENGTH - (MSGHDDRLEN -1); // Need PID - - // First check for UNPROTO exit - ctrl/z or /ex - - if (Buffer->L2DATA[0] == 26 || (Len == 6 && _memicmp(&Buffer->L2DATA[0], "/ex", 3) == 0)) // CTRL/Z or /ex - { - REPLYBUFFER = Buffer; - - Session->UNPROTO = 0; - memset(Session->UADDRESS, 0, 64); - - // SET UP HEADER - - Buffer->PID = 0xf0; - ptr1 = SetupNodeHeader(Buffer); - memcpy(ptr1, OKMSG, 3); - ptr1 += 3; - SendCommandReply(Session, Buffer, (int)(ptr1 - (char *)Buffer)); - - return; - } - - memset(&Msg, 0, sizeof(Msg)); - - Msg.PORT = Port; - Msg.CTL = 3; // UI - memcpy(Msg.DEST, Session->UADDRESS, 7); - Msg.DEST[6] |= 0x80; // set Command Bit - memcpy(Msg.ORIGIN, Session->L4USER, 7); - memcpy(Msg.DIGIS, &Session->UADDRESS[7], Session->UAddrLen - 7); - memcpy(&Msg.PID, &Buffer->PID, Len); - Send_AX_Datagram(&Msg, Len, Port); // Len is Payload - CTL, PID and Data - -// memcpy(&Msg.PID + 1, LongMsg, 260); -// Send_AX_Datagram(&Msg, 241, Port); // Len is Payload - CTL, PID and Data - - -// SendUIModeFrame(Session, (PMESSAGE)Buffer, Session->UNPROTO); - - ReleaseBuffer((UINT *)Buffer); // Not using buffer for reply - - // Assume we don't allow multiple lines in buffer with UI - - if (Session->PARTCMDBUFFER) - { - Buffer = Session->PARTCMDBUFFER; - ReleaseBuffer((UINT *)Buffer); // Not using buffer for reply - Session->PARTCMDBUFFER = NULL; - } - return; - } - - memset(COMMANDBUFFER, 32, 80); // Clear to spaces - - ptr1 = &Buffer->L2DATA[0]; - ptr2 = &COMMANDBUFFER[0]; - ptr3 = &OrigCmdBuffer[0]; - - memset(OrigCmdBuffer, 0, 80); - n = 80; - - while (n--) - { - c = *(ptr1++) & 0x7f; // Mask paritu - - if (c == 13 || c == ';') - break; // CR - - *(ptr3++) = c; // Original Case - - c = toupper(c); - *(ptr2++) = c; - } - - - // USE INPUT MESSAGE _BUFFER FOR REPLY - - REPLYBUFFER = Buffer; - - // SET UP HEADER - - Buffer->PID = 0xf0; - ptr1 = SetupNodeHeader(Buffer); - - ReplyPointer = ptr1; - - ALIASINVOKED = 0; // Clear "Invoked by APPL ALIAS flag" - - DoTheCommand(Session); // We also call DotheCommand when we need to reprocess - eg for alias handling -} - -VOID DoTheCommand(TRANSPORTENTRY * Session) -{ - struct DATAMESSAGE * Buffer = REPLYBUFFER; - char * ptr1, * ptr2; - int n; - - ptr1 = &COMMANDBUFFER[0]; // - - n = 10; - - while ((*ptr1 == ' ' || *ptr1 == 0) && n--) - ptr1++; // STRIP LEADING SPACES and nulls (from keepalive) - - if (n == -1) - { - // Null command - - ReleaseBuffer((UINT *)Buffer); - return; - } - - ptr2 = ptr1; // Save - - - CMD = &COMMANDS[0]; - n = 0; - - for (n = 0; n < NUMBEROFCOMMANDS; n++) - { - int CL = CMD->CMDLEN; - - ptr1 = ptr2; - - CMDPTR = CMD; - - if (n == APPL1) // First APPL command - { - APPLMASK = 1; // FOR APPLICATION ATTACH REQUESTS - ALIASPTR = &CMDALIAS[0][0]; - } - - // ptr1 is input command - - if (memcmp(CMD->String, ptr1, CL) == 0) - { - // Found match so far - check rest - - char * ptr2 = &CMD->String[CL]; - - ptr1 += CL; - - if (*(ptr1) != ' ') - { - while(*(ptr1) == *ptr2 && *(ptr1) != ' ') - { - ptr1++; - ptr2++; - } - } - - if (*(ptr1) == ' ') - { - Session->BADCOMMANDS = 0; // RESET ERROR COUNT - - // SEE IF SYSOP COMMAND, AND IF SO IF PASSWORD HAS BEEN ENTERED - - if (n < PASSCMD) - { - //NEEDS PASSWORD FOR SYSOP COMMANDS - - if (Session->PASSWORD != 0xFFFF) - { - ptr1 = ReplyPointer; - - memcpy(ptr1, PASSWORDMSG, LPASSMSG); - ptr1 += LPASSMSG; - - SendCommandReply(Session, Buffer, (int)(ptr1 - (char *)Buffer)); - return; - } - } -// VALNODESFLAG = 0; // NOT VALID NODES COMMAND - - ptr1++; // Skip space - - CMD->CMDPROC(Session, ReplyPointer, ptr1, CMD); - return; - } - } - - APPLMASK <<= 1; - ALIASPTR += ALIASLEN; - - CMD++; - - } - Session->BADCOMMANDS++; - - if (Session->BADCOMMANDS > 6) // TOO MANY ERRORS - { - ReleaseBuffer((UINT *)Buffer); - Session->STAYFLAG = 0; - CLOSECURRENTSESSION(Session); - return; - } - - ptr1 = ReplyPointer; - - memcpy(ptr1, CMDERRMSG, CMDERRLEN); - 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) - { - int index = PORT->StatsPointer++; - - if (index == 1439) - PORT->StatsPointer = 0; // Cyclic through 24 hours (1440 Mins) - - if (PORT->TNC) - { - struct TNCINFO * TNC = PORT->TNC; - if (TNC->Hardware == H_ARDOP || TNC->Hardware == H_VARA) - { - sum = TNC->PTTActivemS / 600; // ms but want % - PORT->AVSENDING = (UCHAR)sum; - TNC->PTTActivemS = 0; - - sum2 = TNC->BusyActivemS / 600; // ms but want % - PORT->AVACTIVE = (UCHAR)(sum + sum2); - TNC->BusyActivemS = 0; - } - } - else - { - // if KISS port using QtSM Average is already updated - - struct KISSINFO * KISS = (struct KISSINFO *)PORT; - - if (PORT->PORTNUMBER == 17) - { - int x = 17; - } - - if (PORT->PORTTXROUTINE == KISSTX && (KISS->QtSMStats || KISS->FIRSTPORT->PORT.QtSMPort)) // KISS Port QtSM Stats - { - } - else - { - sum = PORT->SENDING / 11; - PORT->AVSENDING = (UCHAR)sum; - - sum = (PORT->SENDING + PORT->ACTIVE) /11; - PORT->AVACTIVE = (UCHAR)sum; - } - } - - if (PORT->TX == NULL && PORT->AVACTIVE) - { - PORT->TX = zalloc(1440); // Keep 1 day history - PORT->BUSY = zalloc(1440); - } - if (PORT->TX) - { - PORT->TX[index] = PORT->AVSENDING; - PORT->BUSY[index] = PORT->AVACTIVE; - } - - PORT->SENDING = 0; - PORT->ACTIVE = 0; - - PORT = PORT->PORTPOINTER; - } -} - - - -extern struct AXIPPORTINFO * Portlist[]; - -#define TCPConnected 4 - - -VOID AXRESOLVER(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // DISPLAY AXIP Resolver info - - int Port = 0, index =0; - char * ptr, *Context; - struct PORTCONTROL * PORT = NULL; - struct AXIPPORTINFO * AXPORT; - char Normcall[11]; - char Flags[10]; - struct arp_table_entry * arp; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - Port = atoi(ptr); - - if (Port) - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - AXPORT = Portlist[Port]; - - if (AXPORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not an AXIP port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "AXIP Resolver info for Port %d\r", Port); - - while (index < AXPORT->arp_table_len) - { - arp = &AXPORT->arp_table[index]; - - if (arp->ResolveFlag && arp->error != 0) - { - // resolver error - Display Error Code - sprintf(AXPORT->hostaddr, "Error %d", arp->error); - } - else - { - if (arp->IPv6) - Format_Addr((unsigned char *)&arp->destaddr6.sin6_addr, AXPORT->hostaddr, TRUE); - else - Format_Addr((unsigned char *)&arp->destaddr.sin_addr, AXPORT->hostaddr, FALSE); - } - - ConvFromAX25(arp->callsign, Normcall); - - Flags[0] = 0; - - if (arp->BCFlag) - strcat(Flags, "B "); - - if (arp->TCPState == TCPConnected) - strcat(Flags, "C "); - - if (arp->AutoAdded) - strcat(Flags, "A"); - - if (arp->port == arp->SourcePort) - Bufferptr = Cmdprintf(Session, Bufferptr,"%.10s = %.64s %d = %-.42s %s\r", - Normcall, - arp->hostname, - arp->port, - AXPORT->hostaddr, - Flags); - - else - Bufferptr = Cmdprintf(Session, Bufferptr,"%.10s = %.64s %d<%d = %-.42s %s\r", - Normcall, - arp->hostname, - arp->port, - arp->SourcePort, - AXPORT->hostaddr, - Flags); - - index++; - } - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID AXMHEARD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - // DISPLAY AXIP Mheard info - - int Port = 0, index = 0; - char * ptr, *Context; - struct PORTCONTROL * PORT = NULL; - struct AXIPPORTINFO * AXPORT; - int n = MHENTRIES; - char Normcall[11]; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - Port = atoi(ptr); - - if (Port) - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - AXPORT = Portlist[Port]; - - if (AXPORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not an AXIP port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "AXIP Mheard for Port %d\r", Port); - - while (index < MaxMHEntries) - { - if (AXPORT->MHTable[index].proto != 0) - { - char Addr[80]; - - Format_Addr((unsigned char *)&AXPORT->MHTable[index].ipaddr6, Addr, AXPORT->MHTable[index].IPv6); - - Normcall[ConvFromAX25(AXPORT->MHTable[index].callsign, Normcall)] = 0; - - Bufferptr = Cmdprintf(Session, Bufferptr, "%-10s%-15s %c %-6d %-25s%c\r", Normcall, - Addr, - AXPORT->MHTable[index].proto, - AXPORT->MHTable[index].port, - asctime(gmtime( &AXPORT->MHTable[index].LastHeard )), - (AXPORT->MHTable[index].Keepalive == 0) ? ' ' : 'K'); - - Bufferptr[-3] = ' '; // Clear CR returned by asctime - } - - index++; - } - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -#pragma pack() - -extern char WL2KCall[10]; -extern char WL2KLoc[7]; - -BOOL GetWL2KSYSOPInfo(char * Call, char * _REPLYBUFFER); -BOOL UpdateWL2KSYSOPInfo(char * Call, char * SQL); - -VOID WL2KSYSOP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char _REPLYBUFFER[1000] = ""; - - char LastUpdated[100]; - char Name[100] = ""; - char Addr1[100] = ""; - char Addr2[100] = ""; - char City[100] = ""; - char State[100] = ""; - char Country[100] = ""; - char PostCode[100] = ""; - char Email[100] = ""; - char Website[100] = ""; - char Phone[100] = ""; - char Data[100] = ""; - char LOC[100] = ""; - BOOL Exists = TRUE; - time_t LastUpdateSecs = 0; - char * ptr1, * ptr2; - - SOCKET sock; - - int Len; - char Message[2048]; - - if (WL2KCall[0] < 33) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Winlink reporting is not configured\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - - if (GetWL2KSYSOPInfo(WL2KCall, _REPLYBUFFER) == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Failed to connect to WL2K Database\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (strstr(_REPLYBUFFER, "\"ErrorMessage\":")) - Exists = FALSE; - - GetJSONValue(_REPLYBUFFER, "\"SysopName\":", Name); - GetJSONValue(_REPLYBUFFER, "\"StreetAddress1\":", Addr1); - GetJSONValue(_REPLYBUFFER, "\"StreetAddress2\":", Addr2); - GetJSONValue(_REPLYBUFFER, "\"City\":", City); - GetJSONValue(_REPLYBUFFER, "\"State\":", State); - GetJSONValue(_REPLYBUFFER, "\"Country\":", Country); - GetJSONValue(_REPLYBUFFER, "\"PostalCode\":", PostCode); - GetJSONValue(_REPLYBUFFER, "\"Email\":", Email); - GetJSONValue(_REPLYBUFFER, "\"Website\":", Website); - GetJSONValue(_REPLYBUFFER, "\"Phones\":", Phone); - GetJSONValue(_REPLYBUFFER, "\"Comments\":", Data); - GetJSONValue(_REPLYBUFFER, "\"GridSquare\":", LOC); - GetJSONValue(_REPLYBUFFER, "\"Timestamp\":", LastUpdated); - - ptr1 = strchr(LastUpdated, '('); - - if (ptr1) - { - ptr2 = strchr(++ptr1, ')'); - - if (ptr2) - { - *(ptr2 - 3) = 0; // remove millisecs - LastUpdateSecs = atoi(ptr1); - - FormatTime3(LastUpdated, LastUpdateSecs); - } - } - - if (_memicmp(CmdTail, "SET ", 4) == 0) - { - if (Exists) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Record already exists in WL2K Database\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // Set New Values. Any other params are values to set, separated by | - -// ptr1 = strtok_s(&CmdTail[4], ",", &Context); - -// if (ptr1 == NULL) -// goto DoReplace; - -// strcpy(Name, ptr1); - -//DoReplace: - - Len = sprintf(Message, - "\"Callsign\":\"%s\"," - "\"GridSquare\":\"%s\"," - "\"SysopName\":\"%s\"," - "\"StreetAddress1\":\"%s\"," - "\"StreetAddress2\":\"%s\"," - "\"City\":\"%s\"," - "\"State\":\"%s\"," - "\"Country\":\"%s\"," - "\"PostalCode\":\"%s\"," - "\"Email\":\"%s\"," - "\"Phones\":\"%s\"," - "\"Website\":\"%s\"," - "\"Comments\":\"%s\",", - - WL2KCall, WL2KLoc, Name, Addr1, Addr2, City, State, Country, PostCode, Email, Phone, Website, Data); - - Debugprintf("Sending %s", Message); - - sock = OpenWL2KHTTPSock(); - - if (sock) - SendHTTPRequest(sock, "api.winlink.org", 80, - "/sysop/add", Message, Len, NULL); - - closesocket(sock); - - Bufferptr = Cmdprintf(Session, Bufferptr, "Database Updated\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (Exists) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "\rWL2K SYSOP Info for %s\r", WL2KCall); - Bufferptr = Cmdprintf(Session, Bufferptr, "Grid Square: %s\r", LOC); - Bufferptr = Cmdprintf(Session, Bufferptr, "Name: %s\r", Name); - Bufferptr = Cmdprintf(Session, Bufferptr, "Addr Line 1: %s\r", Addr1); - Bufferptr = Cmdprintf(Session, Bufferptr, "Addr Line 2: %s\r", Addr2); - Bufferptr = Cmdprintf(Session, Bufferptr, "City: %s\r", City); - Bufferptr = Cmdprintf(Session, Bufferptr, "State: %s\r", State); - Bufferptr = Cmdprintf(Session, Bufferptr, "Country: %s\r", Country); - Bufferptr = Cmdprintf(Session, Bufferptr, "PostCode: %s\r", PostCode); - Bufferptr = Cmdprintf(Session, Bufferptr, "Email Address: %s\r", Email); - Bufferptr = Cmdprintf(Session, Bufferptr, "Website: %s\r", Website); - Bufferptr = Cmdprintf(Session, Bufferptr, "Phone: %s\r", Phone); - Bufferptr = Cmdprintf(Session, Bufferptr, "Additional Data: %s\r", Data); - Bufferptr = Cmdprintf(Session, Bufferptr, "Last Updated: %s\r", LastUpdated); - } - else - Bufferptr = Cmdprintf(Session, Bufferptr, "No SYSOP record for %s\r", WL2KCall); - - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - -VOID CloseKISSPort(struct PORTCONTROL * PortVector); - -VOID STOPCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char _REPLYBUFFER[1000] = ""; - char * ptr, * Context; - - int portno; - - struct TNCINFO * TNC; - struct TCPINFO * TCP; - struct PORTCONTROL * PORT = PORTTABLE; - int n = NUMBEROFPORTS; - - // Get port number - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - { - portno = atoi (ptr); - - if (portno) - { - while (n--) - { - if (PORT->PORTNUMBER == portno) - { - TNC = TNCInfo[portno]; - - if (!TNC || !TNC->TCPInfo) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not a Telnet Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - TCP = TNC->TCPInfo; - - TCP->CMS = 0; - TCP->CMSOK = FALSE; -#ifndef LINBPQ - CheckMenuItem(TCP->hActionMenu, 3, MF_BYPOSITION | TCP->CMS<<3); - SetWindowText(TCP->hCMSWnd, "CMS Off"); -#endif - Bufferptr = Cmdprintf(Session, Bufferptr, "CMS Server Disabled\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - PORT = PORT->PORTPOINTER; - } - } - } - - // Bad port - - strcpy(Bufferptr, BADPORT); - Bufferptr += (int)strlen(BADPORT); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - - -VOID STARTCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char _REPLYBUFFER[1000] = ""; - char * ptr, * Context; - - int portno; - - struct TNCINFO * TNC; - struct TCPINFO * TCP; - struct PORTCONTROL * PORT = PORTTABLE; - int n = NUMBEROFPORTS; - - // Get port number - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - { - portno = atoi (ptr); - - if (portno) - { - while (n--) - { - if (PORT->PORTNUMBER == portno) - { - TNC = TNCInfo[portno]; - - if (!TNC || !TNC->TCPInfo) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not a Telnet Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - TCP = TNC->TCPInfo; - TCP->CMS = 1; -#ifndef LINBPQ - CheckMenuItem(TCP->hActionMenu, 3, MF_BYPOSITION | TCP->CMS<<3); -#endif - CheckCMS(TNC); - - Bufferptr = Cmdprintf(Session, Bufferptr, "CMS Server Enabled\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - PORT = PORT->PORTPOINTER; - } - } - } - - // Bad port - - strcpy(Bufferptr, BADPORT); - Bufferptr += (int)strlen(BADPORT); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - - -VOID STOPPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char _REPLYBUFFER[1000] = ""; - char * ptr, * Context; - - int portno; - struct PORTCONTROL * PORT = PORTTABLE; - int n = NUMBEROFPORTS; - - // Get port number - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - { - portno = atoi (ptr); - - if (portno) - { - while (n--) - { - if (PORT->PORTNUMBER == portno) - { - struct KISSINFO * KISS; - - if (PORT->PORTSTOPCODE) - { - // Port has Close Routine - - PORT->PortStopped = TRUE; - - if (PORT->PORTSTOPCODE(PORT)) - Bufferptr = Cmdprintf(Session, Bufferptr, "Port Closed\r"); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Port Close Failed\r"); - - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - if (PORT->PORTTYPE != 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not a KISS Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (PORT->PORTIPADDR.s_addr || PORT->KISSSLAVE) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not a serial port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - KISS = (struct KISSINFO *) PORT; - - if (KISS->FIRSTPORT != KISS) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not first port of a Multidrop Set\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - CloseKISSPort(PORT); - PORT->PortStopped = TRUE; - Bufferptr = Cmdprintf(Session, Bufferptr, "Port Closed\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - - return; - } - PORT = PORT->PORTPOINTER; - } - } - } - - // Bad port - - strcpy(Bufferptr, BADPORT); - Bufferptr += (int)strlen(BADPORT); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - - -VOID STARTPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char _REPLYBUFFER[1000] = ""; - char * ptr, * Context; - - int portno; - struct PORTCONTROL * PORT = PORTTABLE; - int n = NUMBEROFPORTS; - - // Get port number - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - { - portno = atoi (ptr); - - if (portno) - { - while (n--) - { - if (PORT->PORTNUMBER == portno) - { - struct KISSINFO * KISS; - - if (PORT->PORTSTARTCODE) - { - // Port has Open Routine - - PORT->PortStopped = FALSE; - - if (PORT->PORTSTARTCODE(PORT)) - Bufferptr = Cmdprintf(Session, Bufferptr, "Port Opened\r"); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Port Open Failed\r"); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - - if (PORT->PORTTYPE != 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not a KISS Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (PORT->PORTIPADDR.s_addr || PORT->KISSSLAVE) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not a serial port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - KISS = (struct KISSINFO *) PORT; - - if (KISS->FIRSTPORT != KISS) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not first port of a Multidrop Set\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (OpenConnection(PORT)) - Bufferptr = Cmdprintf(Session, Bufferptr, "Port Opened\r"); - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Port Open Failed\r"); - - PORT->PortStopped = FALSE; - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - PORT = PORT->PORTPOINTER; - } - } - } - - // Bad port - - strcpy(Bufferptr, BADPORT); - Bufferptr += (int)strlen(BADPORT); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - - - -int ASYSEND(struct PORTCONTROL * PortVector, char * buffer, int count); -int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); - -VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char _REPLYBUFFER[1000] = ""; - char * ptr, * Context; - - int portno = 0; - struct PORTCONTROL * PORT = PORTTABLE; - int n = NUMBEROFPORTS; - UCHAR KissString[128]; - UCHAR ENCBUFF[256]; - int KissLen = 0; - unsigned char * Kissptr = KissString; - - // Send KISS Command to TNC - - // Get port number - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - { - portno = atoi (ptr); - ptr = strtok_s(NULL, " ", &Context); - - while (ptr && ptr[0] && KissLen < 120) - { - *(Kissptr++) = atoi (ptr); - KissLen++; - ptr = strtok_s(NULL, " ", &Context); - - } - } - - if (portno == 0 || KissLen == 0) - { - strcpy(Bufferptr, BADMSG); - Bufferptr += (int)strlen(BADMSG); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - while (n--) - { - if (PORT->PORTNUMBER == portno) - { - struct KISSINFO * KISS; - - if (PORT->PORTTYPE != 0 && PORT->PORTTYPE != 22) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not a KISS Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - KISS = (struct KISSINFO *) PORT; - - if (KISS->FIRSTPORT != KISS) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not first port of a Multidrop Set\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // Send Command - - KissLen = KissEncode(KissString, ENCBUFF, KissLen); - - PORT = (struct PORTCONTROL *)KISS->FIRSTPORT; // ALL FRAMES GO ON SAME Q - - PORT->Session = Session; - PORT->LastKISSCmdTime = time(NULL); - - ASYSEND(PORT, ENCBUFF, KissLen); - - Bufferptr = Cmdprintf(Session, Bufferptr, "Command Sent\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - PORT = PORT->PORTPOINTER; - } - - - // Bad port - - strcpy(Bufferptr, BADPORT); - Bufferptr += (int)strlen(BADPORT); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - - -VOID FINDBUFFS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - FindLostBuffers(); - -#ifdef WIN32 - Bufferptr = Cmdprintf(Session, Bufferptr, "Lost buffer info dumped to Debugview\r"); -#else - Bufferptr = Cmdprintf(Session, Bufferptr, "Lost buffer info dumped to syslog\r"); -#endif - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID FLMSG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD) -{ - // Telnet Connection from FLMSG - CLOSECURRENTSESSION(Session); // Kills any crosslink, plus local link - ReleaseBuffer((UINT *)REPLYBUFFER); -} - -BOOL CheckExcludeList(UCHAR * Call) -{ - UCHAR * ptr1 = ExcludeList; - - while (*ptr1) - { - if (memcmp(Call, ptr1, 6) == 0) - return FALSE; - - ptr1 += 7; - } - - return TRUE; -} - - -void ListExcludedCalls(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - - UCHAR * ptr = ExcludeList; - char Normcall[10] = ""; - UCHAR AXCall[8] = ""; - - if (*CmdTail == ' ') - goto DISPLIST; - - if (*CmdTail == 'Z') - { - // CLEAR LIST - - memset(ExcludeList, 0, 70); - goto DISPLIST; - } - - ConvToAX25(CmdTail, AXCall); - - if (strlen(ExcludeList) < 70) - strcat(ExcludeList, AXCall); - -DISPLIST: - - while (*ptr) - { - Normcall[ConvFromAX25(ptr, Normcall)] = 0; - Bufferptr = Cmdprintf(Session, Bufferptr, "%s ", Normcall); - ptr += 7; - } - - *(Bufferptr++) = '\r'; - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -BOOL isSYSOP(TRANSPORTENTRY * Session, char * Bufferptr) -{ - if (Session->PASSWORD != 0xFFFF) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", PASSWORDMSG); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - - return FALSE; - } - - return TRUE; -} - -VOID HELPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - int FileSize; - char MsgFile[MAX_PATH]; - FILE * hFile; - char * MsgBytes; - struct stat STAT; - char * ptr1, * ptr, * ptr2; - - sprintf_s(MsgFile, sizeof(MsgFile), "%s/%s", BPQDirectory, "NodeHelp.txt"); - - if (stat(MsgFile, &STAT) == -1) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Help file not found\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - FileSize = STAT.st_size; - - hFile = fopen(MsgFile, "rb"); - - if (hFile == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Help file not found\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - MsgBytes = malloc(FileSize+1); - - fread(MsgBytes, 1, FileSize, hFile); - - fclose(hFile); - - MsgBytes[FileSize] = 0; - - ptr1 = MsgBytes; - - // Replace LF or CRLF with CR - - // First remove cr from crlf - - while(ptr2 = strstr(ptr1, "\r\n")) - { - memmove(ptr2, ptr2 + 1, strlen(ptr2)); - } - - // Now replace lf with cr - - ptr1 = MsgBytes; - - while (*ptr1) - { - if (*ptr1 == '\n') - *(ptr1) = '\r'; - - ptr1++; - } - - ptr = ptr1 = MsgBytes; - - Bufferptr = Cmdprintf(Session, Bufferptr, "\r"); - - // Read and send a line at a time, converting any line endings into CR - - while (*ptr1) - { - if (*ptr1 == '\r') - { - *(ptr1++) = 0; - - Bufferptr = Cmdprintf(Session, Bufferptr, "%s\r", ptr); - - ptr = ptr1; - } - else - ptr1++; - } - - free(MsgBytes); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -int UZ7HOSetFreq(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMESSAGE buff, PMSGWITHLEN buffptr); -int UZ7HOSetModem(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMESSAGE buff, PMSGWITHLEN buffptr); -int UZ7HOSetFlags(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMESSAGE buff, PMSGWITHLEN buffptr); - - -VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char * Cmd; - int port; - struct TNCINFO * TNC; - struct AGWINFO * AGW = 0; - PDATAMESSAGE buff; - PMSGWITHLEN buffptr; - - CmdTail = CmdTail + (OrigCmdBuffer - COMMANDBUFFER); // Replace with original case version - - Cmd = strlop(CmdTail, ' '); - port = atoi(CmdTail); - - // remove trailing spaces - - while(strlen(Cmd) && Cmd[strlen(Cmd) - 1] == ' ') - Cmd[strlen(Cmd) - 1] = 0; - - TNC = TNCInfo[port]; - - if (TNC) - AGW = TNC->AGWInfo; - - if (TNC == 0 || AGW == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - %d is not UZ7HO port\r", port); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (_memicmp(Cmd, "FREQ", 4) == 0 || _memicmp(Cmd, "MODEM", 5) == 0 || _memicmp(Cmd, "FLAGS", 5) == 0) - { - // Pass to procesing code in UZ7HO driver. This expects command in a PDATAMESSAGE amd places response in a PMSGWITHLEN buffer - - buff = (PDATAMESSAGE)GetBuff(); - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "UZ7HO Command Failed - no buffers\r"); - if (buff) - ReleaseBuffer(buff); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - - - buff->LENGTH = sprintf(buff->L2DATA, "%s\r", Cmd) + MSGHDDRLEN + 1; - - if (_memicmp(Cmd, "FREQ", 4) == 0) - UZ7HOSetFreq(port, TNC, AGW, buff, buffptr); - else if (_memicmp(Cmd, "FLAGS", 5) == 0) - UZ7HOSetFlags(port, TNC, AGW, buff, buffptr); - else - UZ7HOSetModem(port, TNC, AGW, buff, buffptr); - - - Bufferptr = Cmdprintf(Session, Bufferptr, buffptr->Data); - - ReleaseBuffer(buff); - ReleaseBuffer(buffptr); - } - else - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid UZ7HO Command (not Freq Modem or FLAGS)\r"); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - -VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - int port; - struct PORTCONTROL * PORT; - struct KISSINFO * KISS; - - CmdTail = CmdTail + (OrigCmdBuffer - COMMANDBUFFER); // Replace with original case version - - port = atoi(CmdTail); - - PORT = GetPortTableEntryFromPortNum(port); - - if (PORT == NULL || PORT->PORTTXROUTINE != KISSTX) // Must be a kiss like port - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port %d is not a KISS port\r", port); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - KISS = (struct KISSINFO *)PORT; - - if (KISS->QtSMModem == 0) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port %d has no QtSM information\r", port); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "Modem %s Centre frequency %d\r", - (KISS->QtSMModem) ? KISS->QtSMModem : "Not Available", KISS->QtSMFreq); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; -} - - - - - - - - - - - - - diff --git a/Cmd.c b/Cmd.c index 5a194cf..738e2f9 100644 --- a/Cmd.c +++ b/Cmd.c @@ -44,6 +44,8 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include "tncinfo.h" #include "telnetserver.h" + + //#include "GetVersion.h" //#define DllImport __declspec( dllimport ) @@ -64,12 +66,12 @@ VOID L2SENDXID(struct _LINKTABLE * LINK); int CountBits(unsigned long in); VOID SaveMH(); BOOL RestartTNC(struct TNCINFO * TNC); -void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); +void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); VOID WriteMiniDump(); int CheckKissInterlock(struct PORTCONTROL * PORT, int Exclusive); int seeifInterlockneeded(struct PORTCONTROL * PORT); -extern VOID KISSTX(); +extern VOID KISSTX(struct KISSINFO * KISS, PMESSAGE Buffer); char COMMANDBUFFER[81] = ""; // Command Hander input buffer char OrigCmdBuffer[81] = ""; // Command Hander input buffer before toupper @@ -134,8 +136,8 @@ int L4FRAMESRETRIED = 0; int OLDFRAMES = 0; int L3FRAMES = 0; -VOID SENDSABM(); -VOID RESET2(); +VOID SENDSABM(struct _LINKTABLE * LINK); +VOID RESET2(struct _LINKTABLE * LINK); int APPL1 = 0; int PASSCMD = 0; @@ -149,33 +151,35 @@ char * ALIASPTR = &CMDALIAS[0][0]; extern int RigReconfigFlag; -CMDX COMMANDS[]; -int CMDXLEN = sizeof (CMDX); + +struct CMDX COMMANDS[]; + +int CMDXLEN = sizeof (struct CMDX); VOID SENDNODESMSG(); -VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STOPCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STARTCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STOPPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STARTPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID FINDBUFFS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID WL2KSYSOP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID AXRESOLVER(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID AXMHEARD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWTELNET(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWAGW(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWARP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWNAT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID PING(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWIPROUTE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID FLMSG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD); -void ListExcludedCalls(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID APRSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID RECONFIGTELNET (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID HELPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD); -VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD); +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); +VOID STOPPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID STARTPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID FINDBUFFS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID WL2KSYSOP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID AXRESOLVER(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID AXMHEARD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID SHOWTELNET(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID SHOWAGW(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID SHOWARP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID SHOWNAT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID PING(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID SHOWIPROUTE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID FLMSG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD); +void ListExcludedCalls(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID APRSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID RECONFIGTELNET (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID HELPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); +VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD); +VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD); void hookL2SessionAttempt(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK); @@ -242,7 +246,7 @@ char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char } -VOID SENDNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID SENDNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { SENDNODESMSG(); @@ -252,7 +256,7 @@ VOID SENDNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID SAVEMHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID SAVEMHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { SaveMH(); @@ -262,7 +266,7 @@ VOID SAVEMHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID SAVENODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID SAVENODES(struct _TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { SaveNodes(); @@ -272,7 +276,7 @@ VOID SAVENODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID DUMPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID DUMPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { WriteMiniDump(); @@ -282,7 +286,7 @@ VOID DUMPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID RIGRECONFIG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID RIGRECONFIG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { if (!ProcessConfig()) { @@ -297,7 +301,7 @@ VOID RIGRECONFIG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMD SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID REBOOT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID REBOOT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { if (Reboot()) { @@ -313,7 +317,7 @@ VOID REBOOT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * C SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID RESTART(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID RESTART(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { if (Restart()) { @@ -329,7 +333,7 @@ VOID RESTART(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID RESTARTTNC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID RESTARTTNC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char * ptr, *Context; int portno; @@ -373,20 +377,20 @@ VOID RESTARTTNC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX UCHAR VALNODESFLAG = 0, EXTONLY = 0; -VOID PORTVAL (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); +VOID PORTVAL (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); -VOID VALNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID VALNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { VALNODESFLAG = 1; PORTVAL(Session, Bufferptr, CmdTail, CMD); } -VOID EXTPORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID EXTPORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { EXTONLY = 1; PORTVAL(Session, Bufferptr, CmdTail, CMD); } -VOID PORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID PORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // PROCESS PORT VALUE COMMANDS @@ -501,7 +505,7 @@ VOID PORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * } -VOID SWITCHVAL (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID SWITCHVAL (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // Update switch 8 bit value @@ -546,7 +550,7 @@ VOID SWITCHVAL (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX } -VOID SWITCHVALW (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID SWITCHVALW (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // Update switch 16 bit value @@ -709,7 +713,7 @@ BOOL cATTACHTOBBS(TRANSPORTENTRY * Session, UINT Mask, int Paclen, int * AnySess return FALSE; } -VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { BOOL CONFAILED = 0; UINT CONERROR ; @@ -820,13 +824,13 @@ VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * } -VOID CMDI00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDI00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { Bufferptr = Cmdprintf(Session, Bufferptr, "%s", INFOMSG); SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID CMDV00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDV00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { if (sizeof(void *) == 4) Bufferptr = Cmdprintf(Session, Bufferptr, "Version %s\r", VersionString); @@ -836,14 +840,14 @@ VOID CMDV00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * C SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID BYECMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID BYECMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { CLOSECURRENTSESSION(Session); // Kills any crosslink, plus local link ReleaseBuffer((UINT *)REPLYBUFFER); return; } -VOID CMDPAC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDPAC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // SET PACLEN FOR THIS SESSION @@ -865,7 +869,7 @@ VOID CMDPAC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * C SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID CMDIDLE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDIDLE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // SET IDLETIME FOR THIS SESSION @@ -887,7 +891,7 @@ VOID CMDIDLE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID CMDT00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDT00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // SET L4 TIMEOUT FOR CONNECTS ON THIS SESSION @@ -912,7 +916,7 @@ VOID CMDT00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * C UCHAR PWLen; char PWTEXT[80]; -VOID PWDCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID PWDCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char * ptr, *Context; USHORT pwsum = 0; @@ -980,7 +984,7 @@ VOID PWDCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * C return; } -VOID CMDSTATS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDSTATS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char * ptr, *Context; int Port = 0, cols = NUMBEROFPORTS, i; @@ -1214,7 +1218,7 @@ VOID CMDSTATS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID CMDL00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDL00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // PROCESS 'LINKS' MESSAGE @@ -1250,7 +1254,7 @@ VOID CMDL00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * C } -VOID CMDS00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDS00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // PROCESS 'USERS' @@ -1322,7 +1326,7 @@ CMDS60: extern int MasterPort[MAXBPQPORTS+1]; // Pointer to first BPQ port for a specific MPSK or UZ7HO host -VOID CMDP00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDP00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // Process PORTS Message @@ -1577,7 +1581,7 @@ char * DisplayRoute(TRANSPORTENTRY * Session, char * Bufferptr, struct ROUTE * } -VOID CMDR00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDR00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { struct ROUTE * Routes = NEIGHBOURS; int MaxRoutes = MAXNEIGHBOURS; @@ -1867,7 +1871,7 @@ SendReply: } -VOID LISTENCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID LISTENCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // PROCESS LISTEN COMMAND @@ -1950,7 +1954,7 @@ VOID LISTENCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX } -VOID UNPROTOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID UNPROTOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // PROCESS UNPROTO COMMAND @@ -2019,7 +2023,7 @@ VOID UNPROTOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX return; } -VOID CALCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CALCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // PROCESS CAL COMMAND @@ -2072,7 +2076,7 @@ VOID CALCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * C -VOID CQCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CQCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // Send a CQ Beacon on a radio port. Must be in LISTEN state @@ -2278,9 +2282,9 @@ BOOL FindLink(UCHAR * LinkCall, UCHAR * OurCall, int Port, struct _LINKTABLE ** return FALSE; } -VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD); +VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD); -VOID CMDC00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDC00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // PROCESS CONNECT COMMAND @@ -2302,7 +2306,7 @@ VOID CMDC00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * C char PortString[10]; char cmdCopy[256]; struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)PORT; - char toCall[12], fromCall[12]; + #ifdef EXCLUDEBITS @@ -2920,7 +2924,7 @@ BOOL DecodeCallString(char * Calls, BOOL * Stay, BOOL * Spy, UCHAR * AXCalls) } -VOID LINKCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID LINKCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // PROCESS *** LINKED to CALLSIGN @@ -3112,7 +3116,7 @@ int WildCmp(char * pattern, char * string) return 0; } -VOID CMDN00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID CMDN00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { struct DEST_LIST * Dest = DESTS; int count = MAXDESTS, i; @@ -3633,7 +3637,7 @@ SendReply: SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID CMDQUERY(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD) +VOID CMDQUERY(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD) { // DISPLAY AVAILABLE COMMANDS @@ -3642,7 +3646,7 @@ VOID CMDQUERY(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * char ApplList[2048]; char * out = ApplList; - CMDX * CMD = &COMMANDS[APPL1]; + struct CMDX * CMD = &COMMANDS[APPL1]; for (n = 0; n < NumberofAppls; n++) { @@ -3672,7 +3676,7 @@ VOID CMDQUERY(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * char * FormatMH(MHSTRUC * MH, char Format); -VOID MHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID MHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // DISPLAY HEARD LIST @@ -3854,7 +3858,7 @@ VOID MHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CM int Rig_Command(TRANSPORTENTRY * Session, char * Command); -VOID RADIOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD) +VOID RADIOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD) { char * ptr; @@ -3883,7 +3887,7 @@ VOID RADIOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * VOID SendNRRecordRoute(struct DEST_LIST * DEST, TRANSPORTENTRY * Session); -VOID NRRCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD) +VOID NRRCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD) { // PROCESS 'NRR - Netrom Record Route' COMMAND @@ -3953,7 +3957,7 @@ int CHECKINTERLOCK(struct PORTCONTROL * OURPORT) return 0; } -VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD) +VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD) { // ATTACH to a PACTOR or similar port @@ -4318,16 +4322,17 @@ checkattachandcall: // SYSOP COMMANDS -CMDX COMMANDS[] = +struct CMDX COMMANDS[] = { - "SAVENODES ",8, SAVENODES, 0, - "TELRECONFIG ",4, RECONFIGTELNET, 0, - "SAVEMH ",6, SAVEMHCMD, 0, - "REBOOT ",6, REBOOT, 0, - "RIGRECONFIG ",8 , RIGRECONFIG, 0, - "RESTART ",7,RESTART,0, - "RESTARTTNC ",10,RESTARTTNC,0, - "SENDNODES ",8,SENDNODES,0, +// "SAVENODES ",8, SAVENODES(struct _TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD), 0, + "SAVENODES ",8, &SAVENODES, 0, + "TELRECONFIG ",4, &RECONFIGTELNET, 0, + "SAVEMH ",6, &SAVEMHCMD, 0, + "REBOOT ",6, &REBOOT, 0, + "RIGRECONFIG ",8, &RIGRECONFIG, 0, + "RESTART ",7, &RESTART,0, + "RESTARTTNC ",10,&RESTARTTNC,0, + "SENDNODES ",8, &SENDNODES,0, "EXTRESTART ",10, EXTPORTVAL, offsetof(EXTPORTDATA, EXTRESTART), "TXDELAY ",3, PORTVAL, offsetof(PORTCONTROLX, PORTTXDELAY), "MAXFRAME ",3, PORTVAL, offsetof(PORTCONTROLX, PORTWINDOW), @@ -4457,9 +4462,9 @@ CMDX COMMANDS[] = "..FLMSG ",7,FLMSG,0 }; -CMDX * CMD = NULL; +struct CMDX * CMD = NULL; -int NUMBEROFCOMMANDS = sizeof(COMMANDS)/sizeof(CMDX); +int NUMBEROFCOMMANDS = sizeof(COMMANDS)/sizeof(struct CMDX); char * ReplyPointer; // Pointer into reply buffer @@ -4952,7 +4957,7 @@ VOID StatsTimer() int x = 17; } - if (PORT->PORTTXROUTINE == KISSTX && (KISS->QtSMStats || KISS->FIRSTPORT->PORT.QtSMPort)) // KISS Port QtSM Stats + if ((void *)PORT->PORTTXROUTINE == (void *)KISSTX && (KISS->QtSMStats || KISS->FIRSTPORT->PORT.QtSMPort)) // KISS Port QtSM Stats { } else @@ -4990,7 +4995,7 @@ extern struct AXIPPORTINFO * Portlist[]; #define TCPConnected 4 -VOID AXRESOLVER(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID AXRESOLVER(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // DISPLAY AXIP Resolver info @@ -5080,7 +5085,7 @@ VOID AXRESOLVER(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID AXMHEARD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID AXMHEARD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // DISPLAY AXIP Mheard info @@ -5150,7 +5155,7 @@ extern char WL2KLoc[7]; BOOL GetWL2KSYSOPInfo(char * Call, char * _REPLYBUFFER); BOOL UpdateWL2KSYSOPInfo(char * Call, char * SQL); -VOID WL2KSYSOP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID WL2KSYSOP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char _REPLYBUFFER[1000] = ""; @@ -5302,7 +5307,7 @@ VOID WL2KSYSOP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX VOID CloseKISSPort(struct PORTCONTROL * PortVector); -VOID STOPCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID STOPCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char _REPLYBUFFER[1000] = ""; char * ptr, * Context; @@ -5363,7 +5368,7 @@ VOID STOPCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * } -VOID STARTCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID STARTCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char _REPLYBUFFER[1000] = ""; char * ptr, * Context; @@ -5423,7 +5428,7 @@ VOID STARTCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * } -VOID STOPPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID STOPPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char _REPLYBUFFER[1000] = ""; char * ptr, * Context; @@ -5507,7 +5512,7 @@ VOID STOPPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * } -VOID STARTPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID STARTPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char _REPLYBUFFER[1000] = ""; char * ptr, * Context; @@ -5599,7 +5604,7 @@ VOID STARTPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX int ASYSEND(struct PORTCONTROL * PortVector, char * buffer, int count); int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); -VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char _REPLYBUFFER[1000] = ""; char * ptr, * Context; @@ -5690,7 +5695,7 @@ VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * } -VOID FINDBUFFS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID FINDBUFFS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { FindLostBuffers(); @@ -5702,7 +5707,7 @@ VOID FINDBUFFS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID FLMSG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD) +VOID FLMSG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD) { // Telnet Connection from FLMSG CLOSECURRENTSESSION(Session); // Kills any crosslink, plus local link @@ -5725,7 +5730,7 @@ BOOL CheckExcludeList(UCHAR * Call) } -void ListExcludedCalls(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +void ListExcludedCalls(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { UCHAR * ptr = ExcludeList; @@ -5774,7 +5779,7 @@ BOOL isSYSOP(TRANSPORTENTRY * Session, char * Bufferptr) return TRUE; } -VOID HELPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID HELPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { int FileSize; char MsgFile[MAX_PATH]; @@ -5863,7 +5868,7 @@ int UZ7HOSetModem(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMES int UZ7HOSetFlags(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMESSAGE buff, PMSGWITHLEN buffptr); -VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char * Cmd; int port; @@ -5934,7 +5939,7 @@ VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * return; } -VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { int port; struct PORTCONTROL * PORT; @@ -5946,7 +5951,7 @@ VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * PORT = GetPortTableEntryFromPortNum(port); - if (PORT == NULL || PORT->PORTTXROUTINE != KISSTX) // Must be a kiss like port + if (PORT == NULL || (void *)PORT->PORTTXROUTINE != (void *)KISSTX) // Must be a kiss like port { Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port %d is not a KISS port\r", port); SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); diff --git a/CommonCode.c b/CommonCode.c index bfcc8a2..3821bb1 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -571,7 +571,7 @@ void * zalloc(int len) return ptr; } -char * strlop(char * buf, char delim) +char * strlop(const char * buf, char delim) { // Terminate buf at delim, and return rest of string @@ -692,7 +692,7 @@ VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer) } VOID CheckForDetach(struct TNCINFO * TNC, int Stream, struct STREAMINFO * STREAM, - VOID TidyCloseProc(), VOID ForcedCloseProc(), VOID CloseComplete()) + VOID TidyCloseProc(struct TNCINFO * TNC, int Stream), VOID ForcedCloseProc(struct TNCINFO * TNC, int Stream), VOID CloseComplete(struct TNCINFO * TNC, int Stream)) { void ** buffptr; @@ -1020,7 +1020,7 @@ BOOL ProcessIncommingConnectEx(struct TNCINFO * TNC, char * Call, int Stream, BO char * Config; static char * ptr1, * ptr2; -BOOL ReadConfigFile(int Port, int ProcLine()) +BOOL ReadConfigFile(int Port, int ProcLine(char * buf, int Port)) { char buf[256],errbuf[256]; @@ -2437,7 +2437,7 @@ static struct speed_struct HANDLE OpenCOMPort(VOID * pPort, int speed, BOOL SetDTR, BOOL SetRTS, BOOL Quiet, int Stopbits) { char Port[256]; - char buf[100]; + char buf[512]; // Linux Version. @@ -4759,7 +4759,7 @@ LRESULT CALLBACK UIWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam extern struct DATAMESSAGE * REPLYBUFFER; char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char * format, ...); -void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { char FN[250]; FILE *hFile; diff --git a/DRATS.c b/DRATS.c index 73baaef..8c7e9e9 100644 --- a/DRATS.c +++ b/DRATS.c @@ -563,7 +563,7 @@ void DRATSConnectionLost(struct ConnectionInfo * sockptr) #define ZEXPORT __stdcall #endif -#include "zlib.h" +#include int doinflate(unsigned char * source, unsigned char * dest, int Len, int destlen, int * outLen) diff --git a/FBBRoutines.c b/FBBRoutines.c index 051afe6..67ca4ee 100644 --- a/FBBRoutines.c +++ b/FBBRoutines.c @@ -24,7 +24,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include "bpqmail.h" int32_t Encode(char * in, char * out, int32_t inlen, BOOL B1Protocol, int Compress); - +void MQTTMessageEvent(void* message); int MaxRXSize = 99999; int MaxTXSize = 99999; @@ -807,6 +807,11 @@ VOID FlagSentMessages(CIRCUIT * conn, struct UserInfo * user) FBBHeader->FwdMsg->datechanged=time(NULL); } +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(FBBHeader->FwdMsg); +#endif + FBBHeader->FwdMsg->Locked = 0; // Unlock conn->UserPointer->ForwardingInfo->MsgCount--; } diff --git a/FLDigi.c b/FLDigi.c index 0e6711c..89d1597 100644 --- a/FLDigi.c +++ b/FLDigi.c @@ -65,12 +65,12 @@ extern int (WINAPI FAR *GetModuleFileNameExPtr)(); ; int SemHeldByAPI; -static void ConnecttoFLDigiThread(void * portptr); +void ConnecttoFLDigiThread(void * portptr); void CreateMHWindow(); int Update_MH_List(struct in_addr ipad, char * call, char proto); -static int ConnecttoFLDigi(); +int ConnecttoFLDigi(int port); static int ProcessReceivedData(int bpqport); static int ProcessLine(char * buf, int Port); int KillTNC(struct TNCINFO * TNC); @@ -102,8 +102,6 @@ VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); -char * strlop(char * buf, char delim); - extern UCHAR BPQDirectory[]; #define MAXMPSKPORTS 16 @@ -1483,14 +1481,14 @@ static int ProcessLine(char * buf, int Port) return (TRUE); } -static int ConnecttoFLDigi(int port) +int ConnecttoFLDigi(int port) { _beginthread(ConnecttoFLDigiThread, 0, (void *)(size_t)port); return 0; } -static VOID ConnecttoFLDigiThread(void * portptr) +VOID ConnecttoFLDigiThread(void * portptr) { int port = (int)(size_t)portptr; char Msg[255]; @@ -2581,7 +2579,7 @@ VOID ProcessFLDigiData(struct TNCINFO * TNC, UCHAR * Input, int Len, char Channe { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // Make sure app is available diff --git a/FreeDATA.c b/FreeDATA.c index 2b95f66..01fb151 100644 --- a/FreeDATA.c +++ b/FreeDATA.c @@ -347,41 +347,6 @@ loop: return 1; } -BOOL FreeDataReadConfigFile(int Port, int ProcLine()) -{ - char buf[256],errbuf[256]; - - Config = PortConfig[Port]; - - if (Config) - { - // Using config from bpq32.cfg - - if (strlen(Config) == 0) - { - return TRUE; - } - - ptr1 = Config; - ptr2 = strchr(ptr1, 13); - - if (!ProcLine(buf, Port)) - { - WritetoConsoleLocal("\n"); - WritetoConsoleLocal("Bad config record "); - WritetoConsoleLocal(errbuf); - } - } - else - { - sprintf(buf," ** Error - No Configuration info in bpq32.cfg"); - WritetoConsoleLocal(buf); - } - - return (TRUE); -} - - VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); @@ -867,7 +832,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) char Message[256]; int Len, ret; - Len = sprintf(Message, TXF); + Len = sprintf(Message, "%s", TXF); ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); if (buffptr) @@ -1881,7 +1846,7 @@ VOID FreeDataProcessTNCMessage(struct TNCINFO * TNC, char * Call, unsigned char if (App < 32) { - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // if SendTandRtoRelay set and Appl is RMS change to RELAY @@ -2242,7 +2207,7 @@ VOID FreeDataProcessNewConnect(struct TNCINFO * TNC, char * fromCall, char * toC if (App < 32) { - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // if SendTandRtoRelay set and Appl is RMS change to RELAY @@ -2476,7 +2441,7 @@ static void SendCQ(struct TNCINFO * TNC) char Message[256]; int Len, ret; - Len = sprintf(Message, CQ); + Len = sprintf(Message, "%s", CQ); ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); } @@ -2491,7 +2456,7 @@ static void SendBeacon(struct TNCINFO * TNC, int Interval) if (Interval > 0) Len = sprintf(Message, Template1, Interval); else - Len = sprintf(Message, Template2); + Len = sprintf(Message, "%s", Template2); ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); } @@ -3682,7 +3647,7 @@ int FreeDataDisconnect(struct TNCINFO * TNC) // return FreeDataSendCommand(TNC, "D"); - Len = sprintf(Msg, Disconnect); + Len = sprintf(Msg, "%s", Disconnect); return send(TNC->TCPDataSock, Msg, Len, 0); } @@ -3694,7 +3659,7 @@ int FreeGetData(struct TNCINFO * TNC) char Msg[128]; int Len; - Len = sprintf(Msg, GetData); + Len = sprintf(Msg, "%s", GetData); return send(TNC->TCPDataSock, Msg, Len, 0); } diff --git a/HSMODEM.c b/HSMODEM.c index 7675863..a9af669 100644 --- a/HSMODEM.c +++ b/HSMODEM.c @@ -309,47 +309,10 @@ loop: return 1; } -BOOL HSMODEMReadConfigFile(int Port, int ProcLine()) -{ - char buf[256],errbuf[256]; - - Config = PortConfig[Port]; - - if (Config) - { - // Using config from bpq32.cfg - - if (strlen(Config) == 0) - { - return TRUE; - } - - ptr1 = Config; - ptr2 = strchr(ptr1, 13); - - if (!ProcLine(buf, Port)) - { - WritetoConsoleLocal("\n"); - WritetoConsoleLocal("Bad config record "); - WritetoConsoleLocal(errbuf); - } - } - else - { - sprintf(buf," ** Error - No Configuration info in bpq32.cfg"); - WritetoConsoleLocal(buf); - } - - return (TRUE); -} - - - VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - static time_t ltime; diff --git a/HTTPcode.c b/HTTPcode.c index bd96157..2c0a8dd 100644 --- a/HTTPcode.c +++ b/HTTPcode.c @@ -38,7 +38,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #define ZEXPORT __stdcall #endif -#include "zlib.h" +#include #define CKernel #include "httpconnectioninfo.h" @@ -102,7 +102,6 @@ extern int NumberofPorts; extern UCHAR ConfigDirectory[260]; -char * strlop(char * buf, char delim); VOID sendandcheck(SOCKET sock, const char * Buffer, int Len); int CompareNode(const void *a, const void *b); int CompareAlias(const void *a, const void *b); diff --git a/HanksRT.c b/HanksRT.c index 3a7d538..79e1044 100644 --- a/HanksRT.c +++ b/HanksRT.c @@ -1186,7 +1186,7 @@ static BOOL CheckforDups(ChatCIRCUIT * circuit, char * Call, char * Msg) // Duplicate, so discard, but save time DupInfo[i].DupTime = Now; - Logprintf(LOG_CHAT, circuit, '?', "Duplicate Message From %s %s supressed", Call, Msg); + Logprintf(LOG_CHAT, circuit, '?', "Duplicate Message From %s %s suppressed", Call, Msg); return TRUE; // Duplicate } diff --git a/IPCode.c b/IPCode.c index ded97db..80939d1 100644 --- a/IPCode.c +++ b/IPCode.c @@ -95,9 +95,13 @@ TODo ?Multiple Adapters #pragma comment(lib, "IPHLPAPI.lib") #endif -#include "pcap.h" +#include +#ifdef WIN32 int pcap_sendpacket(pcap_t *p, u_char *buf, int size); +#else + PCAP_API int pcap_sendpacket(pcap_t *, const u_char *, int); +#endif #ifndef LINBPQ #include "kernelresource.h" @@ -4731,7 +4735,7 @@ void OpenTAP() extern struct DATAMESSAGE * REPLYBUFFER; char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char * format, ...); -VOID PING(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID PING(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // Send ICMP Echo Request @@ -4789,7 +4793,7 @@ VOID PING(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD return; } -VOID SHOWARP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID SHOWARP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // DISPLAY IP Gateway ARP status or Clear @@ -4884,7 +4888,7 @@ VOID SHOWARP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID SHOWNAT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID SHOWNAT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // DISPLAY IP Gateway ARP status or Clear @@ -4943,7 +4947,7 @@ int CountBits(uint32_t in) return n; } -VOID SHOWIPROUTE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID SHOWIPROUTE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // DISPLAY IP Gateway ARP status or Clear @@ -5334,7 +5338,7 @@ int ProcessSNMPPayload(UCHAR * Msg, int Len, UCHAR * Reply, int * OffPtr) // Should be nothing left } - if (RequestType = 160) + if (RequestType == 160) { int Offset = 255; int PDULen = 0; diff --git a/KISSHF.c b/KISSHF.c index 4008235..7dd76ff 100644 --- a/KISSHF.c +++ b/KISSHF.c @@ -725,7 +725,7 @@ VOID KISSHFReleaseTNC(struct TNCINFO * TNC) ReleaseOtherPorts(TNC); } -VOID KISSHFSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC) +VOID KISSHFSuspendPort(struct TNCINFO * TNC, struct TNCINFO * THISTNC) { TNC->PortRecord->PORTCONTROL.PortSuspended = 1; strcpy(TNC->WEB_TNCSTATE, "Interlocked"); diff --git a/L2Code-skigdebian.c b/L2Code-skigdebian.c deleted file mode 100644 index a36854d..0000000 --- a/L2Code-skigdebian.c +++ /dev/null @@ -1,4143 +0,0 @@ -/* -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 -*/ - -// -// C replacement for L2Code.asm -// -#define Kernel - -#define _CRT_SECURE_NO_DEPRECATE - - -#pragma data_seg("_BPQDATA") - -#include "time.h" -#include "stdio.h" - -#include "CHeaders.h" -#include "tncinfo.h" - -#define PFBIT 0x10 // POLL/FINAL BIT IN CONTROL BYTE - -#define REJSENT 1 // SET WHEN FIRST REJ IS SENT IN REPLY - // TO AN I(P) -#define RNRSET 0x2 // RNR RECEIVED FROM OTHER END -#define DISCPENDING 8 // SEND DISC WHEN ALL DATA ACK'ED -#define RNRSENT 0x10 // WE HAVE SEND RNR -#define POLLSENT 0x20 // POLL BIT OUTSTANDING - -#define ONEMINUTE 60*3 -#define TENSECS 10*3 -#define THREESECS 3*3 - - -VOID L2SENDCOMMAND(); -VOID L2ROUTINE(); -MESSAGE * SETUPL2MESSAGE(struct _LINKTABLE * LINK, UCHAR CMD); -VOID SendSupervisCmd(struct _LINKTABLE * LINK); -void SEND_RR_RESP(struct _LINKTABLE * LINK, UCHAR PF); -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); -VOID L2TIMEOUT(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT); -VOID CLEAROUTLINK(struct _LINKTABLE * LINK); -VOID SENDFRMR(struct _LINKTABLE * LINK); -char * SetupNodeHeader(struct DATAMESSAGE * Buffer); -VOID CLEARSESSIONENTRY(TRANSPORTENTRY * Session); -VOID SDFRMR(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT); -VOID SDNRCHK(struct _LINKTABLE * LINK, UCHAR CTL); -VOID RESETNS(struct _LINKTABLE * LINK, UCHAR NS); -VOID PROC_I_FRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer); -VOID RESET2X(struct _LINKTABLE * LINK); -VOID RESET2(struct _LINKTABLE * LINK); -VOID CONNECTREFUSED(struct _LINKTABLE * LINK); -VOID SDUFRM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL); -VOID SFRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, UCHAR CTL, UCHAR MSGFLAG); -VOID SDIFRM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL, UCHAR MSGFLAG); -VOID SENDCONNECTREPLY(struct _LINKTABLE * LINK); -VOID SETUPNEWL2SESSION(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR MSGFLAG); -BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE); -VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR MSGFLAG); -VOID L2SENDUA(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER); -VOID L2SENDDM(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER); -VOID L2SENDRESP(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL); -int COUNTLINKS(int Port); -VOID L2_PROCESS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL, UCHAR MSGFLAG); -TRANSPORTENTRY * SetupSessionForL2(struct _LINKTABLE * LINK); -BOOL cATTACHTOBBS(TRANSPORTENTRY * Session, UINT Mask, int Paclen, int * AnySessions); -VOID PUT_ON_PORT_Q(struct PORTCONTROL * PORT, MESSAGE * Buffer); -VOID L2SWAPADDRESSES(MESSAGE * Buffer); -BOOL FindLink(UCHAR * LinkCall, UCHAR * OurCall, int Port, struct _LINKTABLE ** REQLINK); -VOID SENDSABM(struct _LINKTABLE * LINK); -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 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); -VOID Digipeat(struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR * OurCall, int toPort, int UIOnly); -VOID DigiToMultiplePorts(struct PORTCONTROL * PORTVEC, PMESSAGE Msg); -VOID MHPROC(struct PORTCONTROL * PORT, MESSAGE * Buffer); -BOOL CheckForListeningSession(struct PORTCONTROL * PORT, MESSAGE * Msg); -VOID L2SENDINVALIDCTRL(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL); -UCHAR * SETUPADDRESSES(struct _LINKTABLE * LINK, PMESSAGE Msg); -VOID ProcessXIDCommand(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG); -int CountBits(uint32_t in); -void AttachKISSHF(struct PORTCONTROL * PORT, MESSAGE * Buffer); -void DetachKISSHF(struct PORTCONTROL * PORT); -void KISSHFConnected(struct PORTCONTROL * PORT, struct _LINKTABLE * LINK); -void WriteConnectLog(char * fromcall, char * tocall, UCHAR * Mode); -int seeifInterlockneeded(struct PORTCONTROL * PORT); -int seeifUnlockneeded(struct _LINKTABLE * LINK); -int CheckKissInterlock(struct PORTCONTROL * MYPORT, int Exclusive); -void hookL2SessionAccepted(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK); -void hookL2SessionDeleted(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK); -void hookL2SessionAttempt(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK); - - -extern int REALTIMETICKS; - -// MSGFLAG contains CMD/RESPONSE BITS - -#define CMDBIT 4 // CURRENT MESSAGE IS A COMMAND -#define RESP 2 // CURRENT MSG IS RESPONSE -#define VER1 1 // CURRENT MSG IS VERSION 1 - -// FRMR REJECT FLAGS - -#define SDINVC 1 // INVALID COMMAND -#define SDNRER 8 // INVALID N(R) - - - -UCHAR NO_CTEXT = 0; -UCHAR ALIASMSG = 0; -extern UINT APPLMASK; -static UCHAR ISNETROMMSG = 0; -UCHAR MSGFLAG = 0; -extern char * ALIASPTR; - -UCHAR QSTCALL[7] = {'Q'+'Q','S'+'S','T'+'T',0x40,0x40,0x40,0xe0}; // QST IN AX25 -UCHAR NODECALL[7] = {0x9C, 0x9E, 0x88, 0x8A, 0xA6, 0x40, 0xE0}; // 'NODES' IN AX25 FORMAT - -extern BOOL LogAllConnects; - -APPLCALLS * APPL; - -VOID L2Routine(struct PORTCONTROL * PORT, PMESSAGE Buffer) -{ - // LEVEL 2 PROCESSING - - MESSAGE * ADJBUFFER; - struct _LINKTABLE * LINK; - UCHAR * ptr; - int n; - UCHAR CTL; - uintptr_t Work; - UCHAR c; - - // Check for invalid length (< 22 7Header + 7Addr + 7Addr + CTL - - if (Buffer->LENGTH < (18 + sizeof(void *))) - { - Debugprintf("BPQ32 Bad L2 Msg Port %d Len %d", PORT->PORTNUMBER, Buffer->LENGTH); - ReleaseBuffer(Buffer); - return; - } - - PORT->L2FRAMES++; - - ALIASMSG = 0; - APPLMASK = 0; - ISNETROMMSG = 0; - - MSGFLAG = 0; // CMD/RESP UNDEFINED - - // Check for Corrupted Callsign in Origin (to keep MH list clean) - - ptr = &Buffer->ORIGIN[0]; - n = 6; - - c = *(ptr) >> 1; - - if (c == ' ') // Blank Call - { - Debugprintf("BPQ32 Blank Call Port %d", PORT->PORTNUMBER); - ReleaseBuffer(Buffer); - return; - } - - while(n--) - { - // Try a bit harder to detect corruption - - c = *(ptr++); - - if (c & 1) - { - ReleaseBuffer(Buffer); - return; - } - - c = c >> 1; - - if (!isalnum(c) && !(c == '#') && !(c == ' ')) - { - ReleaseBuffer(Buffer); - return; - } - } - - // Check Digis if present - - if ((Buffer->ORIGIN[6] & 1) == 0) // Digis - { - ptr = &Buffer->CTL; - n = 6; - - while(n--) - { - c = *(ptr++); - - if (c & 1) - { - ReleaseBuffer(Buffer); - return; - } - - c = c >> 1; - - if (!isalnum(c) && !(c == '#') && !(c == ' ')) - { - ReleaseBuffer(Buffer); - return; - } - } - } - - BPQTRACE(Buffer, TRUE); // TRACE - RX frames to APRS - - if (PORT->PORTMHEARD) - MHPROC(PORT, Buffer); - - /// TAJ added 07/12/2020 for 'all RX traffic as IfinOctects - - InOctets[PORT->PORTNUMBER] += Buffer->LENGTH - MSGHDDRLEN; - - // CHECK THAT ALL DIGIS HAVE BEEN ACTIONED, - // AND ADJUST FOR DIGIPEATERS IF PRESENT - - n = 8; // MAX DIGIS - ptr = &Buffer->ORIGIN[6]; // End of Address bit - - while ((*ptr & 1) == 0) - { - // MORE TO COME - - ptr += 7; - - if ((*ptr & 0x80) == 0) // Digi'd bit - { - // FRAME HAS NOT BEEN REPEATED THROUGH CURRENT DIGI - - // SEE IF WE ARE MEANT TO DIGI IT - - struct XDIGI * XDigi = PORT->XDIGIS; // Cross port digi setup - - ptr -= 6; // To start of Call - - if (CompareCalls(ptr, MYCALL) || CompareAliases(ptr, MYALIAS) || - CompareCalls(ptr, PORT->PORTALIAS) || CompareCalls(ptr, PORT->PORTALIAS2)) - { - Digipeat(PORT, Buffer, ptr, 0, 0); // Digi it (if enabled) - return; - } - - while (XDigi) - { - if (CompareCalls(ptr, XDigi->Call)) - { - Digipeat(PORT, Buffer, ptr, XDigi->Port, XDigi->UIOnly); // Digi it (if enabled) - return; - } - XDigi = XDigi->Next; - } - - ReleaseBuffer(Buffer); - return; // not complete and not for us - } - n--; - - if (n == 0) - { - ReleaseBuffer(Buffer); - return; // Corrupt - no end of address bit - } - } - - // Reached End of digis, and all actioned, so can process it - - Work = (uintptr_t)&Buffer->ORIGIN[6]; - ptr -= Work; // ptr is now length of digis - - Work = (uintptr_t)Buffer; - ptr += Work; - - ADJBUFFER = (MESSAGE * )ptr; // ADJBUFFER points to CTL, etc. allowing for digis - - // GET CMD/RESP BITS - - if (Buffer->DEST[6] & 0x80) - { - if (Buffer->ORIGIN[6] & 0x80) // Both set, assume V1 - MSGFLAG |= VER1; - else - MSGFLAG |= CMDBIT; - } - else - { - if (Buffer->ORIGIN[6] & 0x80) // Only Dest Set - MSGFLAG |= RESP; - else - MSGFLAG |= VER1; // Neither, assume V1 - } - - // SEE IF FOR AN ACTIVE LINK SESSION - - CTL = ADJBUFFER->CTL; - - // IF A UI, THERE IS NO SESSION - - if (FindLink(Buffer->ORIGIN, Buffer->DEST, PORT->PORTNUMBER, &LINK)) - { - L2LINKACTIVE(LINK, PORT, Buffer,ADJBUFFER, CTL, MSGFLAG); - return; - } - - // NOT FOR ACTIVE LINK - SEE IF ADDRESSED TO OUR ADDRESSES - - // FIRST TRY PORT ADDR/ALIAS - - if(PORT->PORTBBSFLAG == 1) - goto PORTCALLISBBS; // PORT CALL/ALIAS ARE FOR BBS - - if (NODE) - goto USING_NODE; - -PORTCALLISBBS: - - // NODE IS NOT ACTIVE, SO PASS CALLS TO PORTCALL/ALIAS TO BBS - - APPLMASK = 1; - - if (CompareCalls(Buffer->DEST, NETROMCALL)) - { - ISNETROMMSG = 1; - goto FORUS; - } - if (PORT->PORTL3FLAG) // L3 Only Port? - goto NOTFORUS; // If L3ONLY, only accept calls to NETROMCALL - - ISNETROMMSG = 0; - -USING_NODE: - - if (CompareCalls(Buffer->DEST, PORT->PORTCALL)) - goto FORUS; - - ALIASMSG = 1; - - if (CompareAliases(Buffer->DEST, PORT->PORTALIAS)) // only compare 6 bits - allow any ssid - goto FORUS; - - if (NODE == 0) - goto TRYBBS; // NOT USING NODE SYSTEM - - ALIASMSG = 0; - - if (CompareCalls(Buffer->DEST, MYCALL)) - goto FORUS; - - ALIASMSG = 1; - - if (CompareAliases(Buffer->DEST, MYALIAS)) // only compare 6 bits - allow any ssid - goto FORUS; - -TRYBBS: - - if (BBS == 0) - goto NOWTRY_NODES; // NOT USING BBS CALLS - - // TRY APPLICATION CALLSIGNS/ALIASES - - - APPLMASK = 1; - ALIASPTR = &CMDALIAS[0][0]; - - n = NumberofAppls; - - APPL = APPLCALLTABLE; - - while (n--) - { - if (APPL->APPLCALL[0] > 0x40) // Valid ax.25 addr - { - // WE MAY NOT BE ALLOWED TO USE THE BBS CALL ON SOME BANDS DUE TO - // THE RATHER ODD UK LICENCING RULES! - // For backward compatibility only apply to appl 1 - - if ((PORT->PERMITTEDAPPLS & APPLMASK) != 0) - { - ALIASMSG = 0; - - if (CompareCalls(Buffer->DEST, APPL->APPLCALL)) - goto FORUS; - - ALIASMSG = 1; - - if (CompareAliases(Buffer->DEST, APPL->APPLALIAS)) // only compare 6 bits - allow any ssid - goto FORUS; - - if (CompareAliases(Buffer->DEST, APPL->L2ALIAS)) // only compare 6 bits - allow any ssid - goto FORUS; - } - } - APPLMASK <<= 1; - ALIASPTR += ALIASLEN; - APPL++; - } - - // NOT FOR US - SEE IF 'NODES' OR IP/ARP BROADCAST MESSAGE - -NOWTRY_NODES: - - if (CompareCalls(Buffer->DEST, QSTCALL)) - { - Q_IP_MSG(Buffer); // IP BROADCAST - return; - } - - if (ADJBUFFER->PID != 0xCF) // NETROM MSG? - goto NOTFORUS; // NO - - if (CompareCalls(Buffer->DEST, NODECALL)) - { - if (Buffer->L2DATA[0] == 0xff) // Valid NODES Broadcast - { - PROCESSNODEMESSAGE(Buffer, PORT); - } - } - - ReleaseBuffer(Buffer); - return; - -NOTFORUS: - // - // MAY JUST BE A REPLY TO A 'PRIMED' CQ CALL - // - if ((CTL & ~PFBIT) == SABM) - if (CheckForListeningSession(PORT, Buffer)) - return; // Used buffer to send UA - - ReleaseBuffer(Buffer); - return; - -FORUS: - - // if a UI frame and UIHook Specified, call it - - if (PORT->UIHook && CTL == 3) - PORT->UIHook(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG); - - L2FORUS(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG); -} - - -VOID MHPROC(struct PORTCONTROL * PORT, MESSAGE * Buffer) -{ - PMHSTRUC MH = PORT->PORTMHEARD; - PMHSTRUC MHBASE = MH; - int i; - int OldCount = 0; - char Freq[64] = ""; - char DIGI = '*'; - double ReportFreq = 0; - - // if port has a freq associated with it use it - - GetPortFrequency(PORT->PORTNUMBER, Freq); - - // if (Buffer->ORIGIN[6] & 1) - DIGI = 0; // DOn't think we want to do this - - // See if in list - - for (i = 0; i < MHENTRIES; i++) - { - if ((MH->MHCALL[0] == 0) || (CompareCalls(Buffer->ORIGIN, MH->MHCALL) && MH->MHDIGI == DIGI)) // Spare or our entry - { - OldCount = MH->MHCOUNT; - goto DoMove; - } - MH++; - } - - // TABLE FULL AND ENTRY NOT FOUND - MOVE DOWN ONE, AND ADD TO TOP - - i = MHENTRIES - 1; - - // Move others down and add at front -DoMove: - if (i != 0) // First - memmove(MHBASE + 1, MHBASE, i * sizeof(MHSTRUC)); - - memcpy (MHBASE->MHCALL, Buffer->ORIGIN, 7 * 9); // Save Digis - MHBASE->MHDIGI = DIGI; - MHBASE->MHTIME = time(NULL); - MHBASE->MHCOUNT = ++OldCount; - strcpy(MHBASE->MHFreq, Freq); - MHBASE->MHLocator[0] = 0; - - return; -} - - -int CountFramesQueuedOnSession(TRANSPORTENTRY * Session) -{ - // COUNT NUMBER OF FRAMES QUEUED ON A SESSION - - if (Session == 0) - return 0; - - if (Session->L4CIRCUITTYPE & BPQHOST) - { - return C_Q_COUNT(&Session->L4TX_Q); - } - - if (Session->L4CIRCUITTYPE & SESSION) - { - // L4 SESSION - GET NUMBER UNACKED, AND ADD NUMBER ON TX QUEUE - - int Count = C_Q_COUNT(&Session->L4TX_Q); - UCHAR Unacked = Session->TXSEQNO - Session->L4WS; - - return Count + Unacked; - } - - if (Session->L4CIRCUITTYPE & PACTOR) - { - // PACTOR Type - Frames are queued on the Port Entry - - struct PORTCONTROL * PORT = Session->L4TARGET.PORT; - EXTPORTDATA * EXT = (EXTPORTDATA *)PORT; - - int ret = EXT->FramesQueued; - - // Check L4 Queue as messages can stay there briefly - - ret += C_Q_COUNT(&Session->L4RX_Q); - - return ret + C_Q_COUNT(&PORT->PORTTX_Q); - } - - // L2 CIRCUIT - - { - int SessCount = C_Q_COUNT(&Session->L4TX_Q); - struct _LINKTABLE * LINK = Session->L4TARGET.LINK; - int L2 = COUNT_AT_L2(LINK); - - return SessCount + L2; - } -} - -int CHECKIFBUSYL2(TRANSPORTENTRY * Session) -{ - // RETURN TOP BIT OF AL SET IF SESSION PARTNER IS BUSY - - if (Session->L4CROSSLINK) // CONNECTED? - { - Session = Session->L4CROSSLINK; - - if (CountFramesQueuedOnSession(Session) > 10) - return L4BUSY;; - } - return 0; -} - -VOID L2FORUS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG) -{ - // MESSAGE ADDRESSED TO OUR CALL OR ALIAS, BUT NOT FOR AN ACTIVE SESSION - - // LINK points to an empty link table entry - - struct ROUTE * ROUTE; - int CTLlessPF = CTL & ~PFBIT; - - PORT->L2FRAMESFORUS++; - - NO_CTEXT = 0; - - // ONLY SABM or UI ALLOWED IF NO SESSION - // Plus XID/TEST/SABME if V2.2 support enabled - - if (CTLlessPF == 3) // UI - { - // A UI ADDRESSED TO US - SHOULD ONLY BE FOR IP, or possibly addressed NODES - - switch(ADJBUFFER->PID) - { - case 0xcf: // Netrom - - if (Buffer->L2DATA[0] == 0xff) // NODES - PROCESSNODEMESSAGE(Buffer, PORT); - - break; - - case 0xcc: // TCP - case 0xcd: // ARP - case 0x08: // NOS FRAGMENTED AX25 TCP/IP - - Q_IP_MSG( Buffer); - return; - } - - ReleaseBuffer(Buffer); - return; - } - - if (PORT->PortUIONLY) // Port is for UI only - { - ReleaseBuffer(Buffer); - return; - } - - if (CTLlessPF == SABME) - { - // Although some say V2.2 requires SABME I don't agree! - - // Reject until we support Mod 128 - - L2SENDINVALIDCTRL(PORT, Buffer, ADJBUFFER, CTL); - return; - } - - if (CTLlessPF == SREJ) // Used to see if other end supports SREJ on 2.0 - { - // Send FRMR if dont support SREJ - // Send DM if we do - - if (SUPPORT2point2) - L2SENDRESP(PORT, Buffer, ADJBUFFER, DM); - else - L2SENDINVALIDCTRL(PORT, Buffer, ADJBUFFER, CTL); - - return; - } - - if (CTLlessPF == XID) - { - // Send FRMR if we only support V 2.0 - - if (SUPPORT2point2 == FALSE) - { - L2SENDINVALIDCTRL(PORT, Buffer, ADJBUFFER, CTL); - return; - } - // if Support 2.2 drop through - } - - if (CTLlessPF == TEST) - { - // I can't see amy harm in replying to TEST - - L2SENDRESP(PORT, Buffer, ADJBUFFER, TEST); - return; - } - - -// if (CTLlessPF != SABM && CTLlessPF != SABME) - if (CTLlessPF != SABM && CTLlessPF != XID) - { - if ((MSGFLAG & CMDBIT) && (CTL & PFBIT)) // Command with P? - L2SENDDM(PORT, Buffer, ADJBUFFER); - else - ReleaseBuffer(Buffer); // Ignore if not - - return; - } - - // Exclude and limit tests are done for XID and SABM - - if (NODE == 0 && BBS == 0) // Don't want any calls - { - ReleaseBuffer(Buffer); - return; - } - -#ifdef EXCLUDEBITS - - // CHECK ExcludeList - - if (CheckExcludeList(Buffer->ORIGIN) == 0) - { - ReleaseBuffer(Buffer); - return; - } -#endif - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (PORT->PERMITTEDCALLS) - { - UCHAR * ptr = PORT->PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(Buffer->ORIGIN, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - ReleaseBuffer(Buffer); - return; - } - } - } - - // IF CALL REQUEST IS FROM A LOCKED NODE WITH QUALITY ZERO, IGNORE IT - - if (FindNeighbour(Buffer->ORIGIN, PORT->PORTNUMBER, &ROUTE)) - { - // From a known node - - NO_CTEXT = 1; - - if (ROUTE->NEIGHBOUR_FLAG == 1 && ROUTE->NEIGHBOUR_QUAL == 0) // Locked, qual 0 - { - ReleaseBuffer(Buffer); - return; - } - } - - // CHECK PORT CONNECT LIMITS - - if (PORT->USERS) - { - if (COUNTLINKS(PORT->PORTNUMBER) >= PORT->USERS) - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - } - - // if KISSHF, check if attached. If so, reject. If not, attach. - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - { - struct TNCINFO * TNC = PORT->TNC; - - if (TNC->PortRecord->ATTACHEDSESSIONS[0]) - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - } - - // OK to accept SABM or XID - - if (CTLlessPF == XID) - { - ProcessXIDCommand(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG); - return; - } - - // Not XID, so must be SABM - - L2SABM(LINK, PORT, Buffer, ADJBUFFER, MSGFLAG); // Process the SABM -} - - -VOID ProcessXIDCommand(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG) -{ - // I think it is fairly safe to accept XID as soon as we - // can process SREJ, but only accept Mod 8 and 256 Byte frames - - // I think the only way to run 2.2 Mod 8 is to preceed a - // SABM with XID, but others don't seem to agree! - - // Run through XID fields, changing any we don't like, - // then return an XID response - - // Decode and process XID - - UCHAR * ptr = &ADJBUFFER->PID; - UCHAR * ptr1, * ptr2; - UCHAR TEMPDIGI[57]; - int n; - - // Check Interlock - should we also check exclude etc?. No, checked in L2FORUS - - if (CheckKissInterlock(PORT, TRUE)) // Interlock with ARDOP/VARA etc - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - - 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 2: //Bin fields - - break; - - case 3: - - if ((value & OPMustHave) != OPMustHave) - goto BadXID; - - if ((value & OPMod8) == 0) - goto BadXID; - - if ((value & OPSREJMult) == 0) - goto BadXID; - - - // Reply Mod 8 SREJMULTI - - value = OPMustHave | OPSREJMult | OPMod8; - ptr -=3; - *ptr++ = value >> 16; - *ptr++ = value >> 8; - *ptr++ = value; - - - break; - - case 6: //RX Size - - break; - - case 8: //RX Window - - break; - } - } - - // Send back as XID response - - LINK->L2STATE = 1; // XID received - LINK->Ver2point2 = TRUE; // Must support 2.2 if sent XID - LINK->L2TIME = PORT->PORTT1; - - LINK->LINKPORT = PORT; - - // save calls so we can match up SABM when it comes - - memcpy(LINK->LINKCALL, Buffer->ORIGIN, 7); - LINK->LINKCALL[6] &= 0x1e; // Mask SSID - - memcpy(LINK->OURCALL, Buffer->DEST, 7); - - LINK->OURCALL[6] &= 0x1e; // Mask SSID - - memset(LINK->DIGIS, 0, 56); // CLEAR DIGI FIELD IN CASE RECONNECT - - if ((Buffer->ORIGIN[6] & 1) == 0) // End of Address - { - // THERE ARE DIGIS TO PROCESS - COPY TO WORK AREA reversed, THEN COPY BACK - - memset(TEMPDIGI, 0, 57); // CLEAR DIGI FIELD IN CASE RECONNECT - - ptr1 = &Buffer->ORIGIN[6]; // End of add - ptr2 = &TEMPDIGI[7 * 7]; // Last Temp Digi - - while((*ptr1 & 1) == 0) // End of address bit - { - ptr1++; - memcpy(ptr2, ptr1, 7); - ptr2[6] &= 0x1e; // Mask Repeated and Last bits - ptr2 -= 7; - ptr1 += 6; - } - - // LIST OF DIGI CALLS COMPLETE - COPY TO LINK CONTROL ENTRY - - n = PORT->PORTMAXDIGIS; - - ptr1 = ptr2 + 7; // First in TEMPDIGIS - ptr2 = &LINK->DIGIS[0]; - - while (*ptr1) - { - if (n == 0) - { - // Too many for us - - CLEAROUTLINK(LINK); - ReleaseBuffer(Buffer); - return; - } - - memcpy(ptr2, ptr1, 7); - ptr1 += 7; - ptr2 += 7; - n--; - } - } - - ADJBUFFER->CTL = CTL | PFBIT; - - // Buffer->LENGTH = (UCHAR *)ADJBUFFER - (UCHAR *)Buffer + MSGHDDRLEN + 15; // SET UP BYTE COUNT - - L2SWAPADDRESSES(Buffer); // SWAP ADDRESSES AND SET RESP BITS - - // We need to save APPLMASK and ALIASPTR so following SABM connects to application - - LINK->APPLMASK = APPLMASK; - LINK->ALIASPTR = ALIASPTR; - - PUT_ON_PORT_Q(PORT, Buffer); - return; - } -BadXID: - L2SENDINVALIDCTRL(PORT, Buffer, ADJBUFFER, CTL); - return; -} - - - -int COUNTLINKS(int Port) -{ - //COUNT LINKS ON PORT - - int i = MAXLINKS, n = 0; - struct _LINKTABLE * LINK = LINKS; - - while (i--) - { - if (LINK->LINKPORT && LINK->LINKPORT->PORTNUMBER == Port) - n++; - - LINK++; - } - - return n; -} - - -VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG) -{ - // MESSAGE ON AN ACTIVE LINK - - int CTLlessPF = CTL & ~PFBIT; - - PORT->L2FRAMESFORUS++; - - // ONLY SABM or UI ALLOWED IF NO SESSION - - if (CTLlessPF == 3) // UI - { - // A UI ADDRESSED TO US - SHOULD ONLY BE FOR IP, or possibly addressed NODES - - switch(ADJBUFFER->PID) - { - case 0xcf: // Netrom - - if (Buffer->L2DATA[0] == 0xff) // NODES - PROCESSNODEMESSAGE(Buffer, PORT); - - break; - - case 0xcc: // TCP - case 0xcd: // ARP - case 0x08: // NOS FRAGMENTED AX25 TCP/IP - - Q_IP_MSG( Buffer); - return; - } - - ReleaseBuffer(Buffer); - return; - } - - if (CTLlessPF == DISC) - { - InformPartner(LINK, NORMALCLOSE); // SEND DISC TO OTHER END - CLEAROUTLINK(LINK); - L2SENDUA(PORT, Buffer, ADJBUFFER); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - return; - } - - - if (LINK->L2STATE == 1) - { - // XID State. Should be XID response if 2.2 ok or DM/FRMR if not - - if (MSGFLAG & RESP) - { - if (CTLlessPF == DM || CTLlessPF == FRMR) - { - // Doesn't support XID - Send SABM - - LINK->L2STATE = 2; - LINK->Ver2point2 = FALSE; - LINK->L2TIMER = 1; // USe retry to send SABM - } - else if (CTLlessPF == XID) - { - // Process response to make sure ok, Send SABM or DISC - - LINK->L2STATE = 2; - LINK->Ver2point2 = TRUE;// Must support 2.2 if responded to XID - LINK->L2TIMER = 1; // USe retry to send SABM - } - - ReleaseBuffer(Buffer); - return; - } - - // Command on existing session. Could be due to other end missing - // the XID response, so if XID just resend response - - } - - 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; - } - - - if (CTLlessPF == SABM) - { - // SABM ON EXISTING SESSION - IF DISCONNECTING, REJECT - - if (LINK->L2STATE == 1) // Sent XID? - { - APPLMASK = LINK->APPLMASK; - ALIASPTR = LINK->ALIASPTR; - - L2SABM(LINK, PORT, Buffer, ADJBUFFER, MSGFLAG); // Process the SABM - return; - } - - if (LINK->L2STATE == 4) // DISCONNECTING? - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - - // THIS IS A SABM ON AN EXISTING SESSION - - // THERE ARE SEVERAL POSSIBILITIES: - - // 1. RECONNECT COMMAND TO TNC - // 2. OTHER END THINKS LINK HAS DIED - // 3. RECOVERY FROM FRMR CONDITION - // 4. REPEAT OF ORIGINAL SABM COS OTHER END MISSED UA - - // FOR 1-3 IT IS REASONABLE TO FULLY RESET THE CIRCUIT, BUT IN 4 - // SUCH ACTION WILL LOSE THE INITIAL SIGNON MSG IF CONNECTING TO A - // BBS. THE PROBLEM IS TELLING THE DIFFERENCE. I'M GOING TO SET A FLAG - // WHEN FIRST INFO RECEIVED - IF SABM REPEATED BEFORE THIS, I'LL ASSUME - // CONDITION 4, AND JUST RESEND THE UA - - - if (LINK->SESSACTIVE == 0) // RESET OF ACTIVE CIRCUIT? - { - L2SENDUA(PORT, Buffer, ADJBUFFER); // No, so repeat UA - return; - } - - InformPartner(LINK, NORMALCLOSE); // SEND DISC TO OTHER END - LINK->CIRCUITPOINTER = 0; - - L2SABM(LINK, PORT, Buffer, ADJBUFFER, MSGFLAG); // Process the SABM - return; - } - - L2_PROCESS(LINK, PORT, Buffer, CTL, MSGFLAG); -} - - -VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR MSGFLAG) -{ - // SET UP NEW SESSION (OR RESET EXISTING ONE) - - TRANSPORTENTRY * Session; - int CONERROR; - - char toCall[12], fromCall[12]; - - - if (LINK == 0) // NO LINK ENTRIES - SEND DM RESPONSE - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - - if (CheckKissInterlock(PORT, TRUE)) // Interlock with ARDOP/VARA etc - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - - SETUPNEWL2SESSION(LINK, PORT, Buffer, MSGFLAG); - - if (LINK->L2STATE != 5) // Setup OK? - { - L2SENDDM(PORT, Buffer, ADJBUFFER); // Failed - return; - } - - // See if need to Interlock non-sharable modes, eg ARDOP and VARA - - seeifInterlockneeded(PORT); - - toCall[ConvFromAX25(ADJBUFFER->DEST, toCall)] = 0; - fromCall[ConvFromAX25(ADJBUFFER->ORIGIN, fromCall)] = 0; - - - // IF CONNECT TO APPL ADDRESS, SET UP APPL SESSION - - if (APPLMASK == 0) - { - // Not ATTACH TO APPL - - // Send CTEXT if connect to NODE/Port Alias, or NODE/Port Call, and FULL_CTEXT set - // Dont sent to known NODEs, or appl connects - - struct DATAMESSAGE * Msg; - int Totallen = 0; - int Paclen= PORT->PORTPACLEN; - UCHAR * ptr; - - if (LogAllConnects) - { - char toCall[12], fromCall[12]; - toCall[ConvFromAX25(ADJBUFFER->DEST, toCall)] = 0; - fromCall[ConvFromAX25(ADJBUFFER->ORIGIN, fromCall)] = 0; - WriteConnectLog(fromCall, toCall, "AX.25"); - } - - hookL2SessionAccepted(PORT->PORTNUMBER, fromCall, toCall, LINK); - - L2SENDUA(PORT, Buffer, ADJBUFFER); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - AttachKISSHF(PORT, Buffer); - - if (NO_CTEXT == 1) - return; - - if (FULL_CTEXT == 0 && !ALIASMSG) // Any connect, or call to alias - return; - - // if Port CTEXT defined, use it - - if (PORT->CTEXT) - { - Totallen = strlen(PORT->CTEXT); - ptr = PORT->CTEXT; - } - else if (CTEXTLEN) - { - Totallen = CTEXTLEN; - ptr = CTEXTMSG; - } - else - return; - - if (Paclen == 0) - Paclen = PACLEN; - - while(Totallen) - { - Msg = GetBuff(); - - if (Msg == NULL) - break; // No Buffers - - Msg->PID = 0xf0; - - if (Paclen > Totallen) - Paclen = Totallen; - - memcpy(Msg->L2DATA, ptr, Paclen); - Msg->LENGTH = Paclen + MSGHDDRLEN + 1; - - C_Q_ADD(&LINK->TX_Q, Msg); - - ptr += Paclen; - Totallen -= Paclen; - } - return; - } - - - // Connnect to APPL - - if (LINK->LINKTYPE != 1) - { - L2SENDUA(PORT, Buffer, ADJBUFFER); // RESET OF DOWN/CROSSLINK - return; - } - - if (LINK->CIRCUITPOINTER) - { - L2SENDUA(PORT, Buffer, ADJBUFFER); // ALREADY SET UP - MUST BE REPEAT OF SABM OR LINK RESET - return; - } - - // IF RUNNING ONLY BBS (NODE=0), THIS MAY BE EITHER A USER OR NODE - // TRYING TO SET UP A L4 CIRCUIT - WE DONT WANT TO ATTACH A NODE TO - // THE BBS! - - if (NODE == 0) - { - // NOW THINGS GET DIFICULT - WE MUST EITHER WAIT TO SEE IF A PID CF MSG - // ARRIVES, OR ASSUME ALL NODES ARE IN NEIGHBOURS - I'LL TRY THE LATTER - // AND SEE HOW IT GOES. tHIS MEANS THAT YOU MUST DEFINE ALL ROUTES - // IN CONFIG FILE - - struct ROUTE * ROUTE; - - if (FindNeighbour(Buffer->ORIGIN, PORT->PORTNUMBER, &ROUTE)) - { - // It's a node - - L2SENDUA(PORT, Buffer, ADJBUFFER); // ALREADY SET UP - MUST BE REPEAT OF SABM OR LINK RESET - return; - } - } - - - Session = SetupSessionForL2(LINK); // CREATE INCOMING L4 SESSION - - if (Session == NULL) - { - CLEAROUTLINK(LINK); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - L2SENDDM(PORT, Buffer, ADJBUFFER); - - return; - } - - // NOW TRY A BBS CONNECT - // IF APPL CONNECT, SEE IF APPL HAS AN ALIAS - - if (ALIASPTR[0] > ' ') - { - struct DATAMESSAGE * Msg; - - // ACCEPT THE CONNECT, THEN INVOKE THE ALIAS - - L2SENDUA(PORT, Buffer, ADJBUFFER); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - { - struct DATAMESSAGE * Msg; - int Totallen = 0; - int Paclen= PORT->PORTPACLEN; - UCHAR * ptr; - - AttachKISSHF(PORT, Buffer); - - // if Port CTEXT defined, use it - - if (PORT->CTEXT) - { - Totallen = strlen(PORT->CTEXT); - ptr = PORT->CTEXT; - } - else if (HFCTEXTLEN) - { - Totallen = HFCTEXTLEN; - ptr = HFCTEXT; - } - - if (Paclen == 0) - Paclen = PACLEN; - - while(Totallen) - { - Msg = GetBuff(); - - if (Msg == NULL) - break; // No Buffers - - Msg->PID = 0xf0; - - if (Paclen > Totallen) - Paclen = Totallen; - - memcpy(Msg->L2DATA, ptr, Paclen); - Msg->LENGTH = Paclen + MSGHDDRLEN + 1; - - C_Q_ADD(&LINK->TX_Q, Msg); - - ptr += Paclen; - Totallen -= Paclen; - } - - } - - if (LogAllConnects) - { - char toCall[12], fromCall[12]; - toCall[ConvFromAX25(ADJBUFFER->DEST, toCall)] = 0; - fromCall[ConvFromAX25(ADJBUFFER->ORIGIN, fromCall)] = 0; - WriteConnectLog(fromCall, toCall, "AX.25"); - } - - Msg = GetBuff(); - - if (Msg) - { - Msg->PID = 0xf0; - - memcpy(Msg->L2DATA, ALIASPTR, 12); - Msg->L2DATA[12] = 13; - - Msg->LENGTH = MSGHDDRLEN + 12 + 2; // 2 for PID and CR - - C_Q_ADD(&LINK->RX_Q, Msg); - } - - return; - } - - if (cATTACHTOBBS(Session, APPLMASK, PORT->PORTPACLEN, &CONERROR) == 0) - { - // NO BBS AVAILABLE - - CLEARSESSIONENTRY(Session); - CLEAROUTLINK(LINK); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - L2SENDDM(PORT, Buffer, ADJBUFFER); - - return; - } - - if (LogAllConnects) - { - char toCall[12], fromCall[12]; - toCall[ConvFromAX25(ADJBUFFER->DEST, toCall)] = 0; - fromCall[ConvFromAX25(ADJBUFFER->ORIGIN, fromCall)] = 0; - WriteConnectLog(fromCall, toCall, "AX.25"); - } - - L2SENDUA(PORT, Buffer, ADJBUFFER); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - { - struct DATAMESSAGE * Msg; - int Totallen = 0; - int Paclen= PORT->PORTPACLEN; - UCHAR * ptr; - - AttachKISSHF(PORT, Buffer); - - // if Port CTEXT defined, use it - - if (PORT->CTEXT) - { - Totallen = strlen(PORT->CTEXT); - ptr = PORT->CTEXT; - } - else if (HFCTEXTLEN) - { - Totallen = HFCTEXTLEN; - ptr = HFCTEXT; - } - else - return; - - if (Paclen == 0) - Paclen = PACLEN; - - while(Totallen) - { - Msg = GetBuff(); - - if (Msg == NULL) - break; // No Buffers - - Msg->PID = 0xf0; - - if (Paclen > Totallen) - Paclen = Totallen; - - memcpy(Msg->L2DATA, ptr, Paclen); - Msg->LENGTH = Paclen + MSGHDDRLEN + 1; - - C_Q_ADD(&LINK->TX_Q, Msg); - - ptr += Paclen; - Totallen -= Paclen; - } - return; - } -} - -VOID SETUPNEWL2SESSION(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR MSGFLAG) -{ - // COPY ADDRESS INFO TO LINK TABLE - - UCHAR * ptr1, * ptr2; - UCHAR TEMPDIGI[57]; - int n; - - memcpy(LINK->LINKCALL, Buffer->ORIGIN, 7); - LINK->LINKCALL[6] &= 0x1e; // Mask SSID - - memcpy(LINK->OURCALL, Buffer->DEST, 7); - LINK->OURCALL[6] &= 0x1e; // Mask SSID - - memset(LINK->DIGIS, 0, 56); // CLEAR DIGI FIELD IN CASE RECONNECT - - LINK->L2TIME = PORT->PORTT1; // Set tomeoiut for no digis - - if ((Buffer->ORIGIN[6] & 1) == 0) // End of Address - { - // THERE ARE DIGIS TO PROCESS - COPY TO WORK AREA reversed, THEN COPY BACK - - memset(TEMPDIGI, 0, 57); // CLEAR DIGI FIELD IN CASE RECONNECT - - ptr1 = &Buffer->ORIGIN[6]; // End of add - ptr2 = &TEMPDIGI[7 * 7]; // Last Temp Digi - - while((*ptr1 & 1) == 0) // End of address bit - { - ptr1++; - memcpy(ptr2, ptr1, 7); - ptr2[6] &= 0x1e; // Mask Repeated and Last bits - ptr2 -= 7; - ptr1 += 6; - } - - // LIST OF DIGI CALLS COMPLETE - COPY TO LINK CONTROL ENTRY - - n = PORT->PORTMAXDIGIS; - - ptr1 = ptr2 + 7; // First in TEMPDIGIS - ptr2 = &LINK->DIGIS[0]; - - while (*ptr1) - { - if (n == 0) - { - // Too many for us - - CLEAROUTLINK(LINK); - return; - } - - memcpy(ptr2, ptr1, 7); - ptr1 += 7; - ptr2 += 7; - n--; - - LINK->L2TIME += PORT->PORTT1; // Adjust timeout for digis - } - } - - // THIS MAY BE RESETTING A LINK - BEWARE OF CONVERTING A CROSSLINK TO - // AN UPLINK AND CONFUSING EVERYTHING - - LINK->LINKPORT = PORT; - - if (LINK->LINKTYPE == 0) - { - if (ISNETROMMSG && NODE == 0) // Only allow crosslink if node = 0 - LINK->LINKTYPE = 3; // Crosslink - else - LINK->LINKTYPE = 1; // Uplink - } - LINK->L2TIMER = 0; // CANCEL TIMER - - LINK->L2SLOTIM = T3; // SET FRAME SENT RECENTLY - - LINK->LINKWINDOW = PORT->PORTWINDOW; - - RESET2(LINK); // RESET ALL FLAGS - - LINK->L2STATE = 5; - - // IF VERSION 1 MSG, SET FLAG - - if (MSGFLAG & VER1) - LINK->VER1FLAG |= 1; - -} - -VOID L2SENDUA(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER) -{ - L2SENDRESP(PORT, Buffer, ADJBUFFER, UA); -} - -VOID L2SENDDM(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER) -{ - if (CheckExcludeList(Buffer->ORIGIN) == 0) // if in exclude, don't send DM - { - ReleaseBuffer(Buffer); // not sure that this is the right place for releasing? - return; - } - - L2SENDRESP(PORT, Buffer, ADJBUFFER, DM); -} - -VOID L2SENDRESP(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL) -{ - // QUEUE RESPONSE TO PORT CONTROL - MAY NOT HAVE A LINK ENTRY - - // SET APPROPRIATE P/F BIT - - ADJBUFFER->CTL = CTL | PFBIT; - - Buffer->LENGTH = (int)((UCHAR *)ADJBUFFER - (UCHAR *)Buffer) + MSGHDDRLEN + 15; // SET UP BYTE COUNT - - L2SWAPADDRESSES(Buffer); // SWAP ADDRESSES AND SET RESP BITS - - PUT_ON_PORT_Q(PORT, Buffer); - - return; -} - - -VOID L2SENDINVALIDCTRL(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL) -{ - // Send FRMR Invalid Control field - - // QUEUE RESPONSE TO PORT CONTROL - MAY NOT HAVE A LINK ENTRY - - // SET APPROPRIATE P/F BIT - - UCHAR * ptr; - - ADJBUFFER->CTL = FRMR | PFBIT; - - ptr = &ADJBUFFER->PID; - - *(ptr++) = CTL; // MOVE REJECT C-BYTE - *(ptr++) = 0; - *(ptr++) = SDINVC; // MOVE REJECT FLAGS - - Buffer->LENGTH = (int)((UCHAR *)ADJBUFFER - (UCHAR *)Buffer) + MSGHDDRLEN + 18; // SET UP BYTE COUNT - - L2SWAPADDRESSES(Buffer); // SWAP ADDRESSES AND SET RESP BITS - - PUT_ON_PORT_Q(PORT, Buffer); - - return; -} - -VOID L2SWAPADDRESSES(MESSAGE * Buffer) -{ - // EXCHANGE ORIGIN AND DEST, AND REVERSE DIGIS (IF PRESENT) - - char TEMPFIELD[7]; - UCHAR * ptr1, * ptr2; - UCHAR TEMPDIGI[57]; - - memcpy(TEMPFIELD, Buffer->ORIGIN, 7); - memcpy(Buffer->ORIGIN, Buffer->DEST, 7); - memcpy(Buffer->DEST, TEMPFIELD, 7); - - Buffer->ORIGIN[6] &= 0x1e; // Mask SSID - Buffer->ORIGIN[6] |= 0xe0; // Reserved and Response - - Buffer->DEST[6] &= 0x1e; // Mask SSID - Buffer->DEST[6] |= 0x60; // Reserved - - if ((TEMPFIELD[6] & 1) == 0) - { - // THERE ARE DIGIS TO PROCESS - COPY TO WORK AREA reversed, THEN COPY BACK - - memset(TEMPDIGI, 0, 57); // CLEAR DIGI FIELD IN CASE RECONNECT - - ptr1 = &Buffer->ORIGIN[6]; // End of add - ptr2 = &TEMPDIGI[7 * 7]; // Last Temp Digi - - while((*ptr1 & 1) == 0) // End of address bit - { - ptr1++; - memcpy(ptr2, ptr1, 7); - ptr2[6] &= 0x1e; // Mask Repeated and Last bits - ptr2 -= 7; - ptr1 += 6; - } - - // LIST OF DIGI CALLS COMPLETE - copy back - - ptr1 = ptr2 + 7; // First in TEMPDIGIS - ptr2 = &Buffer->CTL; - - while (*ptr1) - { - memcpy(ptr2, ptr1, 7); - ptr1 += 7; - ptr2 += 7; - } - - *(ptr2 - 1) |= 1; // End of addresses - } - else - { - Buffer->ORIGIN[6] |= 1; // End of address - } -} - -BOOL InternalL2SETUPCROSSLINK(PROUTE ROUTE, int Retries) -{ - // ROUTE POINTS TO A NEIGHBOUR - FIND AN L2 SESSION FROM US TO IT, OR INITIATE A NEW ONE - - struct _LINKTABLE * LINK; - struct PORTCONTROL * PORT; - int FRACK; - - if (FindLink(ROUTE->NEIGHBOUR_CALL, NETROMCALL, ROUTE->NEIGHBOUR_PORT, &LINK)) - { - // SESSION ALREADY EXISTS - - LINK->LINKTYPE = 3; // MAKE SURE IT KNOWS ITS A CROSSLINK - ROUTE->NEIGHBOUR_LINK = LINK; - LINK->NEIGHBOUR = ROUTE; - - return TRUE; - } - - // SET UP NEW SESSION (OR RESET EXISTING ONE) - - if (LINK == NULL) - return FALSE; // No free links - - - ROUTE->NEIGHBOUR_LINK = LINK; - LINK->NEIGHBOUR = ROUTE; - - LINK->LINKPORT = PORT = GetPortTableEntryFromPortNum(ROUTE->NEIGHBOUR_PORT); - - if (PORT == NULL) - return FALSE; // maybe port has been deleted - - // IF ROUTE HAS A FRACK, SET IT - - if (ROUTE->NBOUR_FRACK) - FRACK = ROUTE->NBOUR_FRACK; - else - FRACK = PORT->PORTT1; - - LINK->L2TIME = FRACK; // SET TIMER VALUE - - // IF ROUTE HAS A WINDOW, SET IT - - if (ROUTE->NBOUR_MAXFRAME) - LINK->LINKWINDOW = ROUTE->NBOUR_MAXFRAME; - else - LINK->LINKWINDOW = PORT->PORTWINDOW; - -// if (SUPPORT2point2) -// LINK->L2STATE = 1; // Send XID -// else - LINK->L2STATE = 2; - - memcpy(LINK->LINKCALL, ROUTE->NEIGHBOUR_CALL, 7); - memcpy(LINK->OURCALL, NETROMCALL, 7); - - if (ROUTE->NEIGHBOUR_DIGI1[0]) - { - memcpy(LINK->DIGIS, ROUTE->NEIGHBOUR_DIGI1, 7); - LINK->L2TIME += FRACK; - } - - if (ROUTE->NEIGHBOUR_DIGI2[0]) - { - memcpy(&LINK->DIGIS[7], ROUTE->NEIGHBOUR_DIGI1, 7); - LINK->L2TIME += FRACK; - } - - LINK->LINKTYPE = 3; // CROSSLINK - - if (Retries) - LINK->L2RETRIES = PORT->PORTN2 - Retries; - - if (LINK->L2STATE == 1) - L2SENDXID(LINK); - else - SENDSABM(LINK); - - return TRUE; -} - - - -BOOL L2SETUPCROSSLINKEX(PROUTE ROUTE, int Retries) -{ - // Allows caller to specify number of times SABM should be sent - - return InternalL2SETUPCROSSLINK(ROUTE, Retries); -} - -BOOL L2SETUPCROSSLINK(PROUTE ROUTE) -{ - return InternalL2SETUPCROSSLINK(ROUTE, 0); -} - -VOID L2_PROCESS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL, UCHAR MSGFLAG) -{ - // PROCESS LEVEL 2 PROTOCOL STUFF - - // SEE IF COMMAND OR RESPONSE - - if ((MSGFLAG & CMDBIT) == 0) - { - - // RESPONSE OR VERSION 1 - - // IF RETRYING, MUST ONLY ACCEPT RESPONSES WITH F SET (UNLESS RUNNING V1) - - if ((CTL & PFBIT) || LINK->VER1FLAG == 1) - { - // F SET or V1 - CAN CANCEL TIMER - - LINK->L2TIMER = 0; // CANCEL LINK TIMER - } - } - - if (LINK->L2STATE == 3) - { - - // FRMR STATE - IF C(P) SEND FRMR, ELSE IGNORE - - if (CTL & PFBIT) - { - if (CTL == (FRMR | PFBIT)) // if both ends in FRMR state, reset link - { - RESET2(LINK); - - LINK->L2STATE = 2; // INITIALISING - LINK->L2ACKREQ = 0; // DONT SEND ANYTHING ELSE - LINK->L2RETRIES = 0; // ALLOW FULL RETRY COUNT FOR SABM - - L2SENDCOMMAND(LINK, SABM | PFBIT); - } - } - - if (MSGFLAG & CMDBIT) - { - // SEND FRMR AGAIN - - SENDFRMR(LINK); - } - - ReleaseBuffer(Buffer); - return; - } - - if (LINK->L2STATE >= 5) - { - // LINK IN STATE 5 OR ABOVE - LINK RUNNING - - if ((CTL & 1) == 0) // I frame - { - SDIFRM(LINK, PORT, Buffer, CTL, MSGFLAG); // consumes buffer - return; - } - - if ((CTL & 2)) // U frame - { - SDUFRM(LINK, PORT, Buffer, CTL); //consumes buffer - return; - } - - // ELSE SUPERVISORY, MASK OFF N(R) AND P-BIT - - switch (CTL & 0x0f) - { - // is there any harm in accepting SREJ even if we don't - // otherwise support 2.2? - - case REJ: - case SREJ: - - PORT->L2REJCOUNT++; - - case RR: - case RNR: - - SFRAME(LINK, PORT, CTL, MSGFLAG); - break; - - default: - - // UNRECOGNISABLE COMMAND - - LINK->SDRBYTE = CTL; // SAVE FOR FRMR RESPONSE - LINK->SDREJF |= SDINVC; // SET INVALID COMMAND REJECT - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - } - - ReleaseBuffer(Buffer); - return; - } - - // NORMAL DISCONNECT MODE - - // COULD BE UA, DM - SABM AND DISC HANDLED ABOVE - - switch (CTL & ~PFBIT) - { - case UA: - - // UA RECEIVED - - if (LINK->L2STATE == 2) - { - // RESPONSE TO SABM - SET LINK UP - - RESET2X(LINK); // LEAVE QUEUED STUFF - - LINK->L2STATE = 5; - LINK->L2TIMER = 0; // CANCEL TIMER - LINK->L2RETRIES = 0; - LINK->L2SLOTIM, T3; // SET FRAME SENT RECENTLY - - // IF VERSION 1 MSG, SET FLAG - - if (MSGFLAG & VER1) - LINK->VER1FLAG |= 1; - - // TELL PARTNER CONNECTION IS ESTABLISHED - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - KISSHFConnected(PORT, LINK); - - SENDCONNECTREPLY(LINK); - ReleaseBuffer(Buffer); - return; - } - - if (LINK->L2STATE == 4) // DISCONNECTING? - { - InformPartner(LINK, NORMALCLOSE); // SEND DISC TO OTHER END - CLEAROUTLINK(LINK); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - } - - // UA, BUT NOT IN STATE 2 OR 4 - IGNORE - - ReleaseBuffer(Buffer); - return; - - case DM: - - // DM RESPONSE - IF TO SABM, SEND BUSY MSG - - if (LINK->L2STATE == 2) - { - CONNECTREFUSED(LINK); // SEND MESSAGE IF DOWNLINK - return; - } - - // DM RESP TO DISC RECEIVED - OTHER END HAS LOST SESSION - - // CLEAR OUT TABLE ENTRY - IF INTERNAL TNC, SHOULD SEND *** DISCONNECTED - - InformPartner(LINK, LINKLOST); // SEND DISC TO OTHER END - CLEAROUTLINK(LINK); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - ReleaseBuffer(Buffer); - return; - - case FRMR: - - // FRAME REJECT RECEIVED - LOG IT AND RESET LINK - - RESET2(LINK); - - LINK->L2STATE = 2; // INITIALISING - LINK->L2ACKREQ = 0; // DONT SEND ANYTHING ELSE - LINK->L2RETRIES = 0; // ALLOW FULL RETRY COUNT FOR SABM - - PORT->L2FRMRRX++; - - L2SENDCOMMAND(LINK, SABM | PFBIT); - return; - - default: - - // ANY OTHER - IGNORE - - ReleaseBuffer(Buffer); - } -} - -VOID SDUFRM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL) -{ - // PROCESS AN UNSEQUENCED COMMAND (IN LINK UP STATES) - - switch (CTL & ~PFBIT) - { - case UA: - - // DISCARD - PROBABLY REPEAT OF ACK OF SABM - - break; - - case FRMR: - - // FRAME REJECT RECEIVED - LOG IT AND RESET LINK - - RESET2(LINK); - - LINK->L2STATE = 2; // INITIALISING - LINK->L2ACKREQ = 0; // DONT SEND ANYTHING ELSE - LINK->L2RETRIES = 0; // ALLOW FULL RETRY COUNT FOR SABM - - PORT->L2FRMRRX++; - - L2SENDCOMMAND(LINK, SABM | PFBIT); - break; - - case DM: - - // DM RESPONSE - SESSION MUST HAVE GONE - - // SEE IF CROSSLINK ACTIVE - - InformPartner(LINK, LINKLOST); // SEND DISC TO OTHER END - CLEAROUTLINK(LINK); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - break; - - default: - - // UNDEFINED COMMAND - - LINK->SDRBYTE = CTL; // SAVE FOR FRMR RESPONSE - LINK->SDREJF |= SDINVC; - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - - } - - ReleaseBuffer(Buffer); -} - - -VOID SFRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, UCHAR CTL, UCHAR MSGFLAG) -{ - // CHECK COUNTS, AND IF RNR INDICATE _BUFFER SHORTAGE AT OTHER END - - if (LINK->SDREJF) // ARE ANY REJECT FLAGS SET? - { - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - return; - } - - SDNRCHK(LINK, CTL); // CHECK RECEIVED N(R) - - if (LINK->SDREJF) // ARE ANY REJECT FLAGS SET NOW? - { - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - return; - } - - if ((CTL & 0xf) == SREJ) - { - // Probably safer to handle SREJ completely separately - - // Can we get SREJ Command with P??(Yes) - - // Can we just resend missing frame ?? (Think so!) - - // We support MultiSREJ (can gave additional missing frame - // numbers in the Info field - - // I don't see the point of Multi unless we wait fot an F bit, - // bur maybe not safe to assume others do the same - - // So if I get SREJ(F) I can send missing frame(s) - - if (MSGFLAG & RESP) - { - // SREJ Response - - if (CTL & PFBIT) - { - // SREJ(F). Send Frames() - - UCHAR NS = (CTL >> 5) & 7; // Frame to resend - - struct PORTCONTROL * PORT; - UCHAR * ptr1, * ptr2; - UCHAR CTL; - int count; - MESSAGE * Msg; - MESSAGE * Buffer; - - Msg = LINK->FRAMES[NS]; // is frame available? - - if (Msg == NULL) - return; // Wot!! - - // send the frame - - // GET BUFFER FOR COPY OF MESSAGE - HAVE TO KEEP ORIGINAL FOR RETRIES - - Buffer = GetBuff(); - - if (Buffer == NULL) - return; - - ptr2 = SETUPADDRESSES(LINK, Buffer); // copy addresses - - // ptr2 NOW POINTS TO COMMAND BYTE - - // GOING TO SEND I FRAME - WILL ACK ANY RECEIVED FRAMES - - LINK->L2ACKREQ = 0; // CLEAR ACK NEEDED - LINK->L2SLOTIM = T3 + rand() % 15; // SET FRAME SENT RECENTLY - LINK->KILLTIMER = 0; // RESET IDLE CIRCUIT TIMER - - CTL = LINK->LINKNR << 5; // GET CURRENT N(R), SHIFT IT TO TOP 3 BITS - CTL |= NS << 1; // BITS 1-3 OF CONTROL BYTE - - // SET P BIT IF NO MORE TO SEND (only more if Multi SREJ) - - if (LINK->VER1FLAG == 0) // NO POLL BIT IF V1 - { - CTL |= PFBIT; - LINK->L2FLAGS |= POLLSENT; - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - // FLAG BUFFER TO CAUSE TIMER TO BE RESET AFTER SEND (or ACK if ACKMODE) - - Buffer->Linkptr = LINK; - } - - *(ptr2++) = CTL; // TO DATA (STARTING WITH PID) - - count = Msg->LENGTH - MSGHDDRLEN; - - if (count > 0) // SHOULD ALWAYS BE A PID, BUT BETTER SAFE THAN SORRY - { - ptr1 = (UCHAR *)Msg; - ptr1 += MSGHDDRLEN; - memcpy(ptr2, ptr1, count); - } - - Buffer->DEST[6] |= 0x80; // SET COMMAND - - Buffer->LENGTH = (int)(ptr2 - (UCHAR *)Buffer) + count; // SET NEW LENGTH - - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - PORT = LINK->LINKPORT; - - if (PORT) - { - Buffer->PORT = PORT->PORTNUMBER; - PUT_ON_PORT_Q(PORT, Buffer); - } - else - { - Buffer->Linkptr = 0; - ReleaseBuffer(Buffer); - } - } - } - - return; - } - - // VALID RR/RNR RECEIVED - - LINK->L2FLAGS &= ~RNRSET; //CLEAR RNR - - if ((CTL & 0xf) == RNR) - LINK->L2FLAGS |= RNRSET; //Set RNR - - if (MSGFLAG & CMDBIT) - { - // ALWAYS REPLY TO RR/RNR/REJ COMMAND (even if no P bit ??) - - // FIRST PROCESS RESEQ QUEUE - - //; CALL PROCESS_RESEQ - - // IGNORE IF AN 'F' HAS BEEN SENT RECENTLY - - if (LINK->LAST_F_TIME + 15 > REALTIMETICKS) - return; // DISCARD - - CTL = RR_OR_RNR(LINK); - - CTL |= LINK->LINKNR << 5; // SHIFT N(R) TO TOP 3 BITS - CTL |= PFBIT; - - L2SENDRESPONSE(LINK, CTL); - - LINK->L2SLOTIM = T3 + rand() % 15; // SET FRAME SENT RECENTLY - - LINK->L2ACKREQ = 0; // CANCEL DELAYED ACKL2 - - // SAVE TIME IF 'F' SENT' - - LINK->LAST_F_TIME = REALTIMETICKS; - - return; - } - - // Response - - if ((CTL & PFBIT) == 0 && LINK->VER1FLAG == 0) - { - // RESPONSE WITHOUT P/F DONT RESET N(S) (UNLESS V1) - - return; - - } - - // RESPONSE WITH P/F - MUST BE REPLY TO POLL FOLLOWING TIMEOUT OR I(P) - - // THERE IS A PROBLEM WITH REPEATED RR(F), SAY CAUSED BY DELAY AT L1 - - // AS FAR AS I CAN SEE, WE SHOULD ONLY RESET N(S) IF AN RR(F) FOLLOWS - // AN RR(P) AFTER A TIMEOUT - AN RR(F) FOLLOWING AN I(P) CANT POSSIBLY - // INDICATE A LOST FRAME. ON THE OTHER HAND, A REJ(F) MUST INDICATE - // A LOST FRAME. So dont reset NS if not retrying, unless REJ - - - // someone (probably WLE KISS Driver) is sending REJ followed by RR(F) - // after lost frame and i(p) - -/* -1:Fm W4DHW-10 To W4DHW [17:08:03R] [+++] -úJƒÑZKÀ)x@DÖBÉrNôÝ4XÔ;i‹#CäM³,ïнҼüÕrÞùOË N¿XæâïÀÄ5Ð(È|©¸ì#íÿÈUþïÒcYÞÍl—çûž)Àú璘oÑȼö>©Ï9¨*ÎG²£ëðû(6À5C‹!áL±Ÿîßì÷³ÙQð»pƒËIH”Š;ØÚi¯Ò>â9p¶B¬õ<ÌcŠEPž«<ŸÊ{0aŽ(’­YÕ–´M¢†—N£+<ÇIÐ[–áÛPw–[^]6ƒ2\ù¿9äÆov{‹¥Å¸mm [17:08:03T] -1:Fm W4DHW To W4DHW-10 [17:08:03T] -1:Fm W4DHW To W4DHW-10 [17:08:03T] - - is there a problem with restting on RR(F) following I(P)? - - I think the problem is restting NS twice if you get delayed responses to - I or RR (P). So lets try only resetting NS once for each P sent - -*/ -// if ((CTL & 0xf) == REJ || LINK->L2RETRIES) - if ((LINK->L2FLAGS & POLLSENT)) - { - RESETNS(LINK, (CTL >> 5) & 7); // RESET N(S) AND COUNT RETRIED FRAMES - - LINK->L2RETRIES = 0; - LINK->L2TIMER = 0; // WILL RESTART TIMER WHEN RETRY SENT - } - - LINK->L2FLAGS &= ~POLLSENT; // CLEAR I(P) or RR(P) SET - - if ((CTL & 0xf) == RNR) - { - // Dont Clear timer on receipt of RNR(F), spec says should poll for clearing of busy, - // and loss of subsequent RR will cause hang. Perhaps should set slightly longer time?? - // Timer may have been cleared earlier, so restart it - - LINK->L2TIMER = LINK->L2TIME; - } -} - -//*** PROCESS AN INFORMATION FRAME - -VOID SDIFRM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL, UCHAR MSGFLAG) -{ - int NS; - - if (LINK->SDREJF) // ARE ANY REJECT FLAGS SET? - { - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - ReleaseBuffer(Buffer); - return; - } - - SDNRCHK(LINK, CTL); // CHECK RECEIVED N(R) - - if (LINK->SDREJF) // ARE ANY REJECT FLAGS SET NOW? - { - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - ReleaseBuffer(Buffer); - return; - } - - LINK->SESSACTIVE = 1; // SESSION IS DEFINITELY SET UP - - NS = (CTL >> 1) & 7; // ISOLATE RECEIVED N(S) - - // IPOLL (sending an I(P) frame following timeout instead of RR(P)) - // is a problem. We need to send REJ(F), but shouldn't add to collector. - // We also need to handle repeated I(P), so shouldn't set REJSENT in - // this state. - - if ((((NS + 1) & 7) == LINK->LINKNR) && (CTL & PFBIT)) - { - // Previous Frame and P set - Assume IPOLL - - PORT->L2OUTOFSEQ++; - LINK->L2STATE = 6; - - LINK->L2ACKREQ = 0; // CANCEL RR NEEDED - - // We need to protect against sending multiple REJ(F) if channel - // delays mean we get two I(P) close together (how close is close ??) - // SM has default IPOLL limit of 30 bytes or about a second at 300 - // ACKMODE should avoid this anyway, and resptime of under 3 secs - // is unlikely so say 2.5 secs ?? - - if (LINK->LAST_F_TIME + 25 > REALTIMETICKS) - { - ReleaseBuffer(Buffer); - return; - } - - SEND_RR_RESP(LINK, PFBIT); - LINK->LAST_F_TIME = REALTIMETICKS; - - ReleaseBuffer(Buffer); - return; - } - -CheckNSLoop: - - if (NS != LINK->LINKNR) // EQUAL TO OUR N(R)? - { - // There is a frame missing. - // if we have just sent a REJ we have at least one out - // of sequence frame in RXFRAMES - - // so if we have frame LINK->LINKNR we can process it - // and remove it from RXFRAMES. If we are then back - // in sequence we just carry on. - - if (LINK->RXFRAMES[LINK->LINKNR]) - { - // We have the first missing frame. Process it. - - MESSAGE * OldBuffer = Q_REM(&LINK->RXFRAMES[LINK->LINKNR]); - - Debugprintf("L2 process saved Frame %d", LINK->LINKNR); - PROC_I_FRAME(LINK, PORT, OldBuffer); // Passes on or releases Buffer - - // NR has been updated. - - goto CheckNSLoop; // See if OK or we have another saved frame - } - - // BAD FRAME, SEND REJ (AFTER RESPTIME - OR WE MAY SEND LOTS!) - - // ALSO SAVE THE FRAME - NEXT TIME WE MAY GET A DIFFERENT SUBSET - // AND SOON WE WILL HANDLE SREJ - - PORT->L2OUTOFSEQ++; - - LINK->L2STATE = 6; - - // IF RUNNING VER1, AND OTHER END MISSES THIS REJ, LINK WILL FAIL - // SO TIME OUT REJ SENT STATE (MUST KEEP IT FOR A WHILE TO AVOID - // 'MULTIPLE REJ' PROBLEM) - - if (LINK->VER1FLAG == 1) - LINK->REJTIMER = TENSECS; - - // SET ACK REQUIRED TIMER - REJ WILL BE SENT WHEN IT EXPIRES - - // if configured RESPTIME is longer than 3 secs use it (may be longer on HF) - - if (PORT->PORTT2 > THREESECS) - LINK->L2ACKREQ = PORT->PORTT2; - else - LINK->L2ACKREQ = THREESECS; // EXTRA LONG RESPTIME, AS SENDING TOO MANY REJ'S IS SERIOUS - - if (LINK->RXFRAMES[NS]) - { - // Already have a copy, so discard old and keep this - - Debugprintf ("Frame %d out of seq but already have copy - release it", NS); - ReleaseBuffer(Q_REM(&LINK->RXFRAMES[NS])); - } - else - { - Debugprintf ("Frame %d out of seq - save", NS); - } - - Buffer->CHAIN = 0; - LINK->RXFRAMES[NS] = Buffer; - goto CheckPF; - } - - // IN SEQUENCE FRAME - - // Remove any stored frame with this seq - - if (LINK->RXFRAMES[NS]) - ReleaseBuffer(Q_REM(&LINK->RXFRAMES[NS])); - - if (LINK->L2STATE == 6) // REJ? - { - // If using REJ we can cancel REJ state. - // If using SREJ we only cancel REJ if we have no stored frames - - if (LINK->Ver2point2) - { - // see if any frames saved. - - int i; - - for (i = 0; i < 8; i++) - { - if (LINK->RXFRAMES[i]) - goto stayinREJ; - } - // Drop through if no stored frames - } - - // CANCEL REJ - - LINK->L2STATE = 5; - LINK->L2FLAGS &= ~REJSENT; - } - -stayinREJ: - - PROC_I_FRAME(LINK, PORT, Buffer); // Passes on or releases Buffer - - -CheckPF: - - if (LINK->Ver2point2 == 0) // Unless using SREJ - { - if (LINK->L2FLAGS & REJSENT) - { - return; // DONT SEND ANOTHER TILL REJ IS CANCELLED - } - } - - if (CTL & PFBIT) - { - if (LINK->L2STATE == 6) - LINK->L2FLAGS |= REJSENT; // Set "REJ Sent" - else - { - // we have all frames. Clear anything in RXFRAMES - - int n = 0; - - while (n < 8) - { - if (LINK->RXFRAMES[n]) - ReleaseBuffer(Q_REM(&LINK->RXFRAMES[n])); - - n++; - } - } - LINK->L2ACKREQ = 0; // CANCEL RR NEEDED - - SEND_RR_RESP(LINK, PFBIT); - - // RECORD TIME - - LINK->LAST_F_TIME = REALTIMETICKS; - } - else - if (LINK->L2ACKREQ == 0) // Resptime is zero so send RR now - SEND_RR_RESP(LINK, 0); - -} - - -VOID PROC_I_FRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer) -{ - int Length; - char * Info; - UCHAR PID; - struct DATAMESSAGE * Msg = (struct DATAMESSAGE *)Buffer; - UCHAR * EOA; - int n = 8; // Max Digis - - LINK->LINKNR++; // INCREMENT OUR N(R) - LINK->LINKNR &= 7; // MODULO 8 - - // ATTACH I FRAMES TO LINK TABLE RX QUEUE - ONLY DATA IS ADDED (NOT ADDRESSES) - - // IF DISC PENDING SET, IGNORE FRAME - - if (LINK->L2FLAGS & DISCPENDING) - { - ReleaseBuffer(Buffer); - return; - } - - // Copy data down the buffer so PID comes after Header (DATAMESSAGE format) - - Length = Buffer->LENGTH - (MSGHDDRLEN + 15); // Buffer Header + addrs + CTL - Info = &Buffer->PID; - - // Adjust for DIGIS - - EOA = &Buffer->ORIGIN[6]; // End of address Bit - - while (((*EOA & 1) == 0) && n--) - { - Length -= 7; - Info += 7; - EOA += 7; - } - - PID = EOA[2]; - - switch(PID) - { - case 0xcc: - case 0xcd: - - // IP Message - - if (n < 8) // If digis, move data back down buffer - { - memmove(&Buffer->PID, &EOA[2], Length); - Buffer->LENGTH -= (int)(&EOA[2] - &Buffer->PID); - } - - Q_IP_MSG( Buffer); - break; - - case 8: - - // NOS FRAGMENTED IP - - if (n < 8) // If digis, move data back down buffer - { - memmove(&Buffer->PID, &EOA[2], Length); - Buffer->LENGTH -= (int)(&EOA[2] - &Buffer->PID); - } - - C_Q_ADD(&LINK->L2FRAG_Q, Buffer); - - if (Buffer->L2DATA[0] == 0) - { - // THERE IS A WHOLE MESSAGE ON FRAG_Q - PASS TO IP - - while(LINK->L2FRAG_Q) - { - Buffer = Q_REM(&LINK->L2FRAG_Q); - Q_IP_MSG( Buffer); - } - } - break; - - default: - - if (Length < 1 || Length > 257) - { - ReleaseBuffer(Buffer); - return; - } - - // Copy Data back over - - memmove(&Msg->PID, Info, Length); - - Buffer->LENGTH = Length + MSGHDDRLEN; - - C_Q_ADD(&LINK->RX_Q, Buffer); - } - - LINK->L2ACKREQ = PORT->PORTT2; // SET RR NEEDED - LINK->KILLTIMER = 0; // RESET IDLE LINK TIMER -} - -//*** CHECK RECEIVED N(R) COUNT - -VOID SDNRCHK(struct _LINKTABLE * LINK, UCHAR CTL) -{ - UCHAR NR = (CTL >> 5) & 7; - - if (NR >= LINK->LINKWS) // N(R) >= WINDOW START? - { - // N(R) ABOVE OR EQUAL TO WINDOW START - OK IF NOT ABOVE N(S), OR N(S) BELOW WS - - if (NR > LINK->LINKNS) // N(R) <= WINDOW END? - { - // N(R) ABOVE N(S) - DOES COUNT WRAP? - - if (LINK->LINKNS >= LINK->LINKWS) // Doesnt wrap - goto BadNR; - } - -GoodNR: - - if ((CTL & 0x0f) == SREJ) - if ((CTL & PFBIT) == 0) - return; // SREJ without F doesn't ACK anything - - LINK->LINKWS = NR; // NEW WINDOW START = RECEIVED N(R) - ACKMSG(LINK); // Remove any acked messages - return; - } - - // N(R) LESS THAN WINDOW START - ONLY OK IF WINDOW WRAPS - - if (NR <= LINK->LINKNS) // N(R) <= WINDOW END? - goto GoodNR; - -BadNR: - - // RECEIVED N(R) IS INVALID - - LINK->SDREJF |= SDNRER; // FLAG A REJECT CONDITION - LINK->SDRBYTE = CTL; // SAVE FOR FRMR RESPONSE -} - -VOID RESETNS(struct _LINKTABLE * LINK, UCHAR NS) -{ - int Resent = (LINK->LINKNS - NS) & 7; // FRAMES TO RESEND - - LINK->LINKNS = NS; // RESET N(S) - - if (LINK->LINKTYPE == 3) // mode-Node - { - if (LINK->NEIGHBOUR) - LINK->NEIGHBOUR->NBOUR_RETRIES += Resent; - } -} - -int COUNT_AT_L2(struct _LINKTABLE * LINK) -{ - // COUNTS FRAMES QUEUED ON AN L2 SESSION (IN BX) - - int count = 0, abovelink = 0; - int n = 0; - - if (LINK == NULL) - return 0; - - abovelink = C_Q_COUNT((UINT *)&LINK->TX_Q); - - // COUNT FRAMES IN TSLOTS - - while (n < 8) - { - if (LINK->FRAMES[n]) - count++; - n++; - } - -// ADD AL,AH ; TOTAL IN AL, NUMBER ABOVE LINK IN AH - - return abovelink + count; -} - -//*** RESET HDLC AND PURGE ALL QUEUES ETC. - -VOID RESET2X(struct _LINKTABLE * LINK) -{ - LINK->SDREJF = 0; // CLEAR FRAME REJECT FLAGS - LINK->LINKWS = 0; // CLEAR WINDOW POINTERS - LINK->LINKOWS = 0; - LINK->LINKNR = 0; // CLEAR N(R) - LINK->LINKNS = 0; // CLEAR N(S) - LINK->SDTSLOT= 0; - LINK->L2STATE = 5; // RESET STATE - LINK->L2FLAGS = 0; -} - - -VOID CLEARL2QUEUES(struct _LINKTABLE * LINK) -{ - // GET RID OF ALL FRAMES THAT ARE QUEUED - - int n = 0; - - while (n < 8) - { - while (LINK->FRAMES[n]) - ReleaseBuffer(Q_REM(&LINK->FRAMES[n])); - while (LINK->RXFRAMES[n]) - ReleaseBuffer(Q_REM(&LINK->RXFRAMES[n])); - n++; - } - - // GET RID OF ALL FRAMES THAT ARE - // QUEUED ON THE TX HOLDING QUEUE, RX QUEUE AND LEVEL 3 QUEUE - - - while (LINK->TX_Q) - ReleaseBuffer(Q_REM(&LINK->TX_Q)); - - while (LINK->RX_Q) - ReleaseBuffer(Q_REM(&LINK->RX_Q)); - -} - -VOID RESET2(struct _LINKTABLE * LINK) -{ - CLEARL2QUEUES(LINK); - RESET2X(LINK); -} - -VOID SENDSABM(struct _LINKTABLE * LINK) -{ - L2SENDCOMMAND(LINK, SABM | PFBIT); -} - - -VOID PUT_ON_PORT_Q(struct PORTCONTROL * PORT, MESSAGE * Buffer) -{ - // TIME STAMP IT - - time(&Buffer->Timestamp); - - if (PORT->TXPORT) - { - Buffer->PORT = PORT->TXPORT; // update port no in header - - PORT = GetPortTableEntryFromPortNum(PORT->TXPORT); - - if (PORT == NULL) - { - ReleaseBuffer(Buffer); - return; - } - } - C_Q_ADD(&PORT->PORTTX_Q, (UINT *)Buffer); -} - - -UCHAR * SETUPADDRESSES(struct _LINKTABLE * LINK, PMESSAGE Msg) -{ - // COPY ADDRESSES FROM LINK TABLE TO MESSAGE _BUFFER - - UCHAR * ptr1 = &LINK->DIGIS[0]; - UCHAR * ptr2 = &Msg->CTL; - int Digis = 8; - - memcpy(&Msg->DEST[0], &LINK->LINKCALL[0], 14); // COPY DEST AND ORIGIN - - Msg->DEST[6] |= 0x60; - Msg->ORIGIN[6] |= 0x60; - - while (Digis) - { - if (*(ptr1)) // any more to copy? - { - memcpy(ptr2, ptr1, 7); - ptr1 += 7; - ptr2 += 7; - Digis--; - } - else - break; - } - - *(ptr2 - 1) |= 1; // SET END OF ADDRESSES - - return ptr2; // Pointer to CTL -} - -VOID SDETX(struct _LINKTABLE * LINK) -{ - // Start sending frsmes if possible - - struct PORTCONTROL * PORT; - int Outstanding; - UCHAR * ptr1, * ptr2; - UCHAR CTL; - int count; - MESSAGE * Msg; - MESSAGE * Buffer; - - // DONT SEND IF RESEQUENCING RECEIVED FRAMES - CAN CAUSE FRMR PROBLEMS - -// if (LINK->L2RESEQ_Q) -// return; - - if (LINK->LINKPORT->PORTNUMBER == 19) - { - int i = 0; - } - - Outstanding = LINK->LINKNS - LINK->LINKOWS; // Was WS not NS - - if (Outstanding < 0) - Outstanding += 8; // allow for wrap - - if (Outstanding >= LINK->LINKWINDOW) // LIMIT - return; - - // See if we can load any more frames into the frame holding q - - while (LINK->TX_Q && LINK->FRAMES[LINK->SDTSLOT] == NULL) - { - Msg = Q_REM(&LINK->TX_Q); - Msg->CHAIN = NULL; - LINK->FRAMES[LINK->SDTSLOT] = Msg; - LINK->SDTSLOT ++; - LINK->SDTSLOT &= 7; - } - - // dont send while poll outstanding - - while ((LINK->L2FLAGS & POLLSENT) == 0) - { - Msg = LINK->FRAMES[LINK->LINKNS]; // is next frame available? - - if (Msg == NULL) - return; - - // send the frame - - // GET BUFFER FOR COPY OF MESSAGE - HAVE TO KEEP ORIGINAL FOR RETRIES - - Buffer = GetBuff(); - - if (Buffer == NULL) - return; - - ptr2 = SETUPADDRESSES(LINK, Buffer); // copy addresses - - // ptr2 NOW POINTS TO COMMAND BYTE - - // GOING TO SEND I FRAME - WILL ACK ANY RECEIVED FRAMES - - LINK->L2ACKREQ = 0; // CLEAR ACK NEEDED - LINK->L2SLOTIM = T3 + rand() % 15; // SET FRAME SENT RECENTLY - LINK->KILLTIMER = 0; // RESET IDLE CIRCUIT TIMER - - CTL = LINK->LINKNR << 5; // GET CURRENT N(R), SHIFT IT TO TOP 3 BITS - CTL |= LINK->LINKNS << 1; // BITS 1-3 OF CONTROL BYTE - - LINK->LINKNS++; // INCREMENT NS - LINK->LINKNS &= 7; // mod 8 - - // SET P BIT IF END OF WINDOW OR NO MORE TO SEND - - if (LINK->VER1FLAG == 0) // NO POLL BIT IF V1 - { - Outstanding = LINK->LINKNS - LINK->LINKOWS; - - if (Outstanding < 0) - Outstanding += 8; // allow for wrap - - // if at limit, or no more to send, set P) - - if (Outstanding >= LINK->LINKWINDOW || LINK->FRAMES[LINK->LINKNS] == NULL) - { - CTL |= PFBIT; - LINK->L2FLAGS |= POLLSENT; - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - // FLAG BUFFER TO CAUSE TIMER TO BE RESET AFTER SEND (or ACK if ACKMODE) - - Buffer->Linkptr = LINK; - } - } - - *(ptr2++) = CTL; // TO DATA (STARTING WITH PID) - - count = Msg->LENGTH - MSGHDDRLEN; - - if (count > 0) // SHOULD ALWAYS BE A PID, BUT BETTER SAFE THAN SORRY - { - ptr1 = (UCHAR *)Msg; - ptr1 += MSGHDDRLEN; - memcpy(ptr2, ptr1, count); - } - - Buffer->DEST[6] |= 0x80; // SET COMMAND - - Buffer->LENGTH = (int)(ptr2 - (UCHAR *)Buffer) + count; // SET NEW LENGTH - - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - PORT = LINK->LINKPORT; - - if (PORT) - { - Buffer->PORT = PORT->PORTNUMBER; - PUT_ON_PORT_Q(PORT, Buffer); - } - else - { - Buffer->Linkptr = 0; - ReleaseBuffer(Buffer); - } - - } -} - -VOID L2TimerProc() -{ - int i = MAXLINKS; - struct _LINKTABLE * LINK = LINKS; - struct PORTCONTROL * PORT = PORTTABLE; - - while (i--) - { - if (LINK->LINKCALL[0] == 0) - { - LINK++; - continue; - } - - // CHECK FOR TIMER EXPIRY OR BUSY CLEARED - - PORT = LINK->LINKPORT; - - if (PORT == NULL) - { - LINK++; - continue; // just ion case!! - } - - if (LINK->L2TIMER) - { - LINK->L2TIMER--; - if (LINK->L2TIMER == 0) - { - L2TIMEOUT(LINK, PORT); - LINK++; - continue; - } - } - else - { - // TIMER NOT RUNNING - MAKE SURE STATE NOT BELOW 5 - IF - // IT IS, SOMETHING HAS GONE WRONG, AND LINK WILL HANG FOREVER - - if (LINK->L2STATE < 5 && LINK->L2STATE != 2 && LINK->L2STATE != 1) // 2 = CONNECT - PROBABLY TO CQ - LINK->L2TIMER = 2; // ARBITRARY VALUE - } - - // TEST FOR RNR SENT, AND NOT STILL BUSY - - if (LINK->L2FLAGS & RNRSENT) - { - // Was busy - - if (RR_OR_RNR(LINK) != RNR) // SEE IF STILL BUSY - { - // Not still busy - tell other end - - // Just sending RR will hause a hang of RR is missed, and other end does not poll on Busy - // Try sending RR CP, so we will retry if not acked - - LINK->L2ACKREQ = 0; // CLEAR ANY DELAYED ACK TIMER - - if (LINK->L2RETRIES == 0) // IF RR(P) OUTSTANDING WILl REPORT ANYWAY - { - SendSupervisCmd(LINK); - LINK++; - continue; - } - } - } - else - { - // NOT BUSY - - if (LINK->L2ACKREQ) // DELAYED ACK TIMER - { - if (LINK->L2RETRIES == 0) // DONT SEND RR RESPONSE WHILEST RR(P) OUTSTANDING - { - LINK->L2ACKREQ--; - if (LINK->L2ACKREQ == 0) - { - SEND_RR_RESP(LINK, 0); // NO F BIT - LINK++; - continue; - } - } - } - } - - // CHECK FOR REJ TIMEOUT - - if (LINK->REJTIMER) - { - LINK->REJTIMER--; - if (LINK->REJTIMER == 0) // {REJ HAS TIMED OUT (THIS MUST BE A VERSION 1 SESSION) - { - // CANCEL REJ STATE - - if (LINK->L2STATE == 6) // REJ? - LINK->L2STATE = 5; // CLEAR REJ - } - } - - // See if time for link validation poll - - if (LINK->L2SLOTIM) - { - LINK->L2SLOTIM--; - if (LINK->L2SLOTIM == 0) // Time to poll - { - SendSupervisCmd(LINK); - LINK++; - continue; - } - } - - // See if idle too long - - LINK->KILLTIMER++; - - if (L2KILLTIME && LINK->KILLTIMER > L2KILLTIME) - { - // CIRCUIT HAS BEEN IDLE TOO LONG - SHUT IT DOWN - - LINK->KILLTIMER = 0; - LINK->L2TIMER = 1; // TO FORCE DISC - LINK->L2STATE = 4; // DISCONNECTING - - // TELL OTHER LEVELS - - InformPartner(LINK, NORMALCLOSE); - } - LINK++; - } -} - -VOID SendSupervisCmd(struct _LINKTABLE * LINK) -{ - // Send Super Command RR/RNR/REJ(P) - - UCHAR CTL; - - if (LINK->VER1FLAG == 1) - { - // VERSION 1 TIMEOUT - - // RESET TO RESEND I FRAMES - - LINK->LINKNS = LINK->LINKOWS; - - SDETX(LINK); // PREVENT FRMR (I HOPE) - } - - // SEND RR COMMAND - EITHER AS LINK VALIDATION POLL OR FOLLOWING TIMEOUT - - LINK->L2ACKREQ = 0; // CLEAR ACK NEEDED - - CTL = RR_OR_RNR(LINK); - -// MOV L2STATE[EBX],5 ; CANCEL REJ - ACTUALLY GOING TO 'PENDING ACK' - - CTL |= LINK->LINKNR << 5; // SHIFT N(R) TO TOP 3 BITS - CTL |= PFBIT; - - LINK->L2FLAGS |= POLLSENT; - - L2SENDCOMMAND(LINK, CTL); - - LINK->L2SLOTIM = T3 + rand() % 15; // SET FRAME SENT RECENTLY -} - -void SEND_RR_RESP(struct _LINKTABLE * LINK, UCHAR PF) -{ - UCHAR CTL; - - CTL = RR_OR_RNR(LINK); - -// MOV L2STATE[EBX],5 ; CANCEL REJ - ACTUALLY GOING TO 'PENDING ACK' - - CTL |= LINK->LINKNR << 5; // SHIFT N(R) TO TOP 3 BITS - CTL |= PF; - - L2SENDRESPONSE(LINK, CTL); - - ACKMSG(LINK); // SEE IF STILL WAITING FOR ACK -} - -VOID ACKMSG(struct _LINKTABLE * LINK) -{ - // RELEASE ANY ACKNOWLEDGED FRAMES - - while (LINK->LINKOWS != LINK->LINKWS) // is OLD WINDOW START EQUAL TO NEW WINDOW START? - { - // No, so frames to ack - - if (LINK->FRAMES[LINK->LINKOWS]) - ReleaseBuffer(Q_REM(&LINK->FRAMES[LINK->LINKOWS])); - else - { - char Call1[12], Call2[12]; - - Call1[ConvFromAX25(LINK->LINKCALL, Call1)] = 0; - Call2[ConvFromAX25(LINK->OURCALL, Call2)] = 0; - - Debugprintf("Missing frame to ack Seq %d Calls %s %s", LINK->LINKOWS, Call1, Call2); - } - - LINK->IFrameRetryCounter = 0; - - LINK->LINKOWS++; // INCREMENT OLD WINDOW START - LINK->LINKOWS &= 7; // MODULO 8 - - // SOMETHING HAS BEEN ACKED - RESET RETRY COUNTER - - if (LINK->L2RETRIES) - LINK->L2RETRIES = 1; // MUSTN'T SET TO ZERO - COULD CAUSE PREMATURE RETRANSMIT - - } - - if (LINK->LINKWS != LINK->LINKNS) // IS N(S) = NEW WINDOW START? - { - // NOT ALL I-FRAMES HAVE BEEN ACK'ED - RESTART TIMER - - // Need to kill link if we are getting repeated RR(F) after timeout - // (Indicating other station is seeing our RR(P) but not the resent I frame) - - if (LINK->IFrameRetryCounter++ > LINK->LINKPORT->PORTN2) - { - Debugprintf("Too many repeats of same I frame - closing connection"); - LINK->L2TIMER = 1; // USE TIMER TO SEND DISC - LINK->L2STATE = 4; // DISCONNECTING - return; - } - - - LINK->L2TIMER = LINK->L2TIME; - return; - } - - // ALL FRAMES HAVE BEEN ACKED - CANCEL TIMER UNLESS RETRYING - // IF RETRYING, MUST ONLY CANCEL WHEN RR(F) RECEIVED - - if (LINK->VER1FLAG == 1 || LINK->L2RETRIES == 0) // STOP TIMER IF LEVEL 1 or not retrying - { - LINK->L2TIMER = 0; - LINK->L2FLAGS &= ~POLLSENT; // CLEAR I(P) SET (IN CASE TALKING TO OLD BPQ!) - } - - // IF DISCONNECT REQUEST OUTSTANDING, AND NO FRAMES ON TX QUEUE, SEND DISC - - if ((LINK->L2FLAGS & DISCPENDING) && LINK->TX_Q == 0) - { - LINK->L2FLAGS &= ~DISCPENDING; - - LINK->L2TIMER = 1; // USE TIMER TO SEND DISC - LINK->L2STATE = 4; // DISCONNECTING - } -} - -VOID CONNECTFAILED(); - -VOID L2TIMEOUT(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT) -{ - // TIMER EXPIRED - - // IF LINK UP (STATE 5 OR ABOVE) SEND RR/RNR AS REQUIRED - // IF S2, REPEAT SABM - // IF S3, REPEAT FRMR - // IF S4, REPEAT DISC - - - PORT->L2TIMEOUTS++; // FOR STATS - - if (LINK->L2STATE == 0) - return; - - if (LINK->L2STATE == 1) - { - // XID - - LINK->L2RETRIES++; - if (LINK->L2RETRIES >= PORT->PORTN2) - { - // RETRIED N2 TIMES - Give up - - CONNECTFAILED(LINK); // TELL LEVEL 4 IT FAILED - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - CLEAROUTLINK(LINK); - return; - } - - L2SENDXID(LINK); - return; - } - - - if (LINK->L2STATE == 2) - { - // CONNECTING - - LINK->L2RETRIES++; - if (LINK->L2RETRIES >= PORT->PORTN2) - { - // RETRIED N2 TIMES - Give up - - CONNECTFAILED(LINK); // TELL LEVEL 4 IT FAILED - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - CLEAROUTLINK(LINK); - return; - } - - SENDSABM(LINK); - return; - } - - if (LINK->L2STATE == 4) - { - // DISCONNECTING - - LINK->L2RETRIES++; - - if (LINK->L2RETRIES >= PORT->PORTN2) - { - // RETRIED N2 TIMES - JUST CLEAR OUT LINK - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - CLEAROUTLINK(LINK); - return; - } - - L2SENDCOMMAND(LINK, DISC | PFBIT); - return; - } - - if (LINK->L2STATE == 3) - { - // FRMR - - LINK->L2RETRIES++; - if (LINK->L2RETRIES >= PORT->PORTN2) - { - // RETRIED N2 TIMES - RESET LINK - - LINK->L2RETRIES = 0; - LINK->L2STATE = 2; - SENDSABM(LINK); - return; - } - } - - // STATE 5 OR ABOVE - - // SEND RR(P) UP TO N2 TIMES - - LINK->L2RETRIES++; - - if (LINK->L2RETRIES >= PORT->PORTN2) - { - // RETRIED N TIMES SEND A COUPLE OF DISCS AND THEN CLOSE - - InformPartner(LINK, RETRIEDOUT); // TELL OTHER END ITS GONE - - LINK->L2RETRIES -= 1; // Just send one DISC - LINK->L2STATE = 4; // CLOSING - - L2SENDCOMMAND(LINK, DISC | PFBIT); - return; - } - - SendSupervisCmd(LINK); -} - -VOID SDFRMR(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT) -{ - PORT->L2FRMRTX++; - - LINK->L2STATE = 3; // ENTER FRMR STATE - - LINK->L2TIMER = LINK->L2TIME; //SET TIMER - - SENDFRMR(LINK); -} - -VOID SENDFRMR(struct _LINKTABLE * LINK) -{ - // RESEND FRMR - - struct PORTCONTROL * PORT; - MESSAGE * Buffer; - UCHAR * ptr; - - Buffer = SETUPL2MESSAGE(LINK, FRMR); - - if (Buffer == NULL) - return; - - Buffer->ORIGIN[6] |= 0x80; // SET RESPONSE - - ptr = &Buffer->PID; - - *(ptr++) = LINK->SDRBYTE; // MOVE REJECT C-BYTE - - *(ptr++) = LINK->LINKNR << 5 | LINK->LINKNS << 1; - - *(ptr++) = LINK->SDREJF; // MOVE REJECT FLAGS - - Buffer->LENGTH += 3; - - PORT = LINK->LINKPORT; - Buffer->PORT = PORT->PORTNUMBER; - - if (PORT) - PUT_ON_PORT_Q(PORT, Buffer); - else - ReleaseBuffer(Buffer); - - return; -} - -VOID CLEAROUTLINK(struct _LINKTABLE * LINK) -{ - char toCall[12], fromCall[12]; - - toCall[ConvFromAX25(LINK->LINKCALL, toCall)] = 0; - fromCall[ConvFromAX25(LINK->OURCALL, fromCall)] = 0; - - hookL2SessionDeleted(LINK->LINKPORT->PORTNUMBER, fromCall, toCall, LINK); - - seeifUnlockneeded(LINK); - - CLEARL2QUEUES(LINK); // TO RELEASE ANY BUFFERS - - memset(LINK, 0, sizeof(struct _LINKTABLE)); -} - -VOID L2SENDXID(struct _LINKTABLE * LINK) -{ - // Set up and send XID - - struct PORTCONTROL * PORT; - UCHAR * ptr; - unsigned int xidval; - MESSAGE * Buffer; - - if (LINK->LINKPORT == 0) - return; //??? has been zapped - - Buffer = SETUPL2MESSAGE(LINK, XID | PFBIT); - - if (Buffer == NULL) - { - // NO BUFFERS - SET TIMER TO FORCE RETRY - - LINK->L2TIMER = 10*3; // SET TIMER - return; - } - - Buffer->DEST[6] |= 0x80; // SET COMMAND - - ptr = &Buffer->PID; - - // Set up default XID Mod 8 - - *ptr++ = 0x82; // FI - *ptr++ = 0x80; // GI - *ptr++ = 0x0; - *ptr++ = 0x10; // Length 16 - - *ptr++ = 0x02; // Classes of Procedures - *ptr++ = 0x02; // Length - *ptr++ = 0x00; // - *ptr++ = 0x21; // ABM Half Duplex - - // We offer REJ, SREJ and SREJ Multiframe - - *ptr++ = 0x03; // Optional Functions - *ptr++ = 0x03; // Len - - // Sync TX, SREJ Multiframe 16 bit FCS, Mod 8, TEST, - // Extended Addressing, REJ, SREJ - - xidval = OPMustHave | OPSREJ | OPSREJMult | OPREJ | OPMod8; - *ptr++ = xidval >> 16; - *ptr++ = xidval >> 8; - *ptr++ = xidval; - - - *ptr++ = 0x06; // RX Packet Len - *ptr++ = 0x02; // Len - *ptr++ = 0x08; // - *ptr++ = 0x00; // 2K bits (256) Bytes - - *ptr++ = 0x08; // RX Window - *ptr++ = 0x01; // Len - *ptr++ = 0x07; // 7 - - Buffer->LENGTH = (int)(ptr - (UCHAR *)Buffer); // SET LENGTH - - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - // FLAG BUFFER TO CAUSE TIMER TO BE RESET AFTER SEND - - Buffer->Linkptr = LINK; - - PORT = LINK->LINKPORT; - - if (PORT) - { - Buffer->PORT = PORT->PORTNUMBER; - PUT_ON_PORT_Q(PORT, Buffer); - } - else - { - Buffer->Linkptr = 0; - ReleaseBuffer(Buffer); - } -} - - - - - - -VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD) -{ - // SEND COMMAND IN CMD - - struct PORTCONTROL * PORT; - MESSAGE * Buffer; - - if (LINK->LINKPORT == 0) - return; //??? has been zapped - - Buffer = SETUPL2MESSAGE(LINK, CMD); - - if (Buffer == NULL) - { - // NO BUFFERS - SET TIMER TO FORCE RETRY - - if (CMD & PFBIT) // RESPONSE EXPECTED? - LINK->L2TIMER = 10*3; // SET TIMER - - return; - } - - Buffer->DEST[6] |= 0x80; // SET COMMAND - - if (CMD & PFBIT) // RESPONSE EXPECTED? - { - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - // FLAG BUFFER TO CAUSE TIMER TO BE RESET AFTER SEND - - Buffer->Linkptr = LINK; - } - - PORT = LINK->LINKPORT; - - if (PORT) - { - Buffer->PORT = PORT->PORTNUMBER; - PUT_ON_PORT_Q(PORT, Buffer); - } - else - { - Buffer->Linkptr = 0; - ReleaseBuffer(Buffer); - } -} - - - - - - -VOID L2SENDRESPONSE(struct _LINKTABLE * LINK, int CMD) -{ - // SEND Response IN CMD - - struct PORTCONTROL * PORT; - MESSAGE * Buffer; - - Buffer = SETUPL2MESSAGE(LINK, CMD); - - if (Buffer == NULL) - { - // NO BUFFERS - SET TIMER TO FORCE RETRY - - if (CMD & PFBIT) // RESPONSE EXPECTED? - LINK->L2TIMER = 10*3; // SET TIMER - - return; - } - - Buffer->ORIGIN[6] |= 0x80; // SET RESPONSE - - LINK->L2SLOTIM = T3 + rand() % 15; // SET FRAME SENT RECENTLY - - PORT = LINK->LINKPORT; - Buffer->PORT = PORT->PORTNUMBER; - - if (PORT) - PUT_ON_PORT_Q(PORT, Buffer); - else - ReleaseBuffer(Buffer); - -} - - -MESSAGE * SETUPL2MESSAGE(struct _LINKTABLE * LINK, UCHAR CMD) -{ - MESSAGE * Buffer; - UCHAR * ptr; - - Buffer = GetBuff(); - - if (Buffer == NULL) - return NULL; - - ptr = SETUPADDRESSES(LINK, Buffer); // copy addresses - - // ptr NOW POINTS TO COMMAND BYTE - - *(ptr)++ = CMD; - - Buffer->LENGTH = (int)(ptr - (UCHAR *)Buffer); // SET LENGTH - - return Buffer; -} - - -VOID L3LINKCLOSED(struct _LINKTABLE * LINK, int Reason); - -VOID InformPartner(struct _LINKTABLE * LINK, int Reason) -{ - // LINK IS DISCONNECTING - IF THERE IS A CROSSLINK, SEND DISC TO IT - - if (LINK->LINKTYPE == 3) - { - L3LINKCLOSED(LINK, Reason); - return; - } - - if (LINK->CIRCUITPOINTER) - { - CloseSessionPartner(LINK->CIRCUITPOINTER); - CLEARSESSIONENTRY(LINK->CIRCUITPOINTER); - } -} - - -UINT RR_OR_RNR(struct _LINKTABLE * LINK) -{ - UCHAR Temp; - TRANSPORTENTRY * Session; - - LINK->L2FLAGS &= ~RNRSENT; - - // SET UP APPROPRIATE SUPER COMMAND - - if (LINK->LINKTYPE == 3) - - // Node to Node - only busy if short of buffers - - goto CHKBUFFS; - -// UP OR DOWN LINK - SEE IF SESSION IS BUSY - - if (LINK->CIRCUITPOINTER == 0) - goto CHKBUFFS; // NOT CONNECTED - - Session = LINK->CIRCUITPOINTER; // TO CIRCUIT ENTRY - - Temp = CHECKIFBUSYL2(Session); //TARGET SESSION BUSY? - - if (Temp & L4BUSY) - goto SENDRNR; // BUSY - -CHKBUFFS: - - if (QCOUNT < 20) - goto SENDRNR; // NOT ENOUGH - - // SEND REJ IF IN REJ STATE - - if (LINK->L2STATE == 6) - { - - // We may have the needed frame in RXFRAMES - -CheckNSLoop2: - - if (LINK->RXFRAMES[LINK->LINKNR]) - { - // We have the first missing frame. Process it. - - struct PORTCONTROL * PORT = LINK->LINKPORT; - MESSAGE * OldBuffer = Q_REM(&LINK->RXFRAMES[LINK->LINKNR]); - - Debugprintf("L2 about to send REJ - process saved Frame %d", LINK->LINKNR); - PROC_I_FRAME(LINK, PORT, OldBuffer); // Passes on or releases Buffer - - // NR has been updated. - - // Clear REJ if we have no more saved - - if (LINK->Ver2point2) // Using SREJ? - { - // see if any frames saved. - - int i; - - for (i = 0; i < 8; i++) - { - if (LINK->RXFRAMES[i]) - goto stayinREJ2; - } - // Drop through if no stored frames - } - - LINK->L2STATE = 5; - LINK->L2FLAGS &= ~REJSENT; -stayinREJ2: - LINK->L2ACKREQ = 0; // Cancel Resptime (Set by PROC_I_FRAME) - - goto CheckNSLoop2; // See if OK or we have another saved frame - } - if (LINK->L2STATE == 6) - - // if we support SREJ send that instesd or REJ - - if (LINK->Ver2point2) // We only allow 2.2 with SREJ Multi - return SREJ; - else - return REJ; - } - return RR; - -SENDRNR: - - LINK->L2FLAGS |= RNRSENT; // REMEMBER - - return RNR; -} - - -VOID ConnectFailedOrRefused(struct _LINKTABLE * LINK, char * Msg); - -VOID CONNECTFAILED(struct _LINKTABLE * LINK) -{ - ConnectFailedOrRefused(LINK, "Failure with"); -} -VOID CONNECTREFUSED(struct _LINKTABLE * LINK) -{ - ConnectFailedOrRefused(LINK, "Busy from"); -} - -VOID L3CONNECTFAILED(); - -VOID ConnectFailedOrRefused(struct _LINKTABLE * LINK, char * Msg) -{ - // IF DOWNLINK, TELL PARTNER - // IF CROSSLINK, TELL ROUTE CONTROL - - struct DATAMESSAGE * Buffer; - UCHAR * ptr1; - char Normcall[10]; - TRANSPORTENTRY * Session; - TRANSPORTENTRY * InSession; - - if (LINK->LINKTYPE == 3) - { - L3CONNECTFAILED(LINK); // REPORT TO LEVEL 3 - return; - } - - if (LINK->CIRCUITPOINTER == 0) // No crosslink?? - return; - - Buffer = GetBuff(); - - if (Buffer == NULL) - return; - - // SET UP HEADER - - Buffer->PID = 0xf0; - - ptr1 = SetupNodeHeader(Buffer); - - Normcall[ConvFromAX25(LINK->LINKCALL, Normcall)] = 0; - - ptr1 += sprintf(ptr1, "%s %s\r", Msg, Normcall); - - Buffer->LENGTH = (int)(ptr1 - (UCHAR *)Buffer); - - Session = LINK->CIRCUITPOINTER; // GET CIRCUIT TABLE ENTRY - InSession = Session->L4CROSSLINK; // TO INCOMMING SESSION - - CLEARSESSIONENTRY(Session); - - if (InSession) - { - InSession->L4CROSSLINK = NULL; // CLEAR REVERSE LINK - C_Q_ADD(&InSession->L4TX_Q, Buffer); - PostDataAvailable(InSession); - } - else - ReleaseBuffer(Buffer); -} - -VOID SENDCONNECTREPLY(struct _LINKTABLE * LINK) -{ - // LINK SETUP COMPLETE - - struct DATAMESSAGE * Buffer; - UCHAR * ptr1; - char Normcall[10]; - TRANSPORTENTRY * Session; - TRANSPORTENTRY * InSession; - - if (LINK->LINKTYPE == 3) - return; - - // UP/DOWN LINK - - if (LINK->CIRCUITPOINTER == 0) // No crosslink?? - return; - - Buffer = GetBuff(); - - if (Buffer == NULL) - return; - - // SET UP HEADER - - Buffer->PID = 0xf0; - - ptr1 = SetupNodeHeader(Buffer); - - Normcall[ConvFromAX25(LINK->LINKCALL, Normcall)] = 0; - - ptr1 += sprintf(ptr1, "Connected to %s\r", Normcall); - - Buffer->LENGTH = (int)(ptr1 - (UCHAR *)Buffer); - - Session = LINK->CIRCUITPOINTER; // GET CIRCUIT TABLE ENTRY - Session->L4STATE = 5; - InSession = Session->L4CROSSLINK; // TO INCOMMONG SESSION - - if (InSession) - { - C_Q_ADD(&InSession->L4TX_Q, Buffer); - PostDataAvailable(InSession); - } -} - - -TRANSPORTENTRY * SetupSessionForL2(struct _LINKTABLE * LINK) -{ - TRANSPORTENTRY * NewSess = L4TABLE; - int Index = 0; - - while (Index < MAXCIRCUITS) - { - if (NewSess->L4USER[0] == 0) - { - // Got One - - LINK->CIRCUITPOINTER = NewSess; // SETUP LINK-CIRCUIT CONNECTION - - memcpy(NewSess->L4USER, LINK->LINKCALL, 7); - memcpy(NewSess->L4MYCALL, MYCALL, 7); // ALWAYS USE _NODE CALL - - NewSess->CIRCUITINDEX = Index; //OUR INDEX - NewSess->CIRCUITID = NEXTID; - - NEXTID++; - if (NEXTID == 0) - NEXTID++; // kEEP nON-ZERO - - NewSess->L4TARGET.LINK = LINK; - - NewSess->L4CIRCUITTYPE = L2LINK | UPLINK; - - NewSess->L4STATE = 5; // SET LINK ACTIVE - - NewSess->SESSPACLEN = LINK->LINKPORT->PORTPACLEN; - - - NewSess->SESSIONT1 = L4T1; // Default - NewSess->L4WINDOW = (UCHAR)L4DEFAULTWINDOW; - - return NewSess; - } - Index++; - NewSess++; - } - - return NULL; -} - - -VOID Digipeat(struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR * OurCall, int toPort, int UIOnly) // Digi it (if enabled) -{ - // WE MAY HAVE DISABLED DIGIPEAT ALTOGETHER, (DIGIFLAG=0), - // OR ALLOW ALLOW ONLY UI FRAMES TO BE DIGIED (DIGIFLAG=-1) - - // toPort and UIOnly are used for Cross Port digi feature - - int n; - - if (PORT->DIGIFLAG == 0 && toPort == 0) - { - ReleaseBuffer(Buffer); - return; - } - - OurCall[6] |= 0x80; // SET HAS BEEN REPEATED - - // SEE IF UI FRAME - scan forward for end of address bit - - n = 8; - - while ((OurCall[6] & 1) == 0) - { - OurCall += 7; - - if ((OurCall - &Buffer->CTL) > 56) - { - // Run off end before findin end of address - - ReleaseBuffer(Buffer); - return; - } - } - - if (toPort) // Cross port digi - { - if (((OurCall[7] & ~PFBIT) == 3) || UIOnly == 0) - { - // UI or Digi all - - Buffer->PORT = toPort; // update port no in header - PORT = GetPortTableEntryFromPortNum(toPort); - - if (PORT == NULL) - ReleaseBuffer(Buffer); - else - PUT_ON_PORT_Q(PORT, Buffer); - return; - } - else - { - ReleaseBuffer(Buffer); - return; - } - } - - if ((OurCall[7] & ~PFBIT) == 3) - { - // UI - - // UI FRAME. IF DIGIMASK IS NON-ZERO, SEND TO ALL PORTS SET, OTHERWISE SEND TO DIGIPORT - - PORT->L2DIGIED++; - - if (toPort) - { - // Cross port digi - - PORT = GetPortTableEntryFromPortNum(toPort); - Buffer->PORT = PORT->DIGIPORT; // update port no in header - - if (PORT == NULL) - ReleaseBuffer(Buffer); - else - PUT_ON_PORT_Q(PORT, Buffer); - - return; - } - - if (PORT->DIGIMASK == 0) - { - if (PORT->DIGIPORT) // Cross Band Digi? - { - Buffer->PORT = PORT->DIGIPORT; // update port no in header - - PORT = GetPortTableEntryFromPortNum(PORT->DIGIPORT); - - if (PORT == NULL) - { - ReleaseBuffer(Buffer); - return; - } - } - PUT_ON_PORT_Q(PORT, Buffer); - } - else - { - DigiToMultiplePorts(PORT, Buffer); - ReleaseBuffer(Buffer); - } - return; - } - - // Not UI - Only Digi if Digiflag not -1 - - if (PORT->DIGIFLAG == -1) - { - ReleaseBuffer(Buffer); - return; - } - - PORT->L2DIGIED++; - - if (PORT->DIGIPORT) // Cross Band Digi? - { - Buffer->PORT = PORT->DIGIPORT; // update port no in header - - PORT = GetPortTableEntryFromPortNum(PORT->DIGIPORT); - - if (PORT == NULL) - { - ReleaseBuffer(Buffer); - return; - } - } - PUT_ON_PORT_Q(PORT, Buffer); -} - -BOOL CheckForListeningSession(struct PORTCONTROL * PORT, MESSAGE * Msg) -{ - TRANSPORTENTRY * L4 = L4TABLE; - struct DATAMESSAGE * Buffer; - int i = MAXCIRCUITS; - UCHAR * ptr; - - while (i--) - { - if ((CountBits64(L4->LISTEN) == 1) && ((1 << ((Msg->PORT & 0x7f) - 1) && L4->LISTEN))) - { - // See if he is calling our call - - UCHAR ourcall[7]; // Call we are using (may have SSID bits inverted - memcpy(ourcall, L4->L4USER, 7); - ourcall[6] ^= 0x1e; // Flip SSID - - if (CompareCalls(Msg->DEST, ourcall)) - { - // Get Session Entry for Downlink - - TRANSPORTENTRY * NewSess = L4TABLE; - struct _LINKTABLE * LINK; - char Normcall[10]; - - int Index = 0; - - while (Index < MAXCIRCUITS) - { - if (NewSess->L4USER[0] == 0) - { - // Got One - - L4->L4CROSSLINK = NewSess; - NewSess->L4CROSSLINK = L4; - - memcpy(NewSess->L4USER, L4->L4USER, 7); - memcpy(NewSess->L4MYCALL, L4->L4USER, 7); - - NewSess->CIRCUITINDEX = Index; //OUR INDEX - NewSess->CIRCUITID = NEXTID; - NewSess->L4STATE = 5; - NewSess->L4CIRCUITTYPE = L2LINK+UPLINK; - - NEXTID++; - if (NEXTID == 0) - NEXTID++; // kEEP nON-ZERO - - NewSess->SESSIONT1 = L4->SESSIONT1; - NewSess->L4WINDOW = (UCHAR)L4DEFAULTWINDOW; - - // SET UP NEW SESSION (OR RESET EXISTING ONE) - - FindLink(Msg->ORIGIN, ourcall, PORT->PORTNUMBER, &LINK); - - if (LINK == NULL) - return FALSE; - - memcpy(LINK->LINKCALL, Msg->ORIGIN, 7); - LINK->LINKCALL[6] &= 0xFE; - memcpy(LINK->OURCALL, ourcall, 7); - - LINK->LINKPORT = PORT; - - LINK->L2TIME = PORT->PORTT1; -/* - // Copy Digis - - n = 7; - ptr = &LINK->DIGIS[0]; - - while (axcalls[n]) - { - memcpy(ptr, &axcalls[n], 7); - n += 7; - ptr += 7; - - LINK->L2TIME += 2 * PORT->PORTT1; // ADJUST TIMER VALUE FOR 1 DIGI - } -*/ - LINK->LINKTYPE = 2; // DOWNLINK - LINK->LINKWINDOW = PORT->PORTWINDOW; - - RESET2(LINK); // RESET ALL FLAGS - - LINK->L2STATE = 5; // CONNECTED - - LINK->CIRCUITPOINTER = NewSess; - - NewSess->L4TARGET.LINK = LINK; - - if (PORT->PORTPACLEN) - NewSess->SESSPACLEN = L4->SESSPACLEN = PORT->PORTPACLEN; - - L2SENDUA(PORT, Msg, Msg); // RESET OF DOWN/CROSSLINK - - L4->LISTEN = FALSE; // Take out of listen mode - - // Tell User - - Buffer = GetBuff(); - - if (Buffer == NULL) - return TRUE; - - // SET UP HEADER - - Buffer->PID = 0xf0; - - ptr = &Buffer->L2DATA[0]; - - Normcall[ConvFromAX25(LINK->LINKCALL, Normcall)] = 0; - - ptr += sprintf(ptr, "Incoming call from %s\r", Normcall); - - Buffer->LENGTH = (int)(ptr - (UCHAR *)Buffer); - - C_Q_ADD(&L4->L4TX_Q, Buffer); - PostDataAvailable(L4); - - return TRUE; - - } - Index++; - NewSess++; - } - return FALSE; - } - } - L4++; - } - return FALSE; -} - - -int COUNTLINKS(int Port); -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); - - -int CheckKissInterlock(struct PORTCONTROL * PORT, int Exclusive) -{ - // This checks for interlocked kiss and other ports. Returns 1 if attach/connect not allowed - - // If Exclusive is not set allow connects on specified port up to l2limit, - - // If Exclusive is set also don't allow any connects on specified port. - - // Generally use Exclusive if locking a port that doesn't allow shared access, eg ARDOP, VARAus - - // Maybe only Exclusive is needed, and just check session mode ports. Sharing of KISS ports is controlled by USERS - - int Interlock = PORT->PORTINTERLOCK; - - if (Interlock == 0) - return 0; // No locking - - PORT = PORTTABLE; - - if (Exclusive) - { - while(PORT) - { - if (PORT->TNC) - { - struct TNCINFO * TNC = PORT->TNC; - - if (Interlock == TNC->RXRadio || Interlock == TNC->TXRadio) // Same Group - { - // See if port in use - - int n; - - for (n = 0; n <= 26; n++) - { - if (TNC->PortRecord->ATTACHEDSESSIONS[n]) - { - return TNC->Port; ; // Refuse Connect - } - } - } - } - PORT = PORT->PORTPOINTER; - } - } - return 0; // ok to connect -} - -int seeifInterlockneeded(struct PORTCONTROL * PORT) -{ - // Can we just call SuspendOtherPorts - it won't do any harm if already suspended - // No, at that needs a TNC Record, so duplicate code here - - int i; - int Interlock = PORT->PORTINTERLOCK; - struct TNCINFO * TNC; - - if (Interlock == 0) - return 0; // No locking - - for (i = 1; i <= MAXBPQPORTS; i++) - { - TNC = TNCInfo[i]; - - if (TNC) - if (Interlock == TNC->RXRadio || Interlock == TNC->TXRadio) // Same Group - if (TNC->SuspendPortProc && TNC->PortRecord->PORTCONTROL.PortSuspended == FALSE) - TNC->SuspendPortProc(TNC, TNC); - } - - return 0; -} - -int seeifUnlockneeded(struct _LINKTABLE * LINK) -{ - // We need to see if any other links are active on any interlocked KISS ports. If not, release the lock - - int i; - int links = 0; - - int Interlock; - struct TNCINFO * TNC; - struct PORTCONTROL * PORT = LINK->LINKPORT; - - if (PORT == NULL) - return 0; - - // Should only be called for KISS links, but just in case - - if (PORT->PORTTYPE > 12) // INTERNAL or EXTERNAL? - return 0; // Not KISS Port - - Interlock = PORT->PORTINTERLOCK; - - if (Interlock == 0) - return 0; // No locking - - - // Count all L2 links on interlocked KISS ports - - PORT = PORTTABLE; - - while(PORT) - { - if (PORT->PORTTYPE <= 12) // INTERNAL or EXTERNAL? - if (Interlock == PORT->PORTINTERLOCK) - links += COUNTLINKS(PORT->PORTNUMBER); - - PORT = PORT->PORTPOINTER; - } - - if (links > 1) // must be the one we are closing - return 0; // Keep lock - - - for (i = 1; i <= MAXBPQPORTS; i++) - { - TNC = TNCInfo[i]; - - if (TNC) - if (Interlock == TNC->RXRadio || Interlock == TNC->TXRadio) // Same Group - if (TNC->ReleasePortProc && TNC->PortRecord->PORTCONTROL.PortSuspended == TRUE) - TNC->ReleasePortProc(TNC, TNC); - } - - return 0; -} - - - - diff --git a/L2Code.c b/L2Code.c index 78369c7..ab0b1f5 100644 --- a/L2Code.c +++ b/L2Code.c @@ -47,8 +47,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #define THREESECS 3*3 -VOID L2SENDCOMMAND(); -VOID L2ROUTINE(); +VOID L2Routine(struct PORTCONTROL * PORT, PMESSAGE Buffer); MESSAGE * SETUPL2MESSAGE(struct _LINKTABLE * LINK, UCHAR CMD); VOID SendSupervisCmd(struct _LINKTABLE * LINK); void SEND_RR_RESP(struct _LINKTABLE * LINK, UCHAR PF); @@ -3098,7 +3097,7 @@ VOID ACKMSG(struct _LINKTABLE * LINK) } } -VOID CONNECTFAILED(); +VOID CONNECTFAILED(struct _LINKTABLE * LINK); VOID L2TIMEOUT(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT) { @@ -3599,7 +3598,7 @@ VOID CONNECTREFUSED(struct _LINKTABLE * LINK) ConnectFailedOrRefused(LINK, "Busy from"); } -VOID L3CONNECTFAILED(); +VOID L3CONNECTFAILED(struct _LINKTABLE * LINK); VOID ConnectFailedOrRefused(struct _LINKTABLE * LINK, char * Msg) { @@ -4135,7 +4134,7 @@ int seeifUnlockneeded(struct _LINKTABLE * LINK) if (TNC) if (Interlock == TNC->RXRadio || Interlock == TNC->TXRadio) // Same Group if (TNC->ReleasePortProc && TNC->PortRecord->PORTCONTROL.PortSuspended == TRUE) - TNC->ReleasePortProc(TNC, TNC); + TNC->ReleasePortProc(TNC); } return 0; diff --git a/L4Code-skigdebian.c b/L4Code-skigdebian.c deleted file mode 100644 index 59fc0e2..0000000 --- a/L4Code-skigdebian.c +++ /dev/null @@ -1,2416 +0,0 @@ -/* -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 -*/ - -// -// C replacement for L4Code.asm -// -#define Kernel - -#define _CRT_SECURE_NO_DEPRECATE - - -#pragma data_seg("_BPQDATA") - -#include "time.h" -#include "stdio.h" -#include - -#include "CHeaders.h" -#include "tncinfo.h" - -extern BPQVECSTRUC BPQHOSTVECTOR[]; -#define BPQHOSTSTREAMS 64 -#define IPHOSTVECTOR BPQHOSTVECTOR[BPQHOSTSTREAMS + 3] - -VOID CLOSECURRENTSESSION(TRANSPORTENTRY * Session); -VOID SENDL4DISC(TRANSPORTENTRY * Session); -int C_Q_COUNT(VOID * Q); -TRANSPORTENTRY * SetupSessionForL2(struct _LINKTABLE * LINK); -VOID InformPartner(struct _LINKTABLE * LINK, int Reason); -VOID IFRM150(TRANSPORTENTRY * Session, PDATAMESSAGE Buffer); -VOID SendConNAK(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG); -BOOL FINDCIRCUIT(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY ** REQL4, int * NewIndex); -int GETBUSYBIT(TRANSPORTENTRY * L4); -BOOL cATTACHTOBBS(TRANSPORTENTRY * Session, UINT Mask, int Paclen, int * AnySessions); -VOID SETUPNEWCIRCUIT(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, - TRANSPORTENTRY * L4, char * BPQPARAMS, int ApplMask, int * BPQNODE); -extern char * ALIASPTR; -VOID SendConACK(struct _LINKTABLE * LINK, TRANSPORTENTRY * L4, L3MESSAGEBUFFER * L3MSG, BOOL BPQNODE, UINT Applmask, UCHAR * ApplCall); -VOID L3SWAPADDRESSES(L3MESSAGEBUFFER * L3MSG); -VOID L4TIMEOUT(TRANSPORTENTRY * L4); -struct DEST_LIST * CHECKL3TABLES(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * Msg); -int CHECKIFBUSYL4(TRANSPORTENTRY * L4); -VOID AUTOTIMER(); -VOID NRRecordRoute(UCHAR * Buff, int Len); -VOID REFRESHROUTE(TRANSPORTENTRY * Session); -VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR); -VOID SENDL4IACK(TRANSPORTENTRY * Session); -VOID CHECKNEIGHBOUR(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * Msg); -VOID ProcessINP3RIF(struct ROUTE * Route, UCHAR * ptr1, int msglen, int Port); -VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len, int Port); -VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, UCHAR * ApplCall); -void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode); -void SendVARANetromMsg(struct TNCINFO * TNC, PL3MESSAGEBUFFER MSG); - -extern UINT APPLMASK; - -extern BOOL LogL4Connects; -extern BOOL LogAllConnects; - -// L4 Flags Values - -#define DISCPENDING 8 // SEND DISC WHEN ALL DATA ACK'ED - -extern APPLCALLS * APPL; - -VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) -{ - // MAKE SURE PID IS 0CF - IN CASE SOMEONE IS SENDING L2 STUFF ON WHAT - // WE THINK IS A _NODE-_NODE LINK - - struct DEST_LIST * DEST; - - int n; - - if (L3MSG->L3PID != 0xCF) - { - ReleaseBuffer(L3MSG); - return; - } - - if (LINK->NEIGHBOUR == 0) - { - // NO ROUTE ASSOCIATED WITH THIS CIRCUIT - SET ONE UP - - CHECKNEIGHBOUR(LINK, L3MSG); - - if (LINK->NEIGHBOUR == 0) - { - // COULDNT SET UP NEIGHBOUR - CAN ONLY THROW IT AWAY - - ReleaseBuffer(L3MSG); - return; - } - } - - // See if a INP3 RIF (first Byte 0xFF) - - if (L3MSG->L3SRCE[0] == 0xff) - { - // INP3 - - ProcessINP3RIF(LINK->NEIGHBOUR, &L3MSG->L3SRCE[1], L3MSG->LENGTH - (MSGHDDRLEN + 2), L3MSG->Port); // = 2 = PID + FF Flag - ReleaseBuffer(L3MSG); - return; - } - - APPLMASK = 0; // NOT APPLICATION - - if (NODE) // _NODE SUPPORT INCLUDED? - { - - if (CompareCalls(L3MSG->L3DEST, MYCALL)) - { - FRAMEFORUS(LINK, L3MSG, APPLMASK, MYCALL); - return; - } - } - - // CHECK ALL L4 CALLS - - APPLMASK = 1; - ALIASPTR = &CMDALIAS[0][0]; - - n = NumberofAppls; - - APPL = APPLCALLTABLE; - - while (n--) - { - if (APPL->APPLCALL[0] > 0x40) // Valid ax.25 addr - { - if (CompareCalls(L3MSG->L3DEST, APPL->APPLCALL)) - { - FRAMEFORUS(LINK, L3MSG, APPLMASK, APPL->APPLCALL); - return; - } - } - APPLMASK <<= 1; - ALIASPTR += ALIASLEN; - APPL++; - } - - // IS IT INP3 (L3RTT) - - if (CompareCalls(L3MSG->L3DEST, L3RTT)) - { - ProcessRTTMsg(LINK->NEIGHBOUR, L3MSG, L3MSG->LENGTH, L3MSG->Port); - return; - } - - L3MSG->L3TTL--; - - if (L3MSG->L3TTL == 0) - { - ReleaseBuffer(L3MSG); - return; - } - - // If it is a record route frame we should add our call to the list before sending on - - if (L3MSG->L4FLAGS == 0 && L3MSG->L4ID == 1 && L3MSG->L4INDEX == 0) - { - // Add our call on end, and increase count - - int Len = L3MSG->LENGTH; - int Count; - - UCHAR * ptr = (UCHAR *)L3MSG; - - if (Len < 248) - { - ptr += (Len - 1); - - Count = (*(ptr++)) & 0x7F; // Mask End of Route - - memcpy(ptr, MYCALL, 7); - - ptr += 7; - - Count--; - *(ptr) = Count; - - if (Count) - L3MSG->LENGTH += 8; - } - } - - if (L3MSG->L3TTL > L3LIVES) - L3MSG->L3TTL = L3LIVES; // ENFORCE LIMIT ON ALL FRAMES SENT - - if (FindDestination(L3MSG->L3DEST, &DEST) == 0) - { - ReleaseBuffer(L3MSG); // CANT FIND DESTINATION - return; - } - - // IF MESSAGE ORIGINTED HERE, THERE MUST BE A ROUTING LOOP - - // THERE IS LITTLE POINT SENDING IT OVER THE SAME ROUTE AGAIN, - // SO SET ANOTHER ROUTE ACTIVE IF POSSIBLE - - if (CompareCalls(L3MSG->L3SRCE, MYCALL) || CompareCalls(L3MSG->L3SRCE, APPLCALLTABLE->APPLCALL)) - { - // MESSAGE HAS COME BACK TO ITS STARTING POINT - ACTIVATE ANOTHER ROUTE, - // UNLESS THERE IS ONLY ONE, IN WHICH CASE DISCARD IT - - if (DEST->NRROUTE[1].ROUT_NEIGHBOUR == 0) // No more routes - { - ReleaseBuffer(L3MSG); - return; - } - - DEST->DEST_ROUTE++; - - if (DEST->DEST_ROUTE == 4) // TO NEXT - DEST->DEST_ROUTE = 1; // TRY TO ACTIVATE FIRST - } - - // IF CURRENT ROUTE IS BACK THE WAY WE CAME, THEN ACTIVATE - //ANOTHER (IF POSSIBLE). - - if (DEST->DEST_ROUTE) - { - if (DEST->NRROUTE[DEST->DEST_ROUTE -1].ROUT_NEIGHBOUR == LINK->NEIGHBOUR) - { - // Current ROUTE IS BACK THE WAY WE CAME - ACTIVATE ANOTHER IF POSSIBLE - - DEST->DEST_ROUTE++; - if (DEST->DEST_ROUTE == 4) - DEST->DEST_ROUTE =1; - } - goto NO_PROBLEM; - } - else - { - // DONT HAVE AN ACTIVE ROUTE - - if (DEST->NRROUTE[0].ROUT_NEIGHBOUR == LINK->NEIGHBOUR) - { - // FIRST ROUTE IS BACK THE WAY WE CAME - ACTIVATE ANOTHER IF POSSIBLE - - DEST->DEST_ROUTE = 2; // WILL BE RESET BY L3 CODE IF THERE IS NOT OTHER ROUTE - } - } - -NO_PROBLEM: - - CHECKL3TABLES(LINK, L3MSG); - -// EVEN IF WE CANT PUT ORIGINATING NODE INTO OUR TABLES, PASS MSG ON -// ANYWAY - THE FINAL TARGET MAY HAVE ANOTHER WAY BACK - - - C_Q_ADD(&DEST->DEST_Q, L3MSG); - - L3FRAMES++; -} - -VOID SENDL4MESSAGE(TRANSPORTENTRY * L4, struct DATAMESSAGE * Msg) -{ - L3MESSAGEBUFFER * L3MSG; - struct DEST_LIST * DEST; - struct DATAMESSAGE * Copy; - int FRAGFLAG = 0; - int Len; - - // These make it simpler to understand code - -#define NullPKTLen 4 + sizeof(void *) // 4 is Port, Len, PID -#define MaxL4Len 236 + 4 + sizeof(void *) // Max NETROM Size - - - if (Msg->LENGTH == NullPKTLen) - { - // NO DATA - DISCARD IT - - ReleaseBuffer(Msg); - return; - } - - L3MSG = GetBuff(); - - if (L3MSG == 0) - { - // DONT THINK WE SHOULD GET HERE, UNLESS _QCOUNT IS CORRUPT, - // BUT IF WE DO, SHOULD RETURN MSG TO FREE Q - START TIMER, AND - // DROP THROUGH TO RELBUFF - - L4->L4TIMER = L4->SESSIONT1; - - ReleaseBuffer(Msg); - return; - } - - L3MSG->L3PID = 0xCF; // NET MESSAGE - - memcpy(L3MSG->L3SRCE, L4->L4MYCALL, 7); - - DEST = L4->L4TARGET.DEST; - memcpy(L3MSG->L3DEST, DEST->DEST_CALL, 7); - - L3MSG->L3TTL = L3LIVES; - - L3MSG->L4ID = L4->FARID; - L3MSG->L4INDEX = L4->FARINDEX; - - L3MSG->L4TXNO = L4->TXSEQNO; - - // SET UP RTT TIMER - - if (L4->RTT_TIMER == 0) - { - L4->RTT_SEQ = L4->TXSEQNO; - - L4->RTT_TIMER = GetTickCount(); - } - - L4->TXSEQNO++; - - - L4->L4LASTACKED = L3MSG->L4RXNO = L4->RXSEQNO; // SAVE LAST NUMBER ACKED - - // SEE IF CROSSSESSION IS BUSY - - GETBUSYBIT(L4); // Sets BUSY in NAKBITS if Busy - - L3MSG->L4FLAGS = L4INFO | L4->NAKBITS; - - L4->L4TIMER = L4->SESSIONT1; // SET TIMER - L4->L4ACKREQ = 0; // CANCEL ACK NEEDED - - Len = Msg->LENGTH; - - if (Len > MaxL4Len) // 236 DATA + 8 HEADER - { - // MUST FRAGMENT MESSAGE - - L3MSG->L4FLAGS |= L4MORE; - FRAGFLAG = 1; - - Len = MaxL4Len; - } - - Len += 20; // L3/4 Header - - L3MSG->LENGTH = Len; - - Len -= (20 + NullPKTLen); // Actual Data - - memcpy(L3MSG->L4DATA, Msg->L2DATA, Len); - - // CREATE COPY FOR POSSIBLE RETRY - - Copy = GetBuff(); - - if (Copy == 0) - { - // SHOULD NEVER HAPPEN - - ReleaseBuffer(Msg); - return; - } - - memcpy(Copy, L3MSG, L3MSG->LENGTH); - - // If we have fragmented, we should adjust length, or retry will send too much - // (bug in .asm code) - - if (FRAGFLAG) - Copy->LENGTH = MaxL4Len; - - C_Q_ADD(&L4->L4HOLD_Q, Copy); - - C_Q_ADD(&DEST->DEST_Q, L3MSG); - - DEST->DEST_COUNT++; // COUNT THEM - - L4FRAMESTX++; - - if (FRAGFLAG) - { - // MESSAGE WAS TOO BIG - ADJUST IT AND LOOP BACK - - Msg->LENGTH -= 236; - - memmove(Msg->L2DATA, &Msg->L2DATA[236], Msg->LENGTH - NullPKTLen); - - SENDL4MESSAGE(L4, Msg); - } -} - - -int GETBUSYBIT(TRANSPORTENTRY * L4) -{ - // SEE IF CROSSSESSION IS BUSY - - L4->NAKBITS &= ~L4BUSY; // Clear busy - - L4->NAKBITS |= CHECKIFBUSYL4(L4); // RETURNS AL WITH BUSY BIT SET IF CROSSSESSION IS BUSY - - return L4->NAKBITS; -} - -VOID Q_IP_MSG(MESSAGE * Buffer) -{ - if (IPHOSTVECTOR.HOSTAPPLFLAGS & 0x80) - { - // CHECK WE ARENT USING TOO MANY BUFFERS - - if (C_Q_COUNT(&IPHOSTVECTOR.HOSTTRACEQ) > 20) - ReleaseBuffer(Q_REM((void *)&IPHOSTVECTOR.HOSTTRACEQ)); - - C_Q_ADD(&IPHOSTVECTOR.HOSTTRACEQ, Buffer); - return; - } - - ReleaseBuffer(Buffer); -} - -VOID SENDL4CONNECT(TRANSPORTENTRY * Session) -{ - PL3MESSAGEBUFFER MSG = (PL3MESSAGEBUFFER)GetBuff(); - struct DEST_LIST * DEST = Session->L4TARGET.DEST; - - if (MSG == NULL) - return; - - if (DEST->DEST_CALL[0] == 0) - { - Debugprintf("Trying to send L4CREQ to NULL Destination"); - ReleaseBuffer(MSG); - return; - } - - MSG->L3PID = 0xCF; // NET MESSAGE - - memcpy(MSG->L3SRCE, Session->L4MYCALL, 7); - memcpy(MSG->L3DEST, DEST->DEST_CALL, 7); - - MSG->L3TTL = L3LIVES; - - MSG->L4INDEX = Session->CIRCUITINDEX; - MSG->L4ID = Session->CIRCUITID; - MSG->L4TXNO = 0; - MSG->L4RXNO = 0; - MSG->L4FLAGS = L4CREQ; - - MSG->L4DATA[0] = L4DEFAULTWINDOW; // PROPOSED WINDOW - - memcpy(&MSG->L4DATA[1], Session->L4USER, 7); // ORIG CALL - memcpy(&MSG->L4DATA[8], Session->L4MYCALL, 7); - - Session->L4TIMER = Session->SESSIONT1; // START TIMER - memcpy(&MSG->L4DATA[15], &Session->SESSIONT1, 2); // AND PUT IN MSG - - MSG->LENGTH = (int)(&MSG->L4DATA[17] - (UCHAR *)MSG); - - if (Session->SPYFLAG) - { - MSG->L4DATA[17] = 'Z'; // ADD SPY ON BBS FLAG - MSG->LENGTH++; - } - C_Q_ADD(&DEST->DEST_Q, (UINT *)MSG); -} - -void RETURNEDTONODE(TRANSPORTENTRY * Session) -{ - // SEND RETURNED TO ALIAS:CALL - - struct DATAMESSAGE * Msg = (struct DATAMESSAGE *)GetBuff(); - char Nodename[20]; - - if (Msg) - { - Msg->PID = 0xf0; - - Nodename[DecodeNodeName(MYCALLWITHALIAS, Nodename)] = 0; // null terminate - - Msg->LENGTH = (USHORT)sprintf(&Msg->L2DATA[0], "Returned to Node %s\r", Nodename) + 4 + sizeof(void *); - C_Q_ADD(&Session->L4TX_Q, (UINT *)Msg); - PostDataAvailable(Session); - } -} - - -extern void * BUFFER; - -VOID L4BG() -{ - // PROCESS DATA QUEUED ON SESSIONS - - int n = MAXCIRCUITS; - TRANSPORTENTRY * L4 = L4TABLE; - int MaxLinks = MAXLINKS; - UCHAR Outstanding; - struct DATAMESSAGE * Msg; - struct PORTCONTROL * PORT; - struct _LINKTABLE * LINK; - int Msglen, Paclen; - - while (n--) - { - if (L4->L4USER[0] == 0) - { - L4++; - continue; - } - while (L4->L4TX_Q) - { - if (L4->L4CIRCUITTYPE & BPQHOST) - break; // Leave on TXQ - - // SEE IF BUSY - NEED DIFFERENT TESTS FOR EACH SESSION TYPE - - if (L4->L4CIRCUITTYPE & SESSION) - { - // L4 SESSION - WILL NEED BUFFERS FOR SAVING COPY, - // AND POSSIBLY FRAGMENTATION - - if (QCOUNT < 15) - break; - - if (L4->FLAGS & L4BUSY) - { - // CHOKED - MAKE SURE TIMER IS RUNNING - - if (L4->L4TIMER == 0) - L4->L4TIMER = L4->SESSIONT1; - - break; - } - - // CHECK WINDOW - - Outstanding = L4->TXSEQNO - L4->L4WS; // LAST FRAME ACKED - GIVES NUMBER OUTSTANING - - // MOD 256, SO SHOULD HANDLE WRAP?? - - if (Outstanding > L4->L4WINDOW) - break; - - } - else if (L4->L4CIRCUITTYPE & L2LINK) - { - // L2 LINK - - LINK = L4->L4TARGET.LINK; - - if (COUNT_AT_L2(LINK) > 8) - break; - } - - // Not busy, so continue - - L4->L4KILLTIMER = 0; //RESET SESSION TIMEOUTS - - if(L4->L4CROSSLINK) - L4->L4CROSSLINK->L4KILLTIMER = 0; - - Msg = Q_REM((void *)&L4->L4TX_Q); - - if (L4->L4CIRCUITTYPE & PACTOR) - { - // PACTOR-like - queue to Port - - // Stream Number is in KAMSESSION - - Msg->PORT = L4->KAMSESSION; - PORT = L4->L4TARGET.PORT; - - C_Q_ADD(&PORT->PORTTX_Q, Msg); - - continue; - } - // non-pactor - - // IF CROSSLINK, QUEUE TO NEIGHBOUR, ELSE QUEUE ON LINK ENTRY - - if (L4->L4CIRCUITTYPE & SESSION) - { - SENDL4MESSAGE(L4, Msg); - ReleaseBuffer(Msg); - continue; - } - - LINK = L4->L4TARGET.LINK; - - // If we want to enforce PACLEN this may be a good place to do it - - Msglen = Msg->LENGTH - (MSGHDDRLEN + 1); //Dont include PID - Paclen = L4->SESSPACLEN; - - if (Paclen == 0) - Paclen = 256; - - if (Msglen > Paclen) - { - // Fragment it. - // Is it best to send Paclen packets then short or equal length? - // I think equal length; - - int Fragments = (Msglen + Paclen - 1) / Paclen; - int Fraglen = Msglen / Fragments; - - if ((Msglen & 1)) // Odd - Fraglen ++; - - while (Msglen > Fraglen) - { - PDATAMESSAGE Fragment = GetBuff(); - - if (Fragment == NULL) - break; // Cant do much else - - Fragment->PORT = Msg->PORT; - Fragment->PID = Msg->PID; - Fragment->LENGTH = Fraglen + (MSGHDDRLEN + 1); - - memcpy(Fragment->L2DATA, Msg->L2DATA, Fraglen); - - C_Q_ADD(&LINK->TX_Q, Fragment); - - memcpy(Msg->L2DATA, &Msg->L2DATA[Fraglen], Msglen - Fraglen); - Msglen -= Fraglen; - Msg->LENGTH -= Fraglen; - } - - // Drop through to send last bit - - } - - C_Q_ADD(&LINK->TX_Q, Msg); - } - - // if nothing on TX Queue If there is stuff on hold queue, timer must be running - -// if (L4->L4TX_Q == 0 && L4->L4HOLD_Q) - if (L4->L4HOLD_Q) - { - if (L4->L4TIMER == 0) - { - L4->L4TIMER = L4->SESSIONT1; - } - } - - // now check for rxed frames - - while(L4->L4RX_Q) - { - Msg = Q_REM((void *)&L4->L4RX_Q); - - IFRM150(L4, Msg); - - if (L4->L4USER[0] == 0) // HAVE JUST CLOSED SESSION! - goto NextSess; - } - - // IF ACK IS PENDING, AND WE ARE AT RX WINDOW, SEND ACK NOW - - Outstanding = L4->RXSEQNO - L4->L4LASTACKED; - if (Outstanding >= L4->L4WINDOW) - SENDL4IACK(L4); -NextSess: - L4++; - } -} - -VOID CLEARSESSIONENTRY(TRANSPORTENTRY * Session) -{ - - // RETURN ANY QUEUED BUFFERS TO FREE QUEUE - - while (Session->L4TX_Q) - ReleaseBuffer(Q_REM((void *)&Session->L4TX_Q)); - - while (Session->L4RX_Q) - ReleaseBuffer(Q_REM((void *)&Session->L4RX_Q)); - - while (Session->L4HOLD_Q) - ReleaseBuffer(Q_REM((void *)&Session->L4HOLD_Q)); - - if (C_Q_COUNT(&Session->L4RESEQ_Q) > Session->L4WINDOW) - { - Debugprintf("Corrupt RESEQ_Q Q Len %d Free Buffs %d", C_Q_COUNT(&Session->L4RESEQ_Q), QCOUNT); - Session->L4RESEQ_Q = 0; - } - - while (Session->L4RESEQ_Q) - ReleaseBuffer(Q_REM((void *)&Session->L4RESEQ_Q)); - - if (Session->PARTCMDBUFFER) - ReleaseBuffer(Session->PARTCMDBUFFER); - - memset(Session, 0, sizeof(TRANSPORTENTRY)); -} - -VOID CloseSessionPartner(TRANSPORTENTRY * Session) -{ - // SEND CLOSE TO CROSSLINKED SESSION AND CLEAR LOCAL SESSION - - if (Session == NULL) - return; - - if (Session->L4CROSSLINK) - CLOSECURRENTSESSION(Session->L4CROSSLINK); - - CLEARSESSIONENTRY(Session); -} - - -VOID CLOSECURRENTSESSION(TRANSPORTENTRY * Session) -{ - MESSAGE * Buffer; - struct _LINKTABLE * LINK; - -// SHUT DOWN SESSION AND UNLINK IF CROSSLINKED - - if (Session == NULL) - return; - - Session->L4CROSSLINK = NULL; - - // IF STAY FLAG SET, KEEP SESSION, AND SEND MESSAGE - - if (Session->STAYFLAG) - { - RETURNEDTONODE(Session); - Session->STAYFLAG = 0; // Only do it once - return; - } - - if (Session->L4CIRCUITTYPE & BPQHOST) - { - // BPQ HOST MODE SESSION - INDICATE STATUS CHANGE - - PBPQVECSTRUC HOST = Session->L4TARGET.HOST; - HOST->HOSTSESSION = 0; - HOST->HOSTFLAGS |= 3; /// State Change - - PostStateChange(Session); - CLEARSESSIONENTRY(Session); - return; - } - - if (Session->L4CIRCUITTYPE & PACTOR) - { - // PACTOR-type (Session linked to Port) - - struct _EXTPORTDATA * EXTPORT = Session->L4TARGET.EXTPORT; - - // If any data is queued, move it to the port entry, so it can be sent before the disconnect - - while (Session->L4TX_Q) - { - Buffer = Q_REM((void *)&Session->L4TX_Q); - EXTPORT->PORTCONTROL.PORTTXROUTINE(EXTPORT, Buffer); - } - - EXTPORT->ATTACHEDSESSIONS[Session->KAMSESSION] = NULL; - - CLEARSESSIONENTRY(Session); - return; - } - - if (Session->L4CIRCUITTYPE & SESSION) - { - // L4 SESSION TO CLOSE - - if (Session->L4HOLD_Q || Session->L4TX_Q) // WAITING FOR ACK or MORE TO SEND - SEND DISC LATER - { - Session->FLAGS |= DISCPENDING; // SEND DISC WHEN ALL DATA ACKED - return; - } - - SENDL4DISC(Session); - return; - } - - // Must be LEVEL 2 SESSION TO CLOSE - - // COPY ANY PENDING DATA TO L2 TX Q, THEN GET RID OF SESSION - - LINK = Session->L4TARGET.LINK; - - if (LINK == NULL) // just in case! - { - CLEARSESSIONENTRY(Session); - return; - } - - while (Session->L4TX_Q) - { - Buffer = Q_REM((void *)&Session->L4TX_Q); - C_Q_ADD(&LINK->TX_Q, Buffer); - } - - // NOTHING LEFT AT SESSION LEVEL - - LINK->CIRCUITPOINTER = NULL; // CLEAR REVERSE LINK - - if ((LINK->LINKWS != LINK->LINKNS) || LINK->TX_Q) - { - // STILL MORE TO SEND - SEND DISC LATER - - LINK->L2FLAGS |= DISCPENDING; // SEND DISC WHEN ALL DATA ACKED - } - else - { - // NOTHING QUEUED - CAN SEND DISC NOW - - LINK->L2STATE = 4; // DISCONNECTING - LINK->L2TIMER = 1; // USE TIMER TO KICK OFF DISC - } - - CLEARSESSIONENTRY(Session); - -} - -VOID L4TimerProc() -{ - // CHECK FOR TIMER EXPIRY - - int n = MAXCIRCUITS; - TRANSPORTENTRY * L4 = L4TABLE; - TRANSPORTENTRY * Partner; - int MaxLinks = MAXLINKS; - - while (n--) - { - if (L4->L4USER[0] == 0) - { - L4++; - continue; - } - - // CHECK FOR L4BUSY SET AND NO LONGER BUSY - - if (L4->NAKBITS & L4BUSY) - { - if ((CHECKIFBUSYL4(L4) & L4BUSY) == 0) - { - // no longer busy - - L4->NAKBITS &= ~L4BUSY; // Clear busy - L4->L4ACKREQ = 1; // SEND ACK - } - } - - if (L4->L4TIMER) // Timer Running? - { - L4->L4TIMER--; - if (L4->L4TIMER == 0) // Expired - L4TIMEOUT(L4); - } - - if (L4->L4ACKREQ) // DELAYED ACK Timer Running? - { - L4->L4ACKREQ--; - if (L4->L4ACKREQ == 0) // Expired - SENDL4IACK(L4); - } - - L4->L4KILLTIMER++; - - // IF BIT 6 OF APPLFLAGS SET, SEND MSG EVERY 11 MINS TO KEEP SESSION OPEN - - if (L4->L4CROSSLINK) // CONNECTED? - if (L4->SESS_APPLFLAGS & 0x40) - if (L4->L4KILLTIMER > 11 * 60) - AUTOTIMER(L4); - - if (L4->L4LIMIT == 0) - L4->L4LIMIT = L4LIMIT; - else - { - if (L4->L4KILLTIMER > L4->L4LIMIT) - { - L4->L4KILLTIMER = 0; - - // CLOSE THIS SESSION, AND ITS PARTNER (IF ANY) - - L4->STAYFLAG = 0; - - Partner = L4->L4CROSSLINK; - CLOSECURRENTSESSION(L4); - - if (Partner) - { - Partner->L4KILLTIMER = 0; //ITS TIMES IS ALSO ABOUT TO EXPIRE - CLOSECURRENTSESSION(Partner); // CLOSE THIS ONE - } - } - } - L4++; - } -} - -VOID L4TIMEOUT(TRANSPORTENTRY * L4) -{ - // TIMER EXPIRED - - // IF LINK UP REPEAT TEXT - // IF S2, REPEAT CONNECT REQUEST - // IF S4, REPEAT DISCONNECT REQUEST - - struct DATAMESSAGE * Msg; - struct DATAMESSAGE * Copy; - struct DEST_LIST * DEST; - - if (L4->L4STATE < 2) - return; - - if (L4->L4STATE == 2) - { - // RETRY CONNECT - - L4->L4RETRIES++; - - if (L4->L4RETRIES > L4N2) - { - // RETRIED N2 TIMES - FAIL LINK - - L4CONNECTFAILED(L4); // TELL OTHER PARTNER IT FAILED - CLEARSESSIONENTRY(L4); - return; - } - - Debugprintf("Retrying L4 Connect Request"); - - SENDL4CONNECT(L4); // Resend connect - return; - } - - if (L4->L4STATE == 4) - { - // RETRY DISCONNECT - - L4->L4RETRIES++; - - if (L4->L4RETRIES > L4N2) - { - // RETRIED N2 TIMES - FAIL LINK - - - CLEARSESSIONENTRY(L4); - return; - } - - SENDL4DISC(L4); // Resend connect - return; - } - // STATE 5 OR ABOVE - RETRY INFO - - - L4->FLAGS &= ~L4BUSY; // CANCEL CHOKE - - L4->L4RETRIES++; - - if (L4->L4RETRIES > L4N2) - { - // RETRIED N2 TIMES - FAIL LINK - - CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT) - return; - } - - // RESEND ALL OUTSTANDING FRAMES - - L4->FLAGS &= 0x7F; // CLEAR CHOKED - - Msg = L4->L4HOLD_Q; - - while (Msg) - { - Copy = GetBuff(); - - if (Copy == 0) - return; - - memcpy(Copy, Msg, Msg->LENGTH); - - DEST = L4->L4TARGET.DEST; - - C_Q_ADD(&DEST->DEST_Q, Copy); - - L4FRAMESRETRIED++; - - Msg = Msg->CHAIN; - } -} - -VOID AUTOTIMER(TRANSPORTENTRY * L4) -{ - // SEND MESSAGE TO USER TO KEEP CIRCUIT OPEN - - struct DATAMESSAGE * Msg = GetBuff(); - - if (Msg == 0) - return; - - Msg->PID = 0xf0; - Msg->L2DATA[0] = 0; - Msg->L2DATA[1] = 0; - - Msg->LENGTH = MSGHDDRLEN + 3; - - C_Q_ADD(&L4->L4TX_Q, Msg); - - PostDataAvailable(L4); - - L4->L4KILLTIMER = 0; - - if (L4->L4CROSSLINK) - L4->L4CROSSLINK->L4KILLTIMER = 0; -} - -VOID L4CONNECTFAILED(TRANSPORTENTRY * L4) -{ - // CONNECT HAS TIMED OUT - SEND MESSAGE TO OTHER END - - struct DATAMESSAGE * Msg; - TRANSPORTENTRY * Partner; - UCHAR * ptr1; - char Nodename[20]; - struct DEST_LIST * DEST; - - Partner = L4->L4CROSSLINK; - - if (Partner == 0) - return; - - Msg = GetBuff(); - - if (Msg == 0) - return; - - Msg->PID = 0xf0; - - ptr1 = SetupNodeHeader(Msg); - - DEST = L4->L4TARGET.DEST; - Nodename[DecodeNodeName(DEST->DEST_CALL, Nodename)] = 0; // null terminate - - ptr1 += sprintf(ptr1, "Failure with %s\r", Nodename); - - Msg->LENGTH = (int)(ptr1 - (UCHAR *)Msg); - - C_Q_ADD(&Partner->L4TX_Q, Msg); - - PostDataAvailable(Partner); - - Partner->L4CROSSLINK = 0; // Back to command lewel -} - - -VOID ProcessIframe(struct _LINKTABLE * LINK, PDATAMESSAGE Buffer) -{ - // IF UP/DOWN LINK, AND CIRCUIT ESTABLISHED, ADD LEVEL 3/4 HEADERS - // (FRAGMENTING IF NECESSARY), AND PASS TO TRANSPORT CONTROL - // FOR ESTABLISHED ROUTE - - // IF INTERNODE MESSAGE, PASS TO ROUTE CONTROL - - // IF UP/DOWN, AND NO CIRCUIT, PASS TO COMMAND HANDLER - - TRANSPORTENTRY * Session; - - // IT IS POSSIBLE TO MULTIPLEX NETROM AND IP STUFF ON THE SAME LINK - - if (Buffer->PID == 0xCC || Buffer->PID == 0xCD) - { - Q_IP_MSG((MESSAGE *)Buffer); - return; - } - - if (Buffer->PID == 0xCF) - { - // INTERNODE frame - - // IF LINKTYPE IS NOT 3, MUST CHECK IF WE HAVE ACCIDENTALLY ATTACHED A BBS PORT TO THE NODE - - if (LINK->LINKTYPE != 3) - { - if (LINK->CIRCUITPOINTER) - { - // MUST KILL SESSION - - InformPartner(LINK, NORMALCLOSE); // CLOSE IT - LINK->CIRCUITPOINTER = NULL; // AND UNHOOK - } - LINK->LINKTYPE = 3; // NOW WE KNOW ITS A CROSSLINK - } - - NETROMMSG(LINK, (L3MESSAGEBUFFER *)Buffer); - return; - } - - if (LINK->LINKTYPE == 3) - { - // Weve receved a non- netrom frame on an inernode link - - ReleaseBuffer(Buffer); - return; - } - - if (LINK->CIRCUITPOINTER) - { - // Pass to Session - - IFRM150(LINK->CIRCUITPOINTER, Buffer); - return; - } - - // UPLINK MESSAGE WITHOUT LEVEL 4 ENTRY - CREATE ONE - - Session = SetupSessionForL2(LINK); - - if (Session == NULL) - return; - - CommandHandler(Session, Buffer); - return; -} - - -VOID IFRM100(struct _LINKTABLE * LINK, PDATAMESSAGE Buffer) -{ - TRANSPORTENTRY * Session; - - if (LINK->CIRCUITPOINTER) - { - // Pass to Session - - IFRM150(LINK->CIRCUITPOINTER, Buffer); - return; - } - - // UPLINK MESSAGE WITHOUT LEVEL 4 ENTRY - CREATE ONE - - Session = SetupSessionForL2(LINK); - - if (Session == NULL) - return; - - CommandHandler(Session, Buffer); - return; -} - - -VOID IFRM150(TRANSPORTENTRY * Session, PDATAMESSAGE Buffer) -{ - TRANSPORTENTRY * Partner; - struct _LINKTABLE * LINK; - - Session->L4KILLTIMER = 0; // RESET SESSION TIMEOUT - - if (Session->L4CROSSLINK == NULL) // CONNECTED? - { - // NO, SO PASS TO COMMAND HANDLER - - CommandHandler(Session, Buffer); - return; - } - - Partner = Session->L4CROSSLINK; // TO SESSION PARTNER - - if (Partner->L4STATE == 5) - { - C_Q_ADD(&Partner->L4TX_Q, Buffer); - PostDataAvailable(Partner); - return; - } - - - - // MESSAGE RECEIVED BEFORE SESSION IS UP - CANCEL SESSION - // AND PASS MESSAGE TO COMMAND HANDLER - - if (Partner->L4CIRCUITTYPE & L2LINK) // L2 SESSION? - { - // MUST CANCEL L2 SESSION - - LINK = Partner->L4TARGET.LINK; - LINK->CIRCUITPOINTER = NULL; // CLEAR REVERSE LINK - - LINK->L2STATE = 4; // DISCONNECTING - LINK->L2TIMER = 1; // USE TIMER TO KICK OFF DISC - - LINK->L2RETRIES = LINK->LINKPORT->PORTN2 - 2; //ONLY SEND DISC ONCE - } - - CLEARSESSIONENTRY(Partner); - - Session->L4CROSSLINK = 0; // CLEAR CROSS LINK - CommandHandler(Session, Buffer); - return; -} - - -VOID SENDL4DISC(TRANSPORTENTRY * Session) -{ - L3MESSAGEBUFFER * MSG; - struct DEST_LIST * DEST = Session->L4TARGET.DEST; - - if (Session->L4STATE < 4) - { - // CIRCUIT NOT UP OR CLOSING - PROBABLY NOT YET SET UP - JUST ZAP IT - - CLEARSESSIONENTRY(Session); - return; - } - - Session->L4TIMER = Session->SESSIONT1; // START TIMER - Session->L4STATE = 4; // SET DISCONNECTING - Session->L4ACKREQ = 0; // CANCEL ACK NEEDED - - MSG = GetBuff(); - - if (MSG == NULL) - return; - - MSG->L3PID = 0xCF; // NET MESSAGE - - memcpy(MSG->L3SRCE, Session->L4MYCALL, 7); - memcpy(MSG->L3DEST, DEST->DEST_CALL, 7); - MSG->L3TTL = L3LIVES; - MSG->L4INDEX = Session->FARINDEX; - MSG->L4ID = Session->FARID; - MSG->L4TXNO = 0; - MSG->L4FLAGS = L4DREQ; - - MSG->LENGTH = (int)(&MSG->L4DATA[0] - (UCHAR *)MSG); - - C_Q_ADD(&DEST->DEST_Q, (UINT *)MSG); -} - - -void WriteL4LogLine(UCHAR * mycall, UCHAR * call, UCHAR * node) -{ - UCHAR FN[MAX_PATH]; - FILE * L4LogHandle; - time_t T; - struct tm * tm; - - char Call1[12], Call2[12], Call3[12]; - - char LogMsg[256]; - int MsgLen; - - Call1[ConvFromAX25(mycall, Call1)] = 0; - Call2[ConvFromAX25(call, Call2)] = 0; - Call3[ConvFromAX25(node, Call3)] = 0; - - - T = time(NULL); - tm = gmtime(&T); - - sprintf(FN,"%s/L4Log_%02d%02d.txt", BPQDirectory, tm->tm_mon + 1, tm->tm_mday); - - L4LogHandle = fopen(FN, "ab"); - - if (L4LogHandle == NULL) - return; - - MsgLen = sprintf(LogMsg, "%02d:%02d:%02d Call to %s from %s at Node %s\r\n", tm->tm_hour, tm->tm_min, tm->tm_sec, Call1, Call2, Call3); - - fwrite(LogMsg , 1, MsgLen, L4LogHandle); - - fclose(L4LogHandle); -} - -VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT ApplMask, UCHAR * ApplCall) -{ - // CONNECT REQUEST - SEE IF EXISTING SESSION - // IF NOT, GET AND FORMAT SESSION TABLE ENTRY - // SEND CONNECT ACK - - // EDI = _BUFFER, EBX = LINK - - TRANSPORTENTRY * L4; - int BPQNODE = 0; // NOT ONE OF MINE - char BPQPARAMS[10]; // Extended Connect Params from BPQ Node - int CONERROR; - int Index; - - memcpy(BPQPARAMS, &L4T1, 2); // SET DEFAULT T1 IN CASE NOT FROM ANOTHER BPQ NODE - - BPQPARAMS[2] = 0; // 'SPY' NOT SET - - if (CheckExcludeList(&L3MSG->L4DATA[1]) == 0) - { - SendConNAK(LINK, L3MSG); - return; - } - - if (FINDCIRCUIT(L3MSG, &L4, &Index)) - { - // SESSION EXISTS - ASSUME RETRY AND SEND ACK - - SendConACK(LINK, L4, L3MSG, BPQNODE, ApplMask, ApplCall); - return; - } - - - if (L4 == 0) - { - SendConNAK(LINK, L3MSG); - return; - } - - L4->CIRCUITINDEX = Index; - - SETUPNEWCIRCUIT(LINK, L3MSG, L4, BPQPARAMS, ApplMask, &BPQNODE); - - if (L4->L4TARGET.DEST == 0) - { - // NODE NOT IN TABLE, AND TABLE FULL - CANCEL IT - - memset(L4, 0, sizeof (TRANSPORTENTRY)); - SendConNAK(LINK, L3MSG); - return; - } - // IF CONNECT TO APPL, ALLOCATE BBS PORT - - if (ApplMask == 0 || BPQPARAMS[2] == 'Z') // Z is "Spy" Connect - { - SendConACK(LINK, L4, L3MSG, BPQNODE, ApplMask, ApplCall); - - return; - } - - // IF APPL CONNECT, SEE IF APPL HAS AN ALIAS - - - if (ALIASPTR[0] > ' ') - { - struct DATAMESSAGE * Msg; - - // ACCEPT THE CONNECT, THEN INVOKE THE ALIAS - - SendConACK(LINK, L4, L3MSG, BPQNODE, ApplMask, ApplCall); - - Msg = GetBuff(); - - if (Msg) - { - Msg->PID = 0xf0; - memcpy(Msg->L2DATA, APPL->APPLCMD, 12); - Msg->L2DATA[12] = 13; - Msg->LENGTH = MSGHDDRLEN + 12 + 2; // 2 for PID and CR - - C_Q_ADD(&L4->L4RX_Q, Msg); - return; - } - } - - if (cATTACHTOBBS(L4, ApplMask, PACLEN, &CONERROR)) - { - SendConACK(LINK, L4, L3MSG, BPQNODE, ApplMask, ApplCall); - return; - } - - // NO BBS AVAILABLE - - CLEARSESSIONENTRY(L4); - SendConNAK(LINK, L3MSG); - return; -} - -VOID SendConACK(struct _LINKTABLE * LINK, TRANSPORTENTRY * L4, L3MESSAGEBUFFER * L3MSG, BOOL BPQNODE, UINT Applmask, UCHAR * ApplCall) -{ - // SEND CONNECT ACK - - struct TNCINFO * TNC; - - L4CONNECTSIN++; - - L3MSG->L4TXNO = L4->CIRCUITINDEX; - L3MSG->L4RXNO = L4->CIRCUITID; - - L3MSG->L4DATA[0] = L4->L4WINDOW; //WINDOW - - L3MSG->L4FLAGS = L4CACK; - - if (LogL4Connects) - WriteL4LogLine(ApplCall, L4->L4USER, L3MSG->L3SRCE); - - if (LogAllConnects) - { - char From[64]; - char toCall[12], fromCall[12], atCall[12]; - - toCall[ConvFromAX25(ApplCall, toCall)] = 0; - fromCall[ConvFromAX25(L4->L4USER, fromCall)] = 0; - atCall[ConvFromAX25(L3MSG->L3SRCE, atCall)] = 0; - - sprintf(From, "%s at Node %s", fromCall, atCall); - WriteConnectLog(From, toCall, "NETROM"); - } - - - if (CTEXTLEN && Applmask == 0) // Connects to Node (not application) - { - struct DATAMESSAGE * Msg; - int Totallen = CTEXTLEN; - int Paclen= PACLEN; - UCHAR * ptr = CTEXTMSG; - - if (Paclen == 0) - Paclen = PACLEN; - - while(Totallen) - { - Msg = GetBuff(); - - if (Msg == NULL) - break; // No Buffers - - Msg->PID = 0xf0; - - if (Paclen > Totallen) - Paclen = Totallen; - - memcpy(Msg->L2DATA, ptr, Paclen); - Msg->LENGTH = Paclen + MSGHDDRLEN + 1; - - C_Q_ADD(&L4->L4TX_Q, Msg); // SEND MESSAGE TO CALLER - PostDataAvailable(L4); - ptr += Paclen; - Totallen -= Paclen; - } - } - - L3SWAPADDRESSES(L3MSG); - - L3MSG->L3TTL = L3LIVES; - - L3MSG->LENGTH = MSGHDDRLEN + 22; // CTL 20 BYTE Header Window - - if (BPQNODE) - { - L3MSG->L4DATA[1] = L3LIVES; // Our TTL - L3MSG->LENGTH++; - } - - TNC = LINK->LINKPORT->TNC; - - if (TNC && TNC->NetRomMode) - SendVARANetromMsg(TNC, L3MSG); - else - C_Q_ADD(&LINK->TX_Q, L3MSG); -} - -int FINDCIRCUIT(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY ** REQL4, int * NewIndex) -{ - // FIND CIRCUIT FOR AN INCOMING MESSAGE - - TRANSPORTENTRY * L4 = L4TABLE; - TRANSPORTENTRY * FIRSTSPARE = NULL; - struct DEST_LIST * DEST; - - int Index = 0; - - while (Index < MAXCIRCUITS) - { - if (L4->L4USER[0] == 0) // Spare - { - if (FIRSTSPARE == NULL) - { - FIRSTSPARE = L4; - *NewIndex = Index; - } - - L4++; - Index++; - continue; - } - - DEST = L4->L4TARGET.DEST; - - if (DEST == NULL) - { - // L4 entry without a Dest shouldn't happen. (I don't think!) - - char Call1[12], Call2[12]; - - Call1[ConvFromAX25(L4->L4USER, Call1)] = 0; - Call2[ConvFromAX25(L4->L4MYCALL, Call2)] = 0; - - Debugprintf("L4 entry without Target. Type = %02x Calls %s %s", - L4->L4CIRCUITTYPE, Call1, Call2); - - L4++; - Index++; - continue; - } - - if (CompareCalls(L3MSG->L3SRCE, DEST->DEST_CALL)) - { - if (L4->FARID == L3MSG->L4ID && L4->FARINDEX == L3MSG->L4INDEX) - { - // Found it - - *REQL4 = L4; - return TRUE; - } - } - L4++; - Index++; - } - - // ENTRY NOT FOUND - FIRSTSPARE HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL - - *REQL4 = FIRSTSPARE; - return FALSE; -} - -VOID L3SWAPADDRESSES(L3MESSAGEBUFFER * L3MSG) -{ - // EXCHANGE ORIGIN AND DEST - - char Temp[7]; - - memcpy(Temp, L3MSG->L3SRCE, 7); - memcpy(L3MSG->L3SRCE, L3MSG->L3DEST, 7); - memcpy(L3MSG->L3DEST, Temp, 7); - - L3MSG->L3DEST[6] &= 0x1E; // Mack EOA and CMD - L3MSG->L3SRCE[6] &= 0x1E; - L3MSG->L3SRCE[6] |= 1; // Set Last Call -} - -VOID SendConNAK(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) -{ - L3MSG->L4FLAGS = L4CACK | L4BUSY; // REJECT - L3MSG->L4DATA[0] = 0; // WINDOW - - L3SWAPADDRESSES(L3MSG); - L3MSG->L3TTL = L3LIVES; - - C_Q_ADD(&LINK->TX_Q, L3MSG); -} - -VOID SETUPNEWCIRCUIT(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, - TRANSPORTENTRY * L4, char * BPQPARAMS, int ApplMask, int * BPQNODE) -{ - struct DEST_LIST * DEST; - int Maxtries = 2; // Just in case - - L4->FARINDEX = L3MSG->L4INDEX; - L4->FARID = L3MSG->L4ID; - - // Index set by caller - - L4->CIRCUITID = NEXTID; - - NEXTID++; - if (NEXTID == 0) - NEXTID++; // kEEP nON-ZERO - - L4->SESSIONT1 = L4T1; - - L4->L4WINDOW = (UCHAR)L4DEFAULTWINDOW; - - if (L3MSG->L4DATA[0] > L4DEFAULTWINDOW) - L4->L4WINDOW = L3MSG->L4DATA[0]; - - memcpy(L4->L4USER, &L3MSG->L4DATA[1], 7); // Originator's call from Call Request - - if (ApplMask) - { - // Should get APPLCALL if set ( maybe ??????????????? - } - -// MOV ESI,APPLCALLTABLEPTR -// LEA ESI,APPLCALL[ESI] - - memcpy(L4->L4MYCALL, MYCALL, 7); - - // GET BPQ EXTENDED CONNECT PARAMS IF PRESENT - - if (L3MSG->LENGTH == MSGHDDRLEN + 38 || L3MSG->LENGTH == MSGHDDRLEN + 39) - { - *BPQNODE = 1; - memcpy(BPQPARAMS, &L3MSG->L4DATA[15],L3MSG->LENGTH - (MSGHDDRLEN + 36)); - } - - L4->L4CIRCUITTYPE = SESSION | UPLINK; - L4->L4STATE = 5; - -TryAgain: - - DEST = CHECKL3TABLES(LINK, L3MSG); - - L4->L4TARGET.DEST = DEST; - - if (DEST == 0) - { - int WorstQual = 256; - struct DEST_LIST * WorstDest = NULL; - int n = MAXDESTS; - - // Node not it table and table full - - // Replace worst quality node with session counts of zero - - // But could have been excluded, so check - - if (CheckExcludeList(L3MSG->L3SRCE) == 0) - return; - - DEST = DESTS; - - while (n--) - { - if (DEST->DEST_COUNT == 0 && DEST->DEST_RTT == 0) // Not used and not INP3 - { - if (DEST->NRROUTE[0].ROUT_QUALITY < WorstQual) - { - WorstQual = DEST->NRROUTE[0].ROUT_QUALITY; - WorstDest = DEST; - } - } - DEST++; - } - - if (WorstDest) - { - REMOVENODE(WorstDest); - if (Maxtries--) - goto TryAgain; // We now have a spare (but protect against loop if something amiss) - } - - // Nothing to delete, so just ignore connect - - return; - } - - if (*BPQNODE) - { - SHORT T1; - - DEST->DEST_STATE |= 0x40; // SET BPQ _NODE BIT - memcpy((char *)&T1, BPQPARAMS, 2); - - if (T1 > 300) - L4->SESSIONT1 = L4T1; - else - L4->SESSIONT1 = T1; - } - else - L4->SESSIONT1 = L4T1; // DEFAULT TIMEOUT - - L4->SESSPACLEN = PACLEN; // DEFAULT -} - - -int CHECKIFBUSYL4(TRANSPORTENTRY * L4) -{ - // RETURN TOP BIT OF AL SET IF SESSION PARTNER IS BUSY - - int Count; - - if (L4->L4CROSSLINK) // CONNECTED? - Count = CountFramesQueuedOnSession(L4->L4CROSSLINK); - else - Count = CountFramesQueuedOnSession(L4); - - if (Count < L4->L4WINDOW) - return 0; - else - return L4BUSY; -} - -VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, UCHAR * ApplCall) -{ - // INTERNODE LINK - - TRANSPORTENTRY * L4; - struct DEST_LIST * DEST; - int Opcode; - char Nodename[20]; - char ReplyText[20]; - struct DATAMESSAGE * Msg; - TRANSPORTENTRY * Partner; - UCHAR * ptr1; - int FramesMissing; - L3MESSAGEBUFFER * Saved; - L3MESSAGEBUFFER ** Prev; - char Call[10]; - struct TNCINFO * TNC; - - L4FRAMESRX++; - - Opcode = L3MSG->L4FLAGS & 15; - - switch (Opcode) - { - case 0: - - // OPCODE 0 is used for a variety of functions, using L4INDEX and L4ID as qualifiers - // 0c0c is used for IP - - if (L3MSG->L4ID == 0x0C && L3MSG->L4INDEX == 0x0C) - { - Q_IP_MSG((MESSAGE *)L3MSG); - return; - } - - // 00 01 Seesm to be Netrom Record Route - - if (L3MSG->L4ID == 1 && L3MSG->L4INDEX == 0) - { - NRRecordRoute((UCHAR *)L3MSG, L3MSG->LENGTH); - return; - } - - ReleaseBuffer(L3MSG); - return; - - case L4CREQ: - - CONNECTREQUEST(LINK, L3MSG, ApplMask, ApplCall); - return; - } - - // OTHERS NEED A SESSION - - L4 = &L4TABLE[L3MSG->L4INDEX]; - - if (L4->CIRCUITID!= L3MSG->L4ID) - { - ReleaseBuffer(L3MSG); - return; - } - - if ((L4->L4CIRCUITTYPE & SESSION) == 0) - { - // Not an L4 Session - must be an old connection - - ReleaseBuffer(L3MSG); - return; - } - - // HAVE FOUND CORRECT SESSION ENTRY - - switch (Opcode) - { - case L4CACK: - - // CONNECT ACK - - DEST = L4->L4TARGET.DEST; - - // EXTRACT EXTENDED PARAMS IF PRESENT - - if (L3MSG->LENGTH > MSGHDDRLEN + 22) // Standard Msg - { - DEST->DEST_STATE &= 0x80; - DEST->DEST_STATE |= (L3MSG->L4DATA[1] - L3MSG->L3TTL) + 0x41; // Hops to dest + x40 - } - - Partner = L4->L4CROSSLINK; - - if (L3MSG->L4FLAGS & L4BUSY) - { - // Refused - - CLEARSESSIONENTRY(L4); - if (Partner) - Partner->L4CROSSLINK = NULL; // CLEAR CROSSLINK - - strcpy(ReplyText, "Busy from"); - } - else - { - // Connect OK - - if (L4->L4STATE == 5) - { - // MUST BE REPEAT MSG - DISCARD - - ReleaseBuffer(L3MSG); - return; - } - - L4->FARINDEX = L3MSG->L4TXNO; - L4->FARID = L3MSG->L4RXNO; - - L4->L4STATE = 5; // ACTIVE - L4->L4TIMER = 0; - L4->L4RETRIES = 0; - - L4->L4WINDOW = L3MSG->L4DATA[0]; - - strcpy(ReplyText, "Connected to"); - } - - if (Partner == 0) - { - ReleaseBuffer(L3MSG); - return; - } - - Msg = (PDATAMESSAGE)L3MSG; // reuse input buffer - - Msg->PID = 0xf0; - ptr1 = SetupNodeHeader(Msg); - - Nodename[DecodeNodeName(DEST->DEST_CALL, Nodename)] = 0; // null terminate - - ptr1 += sprintf(ptr1, "%s %s\r", ReplyText, Nodename); - - Msg->LENGTH = (int)(ptr1 - (UCHAR *)Msg); - - C_Q_ADD(&Partner->L4TX_Q, Msg); - - PostDataAvailable(Partner); - return; - - case L4DREQ: - - // DISCONNECT REQUEST - - L3MSG->L4INDEX = L4->FARINDEX; - L3MSG->L4ID = L4->FARID; - - L3MSG->L4FLAGS = L4DACK; - - L3SWAPADDRESSES(L3MSG); // EXCHANGE SOURCE AND DEST - L3MSG->L3TTL = L3LIVES; - - TNC = LINK->LINKPORT->TNC; - - if (TNC && TNC->NetRomMode) - SendVARANetromMsg(TNC, L3MSG); - else - C_Q_ADD(&LINK->TX_Q, L3MSG); - - CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT) - return; - - case L4DACK: - - CLEARSESSIONENTRY(L4); - ReleaseBuffer(L3MSG); - return; - - case L4INFO: - - //MAKE SURE SESSION IS UP - FIRST I FRAME COULD ARRIVE BEFORE CONNECT ACK - - if (L4->L4STATE == 2) - { - ReleaseBuffer(L3MSG); // SHOULD SAVE - WILL AVOID NEED TO RETRANSMIT - return; - } - - ACKFRAMES(L3MSG, L4, L3MSG->L4RXNO); - - // If DISCPENDING or STATE IS 4, THEN SESSION IS CLOSING - IGNORE ANY I FRAMES - - if ((L4->FLAGS & DISCPENDING) || L4->L4STATE == 4) - { - ReleaseBuffer(L3MSG); - return; - } - - // CHECK RECEIVED SEQUENCE - - FramesMissing = L3MSG->L4TXNO - L4->RXSEQNO; // WHAT WE GOT - WHAT WE WANT - - if (FramesMissing > 128) - FramesMissing -= 256; - - // if NUMBER OF FRAMES MISSING is -VE, THEN IN FACT IT INDICATES A REPEAT - - if (FramesMissing < 0) - { - // FRAME IS A REPEAT - - Call[ConvFromAX25(L3MSG->L3SRCE, Call)] = 0; - Debugprintf("Discarding repeated frame seq %d from %s", L3MSG->L4TXNO, Call); - - L4->L4ACKREQ = 1; - ReleaseBuffer(L3MSG); - return; - } - - if (FramesMissing > 0) - { - // EXPECTED FRAME HAS BEEN MISSED - ASK FOR IT AGAIN, - // AND KEEP THIS FRAME UNTIL MISSING ONE ARRIVES - - L4->NAKBITS |= L4NAK; // SET NAK REQUIRED - - SENDL4IACK(L4); // SEND DATA ACK COMMAND TO ACK OUTSTANDING FRAMES - - // SEE IF WE ALREADY HAVE A COPY OF THIS ONE -/* - Saved = L4->L4RESEQ_Q; - - Call[ConvFromAX25(L3MSG->L3SRCE, Call)] = 0; - Debugprintf("saving seq %d from %s", L3MSG->L4TXNO, Call); - - while (Saved) - { - if (Saved->L4TXNO == L3MSG->L4TXNO) - { - // ALREADY HAVE A COPY - DISCARD IT - - Debugprintf("Already have seq %d - discarding", L3MSG->L4TXNO); - ReleaseBuffer(L3MSG); - return; - } - - Saved = Saved->Next; - } - - C_Q_ADD(&L4->L4RESEQ_Q, L3MSG); // ADD TO CHAIN - return; -*/ - } - - // Frame is OK - -L4INFO_OK: - - if (L3MSG == 0) - { - Debugprintf("Trying to Process NULL L3 Message"); - return; - } - - L4->NAKBITS &= ~L4NAK; // CLEAR MESSAGE LOST STATE - - L4->RXSEQNO++; - - // REMOVE HEADERS, AND QUEUE INFO - - L3MSG->LENGTH -= 20; // L3/L4 Header - - if (L3MSG->LENGTH < (4 + sizeof(void *))) // No PID - { - ReleaseBuffer(L3MSG); - return; - } - - L3MSG->L3PID = 0xF0; // Normal Data PID - - memmove(L3MSG->L3SRCE, L3MSG->L4DATA, L3MSG->LENGTH - (4 + sizeof(void *))); - - REFRESHROUTE(L4); - - L4->L4ACKREQ = L4DELAY; // SEND INFO ACK AFTER L4DELAY (UNLESS I FRAME SENT) - - IFRM150(L4, (PDATAMESSAGE)L3MSG); // CHECK IF SETTING UP AND PASS ON - - // See if anything on reseq Q to process - - if (L4->L4RESEQ_Q == 0) - return; - - Prev = &L4->L4RESEQ_Q; - Saved = L4->L4RESEQ_Q; - - while (Saved) - { - if (Saved->L4TXNO == L4->RXSEQNO) // The one we want - { - // REMOVE IT FROM QUEUE,AND PROCESS IT - - *Prev = Saved->Next; // CHAIN NEXT IN CHAIN TO PREVIOUS - - OLDFRAMES++; // COUNT FOR STATS - - L3MSG = Saved; - Debugprintf("Processing Saved Message %d Address %x", L4->RXSEQNO, L3MSG); - goto L4INFO_OK; - } - - Debugprintf("Message %d %x still on Reseq Queue", Saved->L4TXNO, Saved); - - Prev = &Saved; - Saved = Saved->Next; - } - - return; - - case L4IACK: - - ACKFRAMES(L3MSG, L4, L3MSG->L4RXNO); - REFRESHROUTE(L4); - - // Drop Through - } - - // Unrecognised - Ignore - - ReleaseBuffer(L3MSG); - return; -} - - -VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR) -{ - // SEE HOW MANY FRAMES ARE ACKED - IF NEGATIVE, THAN THIS MUST BE A - // DELAYED REPEAT OF AN ACK ALREADY PROCESSED - - int Count = NR - L4->L4WS; - L3MESSAGEBUFFER * Saved; - struct DEST_LIST * DEST; - struct DATAMESSAGE * Msg; - struct DATAMESSAGE * Copy; - int RTT; - - - if (Count < -128) - Count += 256; - - if (Count < 0) - { - // THIS MAY BE A DELAYED REPEAT OF AN ACK ALREADY PROCESSED - - return; // IGNORE COMPLETELY - } - - while (Count > 0) - { - // new ACK - - // FRAME L4WS HAS BEED ACKED - IT SHOULD BE FIRST ON HOLD QUEUE - - Saved = Q_REM((void *)&L4->L4HOLD_Q); - - if (Saved) - ReleaseBuffer(Saved); - - // CHECK RTT SEQUENCE - - if (L4->L4WS == L4->RTT_SEQ) - { - if (L4->RTT_TIMER) - { - // FRAME BEING TIMED HAS BEEN ACKED - UPDATE DEST RTT TIMER - - DEST = L4->L4TARGET.DEST; - - RTT = GetTickCount() - L4->RTT_TIMER; - - if (DEST->DEST_RTT == 0) - DEST->DEST_RTT = RTT; - else - DEST->DEST_RTT = ((DEST->DEST_RTT * 9) + RTT) /10; // 90% Old + New - } - } - - L4->L4WS++; - Count--; - } - - L4->L4TIMER = 0; - L4->L4RETRIES = 0; - - if (NR != L4->TXSEQNO) - { - // Not all Acked - - L4->L4TIMER = L4->SESSIONT1; // RESTART TIMER - } - else - { - if ((L4->FLAGS & DISCPENDING) && L4->L4TX_Q == 0) - { - // All Acked and DISC Pending, so send it - - SENDL4DISC(L4); - return; - } - } - - // SEE IF CHOKE SET - - L4->FLAGS &= ~L4BUSY; - - if (L3MSG->L4FLAGS & L4BUSY) - { - L4->FLAGS |= L3MSG->L4FLAGS & L4BUSY; // Get Busy flag from message - - if ((L3MSG->L4FLAGS & L4NAK) == 0) - return; // Dont send while biust unless NAC received - } - - if (L3MSG->L4FLAGS & L4NAK) - { - // RETRANSMIT REQUESTED MESSAGE - WILL BE FIRST ON HOLD QUEUE - - Msg = L4->L4HOLD_Q; - - if (Msg == 0) - return; - - Copy = GetBuff(); - - if (Copy == 0) - return; - - memcpy(Copy, Msg, Msg->LENGTH); - - DEST = L4->L4TARGET.DEST; - - C_Q_ADD(&DEST->DEST_Q, Copy); - } -} - - - - - - - - - - - - - - - -VOID SENDL4IACK(TRANSPORTENTRY * Session) -{ - // SEND INFO ACK - - PL3MESSAGEBUFFER MSG = (PL3MESSAGEBUFFER)GetBuff(); - struct DEST_LIST * DEST = Session->L4TARGET.DEST; - - if (MSG == NULL) - return; - - MSG->L3PID = 0xCF; // NET MESSAGE - - memcpy(MSG->L3SRCE, Session->L4MYCALL, 7); - memcpy(MSG->L3DEST, DEST->DEST_CALL, 7); - - MSG->L3TTL = L3LIVES; - - MSG->L4INDEX = Session->FARINDEX; - MSG->L4ID = Session->FARID; - - MSG->L4TXNO = 0; - - - MSG->L4RXNO = Session->RXSEQNO; - Session->L4LASTACKED = Session->RXSEQNO; // SAVE LAST NUMBER ACKED - - MSG->L4FLAGS = L4IACK | GETBUSYBIT(Session) | Session->NAKBITS; - - MSG->LENGTH = MSGHDDRLEN + 22; - - C_Q_ADD(&DEST->DEST_Q, (UINT *)MSG); -} - - - - -/* - PUBLIC KILLSESSION -KILLSESSION: - - pushad - push ebx - CALL _CLEARSESSIONENTRY - pop ebx - popad - - JMP L4CONN90 ; REJECT - - PUBLIC CONNECTACK -CONNECTACK: -; -; EXTRACT EXTENDED PARAMS IF PRESENT -; - - CMP BYTE PTR MSGLENGTH[EDI],L4DATA+1 - JE SHORT NOTBPQ - - MOV AL,L4DATA+1[EDI] - SUB AL,L3MONR[EDI] - ADD AL,41H ; HOPS TO DEST + 40H - - MOV ESI,L4TARGET[EBX] - AND DEST_STATE[ESI],80H - OR DEST_STATE[ESI],AL ; SAVE - - PUBLIC NOTBPQ -NOTBPQ: -; -; SEE IF SUCCESS OR FAIL -; - PUSH EDI - - MOV ESI,L4TARGET[EBX] ; ADDR OF LINK/DEST ENTRY - LEA ESI,DEST_CALL[ESI] - - CALL DECODENODENAME ; CONVERT TO ALIAS:CALL - - MOV EDI,OFFSET32 CONACKCALL - MOV ECX,17 - REP MOVSB - - - POP EDI - - TEST L4FLAGS[EDI],L4BUSY - JNZ SHORT L4CONNFAILED - - CMP L4STATE[EBX],5 - JE SHORT CONNACK05 ; MUST BE REPEAT MSG - DISCARD - - MOV AX,WORD PTR L4TXNO[EDI] ; HIS INDEX - MOV WORD PTR FARINDEX[EBX],AX - - MOV L4STATE[EBX],5 ; ACTIVE - MOV L4TIMER[EBX],0 ; CANCEL TIMER - MOV L4RETRIES[EBX],0 ; CLEAR RETRY COUNT - - MOV AL,L4DATA[EDI] ; WINDOW - MOV L4WINDOW[EBX],AL ; SET WINDOW - - MOV EDX,L4CROSSLINK[EBX] ; POINT TO PARTNER -; - MOV ESI,OFFSET32 CONNECTEDMSG - MOV ECX,LCONNECTEDMSG - - JMP SHORT L4CONNCOMM - - PUBLIC L4CONNFAILED -L4CONNFAILED: -; - MOV EDX,L4CROSSLINK[EBX] ; SAVE PARTNER - pushad - push ebx - CALL _CLEARSESSIONENTRY - pop ebx - popad - - PUSH EBX - - MOV EBX,EDX - MOV L4CROSSLINK[EBX],0 ; CLEAR CROSSLINK - POP EBX - - MOV ESI,OFFSET32 BUSYMSG ; ?? BUSY - MOV ECX,LBUSYMSG - - PUBLIC L4CONNCOMM -L4CONNCOMM: - - OR EDX,EDX - JNZ SHORT L4CONNOK10 -; -; CROSSLINK HAS GONE?? - JUST CHUCK MESSAGE -; - PUBLIC CONNACK05 -CONNACK05: - - JMP L4DISCARD - - PUBLIC L4CONNOK10 -L4CONNOK10: - - PUSH EBX - PUSH ESI - PUSH ECX - - MOV EDI,_BUFFER - - ADD EDI,7 - MOV AL,0F0H - STOSB ; PID - - CALL _SETUPNODEHEADER ; PUT IN _NODE ID - - - POP ECX - POP ESI - REP MOVSB - - MOV ESI,OFFSET32 CONACKCALL - MOV ECX,17 ; MAX LENGTH ALIAS:CALL - REP MOVSB - - MOV AL,0DH - STOSB - - MOV ECX,EDI - MOV EDI,_BUFFER - SUB ECX,EDI - - MOV MSGLENGTH[EDI],CX - - MOV EBX,EDX ; CALLER'S SESSION - - LEA ESI,L4TX_Q[EBX] - CALL _Q_ADD ; SEND MESSAGE TO CALLER - - CALL _POSTDATAAVAIL - - POP EBX ; ORIGINAL CIRCUIT TABLE - RET - - - PUBLIC SENDCONNECTREPLY -SENDCONNECTREPLY: -; -; LINK SETUP COMPLETE - EBX = LINK, EDI = _BUFFER -; - CMP LINKTYPE[EBX],3 - JNE SHORT CONNECTED00 -; -; _NODE - _NODE SESSION SET UP - DONT NEED TO DO ANYTHING (I THINK!) -; - CALL RELBUFF - RET - -; -; UP/DOWN LINK -; - PUBLIC CONNECTED00 -CONNECTED00: - CMP CIRCUITPOINTER[EBX],0 - JNE SHORT CONNECTED01 - - CALL RELBUFF ; UP/DOWN WITH NO SESSION - NOONE TO TELL - RET ; NO CROSS LINK - PUBLIC CONNECTED01 -CONNECTED01: - MOV _BUFFER,EDI - PUSH EBX - PUSH ESI - PUSH ECX - - ADD EDI,7 - MOV AL,0F0H - STOSB ; PID - - CALL _SETUPNODEHEADER ; PUT IN _NODE ID - - LEA ESI,LINKCALL[EBX] - - PUSH EDI - CALL CONVFROMAX25 ; ADDR OF CALLED STATION - POP EDI - - MOV EBX,CIRCUITPOINTER[EBX] - - MOV L4STATE[EBX],5 ; SET LINK UP - - MOV EBX,L4CROSSLINK[EBX] ; TO INCOMING LINK - cmp ebx,0 - jne xxx -; -; NO LINK ??? -; - MOV EDI,_BUFFER - CALL RELBUFF - - POP ECX - POP ESI - POP EBX - - RET - - PUBLIC xxx -xxx: - - POP ECX - POP ESI - REP MOVSB - - MOV ESI,OFFSET32 _NORMCALL - MOVZX ECX,_NORMLEN - REP MOVSB - - MOV AL,0DH - STOSB - - MOV ECX,EDI - MOV EDI,_BUFFER - SUB ECX,EDI - - MOV MSGLENGTH[EDI],CX - - LEA ESI,L4TX_Q[EBX] - CALL _Q_ADD ; SEND MESSAGE TO CALLER - - CALL _POSTDATAAVAIL - - POP EBX - RET -*/ \ No newline at end of file diff --git a/L4Code.c b/L4Code.c index a087281..4efd2d1 100644 --- a/L4Code.c +++ b/L4Code.c @@ -56,7 +56,7 @@ VOID L3SWAPADDRESSES(L3MESSAGEBUFFER * L3MSG); VOID L4TIMEOUT(TRANSPORTENTRY * L4); struct DEST_LIST * CHECKL3TABLES(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * Msg); int CHECKIFBUSYL4(TRANSPORTENTRY * L4); -VOID AUTOTIMER(); +VOID AUTOTIMER(TRANSPORTENTRY * L4); VOID NRRecordRoute(UCHAR * Buff, int Len); VOID REFRESHROUTE(TRANSPORTENTRY * Session); VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR); diff --git a/LinBPQ.c b/LinBPQ.c index d25dfb7..0f9daab 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -667,7 +667,7 @@ void ConTermPoll() // Replace CR with CRLF - printf(ptr); + printf("%s", ptr); if (ptr2) printf("\r\n"); @@ -717,7 +717,7 @@ void ConTermPoll() } -#include "getopt.h" +#include static struct option long_options[] = { @@ -816,7 +816,7 @@ int main(int argc, char * argv[]) { case 'h': - printf(HelpScreen); + printf("%s", HelpScreen); exit (0); case 'l': diff --git a/MBLRoutines.c b/MBLRoutines.c index 87d3d8a..0d33e53 100644 --- a/MBLRoutines.c +++ b/MBLRoutines.c @@ -24,6 +24,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include "bpqmail.h" void SendMessageReadEvent(char * call, struct MsgInfo * Msg); +void MQTTMessageEvent(void* message); VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int len) @@ -199,6 +200,12 @@ VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int l } conn->FwdMsg->Locked = 0; // Unlock + +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(conn->FwdMsg); +#endif + } return; @@ -282,7 +289,7 @@ VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int l { // Reverse forward request - // If we have just sent a nessage, Flag it as sent + // If we have just sent a message, Flag it as sent if (conn->FBBMsgsSent) { @@ -300,6 +307,11 @@ VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int l conn->FwdMsg->Locked = 0; // Unlock +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(conn->FwdMsg); +#endif + conn->UserPointer->ForwardingInfo->MsgCount--; } @@ -354,6 +366,11 @@ VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int l conn->FwdMsg->datechanged=time(NULL); } +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(conn->FwdMsg); +#endif + conn->UserPointer->ForwardingInfo->MsgCount--; } diff --git a/MULTIPSK.c b/MULTIPSK.c index 699db8f..ee14d9a 100644 --- a/MULTIPSK.c +++ b/MULTIPSK.c @@ -60,7 +60,7 @@ static void ConnecttoMPSKThread(void * portptr); void CreateMHWindow(); int Update_MH_List(struct in_addr ipad, char * call, char proto); -static int ConnecttoMPSK(); +static int ConnecttoMPSK(int port); static int ProcessReceivedData(int bpqport); static int ProcessLine(char * buf, int Port); int KillTNC(struct TNCINFO * TNC); @@ -71,8 +71,6 @@ static VOID SendData(struct TNCINFO * TNC, char * Msg, int MsgLen); static VOID DoMonitorHddr(struct TNCINFO * TNC, struct AGWHEADER * RXHeader, UCHAR * Msg); VOID SendRPBeacon(struct TNCINFO * TNC); -char * strlop(char * buf, char delim); - extern UCHAR BPQDirectory[]; #define MAXMPSKPORTS 16 diff --git a/MailRouting.c b/MailRouting.c index 5cc17e7..3bf02be 100644 --- a/MailRouting.c +++ b/MailRouting.c @@ -141,7 +141,7 @@ struct Country Countries[] = "HKG", "ASIA", "AS", // Hong Kong Special Administrative Region of China "MAC", "ASIA", "AS", // Macao Special Administrative Region of China "COL", "ASIA", "SA", // Colombia - "COM", "SAFR", "AF", // Comoros +// "COM", "SAFR", "AF", // Comoros "COG", "CAFR", "AF", // Congo "COK", "SPAC", "OC", // Cook Islands "CRI", "CEAM", "NA", // Costa Rica diff --git a/Moncode.c b/Moncode.c index d807e21..928811c 100644 --- a/Moncode.c +++ b/Moncode.c @@ -59,7 +59,6 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #define NODES_SIG 0xFF -char * strlop(char * buf, char delim); UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, unsigned int msglen); char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen); diff --git a/Multicast.c b/Multicast.c index ba5dcb5..f4bc715 100644 --- a/Multicast.c +++ b/Multicast.c @@ -1612,7 +1612,7 @@ int MulticastStatusHTML(char * Reply) if (Sess ==NULL) return 0; - Len = sprintf(Reply, StatusPage); + Len = sprintf(Reply, "%s", StatusPage); while (Sess) { @@ -1670,7 +1670,7 @@ int MulticastStatusHTML(char * Reply) Sess = Sess->Next; } - Len += sprintf(&Reply[Len], StatusTail); + Len += sprintf(&Reply[Len], "%s", StatusTail); return Len; } diff --git a/NNTPRoutines.c b/NNTPRoutines.c index 16b6478..d2efbbf 100644 --- a/NNTPRoutines.c +++ b/NNTPRoutines.c @@ -25,6 +25,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses VOID __cdecl Debugprintf(const char * format, ...); VOID ReleaseSock(SOCKET sock); +void MQTTMessageEvent(void* message); struct NNTPRec * FirstNNTPRec = NULL; @@ -352,6 +353,12 @@ int CreateNNTPMessage(char * From, char * To, char * MsgTitle, time_t Date, char BuildNNTPList(Msg); // Build NNTP Groups list +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(Msg); +#endif + + return CreateSMTPMessageFile(MsgBody, Msg); } diff --git a/RigControl.c b/RigControl.c index fd47e24..024d17d 100644 --- a/RigControl.c +++ b/RigControl.c @@ -1291,7 +1291,7 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR // use text command - Len = sprintf(CmdPtr, ptr1); + Len = sprintf(CmdPtr, "%S", ptr1); break; case YAESU: @@ -3205,7 +3205,7 @@ VOID ReleasePermission(struct RIGINFO *RIG) while (RIG->PortRecord[i]) { PortRecord = RIG->PortRecord[i]; - PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, 3); // Release Perrmission + PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, (PDATAMESSAGE)3); // Release Perrmission i++; } } @@ -3235,7 +3235,7 @@ int GetPermissionToChange(struct RIGPORTINFO * PORT, struct RIGINFO *RIG) // TNC has been asked for permission, and we are waiting respoonse // Only SCS pactor returns WaitingForPrmission, so check shouldn't be called on others - RIG->OKtoChange = (int)(intptr_t)RIG->PortRecord[0]->PORT_EXT_ADDR(6, RIG->PortRecord[0]->PORTCONTROL.PORTNUMBER, 2); // Get Ok Flag + RIG->OKtoChange = (int)(intptr_t)RIG->PortRecord[0]->PORT_EXT_ADDR(6, RIG->PortRecord[0]->PORTCONTROL.PORTNUMBER, (PDATAMESSAGE)2); // Get Ok Flag if (RIG->OKtoChange == 1) { @@ -3277,7 +3277,7 @@ int GetPermissionToChange(struct RIGPORTINFO * PORT, struct RIGINFO *RIG) // not waiting for permission, so must be first call of a cycle if (RIG->PortRecord[0] && RIG->PortRecord[0]->PORT_EXT_ADDR) - RIG->WaitingForPermission = (int)(intptr_t)RIG->PortRecord[0]->PORT_EXT_ADDR(6, RIG->PortRecord[0]->PORTCONTROL.PORTNUMBER, 1); // Request Perrmission + RIG->WaitingForPermission = (int)(intptr_t)RIG->PortRecord[0]->PORT_EXT_ADDR(6, RIG->PortRecord[0]->PORTCONTROL.PORTNUMBER, (PDATAMESSAGE)1); // Request Perrmission // If it returns zero there is no need to wait. // Normally SCS Returns True for first call, but returns 0 if Link not running @@ -3300,7 +3300,7 @@ CheckOtherPorts: { PortRecord = RIG->PortRecord[i]; - if (PortRecord->PORT_EXT_ADDR && PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, 1)) + if (PortRecord->PORT_EXT_ADDR && PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, (PDATAMESSAGE)1)) { // 1 means can't change - release all @@ -3392,7 +3392,7 @@ VOID DoBandwidthandAntenna(struct RIGINFO *RIG, struct ScanEntry * ptr) RIG->CurrentBandWidth = ptr->Bandwidth; - PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, ptr); + PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, (PDATAMESSAGE)ptr); /* if (ptr->Bandwidth == 'R') // Robust Packet PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, 6); // Set Robust Packet @@ -8385,7 +8385,7 @@ int ProcessHAMLIBSlaveMessage(SOCKET Sock, struct RIGINFO * RIG, unsigned char * switch (Msg[0]) { - case 'f': // Get Freqency + case 'f': // Get Frequency HLGetFreq(Sock, RIG, sep); return 0; @@ -9938,14 +9938,10 @@ void ProcessSDRANGELFrame(struct RIGPORTINFO * PORT) int Length; char * msg; - char * rest; struct RIGINFO * RIG; char * ptr, * ptr1, * ptr2, * ptr3, * pos; - int Len, TotalLen; char cmd[80]; - char ReqBuf[256]; - char SendBuff[256]; int chunklength; int headerlen; int i, n = 0; @@ -10332,7 +10328,6 @@ VOID SDRANGELPoll(struct RIGPORTINFO * PORT) struct RIGINFO * RIG = &PORT->Rigs[0]; int Len, i; - char ReqBuf[256]; char SendBuff[256]; //char * SDRANGEL_GETheader = "GET /sdrangel/deviceset/%d/device/settings " // "HTTP/1.1\nHost: %s\nConnection: keep-alive\n\r\n"; @@ -10379,7 +10374,6 @@ VOID SDRANGELPoll(struct RIGPORTINFO * PORT) if (GetPermissionToChange(PORT, RIG)) { char cmd[80]; - double freq; if (RIG->RIG_DEBUG) Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq); @@ -10451,7 +10445,6 @@ VOID SDRANGELPoll(struct RIGPORTINFO * PORT) VOID SDRANGELSendCommand(struct RIGPORTINFO * PORT, char * Command, char * Value) { int Len, ret; - char ReqBuf[512]; char SendBuff[512]; char ValueString[256] =""; char * SDRANGEL_PATCHheader = "PATCH /sdrangel/deviceset/%d/device/settings " diff --git a/SCSPactor.c b/SCSPactor.c index 3bd0ffe..ddb8277 100644 --- a/SCSPactor.c +++ b/SCSPactor.c @@ -2893,7 +2893,7 @@ VOID ProcessIncomingCall(struct TNCINFO * TNC, struct STREAMINFO * STREAM, int S { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // Make sure app is available @@ -3034,7 +3034,7 @@ VOID ProcessIncomingCall(struct TNCINFO * TNC, struct STREAMINFO * STREAM, int S { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // if SendTandRtoRelay set and Appl is RMS change to RELAY diff --git a/SCSTrackeMulti.c b/SCSTrackeMulti.c index ce5df93..00174cf 100644 --- a/SCSTrackeMulti.c +++ b/SCSTrackeMulti.c @@ -48,7 +48,6 @@ extern UCHAR BPQDirectory[]; static RECT Rect; VOID __cdecl Debugprintf(const char * format, ...); -char * strlop(char * buf, char delim); BOOL KAMStartPort(struct PORTCONTROL * PORT); BOOL KAMStopPort(struct PORTCONTROL * PORT); diff --git a/SCSTracker.c b/SCSTracker.c index d7364f8..e6d356f 100644 --- a/SCSTracker.c +++ b/SCSTracker.c @@ -52,7 +52,6 @@ extern char LOC[]; static RECT Rect; VOID __cdecl Debugprintf(const char * format, ...); -char * strlop(char * buf, char delim); char NodeCall[11]; // Nodecall, Null Terminated @@ -2175,7 +2174,7 @@ VOID TrkProcessDEDFrame(struct TNCINFO * TNC) { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // Make sure app is available diff --git a/SerialPort.c b/SerialPort.c index 004f2ff..0fb09e7 100644 --- a/SerialPort.c +++ b/SerialPort.c @@ -142,7 +142,7 @@ loop: return 1; } -BOOL SerialReadConfigFile(int Port, int ProcLine()) +BOOL SerialReadConfigFile(int Port, int ProcLine(char * buf, int Port)) { char buf[256],errbuf[256]; diff --git a/TNCEmulators.c b/TNCEmulators.c index 131bbf4..cf32c9a 100644 --- a/TNCEmulators.c +++ b/TNCEmulators.c @@ -27,6 +27,16 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include "CHeaders.h" +typedef struct _TCMDX +{ + char String[12]; // COMMAND STRING + UCHAR CMDLEN; // SIGNIFICANT LENGTH + VOID (* CMDPROC)(struct TNCDATA * TNC, char * Tail, struct _TCMDX * CMD);// COMMAND PROCESSOR + size_t CMDFLAG; // FLAG/VALUE Offset + +} TCMDX; + + #define LF 10 #define CR 13 @@ -848,7 +858,7 @@ int LocalSessionState(int stream, int * state, int * change, BOOL ACK) -VOID ONOFF(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID ONOFF(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { // PROCESS COMMANDS WITH ON/OFF PARAM @@ -897,7 +907,7 @@ VOID ONOFF(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -VOID ONOFF_CONOK(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID ONOFF_CONOK(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; @@ -911,7 +921,7 @@ VOID ONOFF_CONOK(struct TNCDATA * TNC, char * Tail, CMDX * CMD) SetAppl(TNCStream->BPQPort, TNC->APPLFLAGS, 0); } -VOID SETMYCALL(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID SETMYCALL(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { char Response[80]; int len; @@ -935,7 +945,7 @@ VOID SETMYCALL(struct TNCDATA * TNC, char * Tail, CMDX * CMD) SENDREPLY(TNC, Response, len); } -VOID CTEXTCMD(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID CTEXTCMD(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { char Response[256]; int len, n; @@ -963,10 +973,10 @@ VOID CTEXTCMD(struct TNCDATA * TNC, char * Tail, CMDX * CMD) SENDREPLY(TNC, Response, len); } -VOID BTEXT(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID BTEXT(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { } -VOID VALUE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID VALUE(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { // PROCESS COMMANDS WITH decimal value @@ -995,7 +1005,7 @@ VOID VALUE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) SENDREPLY(TNC, Response, len); } -VOID VALHEX(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID VALHEX(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { // PROCESS COMMANDS WITH decimal value @@ -1032,7 +1042,7 @@ VOID VALHEX(struct TNCDATA * TNC, char * Tail, CMDX * CMD) SENDREPLY(TNC, Response, len); } -VOID APPL_VALHEX(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID APPL_VALHEX(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { int ApplNum = 1; UINT APPLMASK; @@ -1061,7 +1071,7 @@ VOID APPL_VALHEX(struct TNCDATA * TNC, char * Tail, CMDX * CMD) memcpy(TNC->MYCALL, GetApplCall(ApplNum), 10); } -VOID CSWITCH(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID CSWITCH(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { char Response[80]; int len; @@ -1072,12 +1082,12 @@ VOID CSWITCH(struct TNCDATA * TNC, char * Tail, CMDX * CMD) CONNECTTONODE(TNC); } -VOID CONMODE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID CONMODE(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { SENDREPLY(TNC, CMDMSG, 4); } -VOID TNCCONV(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID TNCCONV(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; @@ -1085,7 +1095,7 @@ VOID TNCCONV(struct TNCDATA * TNC, char * Tail, CMDX * CMD) TNCStream->MODEFLAG &= ~(COMMAND+TRANS); } -VOID TNCNODE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID TNCNODE(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { // CONNECT TO NODE @@ -1099,7 +1109,7 @@ VOID TNCNODE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) CONNECTTONODE(TNC); } -VOID CStatus(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID CStatus(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; @@ -1136,7 +1146,7 @@ VOID CStatus(struct TNCDATA * TNC, char * Tail, CMDX * CMD) } -VOID TNCCONNECT(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID TNCCONNECT(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; @@ -1179,7 +1189,7 @@ VOID TNCCONNECT(struct TNCDATA * TNC, char * Tail, CMDX * CMD) SENDPACKET(TNC); // Will now go to node } -VOID TNCDISC(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID TNCDISC(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; @@ -1194,7 +1204,7 @@ VOID READCHANGE(int Stream) LocalSessionState(Stream, &dummy, &dummy, TRUE); } -VOID TNCRELEASE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID TNCRELEASE(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { ReturntoNode(TNC->BPQPort); @@ -1203,7 +1213,7 @@ VOID TNCRELEASE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) SENDREPLY(TNC, CMDMSG, 4); } -VOID TNCTRANS(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +VOID TNCTRANS(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; @@ -1215,7 +1225,7 @@ VOID TNCTRANS(struct TNCDATA * TNC, char * Tail, CMDX * CMD) TNCStream->MODEFLAG |= TRANS; TNCStream->MODEFLAG &= ~(COMMAND+CONV); } -static VOID TNCRESTART(struct TNCDATA * TNC) +static VOID TNCRESTART(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { // REINITIALISE CHANNEL @@ -1243,12 +1253,12 @@ static VOID TNCRESTART(struct TNCDATA * TNC) } -static VOID TNCUNPROTOCMD(struct TNCDATA * TNC, char * Tail, CMDX * CMD) +static VOID TNCUNPROTOCMD(struct TNCDATA * TNC, char * Tail, TCMDX * CMD) { } -CMDX TNCCOMMANDLIST[] = +TCMDX TNCCOMMANDLIST[] = { "AUTOLF ",2, ONOFF, offsetof(struct TNCDATA, AUTOLF), "BBSMON ",6, ONOFF, offsetof(struct TNCDATA, BBSMON), @@ -1301,7 +1311,7 @@ CMDX TNCCOMMANDLIST[] = -int NUMBEROFTNCCOMMANDS = sizeof(TNCCOMMANDLIST)/sizeof(CMDX); +int NUMBEROFTNCCOMMANDS = sizeof(TNCCOMMANDLIST)/sizeof(TCMDX); /*NEWVALUE DW 0 HEXFLAG DB 0 @@ -2575,7 +2585,7 @@ VOID TNCCOMMAND(struct TNCDATA * TNC) char * ptr, * ptr1, * ptr2; int n; - CMDX * CMD; + TCMDX * CMD; *(--TNC->CURSOR) = 0; @@ -2653,11 +2663,8 @@ VOID TNCCOMMAND(struct TNCDATA * TNC) } CMD++; - } - SENDREPLY(TNC, WHATMSG, 8); - } /* @@ -4926,6 +4933,7 @@ int STATUSPOLL(struct TNCDATA * TNC, struct StreamInfo * Channel) int State, Change, i; char WorkString[256]; + char ConMsg[64]; if (TNC->MSGCHANNEL == 0) // Monitor Chan return 0; @@ -4941,7 +4949,7 @@ int STATUSPOLL(struct TNCDATA * TNC, struct StreamInfo * Channel) { // DISCONNECTED - i = sprintf(CONMSG, "\x3(%d) DISCONNECTED fm 0:SWITCH\r", TNC->MSGCHANNEL); + i = sprintf(ConMsg, "\x3(%d) DISCONNECTED fm 0:SWITCH\r", TNC->MSGCHANNEL); i++; } else @@ -4950,11 +4958,11 @@ int STATUSPOLL(struct TNCDATA * TNC, struct StreamInfo * Channel) GetCallsign(Channel->BPQStream, WorkString); strlop(WorkString, ' '); - i = sprintf(CONMSG, "\x3(%d) CONNECTED to %s\r", TNC->MSGCHANNEL, WorkString); + i = sprintf(ConMsg, "\x3(%d) CONNECTED to %s\r", TNC->MSGCHANNEL, WorkString); i++; } - SENDCMDREPLY(TNC, CONMSG, i); + SENDCMDREPLY(TNC, ConMsg, i); return 1; } diff --git a/TelnetV6.c b/TelnetV6.c index 5832266..b9ed7f1 100644 --- a/TelnetV6.c +++ b/TelnetV6.c @@ -127,7 +127,6 @@ static HMENU hMenu, hPopMenu, hPopMenu2, hPopMenu3; // handle of menu static int ProcessLine(char * buf, int Port); VOID __cdecl Debugprintf(const char * format, ...); -char * strlop(char * buf, char delim); int DisplaySessions(struct TNCINFO * TNC); @@ -6757,7 +6756,7 @@ extern struct DATAMESSAGE * REPLYBUFFER; char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char * format, ...); -VOID RECONFIGTELNET (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID RECONFIGTELNET (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { int Port = 0, index =0; char * ptr, *Context; @@ -6942,7 +6941,7 @@ VOID RECONFIGTELNET (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); } -VOID SHOWTELNET(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) +VOID SHOWTELNET(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) { // DISPLAY Telnet Server Status Mheard diff --git a/UIARQ.c b/UIARQ.c index fe880c3..8c6b00e 100644 --- a/UIARQ.c +++ b/UIARQ.c @@ -869,7 +869,7 @@ static VOID ProcessFLDigiData(struct TNCINFO * TNC, UCHAR * Input, int Len, int { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // Make sure app is available diff --git a/UZ7HODrv.c b/UZ7HODrv.c index 863cc9d..f9b433b 100644 --- a/UZ7HODrv.c +++ b/UZ7HODrv.c @@ -62,7 +62,7 @@ void ConnecttoUZ7HOThread(void * portptr); void CreateMHWindow(); int Update_MH_List(struct in_addr ipad, char * call, char proto); -int ConnecttoUZ7HO(); +int ConnecttoUZ7HO(int port); static int ProcessReceivedData(int bpqport); static int ProcessLine(char * buf, int Port); int KillTNC(struct TNCINFO * TNC); @@ -374,7 +374,7 @@ int UZ7HOSetFreq(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMESS { // Read Freq - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "UZ7HO} Modem Freqency %d\r", AGW->CenterFreq); + buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "UZ7HO} Modem Frequency %d\r", AGW->CenterFreq); return 1; } @@ -2479,7 +2479,7 @@ GotStream: { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // Make sure app is available diff --git a/V4.c b/V4.c index 5e26ca9..5bd6880 100644 --- a/V4.c +++ b/V4.c @@ -1273,7 +1273,7 @@ static VOID ProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // Make sure app is available diff --git a/VARA.c b/VARA.c index 58a2dbf..e8fd061 100644 --- a/VARA.c +++ b/VARA.c @@ -2231,7 +2231,7 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // if SendTandRtoRelay set and Appl is RMS change to RELAY diff --git a/Versions.h b/Versions.h index b50ccd4..96ac12d 100644 --- a/Versions.h +++ b/Versions.h @@ -10,8 +10,8 @@ #endif -#define KVers 6,0,24,53 -#define KVerstring "6.0.24.53\0" +#define KVers 6,0,24,54 +#define KVerstring "6.0.24.54\0" #ifdef CKernel diff --git a/WINMOR.c b/WINMOR.c index a920a4e..7f6763b 100644 --- a/WINMOR.c +++ b/WINMOR.c @@ -508,7 +508,7 @@ static int ProcessLine(char * buf, int Port) void WINMORThread(void * portptr); VOID ProcessDataSocketData(int port); -int ConnecttoWINMOR(); +int ConnecttoWINMOR(int port); static int ProcessReceivedData(struct TNCINFO * TNC); int V4ProcessReceivedData(struct TNCINFO * TNC); VOID ReleaseTNC(struct TNCINFO * TNC); @@ -2231,7 +2231,7 @@ VOID ProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) { char AppName[13]; - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); + memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; // Make sure app is available diff --git a/WPRoutines.c b/WPRoutines.c index da46799..ac39a5b 100644 --- a/WPRoutines.c +++ b/WPRoutines.c @@ -34,6 +34,7 @@ VOID Do_Save_WPRec(HWND hDlg); VOID SaveInt64Value(config_setting_t * group, char * name, long long value); VOID SaveIntValue(config_setting_t * group, char * name, int value); VOID SaveStringValue(config_setting_t * group, char * name, char * value); +void MQTTMessageEvent(void* message); WPRec * AllocateWPRecord() { @@ -1495,6 +1496,10 @@ int CreateWPMessage() BuildNNTPList(Msg); // Build NNTP Groups list +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(Msg); +#endif To++; } diff --git a/WebMail.c b/WebMail.c index edcc107..05dc303 100644 --- a/WebMail.c +++ b/WebMail.c @@ -78,6 +78,7 @@ char * doXMLTransparency(char * string); Dll BOOL APIENTRY APISendAPRSMessage(char * Text, char * ToCall); void SendMessageReadEvent(char * Call, struct MsgInfo * Msg); void SendNewMessageEvent(char * call, struct MsgInfo * Msg); +void MQTTMessageEvent(void* message); extern char NodeTail[]; extern char BBSName[10]; @@ -2020,7 +2021,7 @@ void ProcessWebMailMessage(struct HTTPConnectionInfo * Session, char * Key, BOOL "document.getElementById('myform').action = '/WebMail/QuoteOriginal' + '?%s';" " document.getElementById('myform').submit();}" ""; + "value='Include Original Msg'>"; char Temp[1024]; char ReplyAddr[128]; @@ -2840,6 +2841,11 @@ VOID SaveNewMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, char * R SendNewMessageEvent(user->Call, Msg); +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(Msg); +#endif + if (user && (user->flags & F_APRSMFOR)) { char APRS[128]; @@ -3784,6 +3790,12 @@ VOID WriteOneRecipient(struct MsgInfo * Msg, WebMailInfo * WebMail, int MsgLen, Msg->status = '$'; // Has forwarding BuildNNTPList(Msg); // Build NNTP Groups list + +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(Msg); +#endif + } @@ -4368,6 +4380,12 @@ VOID BuildMessageFromHTMLInput(struct HTTPConnectionInfo * Session, char * Reply BuildNNTPList(Msg); // Build NNTP Groups list +#ifndef NOMQTT + if (MQTT) + MQTTMessageEvent(Msg); +#endif + + SaveMessageDatabase(); SaveBIDDatabase(); diff --git a/WinRPR.c b/WinRPR.c index 03d81ac..d087f47 100644 --- a/WinRPR.c +++ b/WinRPR.c @@ -63,8 +63,6 @@ extern char LOC[]; static RECT Rect; VOID __cdecl Debugprintf(const char * format, ...); -char * strlop(char * buf, char delim); - char NodeCall[11]; // Nodecall, Null Terminated static BOOL WriteCommBlock(struct TNCINFO * TNC); diff --git a/WinRPRHelper.c b/WinRPRHelper.c index af978e1..bb2b6cd 100644 --- a/WinRPRHelper.c +++ b/WinRPRHelper.c @@ -111,7 +111,7 @@ int main(int argc, char ** argv) if (argc < 3) { - printf ("Missing paramters - you need COM port and IP Address and rigctl port of BPQ, eg \r\n" + printf ("Missing parameters - you need COM port and IP Address and rigctl port of BPQ, eg \r\n" " WinRPRHelper com10 192.168.1.64:4532\r\n\r\n" "Press any key to exit\r\n"); diff --git a/asmstrucs.h b/asmstrucs.h index 354d0c4..268b51a 100644 --- a/asmstrucs.h +++ b/asmstrucs.h @@ -62,15 +62,15 @@ extern int ENDOFDATA; extern int L3LIVES; extern int NUMBEROFNODES; -typedef struct _CMDX +struct CMDX { char String[12]; // COMMAND STRING UCHAR CMDLEN; // SIGNIFICANT LENGTH - VOID (* CMDPROC)(); // COMMAND PROCESSOR +// VOID (*CMDPROC)(struct _TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);// COMMAND PROCESSOR + VOID (*CMDPROC)();// COMMAND PROCESSOR size_t CMDFLAG; // FLAG/VALUE Offset -} CMDX; - +}; struct APPLCONFIG { @@ -547,14 +547,14 @@ typedef struct PORTCONTROL PMESSAGE PORTRX_Q; // FRAMES RECEIVED ON THIS PORT PMESSAGE PORTTX_Q; // FRAMES TO BE SENT ON THIS PORT - void (FAR * PORTTXROUTINE)(); // POINTER TO TRANSMIT ROUTINE FOR THIS PORT - void (FAR * PORTRXROUTINE)(); // POINTER TO RECEIVE ROUTINE FOR THIS PORT - void (FAR * PORTINITCODE)(); // INITIALISATION ROUTINE - void (FAR * PORTTIMERCODE)(); // - void (FAR * PORTCLOSECODE)(); // CLOSE ROUTINE - int (FAR * PORTTXCHECKCODE)(); // OK to TX Check - BOOL (FAR * PORTSTOPCODE)(); // Temporarily Stop Port - BOOL (FAR * PORTSTARTCODE)(); // Restart Port + void (FAR * PORTTXROUTINE)(struct _EXTPORTDATA * PORTVEC, MESSAGE * Buffer); // POINTER TO TRANSMIT ROUTINE FOR THIS PORT + void (FAR * PORTRXROUTINE)(struct _EXTPORTDATA * PORTVEC); // POINTER TO RECEIVE ROUTINE FOR THIS PORT + void (FAR * PORTINITCODE)(struct PORTCONTROL * PortVector); // INITIALISATION ROUTINE + void (FAR * PORTTIMERCODE)(struct PORTCONTROL * PortVector); // + void (FAR * PORTCLOSECODE)(struct PORTCONTROL * PortVector); // CLOSE ROUTINE + int (FAR * PORTTXCHECKCODE)(struct PORTCONTROL * PORTVEC, int Chan); // OK to TX Check + BOOL (FAR * PORTSTOPCODE)(struct PORTCONTROL * PORT); // Temporarily Stop Port + BOOL (FAR * PORTSTARTCODE)(struct PORTCONTROL * PORT); // Restart Port BOOL PortStopped; // STOPPORT command used BOOL PortSuspended; // Suspended by interlock @@ -678,7 +678,7 @@ typedef struct PORTCONTROL BOOL IgnoreUnlocked; // Ignore Unlocked routes BOOL INP3ONLY; // Default to INP3 and disallow NODES - FARPROCY UIHook; // Used for KISSARQ + void (* UIHook)(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG); // Used for KISSARQ struct PORTCONTROL * HookPort; int PortSlot; // Index in Port Table struct TNCINFO * TNC; // Associated TNC record @@ -766,7 +766,7 @@ typedef struct _EXTPORTDATA { struct PORTCONTROL PORTCONTROL ; // REMAP HARDWARE INFO - void * (* PORT_EXT_ADDR) (); // ADDR OF RESIDENT ROUTINE + void * (* PORT_EXT_ADDR) (int fn, int port, PDATAMESSAGE buff); // ADDR OF RESIDENT ROUTINE char PORT_DLL_NAME[16]; UCHAR EXTRESTART; // FLAG FOR DRIVER REINIT HINSTANCE DLLhandle; diff --git a/bpqaxip.c b/bpqaxip.c index 690f96d..d03f531 100644 --- a/bpqaxip.c +++ b/bpqaxip.c @@ -194,7 +194,7 @@ extern int OffsetH, OffsetW; static void ResolveNames(struct AXIPPORTINFO * PORT); void OpenSockets(struct AXIPPORTINFO * PORT); -void CloseSockets(); +void CloseSockets(struct AXIPPORTINFO * PORT); static int CONVFROMAX25(char * incall, char * outcall); diff --git a/bpqchat.h b/bpqchat.h index 955ac48..ea322c8 100644 --- a/bpqchat.h +++ b/bpqchat.h @@ -603,7 +603,7 @@ VOID __cdecl nprintf(ChatCIRCUIT * conn, const char * format, ...); VOID nputs(ChatCIRCUIT * conn, char * buf); #endif BOOL matchi(char * p1, char * p2); -char * strlop(char * buf, char delim); +char * strlop(const char * buf, char delim); int rt_cmd(ChatCIRCUIT *circuit, char * Buffer); ChatCIRCUIT *circuit_new(ChatCIRCUIT *circuit, int flags); void makelinks(void); diff --git a/bpqmail.h b/bpqmail.h index 956d7d6..ba6e27b 100644 --- a/bpqmail.h +++ b/bpqmail.h @@ -471,6 +471,8 @@ struct UserInfo { // New Format - with stats maintained by message type and unused fields removed. + // This is no longer a fixed length record so can't be saved as a binarl + char Call[10]; // Connected call without SSID int Length; // To make subsequent format changes easier @@ -877,7 +879,7 @@ struct MSESSION }; VOID __cdecl nprintf(CIRCUIT * conn, const char * format, ...); -char * strlop(char * buf, char delim); +char * strlop(const char * buf, char delim); int rt_cmd(CIRCUIT *circuit, char * Buffer); CIRCUIT *circuit_new(CIRCUIT *circuit, int flags); VOID BBSputs(CIRCUIT * conn, char * buf); @@ -1211,10 +1213,9 @@ VOID Do_Delete_User(HWND hDlg); VOID FlagSentMessages(CIRCUIT * conn, struct UserInfo * user); VOID HoldSentMessages(CIRCUIT * conn, struct UserInfo * user); VOID Do_Save_User(HWND hDlg, BOOL ShowBox); -VOID DeleteBBS(); -VOID AddBBS(); +VOID DeleteBBS(struct UserInfo * user); VOID SaveBBSConfig(); -BOOL GetChatConfig(); +BOOL GetChatConfig(char * ConfigName); VOID SaveChatConfig(); VOID SaveISPConfig(); VOID SaveFWDConfig(); diff --git a/cMain.c b/cMain.c index 0238d3b..7cf47d0 100644 --- a/cMain.c +++ b/cMain.c @@ -42,7 +42,7 @@ VOID L2Routine(struct PORTCONTROL * PORT, PMESSAGE Buffer); VOID ProcessIframe(struct _LINKTABLE * LINK, PDATAMESSAGE Buffer); VOID FindLostBuffers(); VOID ReadMH(); -void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); +void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); int upnpInit(); void AISTimer(); void ADSBTimer(); @@ -332,7 +332,7 @@ BOOL LINKTXCHECK() return 0; } -void * Dummy() // Dummy for missing EXT Driver +void * Dummy(int fn, int port, PDATAMESSAGE buff) // Dummy for missing EXT Driver { return 0; } @@ -340,27 +340,32 @@ void * Dummy() // Dummy for missing EXT Driver VOID EXTINIT(PEXTPORTDATA PORTVEC) { // LOAD DLL - NAME IS IN PORT_DLL_NAME - - VOID * Routine; + + void *(* Startup) (PEXTPORTDATA PORTVEC); // ADDR OF Startup ROUTINE PORTVEC->PORT_EXT_ADDR = Dummy; - Routine = InitializeExtDriver(PORTVEC); - - if (Routine == 0) + Startup = InitializeExtDriver(PORTVEC); + + if (Startup == 0) { WritetoConsoleLocal("Driver installation failed\n"); return; } - PORTVEC->PORT_EXT_ADDR = Routine; -// ALSO CALL THE ROUTINE TO START IT UP, ESPECIALLY IF A L2 ROUTINE - Routine = (VOID *)PORTVEC->PORT_EXT_ADDR(PORTVEC); +// CALL THE ROUTINE TO START IT UP // Startup returns address of processing routine - PORTVEC->PORT_EXT_ADDR = Routine; + PORTVEC->PORT_EXT_ADDR = (void *(__cdecl *)(int,int,PDATAMESSAGE))Startup(PORTVEC);; + + if (PORTVEC->PORT_EXT_ADDR == 0) + { + WritetoConsoleLocal("Driver Initialisation failed\n"); + return; + } + } VOID EXTTX(PEXTPORTDATA PORTVEC, MESSAGE * Buffer) @@ -372,7 +377,7 @@ VOID EXTTX(PEXTPORTDATA PORTVEC, MESSAGE * Buffer) if (PORT->KISSFLAGS == 255) // Used for BAYCOM { - PORTVEC->PORT_EXT_ADDR(2, PORT->PORTNUMBER, Buffer); + PORTVEC->PORT_EXT_ADDR(2, PORT->PORTNUMBER, (PDATAMESSAGE)Buffer); return; // Baycom driver passes frames to trace once sent } @@ -388,7 +393,7 @@ VOID EXTTX(PEXTPORTDATA PORTVEC, MESSAGE * Buffer) Buffer->Linkptr = 0; // CLEAR FLAG FROM BUFFER } - PORTVEC->PORT_EXT_ADDR(2, PORT->PORTNUMBER, Buffer); + PORTVEC->PORT_EXT_ADDR(2, PORT->PORTNUMBER, (PDATAMESSAGE)Buffer); if (PORT->PROTOCOL == 10 && PORT->TNC && PORT->TNC->Hardware != H_KISSHF) { @@ -418,7 +423,7 @@ Loop: if (Message == NULL) return; - Len = (size_t)PORTVEC->PORT_EXT_ADDR(1, PORT->PORTNUMBER, Message); + Len = (size_t)PORTVEC->PORT_EXT_ADDR(1, PORT->PORTNUMBER, (PDATAMESSAGE)Message); if (Len == 0) { @@ -502,7 +507,9 @@ VOID EXTSLOWTIMER(PEXTPORTDATA PORTVEC) size_t EXTTXCHECK(PEXTPORTDATA PORTVEC, int Chan) { - return (size_t)PORTVEC->PORT_EXT_ADDR(3, PORTVEC->PORTCONTROL.PORTNUMBER, Chan); + uintptr_t Temp = Chan; + + return (size_t)PORTVEC->PORT_EXT_ADDR(3, PORTVEC->PORTCONTROL.PORTNUMBER, (void *)Temp); } VOID PostDataAvailable(TRANSPORTENTRY * Session) @@ -578,8 +585,8 @@ extern VOID HDLCTXCHECK(); #endif extern VOID KISSINIT(), KISSTX(), KISSRX(), KISSTIMER(), KISSCLOSE(); -extern VOID EXTINIT(), EXTTX(), LINKRX(), EXTRX(); -extern VOID LINKCLOSE(), EXTCLOSE() ,LINKTIMER(), EXTTIMER(); +extern VOID EXTINIT(PEXTPORTDATA PORTVEC), EXTTX(PEXTPORTDATA PORTVEC, MESSAGE * Buffer), LINKRX(), EXTRX(PEXTPORTDATA PORTVEC); +extern VOID LINKCLOSE(), EXTCLOSE() ,LINKTIMER(), EXTTIMER(PEXTPORTDATA PORTVEC); // VECTORS TO HARDWARE DEPENDENT ROUTINES @@ -609,7 +616,7 @@ extern int L4TimerProc(); extern int L3FastTimer(); extern int StatsTimer(); extern int COMMANDHANDLER(); -extern int SDETX(); +VOID SDETX(struct _LINKTABLE * LINK); extern int L4BG(); extern int L3BG(); extern int TNCTimerProc(); @@ -628,7 +635,7 @@ BOOL Start() APPLCALLS * APPL; struct ROUTE * ROUTE; struct DEST_LIST * DEST; - CMDX * CMD; + struct CMDX * CMD; int PortSlot = 1; uintptr_t int3; @@ -2342,7 +2349,7 @@ L2Packet: PORT->L2FRAMESSENT++; OutOctets[PORT->PORTNUMBER] += Buffer->LENGTH - MSGHDDRLEN; - PORT->PORTTXROUTINE(PORT, Buffer); + PORT->PORTTXROUTINE((struct _EXTPORTDATA *)PORT, Buffer); Sent++; continue; @@ -2388,7 +2395,7 @@ PACTORLOOP: PORT->L2FRAMESSENT++; OutOctets[PORT->PORTNUMBER] += Message->LENGTH; - PORT->PORTTXROUTINE(PORT, Buffer); + PORT->PORTTXROUTINE((struct _EXTPORTDATA *)PORT, Buffer); Sent++; if (Sent < 5) @@ -2401,7 +2408,7 @@ ENDOFLIST: break; } - PORT->PORTRXROUTINE(PORT); // SEE IF MESSAGE RECEIVED + PORT->PORTRXROUTINE((struct _EXTPORTDATA *)PORT); // SEE IF MESSAGE RECEIVED PORT = PORT->PORTPOINTER; } diff --git a/compatbits.h b/compatbits.h index 5804fc5..8cdc714 100644 --- a/compatbits.h +++ b/compatbits.h @@ -208,10 +208,6 @@ VOID md5(char *arg, unsigned char * checksum); int APIENTRY SendRaw(int port, char * msg, int len); - - -BOOL MySetDlgItemText(); - VOID OutputDebugString(char * string); #endif diff --git a/config.c b/config.c index 3220b87..85a55cd 100644 --- a/config.c +++ b/config.c @@ -649,7 +649,7 @@ BOOL ProcessConfig() if (LOCATOR[0] == 0 && LocSpecified == 0 && RFOnly == 0) { Consoleprintf(""); - Consoleprintf("Please enter a LOCATOR statment in your BPQ32.cfg"); + Consoleprintf("Please enter a LOCATOR statement in your BPQ32.cfg"); Consoleprintf("If you really don't want to be on the Node Map you can enter LOCATOR=NONE"); Consoleprintf(""); @@ -1755,8 +1755,7 @@ int tncports(int i) /* FIND OCCURENCE OF ONE STRING WITHIN ANOTHER */ /************************************************************************/ -int xindex(s, t) -char s[], t[]; +int xindex(char s[], char t[]) { int i, j ,k; @@ -1775,8 +1774,7 @@ char s[], t[]; /* FIND FIRST OCCURENCE OF A CHARACTER THAT IS NOT c */ /************************************************************************/ -int verify(s, c) -char s[], c; +int verify(char s[], char c) { int i; @@ -2297,10 +2295,7 @@ int decode_port_rec(char * rec) } -int doid(i, value, rec) -int i; -char value[]; -char rec[]; +int doid(int i, char value[], char rec[]) { unsigned int j; for (j = 3;( j < (unsigned int)strlen(rec)+1); j++) @@ -2334,10 +2329,7 @@ char rec[]; return(1); } -int dodll(i, value, rec) -int i; -char value[]; -char rec[]; +int dodll(int i, char value[], char rec[]) { unsigned int j; @@ -2424,7 +2416,7 @@ int doSerialPortName(int i, char * value, char * rec) if (IsNumeric(rec)) xxp.IOADDR = atoi(rec); else - xxp.SerialPortName = strdup(rec); + xxp.SerialPortName = _strdup(rec); return 1; } @@ -2457,10 +2449,7 @@ int doKissCommand(int i, char * value, char * rec) } -int hwtypes(i, value, rec) -int i; -char value[]; -char rec[]; +int hwtypes(int i, char value[], char rec[]) { hw = 255; if (_stricmp(value,"ASYNC") == 0) @@ -2543,10 +2532,7 @@ char rec[]; return(1); } -int protocols(i, value, rec) -int i; -char value[]; -char rec[]; +int protocols(int i, char value[], char rec[]) { int hw; @@ -2580,10 +2566,7 @@ char rec[]; } -int bbsflag(i, value, rec) -int i; -char value[]; -char rec[]; +int bbsflag(int i, char value[],char rec[]) { int hw=255; @@ -2634,10 +2617,7 @@ int validcalls(int i, char * value, char * rec) } -int kissoptions(i, value, rec) -int i; -char value[]; -char rec[]; +int kissoptions(int i, char value[], char rec[]) { int err=255; @@ -2689,7 +2669,19 @@ static int troutine[] = #define TPARAMLIM 6 -extern CMDX TNCCOMMANDLIST[]; + +typedef struct _TCMDX +{ + char String[12]; // COMMAND STRING + UCHAR CMDLEN; // SIGNIFICANT LENGTH + VOID (* CMDPROC)(struct TNCDATA * TNC, char * Tail, struct _TCMDX * CMD);// COMMAND PROCESSOR + size_t CMDFLAG; // FLAG/VALUE Offset + +} TCMDX; + + + +extern TCMDX TNCCOMMANDLIST[]; extern int NUMBEROFTNCCOMMANDS; int decode_tnc_rec(char * rec) @@ -2766,7 +2758,7 @@ int decode_tnc_rec(char * rec) // Try process as TNC2 Command int n = 0; - CMDX * CMD = &TNCCOMMANDLIST[0]; + TCMDX * CMD = &TNCCOMMANDLIST[0]; char * ptr1 = key_word; UCHAR * valueptr; diff --git a/kiss.c b/kiss.c index 8c21d44..ccfc297 100644 --- a/kiss.c +++ b/kiss.c @@ -1485,7 +1485,7 @@ SeeifMore: } } else - Debugprintf("Polled KISS - response from wrong address - Polled %d Reponse %d", + Debugprintf("Polled KISS - response from wrong address - Polled %d Response %d", KISS->POLLPOINTER->OURCTRL, (Port->RXMSG[0] & 0xf0)); goto SeeifMore; // SEE IF ANYTHING ELSE diff --git a/mailapi.c b/mailapi.c index cb0f223..750f73e 100644 --- a/mailapi.c +++ b/mailapi.c @@ -38,7 +38,7 @@ typedef struct MailAPI { char *URL; int URLLen; - int (* APIRoutine)(); + int (* APIRoutine)(struct HTTPConnectionInfo * Session, char * response, char * Rest, int Auth); int Auth; } MailAPI; @@ -1100,8 +1100,13 @@ int unroutableCount = 0; ptr += sprintf(ptr, "\"location\": \"%s\",\r\n", ourBBSRec->Address); ptr += sprintf(ptr, "\"unroutable\": %s\r\n}\r\n", Unroutables); +#ifdef LINBPQ SendWebRequest("packetnodes.spots.radio", Request, Params, 0); +#else + pSendWebRequest("packetnodes.spots.radio", Request, Params, 0); +#endif free(Messages); free(Unroutables); free(Params); } + diff --git a/md5.c b/md5.c index e3927e6..441f0cc 100644 --- a/md5.c +++ b/md5.c @@ -74,17 +74,14 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses surprised if they were a performance bottleneck for MD5. */ static cvs_uint32 -getu32 (addr) - const unsigned char *addr; +getu32(const unsigned char *addr) { return (((((uint32_t)addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0]; } static void -putu32 (data, addr) - cvs_uint32 data; - unsigned char *addr; +putu32 (cvs_uint32 data, unsigned char *addr) { addr[0] = (unsigned char)data; addr[1] = (unsigned char)(data >> 8); @@ -97,8 +94,7 @@ putu32 (data, addr) * initialization constants. */ void -cvs_MD5Init (ctx) - struct cvs_MD5Context *ctx; +cvs_MD5Init (struct cvs_MD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; @@ -114,10 +110,8 @@ cvs_MD5Init (ctx) * of bytes. */ void -cvs_MD5Update (ctx, buf, len) - struct cvs_MD5Context *ctx; - unsigned char const *buf; - unsigned len; +cvs_MD5Update ( + struct cvs_MD5Context *ctx, unsigned char const *buf, unsigned len) { cvs_uint32 t; @@ -164,10 +158,7 @@ cvs_MD5Update (ctx, buf, len) * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ -void -cvs_MD5Final (digest, ctx) - unsigned char digest[16]; - struct cvs_MD5Context *ctx; +void cvs_MD5Final (unsigned char digest[16], struct cvs_MD5Context *ctx) { unsigned count; unsigned char *p; @@ -227,10 +218,7 @@ cvs_MD5Final (digest, ctx) * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ -void -cvs_MD5Transform (buf, inraw) - cvs_uint32 buf[4]; - const unsigned char inraw[64]; +void cvs_MD5Transform (cvs_uint32 buf[4], const unsigned char inraw[64]) { register cvs_uint32 a, b, c, d; cvs_uint32 in[16]; diff --git a/mqtt.c b/mqtt.c index 51e5631..4f7571f 100644 --- a/mqtt.c +++ b/mqtt.c @@ -317,7 +317,60 @@ int MQTTConnect(char* host, int port, char* user, char* pass) return 0; } -/* +// Message Database Entry. Designed to be compatible with FBB + +#define NBBBS 160 // Max BBSes we can forward to. Must be Multiple of 8, and must be 80 for FBB compatibliliy +#define NBMASK NBBBS/8 // Number of bytes in Forward bitlists. + +#pragma pack(1) + +struct MsgInfo +{ + char type; + char status; + int number; + int length; + int xdatereceived; + char bbsfrom[7]; // ? BBS we got it from ? + char via[41]; + char from[7]; + char to[7]; + char bid[13]; + char title[61]; + int nntpnum; // Number within topic (ie Bull TO Addr) - used for nntp + + UCHAR B2Flags; // Not all flags specific to B2 + + #define B2Msg 1 // Set if Message File is a formatted B2 message + #define Attachments 2 // Set if B2 message has attachments + #define FromPaclink 4 + #define FromCMS 8 + #define FromRMSExpress 16 + #define RadioOnlyMsg 32 // Received using call-T + #define RadioOnlyFwd 64 // Received using call-R + #define WarnNotForwardedSent 128 + + int xdatecreated; + int xdatechanged; + UCHAR fbbs[NBMASK]; + UCHAR forw[NBMASK]; + char emailfrom[41]; + char Locked; // Set if selected for sending (NTS Pickup) + char Defered; // FBB response '=' received + UCHAR UTF8; // Set if Message is in UTF8 (ie from POP/SMTP) + +// For 64 bit time_t compatibility define as long long +// (so struct is same with 32 or 64 bit time_t) + + int64_t datereceived; + int64_t datecreated; + int64_t datechanged; + + char Spare[61 - 24]; // For future use +} ; + +#pragma pack() + void MQTTMessageEvent(void* message) { struct MsgInfo* msg = (struct MsgInfo *)message; @@ -360,7 +413,6 @@ void MQTTMessageEvent(void* message) MQTTAsync_sendMessage(client, topic, &pubmsg, &opts); } -*/ #else diff --git a/nodeapi.c b/nodeapi.c index 8ac9c3c..0d2fa49 100644 --- a/nodeapi.c +++ b/nodeapi.c @@ -26,7 +26,7 @@ typedef struct API { char *URL; int URLLen; - int (* APIRoutine)(); + int (* APIRoutine)(char * response, char * token, char * param); int Auth; } API; diff --git a/pngerror.c b/pngerror.c index f184f2b..823a0b0 100644 --- a/pngerror.c +++ b/pngerror.c @@ -211,7 +211,7 @@ png_default_error(png_structp png_ptr, png_const_charp error_message) #endif #ifdef PNG_NO_CONSOLE_IO /* make compiler happy */ ; - if (&error_message != NULL) + // if (&error_message != NULL) return; #endif } diff --git a/templatedefs.c b/templatedefs.c index b532031..47bdfc3 100644 --- a/templatedefs.c +++ b/templatedefs.c @@ -1165,7 +1165,7 @@ char * Housekeepingtxt() "Send Non-delivery Notifications
\r\n" "for P and T messages
\r\n" "
\r\n" - "Supress Mailing of
\r\n" + "Suppress Mailing of
\r\n" "Housekeeping Result

\r\n" "Generate Traffic Report

\r\n" "
\r\n" @@ -1454,7 +1454,7 @@ char * ChatConfigtxt() "
The Nodes to link to box defines which other Chat Nodes should be connected to, or from which " "connections may be accepted. The format is ALIAS:CALL, eg BPQCHT:G8BPQ-4. If the node is not directly " "connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands " - "seperared by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT" + "separared by |, eg NOTCHT:G8BPQ-4|C 3 GM8BPQ-9|CHAT" "

The Callsign of the Chat Node is not defined here - it is obtained from the bpq32.cfg APPLICATION line corresponding to the Chat Appl Number.
\r\n" "
\n" diff --git a/tncinfo.h b/tncinfo.h index 87d3f36..d038554 100644 --- a/tncinfo.h +++ b/tncinfo.h @@ -814,9 +814,9 @@ typedef struct TNCINFO HMENU hMenu; HMENU hWndMenu; - VOID (* SuspendPortProc) (); - VOID (* ReleasePortProc) (); - VOID (* ForcedCloseProc) (); + VOID (* SuspendPortProc) (struct TNCINFO * TNC, struct TNCINFO * ThisTNC); + VOID (* ReleasePortProc) (struct TNCINFO * TNC); + VOID (* ForcedCloseProc) (struct TNCINFO * TNC, int Stream); time_t WinmorRestartCodecTimer; int WinmorCurrentMode;