From 83bc496f335e495cad07e53f577a554fbe1d9507 Mon Sep 17 00:00:00 2001 From: g8bpq Date: Sat, 15 Feb 2025 07:36:33 +0000 Subject: [PATCH] 6.0.24.62 --- .rej | 139 - APRSCode.c.orig | 9223 ----------------- APRSCode.c.rej | 139 - BPQChat.vcproj.NOTTSDESKTOP.John.user | 65 - BPQChat.vcproj.SKIGACER.johnw.user | 65 - BPQINP3.c | 2 +- BPQMail.c | 1 + BPQMail.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - BPQMail.vcproj.NOTTSDESKTOP.John.user | 65 - BPQMail.vcproj.SKIGACER.johnw.user | 65 - BPQMail.vcxproj.filters | 113 - BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - BPQWinAPP.vcproj.NOTTSDESKTOP.John.user | 65 - Bpq32.c | 12 +- CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - CBPQ32.vcproj.NOTTSDESKTOP.John.user | 65 - CBPQ32.vcproj.SKIGACER.johnw.user | 65 - CBPQ32.vcxproj.filters | 228 - Cmd.c | 174 +- CommonCode.c | 13 +- FormatHTML.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - HTTPcode.c | 14 +- L2Code.c | 2 +- L3Code.c | 8 +- L4Code.c | 356 +- MailNode.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - ...vcproj.NOTTSDESKTOP.John-skigdebian-2.user | 65 - MailNode.vcproj.NOTTSDESKTOP.John.user | 65 - MailNode.vcxproj.filters | 327 - RHP.c | 5 +- Versions.h | 4 +- WinRPRHelper.vcproj.NOTTSDESKTOP.John.user | 65 - ...rControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - WinmorControl.vcproj.NOTTSDESKTOP.John.user | 65 - asmstrucs.h | 18 +- cMain.c | 28 +- config.c | 13 +- configstructs.h | 5 +- 38 files changed, 417 insertions(+), 11512 deletions(-) delete mode 100644 .rej delete mode 100644 APRSCode.c.orig delete mode 100644 APRSCode.c.rej delete mode 100644 BPQChat.vcproj.NOTTSDESKTOP.John.user delete mode 100644 BPQChat.vcproj.SKIGACER.johnw.user delete mode 100644 BPQMail.vcproj.LAPTOP-Q6S4RP5Q.johnw.user delete mode 100644 BPQMail.vcproj.NOTTSDESKTOP.John.user delete mode 100644 BPQMail.vcproj.SKIGACER.johnw.user delete mode 100644 BPQMail.vcxproj.filters delete mode 100644 BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user delete mode 100644 BPQWinAPP.vcproj.NOTTSDESKTOP.John.user delete mode 100644 CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user delete mode 100644 CBPQ32.vcproj.NOTTSDESKTOP.John.user delete mode 100644 CBPQ32.vcproj.SKIGACER.johnw.user delete mode 100644 CBPQ32.vcxproj.filters delete mode 100644 FormatHTML.vcproj.LAPTOP-Q6S4RP5Q.johnw.user delete mode 100644 MailNode.vcproj.LAPTOP-Q6S4RP5Q.johnw.user delete mode 100644 MailNode.vcproj.NOTTSDESKTOP.John-skigdebian-2.user delete mode 100644 MailNode.vcproj.NOTTSDESKTOP.John.user delete mode 100644 MailNode.vcxproj.filters delete mode 100644 WinRPRHelper.vcproj.NOTTSDESKTOP.John.user delete mode 100644 WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user delete mode 100644 WinmorControl.vcproj.NOTTSDESKTOP.John.user diff --git a/.rej b/.rej deleted file mode 100644 index 1137117..0000000 --- a/.rej +++ /dev/null @@ -1,139 +0,0 @@ ---- 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/APRSCode.c.orig b/APRSCode.c.orig deleted file mode 100644 index b4ed594..0000000 --- a/APRSCode.c.orig +++ /dev/null @@ -1,9223 +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 -*/ - -// 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 deleted file mode 100644 index 1137117..0000000 --- a/APRSCode.c.rej +++ /dev/null @@ -1,139 +0,0 @@ ---- 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/BPQChat.vcproj.NOTTSDESKTOP.John.user b/BPQChat.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index b627f78..0000000 --- a/BPQChat.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQChat.vcproj.SKIGACER.johnw.user b/BPQChat.vcproj.SKIGACER.johnw.user deleted file mode 100644 index bbece07..0000000 --- a/BPQChat.vcproj.SKIGACER.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQINP3.c b/BPQINP3.c index 38c49b9..dcc17c6 100644 --- a/BPQINP3.c +++ b/BPQINP3.c @@ -932,7 +932,7 @@ int SendRIPTimer() // Delay more if Locked - they could be retrying for a long time - if ((Route->NEIGHBOUR_FLAG & 1)) // LOCKED ROUTE + if ((Route->NEIGHBOUR_FLAG)) // LOCKED ROUTE INP3Delay = 1200; else INP3Delay = 600; diff --git a/BPQMail.c b/BPQMail.c index f566d64..a0971d9 100644 --- a/BPQMail.c +++ b/BPQMail.c @@ -1147,6 +1147,7 @@ // Send forwarding info to packetnodes.spots.radio database (51) // Fix bug in WP Message processing (56) // Fix treating addresses ending in WW as Internet (57) +// Run sending to packetnodes.spots.radio in a separate thread (61) #include "bpqmail.h" #include "winstdint.h" diff --git a/BPQMail.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/BPQMail.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index bed4096..0000000 --- a/BPQMail.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQMail.vcproj.NOTTSDESKTOP.John.user b/BPQMail.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index fa82c00..0000000 --- a/BPQMail.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQMail.vcproj.SKIGACER.johnw.user b/BPQMail.vcproj.SKIGACER.johnw.user deleted file mode 100644 index bbece07..0000000 --- a/BPQMail.vcproj.SKIGACER.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQMail.vcxproj.filters b/BPQMail.vcxproj.filters deleted file mode 100644 index 8025626..0000000 --- a/BPQMail.vcxproj.filters +++ /dev/null @@ -1,113 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index bed4096..0000000 --- a/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user b/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index fa82c00..0000000 --- a/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/Bpq32.c b/Bpq32.c index b6acf29..b515b8a 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1243,12 +1243,12 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Fix MailAPI msgs endpoint // Attempt to fix NC going to wrong application. (57) // Improve ARDOP end of session code (58) -// Run M0LTE Map repoorting in a separate thread (59) -// Add support fro WhatsPac (59) -// Add timestamps to LIS monitor - - - +// Run M0LTE Map reporting in a separate thread (59/60) +// Add support for WhatsPac (59) +// Add timestamps to LIS monitor (60) +// Fix problem with L4 frames being delivered out of sequence (60) +// Add Compression of Netrom connections (62) +// Improve handling of Locked Routes (62) #define CKernel diff --git a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index fa74d31..0000000 --- a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.NOTTSDESKTOP.John.user b/CBPQ32.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index 270b67b..0000000 --- a/CBPQ32.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.SKIGACER.johnw.user b/CBPQ32.vcproj.SKIGACER.johnw.user deleted file mode 100644 index 6aa33d1..0000000 --- a/CBPQ32.vcproj.SKIGACER.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcxproj.filters b/CBPQ32.vcxproj.filters deleted file mode 100644 index 7c08db6..0000000 --- a/CBPQ32.vcxproj.filters +++ /dev/null @@ -1,228 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Header Files - - - Header Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/Cmd.c b/Cmd.c index c5f43dd..8973d72 100644 --- a/Cmd.c +++ b/Cmd.c @@ -1516,7 +1516,7 @@ VOID CMDP00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct C char * DisplayRoute(TRANSPORTENTRY * Session, char * Bufferptr, struct ROUTE * Routes, char Verbose) { char Normcall[10]; - char locked[] = " ! "; + char locked[4] = " "; int NodeCount; int Percent = 0; char PercentString[20]; @@ -1530,11 +1530,16 @@ char * DisplayRoute(TRANSPORTENTRY * Session, char * Bufferptr, struct ROUTE * Normcall[9]=0; - if ((Routes->NEIGHBOUR_FLAG & 1) == 1) + if (Routes->NEIGHBOUR_FLAG == LOCKEDBYCONFIG) strcpy(locked, "!"); + else if (Routes->NEIGHBOUR_FLAG == LOCKEDBYSYSOP) + strcpy(locked, "!!"); + else if (Routes->NEIGHBOUR_FLAG == LOCKEDBYSYSOP + LOCKEDBYCONFIG) + strcpy(locked, "!!!"); else strcpy(locked, " "); + NodeCount = COUNTNODES(Routes); if (Routes->NEIGHBOUR_LINK && Routes->NEIGHBOUR_LINK->L2STATE >= 5) @@ -1678,7 +1683,7 @@ ROUTEUPDATE: { // Toggle Lock - Routes->NEIGHBOUR_FLAG ^= 1; // FLIP LOCKED BIT + Routes->NEIGHBOUR_FLAG ^= LOCKEDBYSYSOP; // FLIP LOCKED BIT goto Displayit; } @@ -1697,7 +1702,7 @@ ROUTEUPDATE: { // Toggle Lock - Routes->NEIGHBOUR_FLAG ^= 1; // FLIP LOCKED BIT + Routes->NEIGHBOUR_FLAG ^= LOCKEDBYSYSOP; // FLIP LOCKED BIT goto Displayit; } } @@ -1711,167 +1716,6 @@ Displayit: 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)); diff --git a/CommonCode.c b/CommonCode.c index f1cd059..cb5c0b7 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -2687,6 +2687,14 @@ int DoRoutes() { if (Routes->NEIGHBOUR_CALL[0] != 0) { + // Dont save routes from config file here or they are diccicult to get rid of + + if (Routes->NEIGHBOUR_FLAG & LOCKEDBYCONFIG) + { + Routes++; + continue; + } + len=ConvFromAX25(Routes->NEIGHBOUR_CALL,Normcall); Normcall[len]=0; @@ -2710,7 +2718,7 @@ int DoRoutes() digis[0] = 0; len=sprintf(line, - "ROUTE ADD %s %d %d %s %d %d %d %d %d\n", + "ROUTE ADD %s %d %d %s %d %d %d %d %d %c\n", Normcall, Routes->NEIGHBOUR_PORT, Routes->NEIGHBOUR_QUAL, digis, @@ -2718,7 +2726,8 @@ int DoRoutes() Routes->NBOUR_FRACK, Routes->NBOUR_PACLEN, Routes->INP3Node | (Routes->NoKeepAlive << 2), - Routes->OtherendsRouteQual); + Routes->OtherendsRouteQual, + (Routes->NEIGHBOUR_FLAG & LOCKEDBYSYSOP)?'!':' '); fputs(line, file); } diff --git a/FormatHTML.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/FormatHTML.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index bed4096..0000000 --- a/FormatHTML.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/HTTPcode.c b/HTTPcode.c index b19883b..74aff73 100644 --- a/HTTPcode.c +++ b/HTTPcode.c @@ -145,7 +145,7 @@ char Tail[] = ""; char RouteHddr[] = "

Routes

" ""; -char RouteLine[] = ""; +char RouteLine[] = ""; char xNodeHddr[] = "
" "
PortCallQualityNode CountFrame CountRetriesPercentMaxframeFrackLast HeardQueuedRem Qual
%s%d%s%c%d%d%d%d%d%%d%d%02d:%02d%d%d
%s%d%s%s%d%d%d%d%d%%d%d%02d:%02d%d%d
" "
" @@ -3798,7 +3798,7 @@ doHeader: int MaxRoutes = MAXNEIGHBOURS; int count; char Normcall[10]; - char locked; + char locked[4] = " "; int NodeCount; int Percent = 0; int Iframes, Retries; @@ -3814,10 +3814,14 @@ doHeader: int len = ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall); Normcall[len]=0; - if ((Routes->NEIGHBOUR_FLAG & 1) == 1) - locked = '!'; + if (Routes->NEIGHBOUR_FLAG == LOCKEDBYCONFIG) + strcpy(locked, "!"); + else if (Routes->NEIGHBOUR_FLAG == LOCKEDBYSYSOP) + strcpy(locked, "!!"); + else if (Routes->NEIGHBOUR_FLAG == LOCKEDBYSYSOP + LOCKEDBYCONFIG) + strcpy(locked, "!!!"); else - locked = ' '; + strcpy(locked, " "); NodeCount = COUNTNODES(Routes); diff --git a/L2Code.c b/L2Code.c index 3cac44d..f4c83e5 100644 --- a/L2Code.c +++ b/L2Code.c @@ -759,7 +759,7 @@ VOID L2FORUS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buff NO_CTEXT = 1; - if (ROUTE->NEIGHBOUR_FLAG == 1 && ROUTE->NEIGHBOUR_QUAL == 0) // Locked, qual 0 + if (ROUTE->NEIGHBOUR_FLAG && ROUTE->NEIGHBOUR_QUAL == 0) // Locked, qual 0 { ReleaseBuffer(Buffer); return; diff --git a/L3Code.c b/L3Code.c index 0acd2f2..b4f3d65 100644 --- a/L3Code.c +++ b/L3Code.c @@ -319,13 +319,13 @@ VOID PROCESSNODEMESSAGE(MESSAGE * Msg, struct PORTCONTROL * PORT) // if locked route with quality zero ignore - if ((ROUTE->NEIGHBOUR_FLAG & 1)) // LOCKED ROUTE + if ((ROUTE->NEIGHBOUR_FLAG)) // LOCKED ROUTE if (ROUTE->NEIGHBOUR_QUAL == 0) return; // If Ignoreunlocked set, ignore it not locked - if ((ROUTE->NEIGHBOUR_FLAG & 1) == 0) // LOCKED ROUTE + if ((ROUTE->NEIGHBOUR_FLAG) == 0) // LOCKED ROUTE if (PORT->IgnoreUnlocked) return; @@ -333,7 +333,7 @@ VOID PROCESSNODEMESSAGE(MESSAGE * Msg, struct PORTCONTROL * PORT) // if not locked, update route quality from port quality (may have changed config and not cleared SAVENODES - if ((ROUTE->NEIGHBOUR_FLAG & 1) == 0) // Not LOCKED ROUTE + if (ROUTE->NEIGHBOUR_FLAG == 0) // Not LOCKED ROUTE ROUTE->NEIGHBOUR_QUAL = PORT->PORTQUALITY; // GET TIME FROM BIOS DATA AREA OR RTC @@ -1038,7 +1038,7 @@ VOID L3TimerProc() { ROUTE++; - if (ROUTE->NEIGHBOUR_FLAG & 1) // Locked? + if (ROUTE->NEIGHBOUR_FLAG) // Locked? continue; if (ROUTE->NEIGHBOUR_LINK) // Has an active Session diff --git a/L4Code.c b/L4Code.c index 17239fb..349e975 100644 --- a/L4Code.c +++ b/L4Code.c @@ -76,6 +76,8 @@ extern BOOL LogL4Connects; extern BOOL LogAllConnects; extern int L4Compress; +extern int L4CompMaxframe; +extern int L4CompPaclen; // L4 Flags Values @@ -350,6 +352,11 @@ VOID SENDL4MESSAGE(TRANSPORTENTRY * L4, struct DATAMESSAGE * Msg) L3MSG->L4FLAGS |= L4COMP; Msg->PID = 0xF0; } + else if (Msg->PID == 0xF2) // Compressed Message - More to come + { + L3MSG->L4FLAGS |= (L4COMP | L4MORE); + Msg->PID = 0xF0; + } L4->L4TIMER = L4->SESSIONT1; // SET TIMER L4->L4ACKREQ = 0; // CANCEL ACK NEEDED @@ -513,6 +520,53 @@ void RETURNEDTONODE(TRANSPORTENTRY * Session) extern void * BUFFER; +void sendChunk(TRANSPORTENTRY * L4, unsigned char * Compressed, int complen, int savePort) +{ + unsigned char * compdata; + struct DATAMESSAGE * Msg; + int sendLen = complen; + int fragments; + + L4->SentAfterCompression += complen; + + if (complen > L4CompPaclen) + { + fragments = (complen / L4CompPaclen); // Split to roughly equal sized fraagments + + if (fragments * L4CompPaclen != complen) + fragments++; + + sendLen = (complen / fragments) + 1; + } + + compdata = Compressed; + + while (complen > 0) + { + int PID = 0xF1; + + if (complen > sendLen) + PID = 0xF2; // More to come + + Msg = GetBuff(); + + if (!Msg) + return; + + Msg->PORT = savePort; + + memcpy(Msg->L2DATA, compdata, sendLen); + Msg->LENGTH = sendLen + MSGHDDRLEN + 1; // 1 for pid field + Msg->PID = PID; // Not sent so use as a flag for compressed msg + + compdata += sendLen; + complen -= sendLen; + + SENDL4MESSAGE(L4, Msg); + ReleaseBuffer(Msg); + } +} + VOID L4BG() { // PROCESS DATA QUEUED ON SESSIONS @@ -613,41 +667,144 @@ VOID L4BG() { int complen = 0; unsigned char * Compressed; + int dataLen; + int savePort = Msg->PORT; + int maxCompSendLen; + + // Save first packet, then see if more on TX_Q + + L4->toCompress = malloc(8192); + L4->toCompressLen = 0; + + dataLen = Msg->LENGTH - MSGHDDRLEN - 1; // No header or pid + + L4->Sent += dataLen; + + memcpy(&L4->toCompress[L4->toCompressLen], Msg->L2DATA, dataLen); + L4->toCompressLen += dataLen; + + // See if first will compress. If not assume too short or already compressed data and just send + + Compressed = Compressit(L4->toCompress, L4->toCompressLen, &complen); + + if (complen >= dataLen) + { + free(Compressed); + L4->SentAfterCompression += dataLen; + SENDL4MESSAGE(L4, Msg); + ReleaseBuffer(Msg); + free(L4->toCompress); + L4->toCompress = 0; + L4->toCompressLen = 0; + continue; + } + + // Worth compressing. Try to collect several packets - // if (L4->L4TX_Q) + if (L4->L4TX_Q == 0) { - // Collect the data from L4TX_Q + // no more, so just send the stuff we've just compressed. Compressed data will fit in input packet + +// Debugprintf("%d %d %d%%", L4->toCompressLen, complen, ((L4->toCompressLen - complen) * 100) / L4->toCompressLen); + + memcpy(Msg->L2DATA, Compressed, complen); + + Msg->PID = 0xF1; // Compressed + Msg->LENGTH = complen + MSGHDDRLEN + 1; // 1 for pid field - int dataLen; + L4->SentAfterCompression += complen; + SENDL4MESSAGE(L4, Msg); + ReleaseBuffer(Msg); + + free(L4->toCompress); + L4->toCompressLen = 0; + L4->toCompress = 0; + free(Compressed); + continue; + } - // L4->toCompress = malloc(8192); - // L4->toCompressLen = 0; + free(Compressed); + ReleaseBuffer(Msg); // Not going to use it + while (L4->L4TX_Q && L4->toCompressLen < (8192 - 256)) // Make sure can't overrin buffer + { + // Collect the data from L4TX_Q + + Msg = Q_REM((void *)&L4->L4TX_Q); dataLen = Msg->LENGTH - MSGHDDRLEN - 1; // No header or pid + L4->Sent += dataLen; + + memcpy(&L4->toCompress[L4->toCompressLen], Msg->L2DATA, dataLen); + L4->toCompressLen += dataLen; - // memcpy(&L4->toCompress[L4->toCompressLen], Msg->L2DATA, dataLen); - // L4->toCompressLen += dataLen; + ReleaseBuffer(Msg); + } - Msg->L2DATA[dataLen] = 0; + L4->toCompress[L4->toCompressLen] = 0; - Compressed = Compressit(Msg->L2DATA, dataLen, &complen); - Debugprintf("%d %d %d%% %s", dataLen, complen, ((dataLen - complen) * 100) / dataLen, Msg->L2DATA); + Compressed = Compressit(L4->toCompress, L4->toCompressLen, &complen); +// Debugprintf("%d %d %d%%", L4->toCompressLen, complen, ((L4->toCompressLen - complen) * 100) / L4->toCompressLen); + + // Send compressed - if (complen < dataLen) + // Fragment if more than L4CompPaclen + + // Entered with original first fragment in saveMsg; + + // Check for too big a compressed frame size. Bigger compresses better but adds latency to link + + maxCompSendLen = L4CompPaclen * L4CompMaxframe; + + if (complen > maxCompSendLen) + { + // Too Much Data. Needs to recompress less. To avoid too many recompresses be a bit conservative in calulating max size + // to allow for a bit less compression of part of data. Getting it wrong isn't fatal as sending more than optimum isn't fatal + + int Fragments; + int ChunkSize; + unsigned char * CompressPtr = L4->toCompress; + int bytesleft = L4->toCompressLen; + + // Assume 10% worse compression on smaller input + + int j = (complen * 11) / 10; // New Comp size + + Fragments = j / maxCompSendLen; + Fragments++; + ChunkSize = (L4->toCompressLen / Fragments) + 1; // 1 for rounding + + while (bytesleft > 0) { - // Send compressed + int Len = bytesleft; + if (Len > ChunkSize) + Len = ChunkSize; + + free (Compressed); + Compressed = Compressit(CompressPtr, Len, &complen); +// Debugprintf("Chunked %d %d %d%%", Len, complen, ((Len - complen) * 100) / Len); - memcpy(Msg->L2DATA, Compressed, complen); - Msg->LENGTH = complen + MSGHDDRLEN + 1; // 1 for pid field - Msg->PID = 0xF1; // Not sent so use as a flag for compressed msg + sendChunk(L4, Compressed, complen, savePort); + + CompressPtr += Len; + bytesleft -= Len; } - free(Compressed); } + else + sendChunk(L4, Compressed, complen,savePort); + + free(L4->toCompress); + L4->toCompressLen = 0; + L4->toCompress = 0; + free(Compressed); + } + else + { + // Compression Disabled + + SENDL4MESSAGE(L4, Msg); + ReleaseBuffer(Msg); } - - SENDL4MESSAGE(L4, Msg); - ReleaseBuffer(Msg); continue; } @@ -756,12 +913,35 @@ VOID CLEARSESSIONENTRY(TRANSPORTENTRY * Session) Session->L4RESEQ_Q = 0; } + // if compressed session display stats + + if (Session->Sent && Session->Received) + { + char SRCE[10]; + char TO[10]; + + struct DEST_LIST * DEST = Session->L4TARGET.DEST; + + SRCE[ConvFromAX25(Session->L4MYCALL, SRCE)] = 0; + TO[ConvFromAX25(DEST->DEST_CALL, TO)] = 0; + + Debugprintf("L4 Compression Stats %s %s TX %d %d %d%% RX %d %d %d%%", SRCE, TO, + Session->Sent, Session->SentAfterCompression, ((Session->Sent - Session->SentAfterCompression) * 100) / Session->Sent, + Session->Received, Session->ReceivedAfterExpansion, ((Session->ReceivedAfterExpansion - Session->Received) * 100) / Session->Received); + } + while (Session->L4RESEQ_Q) ReleaseBuffer(Q_REM((void *)&Session->L4RESEQ_Q)); if (Session->PARTCMDBUFFER) ReleaseBuffer(Session->PARTCMDBUFFER); + if (Session->toCompress) + free(Session->toCompress); + + if (Session->unCompress) + free(Session->unCompress); + memset(Session, 0, sizeof(TRANSPORTENTRY)); } @@ -953,10 +1133,14 @@ VOID L4TimerProc() L4->STAYFLAG = 0; Partner = L4->L4CROSSLINK; + CLOSECURRENTSESSION(L4); if (Partner) { + // if compressed session display stats + + Partner->L4KILLTIMER = 0; //ITS TIMES IS ALSO ABOUT TO EXPIRE CLOSECURRENTSESSION(Partner); // CLOSE THIS ONE } @@ -1031,6 +1215,8 @@ VOID L4TIMEOUT(TRANSPORTENTRY * L4) { // RETRIED N2 TIMES - FAIL LINK + // if compressed session display stats + CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT) return; } @@ -1303,6 +1489,7 @@ VOID SENDL4DISC(TRANSPORTENTRY * Session) MSG->LENGTH = (int)(&MSG->L4DATA[0] - (UCHAR *)MSG); C_Q_ADD(&DEST->DEST_Q, (UINT *)MSG); + } @@ -1662,11 +1849,10 @@ VOID SETUPNEWCIRCUIT(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, // 40 bit of 2nd byte is Compress Flag - if (BPQPARAMS[1] & 0x40) - { + if (BPQPARAMS[1] & 0x40 && L4Compress) L4->AllowCompress = 1; - BPQPARAMS[1] &= 0xf; // Only bottom bit is significant in Timeeout field - } + + BPQPARAMS[1] &= 0xf; // Only bottom bit is significant in Timeeout field } L4->L4CIRCUITTYPE = SESSION | UPLINK; @@ -2051,27 +2237,120 @@ L4INFO_OK: // if compressed, expand - if (L3MSG->L4FLAGS & L4COMP) + if ((L3MSG->L4FLAGS & L4COMP) == 0) { - char Buffer[512]; + // Not Compressed + + L4->Received += L3MSG->LENGTH - MSGHDDRLEN - 1; + L4->ReceivedAfterExpansion += L3MSG->LENGTH - MSGHDDRLEN - 1; + + memmove(L3MSG->L3SRCE, L3MSG->L4DATA, L3MSG->LENGTH - (4 + sizeof(void *))); + IFRM150(L4, (PDATAMESSAGE)L3MSG); // CHECK IF SETTING UP AND PASS ON + } + else + { + char Buffer[8192]; int Len; int outLen; - - Len = doinflate(L3MSG->L4DATA, Buffer, L3MSG->LENGTH - MSGHDDRLEN - 1, 512, &outLen); + int sendLen; + char * sendptr; + int savePort = L3MSG->Port; - memcpy(L3MSG->L4DATA, Buffer, outLen); - L3MSG->LENGTH = outLen + MSGHDDRLEN + 1; - } + // May be more thsn one packet - memmove(L3MSG->L3SRCE, L3MSG->L4DATA, L3MSG->LENGTH - (4 + sizeof(void *))); + Len = L3MSG->LENGTH - MSGHDDRLEN - 1; - REFRESHROUTE(L4); + L4->Received += Len; + + if (L3MSG->L4FLAGS & L4MORE) + { + if (L4->unCompressLen == 0) + { + // New packet + + L4->unCompress = malloc(8192); + } + + // Save data + + memcpy(&L4->unCompress[L4->unCompressLen], L3MSG->L4DATA, Len); + L4->unCompressLen += Len; + + ReleaseBuffer(L3MSG); + goto checkReseq; + } + + if (L4->unCompressLen) + { + // Already have some data - add this to it + + memcpy(&L4->unCompress[L4->unCompressLen], L3MSG->L4DATA, Len); + L4->unCompressLen += Len; + + Len = doinflate(L4->unCompress, Buffer, L4->unCompressLen, 8192, &outLen); + } + + else + { + // Just inflate this bit + + Len = doinflate(L3MSG->L4DATA, Buffer, L3MSG->LENGTH - MSGHDDRLEN - 1, 8192, &outLen); + } + + free(L4->unCompress); + L4->unCompress = 0; + L4->unCompressLen = 0; + + sendLen = outLen; + sendptr = Buffer; + + L4->ReceivedAfterExpansion += outLen; + + // Send first bit in input buffer. If still some left get new buffers for it + + if (sendLen > 236) + sendLen = 236; + + memcpy(L3MSG->L3SRCE, sendptr, sendLen); // Converting to DATAMESSAGE format + L3MSG->LENGTH = sendLen + MSGHDDRLEN + 1; + + IFRM150(L4, (PDATAMESSAGE)L3MSG); // CHECK IF SETTING UP AND PASS ON + + outLen -= sendLen; + sendptr += sendLen; + + while (outLen > 0) + { + sendLen = outLen; + + if (sendLen > 236) + sendLen = 236; + + Msg = GetBuff(); + + if (Msg) + { + // Just ignore if no buffers - shouldn't happen + + Msg->PID = 240; + Msg->PORT = savePort; + memcpy(Msg->L2DATA, sendptr, sendLen); + Msg->LENGTH = sendLen + MSGHDDRLEN + 1; + + IFRM150(L4, Msg); // CHECK IF SETTING UP AND PASS ON + } + + outLen -= sendLen; + sendptr += sendLen; + } + } L4->L4ACKREQ = L4DELAY; // SEND INFO ACK AFTER L4DELAY (UNLESS I FRAME SENT) + REFRESHROUTE(L4); - IFRM150(L4, (PDATAMESSAGE)L3MSG); // CHECK IF SETTING UP AND PASS ON // See if anything on reseq Q to process +checkReseq: if (L4->L4RESEQ_Q == 0) return; @@ -2163,10 +2442,13 @@ VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR) 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 + if (RTT < 180) // Sanity Check + { + if (DEST->DEST_RTT == 0) + DEST->DEST_RTT = RTT; + else + DEST->DEST_RTT = ((DEST->DEST_RTT * 9) + RTT) /10; // 90% Old + New + } } } diff --git a/MailNode.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/MailNode.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index bed4096..0000000 --- a/MailNode.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/MailNode.vcproj.NOTTSDESKTOP.John-skigdebian-2.user b/MailNode.vcproj.NOTTSDESKTOP.John-skigdebian-2.user deleted file mode 100644 index fa82c00..0000000 --- a/MailNode.vcproj.NOTTSDESKTOP.John-skigdebian-2.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/MailNode.vcproj.NOTTSDESKTOP.John.user b/MailNode.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index c98c2c9..0000000 --- a/MailNode.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/MailNode.vcxproj.filters b/MailNode.vcxproj.filters deleted file mode 100644 index d32f45b..0000000 --- a/MailNode.vcxproj.filters +++ /dev/null @@ -1,327 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - \ No newline at end of file diff --git a/RHP.c b/RHP.c index b9ff0d6..f86fed1 100644 --- a/RHP.c +++ b/RHP.c @@ -312,7 +312,7 @@ void ProcessRHPWebSock(SOCKET Socket, char * Msg, int MsgLen) return; } - Debugprintf(Msg); + Debugprintf("Unrecognised RHP Message - %s", Msg); } void ProcessRHPWebSockClosed(SOCKET socket) @@ -496,12 +496,9 @@ int processRHCPSend(SOCKET Socket, char * Msg, char * ReplyBuffer) ptr++; } - Debugprintf(Data); - Len = strlen(Data); ptr = Data; - while (Len > RHPPaclen) { SendMsg(RHPSession->BPQStream, ptr, RHPPaclen); diff --git a/Versions.h b/Versions.h index c4d385a..d0a9895 100644 --- a/Versions.h +++ b/Versions.h @@ -10,8 +10,8 @@ #endif -#define KVers 6,0,24,61 -#define KVerstring "6.0.24.61\0" +#define KVers 6,0,24,62 +#define KVerstring "6.0.24.62\0" #ifdef CKernel diff --git a/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user b/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index fa82c00..0000000 --- a/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index bed4096..0000000 --- a/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/WinmorControl.vcproj.NOTTSDESKTOP.John.user b/WinmorControl.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index fa82c00..0000000 --- a/WinmorControl.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/asmstrucs.h b/asmstrucs.h index 48fcde2..2ae6907 100644 --- a/asmstrucs.h +++ b/asmstrucs.h @@ -178,6 +178,16 @@ typedef struct _TRANSPORTENTRY unsigned char * toCompress; // Data being saved to compress int toCompressLen; + unsigned char * unCompress; // Data being saved to uncompress + int unCompressLen; + + int Sent; + int SentAfterCompression; + + int Received; + int ReceivedAfterExpansion; + + } TRANSPORTENTRY; // @@ -203,6 +213,9 @@ typedef struct ROUTE UCHAR NEIGHBOUR_QUAL; UCHAR NEIGHBOUR_FLAG; // SET IF 'LOCKED' ROUTE +#define LOCKEDBYCONFIG 1 +#define LOCKEDBYSYSOP 2 + struct _LINKTABLE * NEIGHBOUR_LINK; // POINTER TO LINK FOR THIS NEIGHBOUR USHORT NEIGHBOUR_TIME; // TIME LAST HEARD (HH MM) @@ -453,7 +466,8 @@ typedef struct NR_DEST_ROUTE_ENTRY struct ROUTE * ROUT_NEIGHBOUR; // POINTER TO NEXT NODE IN PATH UCHAR ROUT_QUALITY; // QUALITY UCHAR ROUT_OBSCOUNT; - UCHAR Padding[5]; // SO Entries are the same length + UCHAR ROUT_LOCKED; + UCHAR Padding[4]; // SO Entries are the same length } *PNR_DEST_ROUTE_ENTRY; typedef struct DEST_ROUTE_ENTRY @@ -475,12 +489,12 @@ typedef struct DEST_LIST UCHAR DEST_ALIAS[6]; UCHAR DEST_STATE; // CONTROL BITS - SETTING UP, ACTIVE ETC + UCHAR DEST_LOCKED; UCHAR DEST_ROUTE; // CURRENTY ACTIVE DESTINATION UCHAR INP3FLAGS; struct NR_DEST_ROUTE_ENTRY NRROUTE[3];// Best 3 NR neighbours for this dest - struct DEST_ROUTE_ENTRY ROUTE[3]; // Best 3 INP neighbours for this dest void * DEST_Q; // QUEUE OF FRAMES FOR THIS DESTINATION diff --git a/cMain.c b/cMain.c index 0b7435a..9845900 100644 --- a/cMain.c +++ b/cMain.c @@ -140,6 +140,9 @@ int NODE = 1; // INCLUDE SWITCH SUPPORT int FULL_CTEXT = 1; // CTEXT ON ALL CONNECTS IF NZ int L4Compress = 0; +int L4CompMaxframe = 3; +int L4CompPaclen = 236; + BOOL LogL4Connects = FALSE; BOOL LogAllConnects = FALSE; BOOL AUTOSAVEMH = TRUE; @@ -824,6 +827,14 @@ BOOL Start() strcpy(MQTT_USER, cfg->C_MQTT_USER); strcpy(MQTT_PASS, cfg->C_MQTT_PASS); L4Compress = cfg->C_L4Compress; + L4CompMaxframe = cfg->C_L4CompMaxframe; + L4CompPaclen = cfg->C_L4CompPaclen; + + if (L4CompMaxframe < 1 || L4CompMaxframe > 16) + L4CompMaxframe = 3; + + if (L4CompPaclen < 64 || L4CompPaclen > 236) + L4CompPaclen = 236; // Get pointers to PASSWORD and APPL1 commands @@ -1340,7 +1351,7 @@ BOOL Start() ROUTE->NBOUR_PACLEN = Rcfg->ppacl; ROUTE->OtherendsRouteQual = ROUTE->OtherendLocked = Rcfg->farQual; - ROUTE->NEIGHBOUR_FLAG = 1; // Locked + ROUTE->NEIGHBOUR_FLAG = LOCKEDBYCONFIG; // Locked Rcfg++; ROUTE++; @@ -1845,12 +1856,11 @@ VOID ReadNodes() if (ptr == NULL) continue; // I don't thinlk we should load locked flag from save file - only from config - - // But need to parse it until I stop saving it + // Now (2025) have two locked flags, from config or by sysop. Latter is saved and restored if (ptr[0] == '!') { -// ROUTE->NEIGHBOUR_FLAG = 1; // LOCKED ROUTE + ROUTE->NEIGHBOUR_FLAG = LOCKEDBYSYSOP; // LOCKED ROUTE ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; } @@ -1867,7 +1877,7 @@ VOID ReadNodes() memcpy(ROUTE->NEIGHBOUR_DIGI1, axcall, 7); - ROUTE->NEIGHBOUR_FLAG = 1; // LOCKED ROUTE - Digi'ed routes must be locked + ROUTE->NEIGHBOUR_FLAG = LOCKEDBYSYSOP; // LOCKED ROUTE - Digi'ed routes must be locked ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; @@ -1923,6 +1933,14 @@ VOID ReadNodes() if (ROUTE->NEIGHBOUR_FLAG == 0 || ROUTE->OtherendLocked == 0); // Not LOCKED ROUTE ROUTE->OtherendsRouteQual = atoi(ptr); + ptr = strtok_s(NULL, seps, &Context); // INP3 + if (ptr == NULL) continue; + + if (ptr[0] == '!') + { + ROUTE->NEIGHBOUR_FLAG = LOCKEDBYSYSOP; // LOCKED ROUTE + ptr = strtok_s(NULL, seps, &Context); + } continue; } diff --git a/config.c b/config.c index 10ce16a..8ca9b68 100644 --- a/config.c +++ b/config.c @@ -307,7 +307,8 @@ static char *keywords[] = "APPL5QUAL", "APPL6QUAL", "APPL7QUAL", "APPL8QUAL", "BTEXT:", "NETROMCALL", "C_IS_CHAT", "MAXRTT", "MAXHOPS", // IPGATEWAY= no longer allowed "LogL4Connects", "LogAllConnects", "SAVEMH", "ENABLEADIFLOG", "ENABLEEVENTS", "SAVEAPRSMSGS", -"EnableM0LTEMap", "MQTT", "MQTT_HOST", "MQTT_PORT", "MQTT_USER", "MQTT_PASS", "L4Compress" +"EnableM0LTEMap", "MQTT", "MQTT_HOST", "MQTT_PORT", "MQTT_USER", "MQTT_PASS", +"L4Compress", "L4CompMaxframe", "L4CompPaclen" }; /* parameter keywords */ static void * offset[] = @@ -328,7 +329,8 @@ static void * offset[] = &xxcfg.C_APPL[4].ApplQual, &xxcfg.C_APPL[5].ApplQual, &xxcfg.C_APPL[6].ApplQual, &xxcfg.C_APPL[7].ApplQual, &xxcfg.C_BTEXT, &xxcfg.C_NETROMCALL, &xxcfg.C_C, &xxcfg.C_MAXRTT, &xxcfg.C_MAXHOPS, // IPGATEWAY= no longer allowed &xxcfg.C_LogL4Connects, &xxcfg.C_LogAllConnects, &xxcfg.C_SaveMH, &xxcfg.C_ADIF, &xxcfg.C_EVENTS, &xxcfg.C_SaveAPRSMsgs, -&xxcfg.C_M0LTEMap, &xxcfg.C_MQTT, &xxcfg.C_MQTT_HOST, &xxcfg.C_MQTT_PORT, &xxcfg.C_MQTT_USER, &xxcfg.C_MQTT_PASS, &xxcfg.C_L4Compress}; /* offset for corresponding data in config file */ +&xxcfg.C_M0LTEMap, &xxcfg.C_MQTT, &xxcfg.C_MQTT_HOST, &xxcfg.C_MQTT_PORT, &xxcfg.C_MQTT_USER, &xxcfg.C_MQTT_PASS, +&xxcfg.C_L4Compress, &xxcfg.C_L4CompMaxframe, &xxcfg.C_L4CompPaclen}; /* offset for corresponding data in config file */ static int routine[] = { @@ -348,7 +350,8 @@ static int routine[] = 14, 14 ,14, 14, 15, 0, 2, 9, 9, 2, 2, 1, 2, 2, 2, -2, 2, 0, 1, 20, 20, 1} ; // Routine to process param +2, 2, 0, 1, 20, 20, +1, 1, 1} ; // Routine to process param int PARAMLIM = sizeof(routine)/sizeof(int); //int NUMBEROFKEYWORDS = sizeof(routine)/sizeof(int); @@ -615,6 +618,10 @@ BOOL ProcessConfig() paramok[83]=1; // MQTT Params paramok[84]=1; // MQTT Params paramok[85]=1; // MQTT Params + paramok[86]=1; // L4Compress + paramok[87]=1; // L4Compress Maxframe + paramok[88]=1; // L4Compress Paclen + for (i=0; i < PARAMLIM; i++) { diff --git a/configstructs.h b/configstructs.h index d6e8b50..a7e51a8 100644 --- a/configstructs.h +++ b/configstructs.h @@ -171,7 +171,10 @@ struct CONFIGTABLE char C_MQTT_USER[80]; char C_MQTT_PASS[80]; int C_L4Compress; - + int C_L4CompMaxframe; + int C_L4CompPaclen; + + //#define ApplOffset 80000 // Applications offset in config buffer //#define InfoOffset 85000 // Infomsg offset in buffer //#define InfoMax 2000 // Max Info