From c858986248f9ee86835be732f413824c0e42d729 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Tue, 25 Feb 2025 09:32:57 +0000 Subject: [PATCH] New upstream version 6.0.24.65+repack --- .rej | 139 - 6pack.c | 5 +- AEAPactor.c | 5 +- APRSCode.c.orig | 9223 --------------------------------------- APRSCode.c.rej | 139 - ARDOP.c | 20 +- BPQINP3.c | 2 +- BPQMail.c | 1 + Bpq32-skigdebian.c | 6741 ---------------------------- Bpq32.c | 15 +- Cmd.c | 191 +- CommonCode-skigdebian.c | 5647 ------------------------ CommonCode.c | 22 +- FLDigi.c | 3 +- FreeDATA.c | 4 +- HALDriver.c | 4 +- HFCommon.c | 3 +- HSMODEM.c | 4 +- HTTPcode-skigdebian.c | 5175 ---------------------- HTTPcode.c | 24 +- IPCode.c | 5 +- KAMPactor.c | 4 +- KISSHF.c | 4 +- L2Code.c | 2 +- L3Code.c | 8 +- L4Code.c | 553 ++- LinBPQ-skigdebian.c | 2154 --------- MULTIPSK.c | 2 +- Moncode.c | 7 + RHP-skigdebian.c | 641 --- RHP.c | 1467 ++++--- SCSPactor.c | 5 +- SCSTrackeMulti.c | 5 +- SCSTracker.c | 5 +- SerialPort.c | 4 +- TelnetV6-skigdebian.c | 7157 ------------------------------ TelnetV6.c | 71 +- UIARQ.c | 2 +- UZ7HODrv.c | 2 +- V4.c | 4 +- VARA.c | 43 +- Versions-skigdebian.h | 125 - Versions.h | 4 +- WINMOR.c | 4 +- WinRPR.c | 5 +- asmstrucs.h | 28 +- cMain-skigdebian.c | 2788 ------------ cMain.c | 33 +- cheaders.h | 901 ++-- config.c | 16 +- configstructs.h | 6 +- mailapi.c | 7 + makefile~ | 43 - nodeapi-skigdebian.c | 858 ---- nodeapi.c | 57 +- tncinfo.h | 5 +- 56 files changed, 2003 insertions(+), 42389 deletions(-) delete mode 100644 .rej delete mode 100644 APRSCode.c.orig delete mode 100644 APRSCode.c.rej delete mode 100644 Bpq32-skigdebian.c delete mode 100644 CommonCode-skigdebian.c delete mode 100644 HTTPcode-skigdebian.c delete mode 100644 LinBPQ-skigdebian.c delete mode 100644 RHP-skigdebian.c delete mode 100644 TelnetV6-skigdebian.c delete mode 100644 Versions-skigdebian.h delete mode 100644 cMain-skigdebian.c delete mode 100644 makefile~ delete mode 100644 nodeapi-skigdebian.c 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/6pack.c b/6pack.c index 8f954d8..5557827 100644 --- a/6pack.c +++ b/6pack.c @@ -1412,10 +1412,11 @@ VOID * SIXPACKExtInit(EXTPORTDATA * PortEntry) TNC->sixPack = zalloc(sizeof(struct sixPackTNCInfo)); TNC->Port = port; - TNC->Hardware = H_SIXPACK; + TNC->PortRecord = PortEntry; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_SIXPACK; + TNC->ARDOPBuffer = malloc(8192); - TNC->PortRecord = PortEntry; if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); diff --git a/AEAPactor.c b/AEAPactor.c index 2d5af4b..bb7a8d4 100644 --- a/AEAPactor.c +++ b/AEAPactor.c @@ -382,7 +382,8 @@ VOID * AEAExtInit(EXTPORTDATA * PortEntry) TNC->Port = port; - TNC->Hardware = H_AEA; + TNC->PortRecord = PortEntry; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_AEA; TNC->TEXTMODE = FALSE; @@ -390,8 +391,6 @@ VOID * AEAExtInit(EXTPORTDATA * PortEntry) TNC->InitScript = _strupr(TNC->InitScript); - TNC->PortRecord = PortEntry; - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) { memcpy(TNC->NodeCall, MYNODECALL, 10); 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/ARDOP.c b/ARDOP.c index 4e4cc8d..8cae151 100644 --- a/ARDOP.c +++ b/ARDOP.c @@ -136,6 +136,7 @@ BOOL ARDOPStopPort(struct PORTCONTROL * PORT) if (TNC->Streams[0].Attached) TNC->Streams[0].ReportDISC = TRUE; + TNC->Streams[0].Connecting = 0; TNC->Streams[0].Connected = 0; TNC->Streams[0].Attached = 0; @@ -888,7 +889,8 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) if (TNC->SessionTimeLimit && STREAM->ConnectTime && time(NULL) > (TNC->SessionTimeLimit + STREAM->ConnectTime)) { ARDOPSendCommand(TNC, "DISCONNECT", TRUE); - STREAM->Disconnecting = TRUE; + STREAM->ReportDISC = 1; + STREAM->AttachTime = 0; } } @@ -1731,7 +1733,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) return TNC->CONNECTED << 8 | 1; return (TNC->CONNECTED << 8 | TNC->Streams[Stream].Disconnecting << 15); // OK - + case 4: // reinit7 @@ -1979,6 +1981,7 @@ VOID * ARDOPExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; + TNC->PortRecord = PortEntry; if (TNC->LogPath) ARDOPOpenLogFiles(TNC); @@ -1991,7 +1994,7 @@ VOID * ARDOPExtInit(EXTPORTDATA * PortEntry) if (TNC->ProgramPath) TNC->WeStartedTNC = RestartTNC(TNC); - TNC->Hardware = H_ARDOP; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_ARDOP; if (TNC->BusyWait == 0) TNC->BusyWait = 10; @@ -1999,7 +2002,6 @@ VOID * ARDOPExtInit(EXTPORTDATA * PortEntry) if (TNC->BusyHold == 0) TNC->BusyHold = 1; - TNC->PortRecord = PortEntry; if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); @@ -2282,11 +2284,11 @@ VOID TNCLost(struct TNCINFO * TNC) } if (STREAM->Attached) - { - STREAM->Connected = FALSE; - STREAM->Connecting = FALSE; STREAM->ReportDISC = TRUE; - } + + STREAM->Connected = FALSE; + STREAM->Connecting = FALSE; + } } @@ -3318,9 +3320,9 @@ VOID ARDOPProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) } } - if (_memicmp(Buffer, "DISCONNECTED", 12) == 0 || _memicmp(Buffer, "STATUS CONNECT TO", 17) == 0 + || _memicmp(Buffer, "STATUS END ARQ CALL", 19) == 0 || _memicmp(Buffer, "STATUS ARQ TIMEOUT FROM PROTOCOL STATE", 24) == 0 // || _memicmp(Buffer, "NEWSTATE DISC", 13) == 0 || _memicmp(Buffer, "ABORT", 5) == 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/Bpq32-skigdebian.c b/Bpq32-skigdebian.c deleted file mode 100644 index a78510b..0000000 --- a/Bpq32-skigdebian.c +++ /dev/null @@ -1,6741 +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 modifyextern int HTTP -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 -*/ -// -// 409l Oct 2001 Fix l3timeout for KISS -// -// 409m Oct 2001 Fix Crossband Digi -// -// 409n May 2002 Change error handling on load ext DLL - -// 409p March 2005 Allow Multidigit COM Ports (kiss.c) - -// 409r August 2005 Treat NULL string in Registry as use current directory -// Allow shutdown to close BPQ Applications - -// 409s October 2005 Add DLL:Export entries to API for BPQTNC2 - -// 409t January 2006 -// -// Add API for Perl "GetPerlMsg" -// Add API for BPQ1632 "GETBPQAPI" - returns address of Assembler API routine -// Add Registry Entry "BPQ Directory". If present, overrides "Config File Location" -// Add New API "GetBPQDirectory" - Returns location of config file -// Add New API "ChangeSessionCallsign" - equivalent to "*** linked to" command -// Rename BPQNODES to BPQNODES.dat -// New API "GetAttachedProcesses" - returns number of processes connected. -// Warn if user trys to close Console Window. -// Add Debug entries to record Process Attach/Detach -// Fix recovery following closure of first process - -// 409t Beta 2 February 2006 -// -// Add API Entry "GetPortNumber" -// -// 409u February 2006 -// -// Fix crash if allocate/deallocate called with stream=0 -// Add API to ch -// Display config file path -// Fix saving of Locked Node flag -// Added SAVENODES SYSOP command -// -// 409u 2 March 2006 -// -// Fix SetupBPQDirectory -// Add CopyBPQDirectory (for Basic Programs) -// -// 409u 3 March 2006 -// -// Release streams on DLL unload - -// 409v October 2006 -// -// Support Minimize to Tray for all BPQ progams -// Implement L4 application callsigns - -// 410 November 2006 -// -// Modified to compile with C++ 2005 Express Edition -// Make MCOM MTX MMASK local variables -// -// 410a January 2007 -// -// Add program name to Attach-Detach messages -// Attempt to detect processes which have died -// Fix bug in NETROM and IFrame decode which would cause crash if frame was corrupt -// Add BCALL - origin call for Beacons -// Fix KISS ACKMODE ACK processing -// - -// 410b November 2007 -// -// Allow CTEXT of up to 510, and enforce PACLEN, fragmenting if necessary - -// 410c December 2007 - -// Fix problem with NT introduced in V410a -// Display location of DLL on Console - -// 410d January 2008 - -// Fix crash in DLL Init caused by long path to program -// Invoke Appl2 alias on C command (if enabled) -// Allow C command to be disabled -// Remove debug trap in GETRAWFRAME -// Validate Alias of directly connected node, mainly for KPC3 DISABL Problem -// Move Port statup code out of DLLInit (mainly for perl) -// Changes to allow Load/Unload of bpq32.dll by appl -// CloseBPQ32 API added -// Ext Driver Close routes called -// Changes to release Mutex - -// 410e May 2008 - -// Fix missing SSID on last call of UNPROTO string (CONVTOAX25 in main.asm) -// Fix VCOM Driver (RX Len was 1 byte too long) -// Fix possible crash on L4CODE if L4DACK received out of sequence -// Add basic IP decoding - -// 410f October 2008 - -// Add IP Gateway -// Add Multiport DIGI capability -// Add GetPortDescription API -// Fix potential hangs if RNR lost -// Fix problem if External driver failes to load -// Put pushad/popad round _INITIALISEPORTS (main.asm) -// Add APIs GetApplCallVB and GetPortDescription (mainly for RMS) -// Ensure Route Qual is updated if Port Qual changed -// Add Reload Option, plus menu items for DUMP and SAVENODES - -// 410g December 2008 - -// Restore API Exports BPQHOSTAPIPTR and MONDECODEPTR (accidentally deleted) -// Fix changed init of BPQDirectory (accidentally changed) -// Fix Checks for lost processes (accidentally deleted) -// Support HDLC Cards on W2K and above -// Delete Tray List entries for crashed processes -// Add Option to NODES command to sort by Callsign -// Add options to save or clear BPQNODES before Reconfig. -// Fix Reconfig in Win98 -// Monitor buffering tweaks -// Fix Init for large (>64k) tables -// Fix Nodes count in Stats - -// 410h January 2009 - -// Add Start Minimized Option -// Changes to KISS for WIn98 Virtual COM -// Open \\.\com instead of //./COM -// Extra Dignostics - -// 410i Febuary 2009 - -// Revert KISS Changes -// Save Window positions - -// 410j June 2009 - -// Fix tidying of window List when program crashed -// Add Max Nodes to Stats -// Don't update APPLnALIAS with received NODES info -// Fix MH display in other timezones -// Fix Possible crash when processing NETROM type Zero frames (eg NRR) -// Basic INP3 Stuff -// Add extra diagnostics to Lost Process detection -// Process Netrom Record Route frames. - -// 410k June 2009 - -// Fix calculation of %retries in extended ROUTES display -// Fix corruption of ROUTES table - -// 410l October 2009 - -// Add GetVersionString API call. -// Add GetPortTableEntry API call -// Keep links to neighbouring nodes open - -// Build 2 - -// Fix PE in NOROUTETODEST (missing POP EBX) - -// 410m November 2009 - -// Changes for PACTOR and WINMOR to support the ATTACH command -// Enable INP3 if configured on a route. -// Fix count of nodes in Stats Display -// Overwrite the worst quality unused route if a call is received from a node not in your -// table when the table is full - -// Build 5 - -// Rig Control Interface -// Limit KAM VHF attach and RADIO commands to authorised programs (MailChat and BPQTerminal) - -// Build 6 - -// Fix reading INP3 Flag from BPQNODES - -// Build 7 - -// Add MAXHOPS and MAXRTT config options - -// Build 8 - -// Fix INP3 deletion of Application Nodes. -// Fix GETCALLSIGN for Pactor Sessions -// Add N Call* to display all SSID's of a call -// Fix flow control on Pactor sessions. - -// Build 9 - -// HDLC Support for XP -// Add AUTH routines - -// Build 10 - -// Fix handling commands split over more that one packet. - -// Build 11 - -// Attach cmd changes for winmor disconnecting state -// Option Interlock Winmor/Pactor ports - -// Build 12 - -// Add APPLS export for winmor -// Handle commands ending CR LF - -// Build 13 - -// Incorporate Rig Control in Kernel - -// Build 14 - -// Fix config reload for Rig COntrol - -// 410n March 2010 - -// Implement C P via PACTOR/WINMOR (for Airmail) - -// Build 2 - -// Don't flip SSID bits on Downlink Connect if uplink is Pactor/WINMOR -// Fix resetting IDLE Timer on Pactor/WINMOR sessions -// Send L4 KEEPLI messages based on IDLETIME - -// 410o July 2010 - -// Read bpqcfg.txt instead of .bin -// Support 32 bit MMASK (Allowing 32 Ports) -// Support 32 bit _APPLMASK (Allowing 32 Applications) -// Allow more commands -// Allow longer command aliases -// Fix logic error in RIGControl Port Initialisation (wasn't always raising RTS and DTR -// Clear RIGControl RTS and DTR on close - -// 410o Build 2 August 2010 - -// Fix couple of errors in config (needed APPLICATIONS and BBSCALL/ALIAS/QUAL) -// Fix Kenwood Rig Control when more than one message received at once. -// Save minimzed state of Rigcontrol Window - -// 410o Build 3 August 2010 - -// Fix reporting of set errors in scan to a random session - -// 410o Build 4 August 2010 - -// Change All xxx Ports are in use to no xxxx Ports are available if there are no sessions with _APPLMASK -// Fix validation of TRANSDELAY - -// 410o Build 5 August 2010 - -// Add Repeater Shift and Set Data Mode options to Rigcontrol (for ICOM only) -// Add WINMOR and SCS Pactor mode control option to RigControl -// Extend INFOMSG to 2000 bytes -// Improve Scan freq change lock (check both SCS and WINMOR Ports) - -// 410o Build 6 September 2010 - -// Incorporate IPGateway in main code. -// Fix GetSessionInfo for Pactor/Winmor Ports -// Add Antenna Selection to RigControl -// Allow Bandwidth options on RADIO command line (as well as in Scan definitions) - -// 410o Build 7 September 2010 - -// Move rigconrtol display to driver windows -// Move rigcontrol config to driver config. -// Allow driver and IPGateway config info in bpq32.cfg -// Move IPGateway, AXIP, VKISS, AGW and WINMOR drivers into bpq32.dll -// Add option to reread IP Gateway config. -// Fix Reinit after process with timer closes (error in TellSessions). - -// 410p Build 2 October 2010 - -// Move KAM and SCS drivers to bpq32.dll - -// 410p Build 3 October 2010 - -// Support more than one axip port. - -// 410p Build 4 October 2010 - -// Dynamically load psapi.dll (for 98/ME) - -// 410p Build 5 October 2010 - -// Incorporate TelnetServer -// Fix AXIP ReRead Config -// Report AXIP accept() fails to syslog, not a popup. - -// 410p Build 6 October 2010 - -// Includes HAL support -// Changes to Pactor Drivers disconnect code -// AXIP now sends with source port = dest port, unless overridden by SOURCEPORT param -// Config now checks for duplicate port definitions -// Add Node Map reporting -// Fix WINMOR deferred disconnect. -// Report Pactor PORTCALL to WL2K instead of RMS Applcall - -// 410p Build 7 October 2010 - -// Add In/Out flag to Map reporting, and report centre, not dial -// Write Telnet log to BPQ Directory -// Add Port to AXIP resolver display -// Send Reports to update.g8bpq.net:81 -// Add support for FT100 to Rigcontrol -// Add timeout to Rigcontrol PTT -// Add Save Registry Command - -// 410p Build 8 November 2010 - -// Add NOKEEPALIVES Port Param -// Renumbered for release - -// 410p Build 9 November 2010 - -// Get Bandwith for map report from WL2K Report Command -// Fix freq display for FT100 (was KHz, not MHz) -// Don't try to change SCS mode whilst initialising -// Allow reporting of Lat/Lon as well as Locator -// Fix Telnet Log Name -// Fix starting with Minimized windows when Minimizetotray isn't set -// Extra Program Error trapping in SessionControl -// Fix reporting same freq with different bandwidths at different times. -// Code changes to support SCS Robust Packet Mode. -// Add FT2000 to Rigcontrol -// Only Send CTEXT to connects to Node (not to connects to an Application Call) - -// Released as Build 10 - -// 410p Build 11 January 2011 - -// Fix MH Update for SCS Outgoing Calls -// Add Direct CMS Access to TelnetServer -// Restructure DISCONNECT processing to run in Timer owning process - -// 410p Build 12 January 2011 - -// Add option for Hardware PTT to use a different com port from the scan port -// Add CAT PTT for Yaesu 897 (and maybe others) -// Fix RMS Packet ports busy after restart -// Fix CMS Telnet with MAXSESSIONS > 10 - -// 410p Build 13 January 2011 - -// Fix loss of buffers in TelnetServer -// Add CMS logging. -// Add non - Promiscuous mode option for BPQETHER - -// 410p Build 14 January 2011 - -// Add support for BPQTermTCP -// Allow more that one FBBPORT -// Allow Telnet FBB mode sessions to send CRLF as well as CR on user and pass msgs -// Add session length to CMS Telnet logging. -// Return Secure Session Flag from GetConnectionInfo -// Show Uptime as dd/hh/mm - -// 4.10.16.17 March 2011 - -// Add "Close all programs" command -// Add BPQ Program Directory registry key -// Use HKEY_CURRENT_USER on Vista and above (and move registry if necessary) -// Time out IP Gateway ARP entries, and only reload ax.25 ARP entries -// Add support for SCS Tracker HF Modes -// Fix WL2K Reporting -// Report Version to WL2K -// Add Driver to support Tracker with multiple sessions (but no scanning, wl2k report, etc) - - -// Above released as 5.0.0.1 - -// 5.2.0.1 - -// Add caching of CMS Server IP addresses -// Initialise TNC State on Pactor Dialogs -// Add Shortened (6 digit) AUTH mode. -// Update MH with all frames (not just I/UI) -// Add IPV6 Support for TelnetServer and AXIP -// Fix TNC OK Test for Tracker -// Fix crash in CMS mode if terminal disconnects while tcp commect in progress -// Add WL2K reporting for Robust Packet -// Add option to suppress WL2K reporting for specific frequencies -// Fix Timeband processing for Rig Control -// New Driver for SCS Tracker allowing multiple connects, so Tracker can be used for user access -// New Driver for V4 TNC - -// 5.2.1.3 October 2011 - -// Combine busy detector on Interlocked Ports (SCS PTC, WINMOR or KAM) -// Improved program error logging -// WL2K reporting changed to new format agreed with Lee Inman - -// 5.2.3.1 January 2012 - -// Connects from the console to an APPLCALL or APPLALIAS now invoke any Command Alias that has been defined. -// Fix reporting of Tracker freqs to WL2K. -// Fix Tracker monitoring setup (sending M UISC) -// Fix possible call/application routing error on RP -// Changes for P4Dragon -// Include APRS Digi/IGate -// Tracker monitoring now includes DIGIS -// Support sending UI frames using SCSTRACKER, SCTRKMULTI and UZ7HO drivers -// Include driver for UZ7HO soundcard modem. -// Accept DRIVER as well as DLLNAME, and COMPORT as well as IOADDR in bpq32.cfg. COMPORT is decimal -// No longer supports separate config files, or BPQTELNETSERVER.exe -// Improved flow control for Telnet CMS Sessions -// Fix handling Config file without a newline after last line -// Add non - Promiscuous mode option for BPQETHER -// Change Console Window to a Dialog Box. -// Fix possible corruption and loss of buffers in Tracker drivers -// Add Beacon After Session option to Tracker and UZ7HO Drivers -// Rewrite RigControl and add "Reread Config Command" -// Support User Mode VCOM Driver for VKISS ports - -// 5.2.4.1 January 2012 - -// Remove CR from Telnet User and Password Prompts -// Add Rigcontrol to UZ7HO driver -// Fix corruption of Free Buffer Count by Rigcontol -// Fix WINMOR and V4 PTT -// Add MultiPSK Driver -// Add SendBeacon export for BPQAPRS -// Add SendChatReport function -// Fix check on length of Port Config ID String with trailing spaces -// Fix interlock when Port Number <> Port Slot -// Add NETROMCALL for L3 Activity -// Add support for APRS Application -// Fix Telnet with FBBPORT and no TCPPORT -// Add Reread APRS Config -// Fix switching to Pactor after scanning in normal packet mode (PTC) - -// 5.2.5.1 February 2012 - -// Stop reading Password file. -// Add extra MPSK commands -// Fix MPSK Transparency -// Make LOCATOR command compulsory -// Add MobileBeaconInterval APRS param -// Send Course and Speed when APRS is using GPS -// Fix Robust Packet reporting in PTC driver -// Fix corruption of some MIC-E APRS packets - -// 5.2.6.1 February 2012 - -// Convert to MDI presentation of BPQ32.dll windows -// Send APRS Status packets -// Send QUIT not EXIT in PTC Init -// Implement new WL2K reporting format and include traffic reporting info in CMS signon -// New WL2KREPORT format -// Prevent loops when APPL alias refers to itself -// Add RigControl for Flex radios and ICOM IC-M710 Marine radio - -// 5.2.7.1 - -// Fix opening more thn one console window on Win98 -// Change method of configuring multiple timelots on WL2K reporting -// Add option to update WK2K Sysop Database -// Add Web server -// Add UIONLY port option - -// 5.2.7.2 - -// Fix handling TelnetServer packets over 500 bytes in normal mode - -// 5.2.7.3 - -// Fix Igate handling packets from UIView - -// 5.2.7.4 - -// Prototype Baycom driver. - -// 5.2.7.5 - -// Set WK2K group ref to MARS (3) if using a MARS service code - -// 5.2.7.7 - -// Check for programs calling CloseBPQ32 when holding semaphore -// Try/Except round Status Timer Processing - -// 5.2.7.8 - -// More Try/Except round Timer Processing - -// 5.2.7.9 - -// Enable RX in Baycom, and remove test loopback in tx - -// 5.2.7.10 - -// Try/Except round ProcessHTTPMessage - -// 5.2.7.11 - -// BAYCOM tweaks - -// 5.2.7.13 - -// Release semaphore after program error in Timer Processing -// Check fro valid dest in REFRESHROUTE - - -// Add TNC-X KISSOPTION (includes the ACKMODE bytes in the checksum( - -// Version 5.2.9.1 Sept 2012 - -// Fix using KISS ports with COMn > 16 -// Add "KISS over UDP" driver for PI as a TNC concentrator - -// Version 6.0.1.1 - -// Convert to C for linux portability -// Try to speed up kiss polling - -// Version 6.0.2.1 - -// Fix operation on Win98 -// Fix callsign error with AGWtoBPQ -// Fix PTT problem with WINMOR -// Fix Reread telnet config -// Add Secure CMS signon -// Fix error in cashing addresses of CMS servers -// Fix Port Number when using Send Raw. -// Fix PE in KISS driver if invalid subchannel received -// Fix Orignal address of beacons -// Speed up Telnet port monitoring. -// Add TNC Emulators -// Add CountFramesQueuedOnStream API -// Limit number of frames that can be queued on a session. -// Add XDIGI feature -// Add Winmor Robust Mode switching for compatibility with new Winmor TNC -// Move most APRS code from BPQAPRS to here -// Stop corruption caused by overlong KISS frames - -// Version 6.0.3.1 - -// Add starting/killing WINMOR TNC on remote host -// Fix Program Error when APRS Item or Object name is same as call of reporting station -// Dont digi a frame that we have already digi'ed -// Add ChangeSessionIdleTime API -// Add WK2KSYSOP Command -// Add IDLETIME Command -// Fix Errors in RELAYAPPL processing -// Fix PE cauaed by invalid Rigcontrol Line - -// Version 6.0.4.1 - -// Add frequency dependent autoconnect appls for SCS Pactor -// Fix DED Monitoring of I and UI with no data -// Include AGWPE Emulator (from AGWtoBPQ) -// accept DEL (Hex 7F) as backspace in Telnet -// Fix re-running resolver on re-read AXIP config -// Speed up processing, mainly for Telnet Sessions -// Fix APRS init on restart of bpq32.exe -// Change to 2 stop bits -// Fix scrolling of WINMOR trace window -// Fix Crash when ueing DED TNC Emulator -// Fix Disconnect when using BPQDED2 Driver with Telnet Sessions -// Allow HOST applications even when CMS option is disabled -// Fix processing of APRS DIGIMAP command with no targets (didn't suppress default settings) - -// Version 6.0.5.1 January 2014 - -// Add UTF8 conversion mode to Telnet (converts non-UTF-8 chars to UTF-8) -// Add "Clear" option to MH command -// Add "Connect to RMS Relay" Option -// Revert to one stop bit on serial ports, explictly set two on FT2000 rig control -// Fix routing of first call in Robust Packet -// Add Options to switch input source on rigs with build in soundcards (sor far only IC7100 and Kenwood 590) -// Add RTS>CAT PTT option for Sound Card rigs -// Add Clear Nodes Option (NODE DEL ALL) -// SCS Pactor can set differeant APPLCALLS when scanning. -// Fix possible Scan hangup after a manual requency change with SCS Pactor -// Accept Scan entry of W0 to disable WINMOR on that frequency -// Fix corruption of NETROMCALL by SIMPLE config command -// Enforce Pactor Levels -// Add Telnet outward connect -// Add Relay/Trimode Emulation -// Fix V4 Driver -// Add PTT Mux -// Add Locked ARP Entries (via bpq32.cfg) -// Fix IDLETIME node command -// Fix STAY param on connect -// Add STAY option to Attach and Application Commands -// Fix crash on copying a large AXIP MH Window -// Fix possible crash when bpq32.exe dies -// Fix DIGIPORT for UI frames - -// Version 6.0.6.1 April 2014 - -// FLDigi Interface -// Fix "All CMS Servers are inaccessible" message so Mail Forwarding ELSE works. -// Validate INP3 messages to try to prevent crash -// Fix possible crash if an overlarge KISS frame is received -// Fix error in AXR command -// Add LF to Telnet Outward Connect signin if NEEDLF added to connect line -// Add CBELL to TNC21 emulator -// Add sent objects and third party messages to APRS Dup List -// Incorporate UIUtil -// Use Memory Mapped file to pass APRS info to BPQAPRS, and process APRS HTTP in BPQ32 -// Improvements to FLDIGI interlocking -// Fix TNC State Display for Tracker -// Cache CMS Addresses on LinBPQ -// Fix count error on DED Driver when handling 256 byte packets -// Add basic SNMP interface for MRTG -// Fix memory loss from getaddrinfo -// Process "BUSY" response from Tracker -// Handle serial port writes that don't accept all the data -// Trap Error 10038 and try to reopen socket -// Fix crash if overlong command line received - -// Version 6.0.7.1 Aptil 2014 -// Fix RigContol with no frequencies for Kenwood and Yaesu -// Add busy check to FLDIGI connects - -// Version 6.0.8.1 August 2014 - -// Use HKEY_CURRENT_USER on all OS versions -// Fix crash when APRS symbol is a space. -// Fixes for FT847 CAT -// Fix display of 3rd byte of FRMR -// Add "DEFAULT ROBUST" and "FORCE ROBUST" commands to SCSPactor Driver -// Fix possible memory corruption in WINMOR driver -// Fix FT2000 Modes -// Use new WL2K reporting system (Web API Based) -// APRS Server now cycles through hosts if DNS returns more than one -// BPQ32 can now start and stop FLDIGI -// Fix loss of AXIP Resolver when running more than one AXIP port - -// Version 6.0.9.1 November 2014 - -// Fix setting NOKEEPALIVE flag on route created from incoming L3 message -// Ignore NODES from locked route with quality 0 -// Fix seting source port in AXIP -// Fix Dual Stack (IPV4/V6) on Linux. -// Fix RELAYSOCK if IPv6 is enabled. -// Add support for FT1000 -// Fix hang when APRS Messaging packet received on RF -// Attempt to normalize Node qualies when stations use widely differing Route qualities -// Add NODES VIA command to display nodes reachable via a specified neighbour -// Fix applying "DisconnectOnClose" setting on HOST API connects (Telnet Server) -// Fix buffering large messages in Telnet Host API -// Fix occasional crash in terminal part line processing -// Add "NoFallback" command to Telnet server to disable "fallback to Relay" -// Improved support for APPLCALL scanning with Pactor -// MAXBUFFS config statement is no longer needed. -// Fix USEAPPLCALLS with Tracker when connect to APPLCALL fails -// Implement LISTEN and CQ commands -// FLDIGI driver can now start FLDIGI on a remote system. -// Add IGNOREUNLOCKEDROUTES parameter -// Fix error if too many Telnet server connections - -// Version 6.0.10.1 Feb 2015 - -// Fix crash if corrupt HTML request received. -// Allow SSID's of 'R' and 'T' on non-ax.25 ports for WL2K Radio Only network. -// Make HTTP server HTTP Version 1.1 complient - use persistent conections and close after 2.5 mins -// Add INP3ONLY flag. -// Fix program error if enter UNPROTO without a destination path -// Show client IP address on HTTP sessions in Telnet Server -// Reduce frequency and number of attempts to connect to routes when Keepalives or INP3 is set -// Add FT990 RigControl support, fix FT1000MP support. -// Support ARMV5 processors -// Changes to support LinBPQ APRS Client -// Add IC7410 to supported Soundcard rigs -// Add CAT PTT to NMEA type (for ICOM Marine Radios_ -// Fix ACKMODE -// Add KISS over TCP -// Support ACKMode on VKISS -// Improved reporting of configuration file format errors -// Experimental driver to support ARQ sessions using UI frames - -// Version 6.0.11.1 September 2015 - -// Fixes for IPGateway configuration and Virtual Circuit Mode -// Separate Portmapper from IPGateway -// Add PING Command -// Add ARDOP Driver -// Add basic APPLCALL support for PTC-PRO/Dragon 7800 Packet (using MYALIAS) -// Add "VeryOldMode" for KAM Version 5.02 -// Add KISS over TCP Slave Mode. -// Support Pactor and Packet on P4Dragon on one port -// Add "Remote Staton Quality" to Web ROUTES display -// Add Virtual Host option for IPGateway NET44 Encap -// Add NAT for local hosts to IPGateway -// Fix setting filter from RADIO command for IC7410 -// Add Memory Channel Scanning for ICOM Radios -// Try to reopen Rig Control port if it fails (could be unplugged USB) -// Fix restoring position of Monitor Window -// Stop Codec on Winmor and ARDOP when an interlocked port is attached (instead of listen false) -// Support APRS beacons in RP mode on Dragon// -// Change Virtual MAC address on IPGateway to include last octet of IP Address -// Fix "NOS Fragmentation" in IP over ax.25 Virtual Circuit Mode -// Fix sending I frames before L2 session is up -// Fix Flow control on Telnet outbound sessions. -// Fix reporting of unterminatred comments in config -// Add option for RigControl to not change mode on FT100/FT990/FT1000 -// Add "Attach and Connect" for Telnet ports - -// Version 6.0.12.1 November 2015 - -// Fix logging of IP addresses for connects to FBBPORT -// Allow lower case user and passwords in Telnet "Attach and Connect" -// Fix possible hang in KISS over TCP Slave mode -// Fix duplicating LinBPQ process if running ARDOP fails -// Allow lower case command aliases and increase alias length to 48 -// Fix saving long IP frames pending ARP resolution -// Fix dropping last entry from a RIP44 message. -// Fix displaying Digis in MH list -// Add port name to Monitor config screen port list -// Fix APRS command display filter and add port filter -// Support port names in BPQTermTCP Monitor config -// Add FINDBUFFS command to dump lost buffers to Debugview/Syslog -// Buffer Web Mgmt Edit Config output -// Add WebMail Support -// Fix not closing APRS Send WX file. -// Add RUN option to APRS Config to start APRS Client -// LinBPQ run FindLostBuffers and exit if QCOUNT < 5 -// Close and reopen ARDOP connection if nothing received for 90 secs -// Add facility to bridge traffic between ports (similar to APRS Bridge but for all frame types) -// Add KISSOPTION TRACKER to set SCS Tracker into KISS Mode - -// 6.0.13.1 - -// Allow /ex to exit UNPROTO mode -// Support ARQBW commands. -// Support IC735 -// Fix sending ARDOP beacons after a busy holdoff -// Enable BPQDED driver to beacon via non-ax.25 ports. -// Fix channel number in UZ7HO monitoring -// Add SATGate mode to APRSIS Code. -// Fix crash caused by overlong user name in telnet logon -// Add option to log L4 connects -// Add AUTOADDQuiet mode to AXIP. -// Add EXCLUDE processing -// Support WinmorControl in UZ7HO driver and fix starting TNC on Linux -// Convert calls in MAP entries to upper case. -// Support Linux COM Port names for APRS GPS -// Fix using NETROM serial protocol on ASYNC Port -// Fix setting MYLEVEL by scanner after manual level change. -// Add DEBUGLOG config param to SCS Pactor Driver to log serial port traffic -// Uue #myl to set SCS Pactor MYLEVEL, and add checklevel command -// Add Multicast RX interface to FLDIGI Driver -// Fix processing application aliases to a connect command. -// Fix Buffer loss if radio connected to PTC rig port but BPQ not configured to use it -// Save backups of bpq32.cfg when editing with Web interface and report old and new length -// Add DD command to SCS Pactor, and use it for forced disconnect. -// Add ARDOP mode select to scan config -// ARDOP changes for ARDOP V 0.5+ -// Flip SSID bits on UZ7HO downlink connects - - -// Version 6.0.14.1 - -// Fix Socket leak in ARDOP and FLDIGI drivers. -// Add option to change CMS Server hostname -// ARDOP Changes for 0.8.0+ -// Discard Terminal Keepalive message (two nulls) in ARDOP command hander -// Allow parameters to be passed to ARDOP TNC when starting it -// Fix Web update of Beacon params -// Retry connects to KISS ports after failure -// Add support for ARDOP Serial Interface Native mode. -// Fix gating APRS-IS Messages to RF -// Fix Beacons when PORTNUM used -// Make sure old monitor flag is cleared for TermTCP sessions -// Add CI-V antenna control for IC746 -// Don't allow ARDOP beacons when connected -// Add support for ARDOP Serial over I2C -// Fix possble crash when using manual RADIO messages -// Save out of sequence L2 frames for possible reuse after retry -// Add KISS command to send KISS control frame to TNC -// Stop removing unused digis from packets sent to APRS-IS - -// Processing of ARDOP PING and PINGACK responses -// Handle changed encoding of WL2K update responses. -// Allow anonymous logon to telnet -// Don't use APPL= for RP Calls in Dragon Single mode. -// Add basic messaging page to APRS Web Server -// Add debug log option to SCSTracker and TrkMulti Driver -// Support REBOOT command on LinBPQ -// Allow LISTEN command on all ports that support ax.25 monitoring - -// Version 6.0.15.1 Feb 2018 - -// partial support for ax.25 V2.2 -// Add MHU and MHL commands and MH filter option -// Fix scan interlock with ARDOP -// Add Input source seiect for IC7300 -// Remove % transparency from web terminal signon message -// Fix L4 Connects In count on stats -// Fix crash caused by corrupt CMSInfo.txt -// Add Input peaks display to ARDOP status window -// Add options to show time in local and distances in KM on APRS Web pages -// Add VARA support -// Fix WINMOR Busy left set when port Suspended -// Add ARDOP-Packet Support -// Add Antenna Switching for TS 480 -// Fix possible crash in Web Terminal -// Support different Code Pages on Console sessions -// Use new Winlink API interface (api.winlink.org) -// Support USB/ACC switching on TS590SG -// Fix scanning when ARDOP or WINMOR is used without an Interlocked Pactor port. -// Set NODECALL to first Application Callsign if NODE=0 and BBSCALL not set. -// Add RIGCONTROL TUNE and POWER commands for some ICOM and Kenwwod rigs -// Fix timing out ARDOP PENDING Lock -// Support mixed case WINLINK Passwords -// Add TUNE and POWER Rigcontol Commands for some radios -// ADD LOCALTIME and DISPKM options to APRS Digi/Igate - -// 6.0.16.1 March 2018 - -// Fix Setting data mode and filter for IC7300 radios -// Add VARA to WL2KREPORT -// Add trace to SCS Tracker status window -// Fix possible hang in IPGATEWAY -// Add BeacontoIS parameter to APRSDIGI. Allows you to stop sending beacons to APRS-IS. -// Fix sending CTEXT on WINMOR sessions - -// 6.0.17.1 November 2018 - -// Change WINMOR Restart after connection to Restart after Failure and add same option to ARDOP and VARA -// Add Abort Connection to WINMOR and VARA Interfaces -// Reinstate accidentally removed CMS Access logging -// Fix MH CLEAR -// Fix corruption of NODE table if NODES received from station with null alias -// Fix loss of buffer if session closed with something in PARTCMDBUFFER -// Fix Spurious GUARD ZONE CORRUPT message in IP Code. -// Remove "reread bpq32.cfg and reconfigure" menu options -// Add support for PTT using CM108 based soundcard interfaces -// Datestamp Telnet log files and delete old Telnet and CMSAcces logs - -// 6.0.18.1 January 2019 - -// Fix validation of NODES broadcasts -// Fix HIDENODES -// Check for failure to reread config on axip reconfigure -// Fix crash if STOPPORT or STARTPORT used on KISS over TCP port -// Send Beacons from BCALL or PORTCALL if configured -// Fix possible corruption of last entry in MH display -// Ensure RTS/DTR is down when opening PTT Port -// Remove RECONFIG command -// Preparations for 64 bit version - -// 6.0.19 Sept 2019 -// Fix UZ7HO interlock -// Add commands to set Centre Frequency and Modem with UZ7HO Soundmodem (on Windows only) -// Add option to save and restore MH lists and SAVEMH command -// Add Frequency (if known) to UZ7HO MH lists -// Add Gateway option to Telnet for PAT -// Try to fix SCS Tracker recovery -// Ensure RTS/DTR is down on CAT port if using that line for PTT -// Experimental APRS Messaging in Kernel -// Add Rigcontrol on remote PC's using WinmorControl -// ADD VARAFM and VARAFM96 WL2KREPORT modes -// Fix WL2K sysop update for new Winlink API -// Fix APRS when using PORTNUM higher than the number of ports -// Add Serial Port Type -// Add option to linbpq to log APRS-IS messages. -// Send WL2K Session Reports -// Drop Tunneled Packets from 44.192 - 44.255 -// Log incoming Telnet Connects -// Add IPV4: and IPV6: overrides on AXIP Resolver. -// Add SessionTimeLimit to HF sessions (ARDOP, SCSPactor, WINMOR, VARA) -// Add RADIO FREQ command to display current frequency - -// 6.0.20 April 2020 - -// Trap and reject YAPP file transfer request. -// Fix possible overrun of TCP to Node Buffer -// Fix possible crash if APRS WX file doesn't have a terminating newline -// Change communication with BPQAPRS.exe to restore old message popup behaviour -// Preparation for 64 bit version -// Improve flow control on SCS Dragon -// Fragment messages from network links to L2 links with smaller paclen -// Change WL2K report rate to once every two hours -// Add PASS, CTEXT and CMSG commands and Stream Switch support to TNC2 Emulator -// Add SessionTimeLimit command to HF drivers (ARDOP, SCSPactor, WINMOR, VARA) -// Add links to Ports Web Manangement Page to open individual Driver windows -// Add STOPPORT/STARTPORT support to ARDOP, KAM and SCSPactor drivers -// Add CLOSE and OPEN RADIO command so Rigcontrol port can be freed fpr other use. -// Don't try to send WL2K Traffic report if Internet is down -// Move WL2K Traffic reporting to a separate thread so it doesn't block if it can't connect to server -// ADD AGWAPPL config command to set application number. AGWMASK is still supported -// Register Node Alias with UZ7HO Driver -// Register calls when UZ7HO TNC Restarts and at intervals afterwards -// Fix crash when no IOADDR or COMPORT in async port definition -// Fix Crash with Paclink-Unix when parsing ; VE7SPR-10 DE N7NIX QTC 1 -// Only apply BBSFLAG=NOBBS to APPPLICATION 1 -// Add RIGREONFIG command -// fix APRS RECONFIG on LinBPQ -// Fix Web Terminal scroll to end problem on some browsers -// Add PTT_SETS_INPUT option for IC7600 -// Add TELRECONFIG command to reread users or whole config -// Enforce PACLEN on UZ7HO ports -// Fix PACLEN on Command Output. -// Retry axip resolver if it fails at startup -// Fix AGWAPI connect via digis -// Fix Select() for Linux in MultiPSK, UZ7HO and V4 drivers -// Limit APRS OBJECT length to 80 chars -// UZ7HO disconnect incoming call if no free streams -// Improve response to REJ (no F) followed by RR (F). -// Try to prevent more than MAXFRAME frames outstanding when transmitting -// Allow more than one instance of APRS on Linux -// Stop APRS digi by originating station -// Send driver window trace to main monitor system -// Improve handling of IPOLL messages -// Fix setting end of address bit on dest call on connects to listening sessions -// Set default BBS and CHAT application number and number of streams on LinBPQ -// Support #include in bpq32.cfg processing - -// Version 6.0.21 14 December 2020 - -// Fix occasional missing newlines in some node command reponses -// More 64 bit fixes -// Add option to stop setting PDUPLEX param in SCSPACTOR -// Try to fix buffer loss -// Remove extra space from APRS position reports -// Suppress VARA IAMALIVE messages -// Add display and control of QtSoundModem modems -// Only send "No CMS connection available" message if fallbacktorelay is set. -// Add HAMLIB backend and emulator support to RIGCONTROL -// Ensure all beacons are sent even with very short beacon intervals -// Add VARA500 WL2K Reporting Mode -// Fix problem with prpcessing frame collector -// Temporarily disable L2 and L4 collectors till I can find problem -// Fix possible problem with interactive RADIO commands not giving a response, -// Incease maximum length of NODE command responses to handle maximum length INFO message, -// Allow WL2KREPORT in CONFIG section of UZ7HO port config. -// Fix program error in processing hamlib frame -// Save RestartAfterFailure option for VARA -// Check callsign has a winlink account before sending WL2KREPORT messages -// Add Bandwidth control to VARA scanning -// Renable L2 collector -// Fix TNCPORT reconnect on Linux -// Add SecureTelnet option to limit telnet outward connect to sysop mode sessions or Application Aliases -// Add option to suppress sending call to application in Telnet HOST API -// Add FT991A support to RigControl -// Use background.jpg for Edit Config page -// Send OK response to SCS Pactor commands starting with # -// Resend ICOM PTT OFF command after 30 seconds -// Add WXCall to APRS config -// Fixes for AEAPactor -// Allow PTTMUX to use real or com0com com ports -// Fix monitoring with AGW Emulator -// Derive approx position from packets on APRS ports with a valid 6 char location -// Fix corruption of APRS message lists if the station table fills up. -// Don't accept empty username or password on Relay sessions. -// Fix occasional empty Nodes broadcasts -// Add Digis to UZ7HO Port MH list -// Add PERMITTEDAPPLS port param -// Fix WK2K Session Record Reporting for Airmail and some Pactor Modes. -// Fix handling AX/IP (proto 93) frames -// Fix possible corruption sending APRS messages -// Allow Telnet connections to be made using Connect command as well as Attach then Connect -// Fix Cancel Sysop Signin -// Save axip resolver info and restore on restart -// Add Transparent mode to Telnet Server HOST API -// Fix Tracker driver if WL2KREPRRT is in main config section -// SNMP InOctets count corrected to include all frames and encoding of zero values fixed. -// Change IP Gateway to exclude handling bits of 44 Net sold to Amazon -// Fix crash in Web terminal when processing very long lines - -// Version 6.0.22.1 August 2021 - -// Fix bug in KAM TNCEMULATOR -// Add WinRPR Driver (DED over TCP) -// Fix handling of VARA config commands FM1200 and FM9600 -// Improve Web Termanal Line folding -// Add StartTNC to WinRPR driver -// Add support for VARA2750 Mode -// Add support for VARA connects via a VARA Digipeater -// Add digis to SCSTracker and WinRPR MHeard -// Separate RIGCONTROL config from PORT config and add RigControl window -// Fix crash when a Windows HID device doesn't have a product_string -// Changes to VARA TNC connection and restart process -// Trigger FALLBACKTORELAY if attempt to connect to all CMS servers fail. -// Fix saving part lines in adif log and Winlink Session reporting -// Add port specific CTEXT -// Add FRMR monitoring to UZ7HO driver -// Add audio input switching for IC7610 -// Include Rigcontrol Support for IC-F8101E -// Process any response to KISS command -// Fix NODE ADD command -// Add noUpdate flag to AXIP MAP -// Fix clearing NOFALLBACK flag in Telnet Server -// Allow connects to RMS Relay running on another host -// Allow use of Power setting in Rigcontol scan lines for Kenwood radios -// Prevent problems caused by using "CMS" as a Node Alias -// Include standard APRS Station pages in code -// Fix VALIDCALLS processing in HF drivers -// Send Netrom Link reports to Node Map -// Add REALTELNET mode to Telnet Outward Connect -// Fix using S (Stay) parameter on Telnet connects when using CMDPORT and C HOST -// Add Default frequency to rigcontrol to set a freq/mode to return to after a connection -// Fix long (> 60 seconds) scan intervals -// Improved debugging of stuck semaphores -// Fix potential securiby bug in BPQ Web server -// Send Chat Updates to chatupdate.g8bpq.net port 81 -// Add ReportRelayTraffic to Telnet config to send WL2K traffic reports for connections to RELAY -// Add experimental Mode reporting -// Add SendTandRtoRelay param to SCS Pactor, ARDOP and VARA drivers to divert calls to CMS for -T and -R to RELAY -// Add UPNP Support - -// Version 6.0.23.1 June 2022 - -// Add option to control which applcalls are enabled in VARA -// Add support for rtl_udp to Rig Control -// Fix Telnet Auto Conneect to Application when using TermTCP or Web Terminal -// Allow setting css styles for Web Terminal -// And Kill TNC and Kill and Restart TNC commands to Web Driver Windows -// More flexible RigControl for split frequency operation, eg for QO100 -// Increase stack size for ProcessHTMLMessage (.11) -// Fix HTML Content-Type on images (.12) -// Add AIS and ADSB Support (.13) -// Compress web pages (.14) -// Change minidump routine and close after program error (.15) -// Add RMS Relay SYNC Mode (.17) -// Changes for compatibility with Winlink Hybrid -// Add Rigcontrol CMD feature to Yaesu code (21) -// More diagnostic code -// Trap potential buffer overrun in ax/tcp code -// Fix possible hang in UZ7HO driver if connect takes a long time to succeed or fail -// Add FLRIG as backend for RigControl (.24) -// Fix bug in compressing some management web pages -// Fix bugs in AGW Emulator (.25) -// Add more PTT_Sets_Freq options for split frequency working (.26) -// Allow RIGCONTROL using Radio Number (Rnn) as well as Port (.26) -// Fix Telnet negotiation and backspace processing (.29) -// Fix VARA Mode change when scanning (.30) -// Add Web Mgmt Log Display (.33) -// Fix crash when connecting to RELAY when CMS=0 (.36) -// Send OK to user for manual freq changes with hamlib or flrig -// Fix Rigcontrol leaving port disabled when using an empty timeband -// Fix processing of backspace in Telnet character processing (.40) -// Increase max size of connect script -// Fix HAMLIB Slave Thread control -// Add processing of VARA mode responses and display of VARA Mode (41) -// Fix crash when VARA session aborted on LinBPQ (43) -// Fix handling port selector (2:call or p2 call) on SCS PTC packet ports (44) -// Include APRS Map web page -// Add Enable/Disable to KAMPACTOR scan control (use P0 or P1) (45) -// Add Basic DRATS interface (46) -// Fix MYCALLS on VARA (49) -// Add FreeData driver (51) -// Add additonal Rigcontrol options for QO100 (51) -// Set Content-Type: application/pdf for pdf files downloaded via web interface (51) -// Fix sending large compressed web messages (52) -// Fix freq display when using flrig or hamlib backends to rigcontrol -// Change VARA Driver to send ABORT when Session Time limit expires -// Add Chat Log to Web Logs display -// Fix possible buffer loss in RigControl -// Allow hosts on local lan to be treated as secure -// Improve validation of data sent to Winlink SessionAdd API call -// Add support for FreeDATA modem. -// Add GetLOC API Call -// Change Leaflet link in aprs map. -// Add Connect Log (64) -// Fix crash when Resolve CMS Servers returns ipv6 addresses -// Fix Reporting P4 sessions to Winlink (68) -// Add support for FreeBSD (68) -// Fix Rigcontrol PTCPORT (69) -// Set TNC Emulator sessions as secure (72) -// Fix not always detecting loss of FLRIG (73) -// Add ? and * wildcards to NODES command (74) -// Add Port RADIO config parameter (74) - -// Version 6.0.24.1 August 2023 - -// Apply NODES command wildcard to alias as well a call (2) -// Add STOPPORT/STARTPORT to VARA Driver (2) -// Add bandwidth setting to FLRIG interface. (2) -// Fix N VIA (3) -// Fix NODE ADD and NODE DEL (4) -// Improvements to FLRIG Rigcontrol backend (6, 7) -// Fix UZ7HO Window Title Update -// Reject L2 calls with a blank from call (8) -// Update WinRPR Window header with BPQ Port Description (8) -// Fix error in blank call code (9) -// Change web buttons to white on black when pressed (10) -// Fix Port CTEXT paclen on Tracker and WinRPR drivers (11) -// Add RADIO PTT command for testing PTT (11) -// Fix using APPLCALLs on SCSTracker RP call (12) -// Add Rigcntol Web Page (13) -// Fix scan bandwidth change with ARDOPOFDM (13) -// Fix setting Min Pactor Level in SCSPactor (13) -// Fix length of commands sent via CMD_TO_APPL flag (14) -// Add filter by quality option to N display (15) -// Fix VARA Mode reporting to WL2K (16) -// Add FLRIG POWER and TUNE commands (18) -// Fix crash when processing "C " without a call in UZ7HO, FLDIGI or MULTIPSK drivers (19) -// FLDIGI improvements (19) -// Fix hang at start if Telnet port Number > Number of Telnet Streams (20) -// Fix processing C command if first port driver is SCSPACTROR (20) -// Fix crash in UZ7HO driver if bad raw frame received (21) -// Fix using FLARQ chat mode with FLDIGI ddriover (22) -// Fix to KISSHF driver (23) -// Fix for application buffer loss (24) -// Add Web Sockets auto-refresh option for Webmail index page (25) -// Fix FREEDATA driver for compatibility with FreeData TNC version 0.6.4-alpha.3 (25) -// Add SmartID for bridged frames - Send ID only if packets sent recently (26) -// Add option to save and restore received APRS messages (27) -// Add mechanism to run a user program on certain events (27) -// If BeacontoIS is zero don't Gate any of our messages received locally to APRS-IS (28) -// Add Node Help command (28) -// Add APRS Igate RXOnly option (29) -// Fix RMC message handling with prefixes other than GP (29) -// Add GPSD support for APRS (30) -// Attempt to fix Tracker/WinRPR reconnect code (30) -// Changes to FreeDATA - Don't use deamon and add txlevel and send text commands (31) -// Fix interactive commands in tracker driver (33) -// Fix SESSIONTIMELIMIT processing -// Add STOPPORT/STARTPORT for UZ7HO driver -// Fix processing of extended QtSM 'g' frame (36) -// Allow setting just freq on Yaseu rigs (37) -// Enable KISSHF driver on Linux (40) -// Allow AISHOST and ADSBHOST to be a name as well as an address (41) -// Fix Interlock of incoming UZ7HO connections (41) -// Disable VARA Actions menu if not sysop (41) -// Fix Port CTEXT on UZ7HO B C or D channels (42) -// Fix repeated trigger of SessionTimeLimit (43) -// Fix posible memory corruption in UpateMH (44) -// Add PHG to APRS beacons (45) -// Dont send DM to stations in exclude list(45) -// Improvements to RMS Relay SYNC Mode (46) -// Check L4 connects against EXCLUDE list (47) -// Add vaidation of LOC in WL2K Session Reports (49) -// Change gpsd support for compatibility with Share Gps (50) -// Switch APRS Map to my Tiles (52) -// Fix using ; in UNPROTO Mode messages (52) -// Use sha1 code from https://www.packetizer.com/security/sha1/ instead of openssl (53) -// Fix TNC Emulator Monitoring (53) -// Fix attach and connect on Telnet port bug introduced in .55 (56) -// Fix stopping WinRPR TNC and Start/Stop UZ7HO TNCX on Linux (57) -// Fix stack size in beginthread for MAC (58) -// Add NETROM over VARA (60) -// Add Disconnect Script (64) -// Add node commands to set UZ7HO modem mode and freq (64) -// Trap empty NODECALL or NETROMCALL(65) -// Trap NODES messages with empty From Call (65) -// Add RigControl for SDRConsole (66) -// Fix FLRig crash (66) -// Fix VARA disconnect handling (67) -// Support 64 ports (69) -// Fix Node commands for setting UZ7HO Modem (70) -// Fix processing SABM on an existing session (71) -// Extend KISS Node command to send more than one parameter byte (72) -// Add G7TAJ's code to record activity of HF ports for stats display (72) -// Add option to send KISS command to TNC on startup (73) -// Fix Bug in DED Emulator Monitor code (74) -// Add Filters to DED Monitor code (75) -// Detect loss of DED application (76) -// Fix connects to Application Alias with UZ7HO Driver (76) -// Fix Interlock of ports on same UZ7HO modem. (76) -// Add extended Ports command (77) -// Fix crash in Linbpq when stdout is redirected to /dev/tty? and stdin ia redirected (78) -// Fix Web Terminal (80) -// Trap ENCRYPTION message from VARA (81) -// Fix processing of the Winlink API /account/exists response (82) -// Fix sending CTEXT to L4 connects to Node when FULL_CTEXT is not set - -// Version 6.0.25.? - -// Fix 64 bit compatibility problems in SCSTracker and UZ7HO drivers -// Add Chat PACLEN config (5) -// Fix NC to Application Call (6) -// Fix INP3 L3RTT messages on Linux and correct RTT calculation (9) -// Get Beacon config from config file on Windows (9) -// fix processing DED TNC Emulator M command with space between M and params (10) -// Fix sending UI frames on SCSPACTOR (11) -// Dont allow ports that can't set digi'ed bit in callsigns to digipeat. (11) -// Add SDRAngel rig control (11) -// Add option to specify config and data directories on linbpq (12) -// Allow zero resptime (send RR immediately) (13) -// Make sure CMD bit is set on UI frames -// Add setting Modem Flags in QtSM AGW mode -// If FT847 om PTC Port send a "Cat On" command (17) -// Fix some 63 port bugs in RigCOntrol (17) -// Fix 63 port bug in Bridging (18) -// Add FTDX10 Rigcontrol (19) -// Fix 64 bit bug in displaying INP3 Messages (20) -// Improve restart of WinRPR TNC on remote host (21) -// Fix some Rigcontrol issues with empty timebands (22) -// Fix 64 bit bug in processing INP3 Messages (22) -// First pass at api (24) -// Send OK in response to Rigcontrol CMD (24) -// Disable CTS check in WriteComBlock (26) -// Improvments to reporting to M0LTE Map (26) -// IPGateway fix from github user isavitsky (27) -// Fix possible crash in SCSPactor PTCPORT code (29) -// Add NodeAPI call sendLinks and remove get from other calls (32) -// Improve validation of Web Beacon Config (33) -// Support SNMP via host ip stack as well as IPGateway (34) -// Switch APRS Map to OSM tile servers (36) -// Fix potential buffer overflow in Telnet login (36) -// Allow longer serial device names (37) -// Fix ICF8101 Mode setting (37) -// Kill link if we are getting repeated RR(F) after timeout -// (Indicating other station is seeing our RR(P) but not the resent I frame) (40) -// Change default of SECURETELNET to 1 (41) -// Add optional ATTACH time limit for ARDOP (42) -// Fix buffer overflow risk in HTTP Terminal(42) -// Fix KISSHF Interlock (43) -// Support other than channel A on HFKISS (43) -// Support additional port info reporting for M0LTE Map (44) -// Allow interlocking of KISS and Session mode ports (eg ARDOP and VARA) (45) -// Add ARDOP UI Packets to MH (45) -// Add support for Qtsm Mgmt Interface (45) -// NodeAPI improvements (46) -// Add MQTT Interface (46) -// Fix buffer leak in ARDOP code(46) -// Fix possible crash if MQTT not in use (47) -// Add optional ATTACH time limit for VARA (48) -// API format fixes (48) -// AGWAPI Add protection against accidental connects from a non-agw application (50) -// Save MH and NODES every hour (51) -// Fix handling long unix device names (now max 250 bytes) (52) -// Fix error reporting in api update (53) -// Coding changes to remove some compiler warnings (53, 54) -// Add MQTT reporting of Mail Events (54) -// Fix beaconong on KISSHF ports (55) -// Fix MailAPI msgs endpoint -// Attempt to fix NC going to wrong application. (57) -// Improve ARDOP send of session code (58) - - -#define CKernel - -#include "Versions.h" - -#define _CRT_SECURE_NO_DEPRECATE - -#pragma data_seg("_BPQDATA") - -#include "time.h" -#include "stdio.h" -#include - -#include "compatbits.h" -#include "AsmStrucs.h" - -#include "SHELLAPI.H" -#include "kernelresource.h" - -#include -#include -#include "BPQTermMDI.h" - -#include "GetVersion.h" - -#define DllImport __declspec( dllimport ) - -#define CheckGuardZone() _CheckGuardZone(__FILE__, __LINE__) -void _CheckGuardZone(char * File, int Line); - -#define CHECKLOADED 0 -#define SETAPPLFLAGS 1 -#define SENDBPQFRAME 2 -#define GETBPQFRAME 3 -#define GETSTREAMSTATUS 4 -#define CLEARSTREAMSTATUS 5 -#define BPQCONDIS 6 -#define GETBUFFERSTATUS 7 -#define GETCONNECTIONINFO 8 -#define BPQRETURN 9 // GETCALLS -//#define RAWTX 10 //IE KISS TYPE DATA -#define GETRAWFRAME 11 -#define UPDATESWITCH 12 -#define BPQALLOC 13 -//#define SENDNETFRAME 14 -#define GETTIME 15 - -extern short NUMBEROFPORTS; -extern long PORTENTRYLEN; -extern long LINKTABLELEN; -extern struct PORTCONTROL * PORTTABLE; -extern void * FREE_Q; -extern UINT APPL_Q; // Queue of frames for APRS Appl - -extern TRANSPORTENTRY * L4TABLE; -extern UCHAR NEXTID; -extern DWORD MAXCIRCUITS; -extern DWORD L4DEFAULTWINDOW; -extern DWORD L4T1; -extern APPLCALLS APPLCALLTABLE[]; -extern char * APPLS; - -extern struct WL2KInfo * WL2KReports; - -extern int NUMBEROFTNCPORTS; - - -void * VCOMExtInit(struct PORTCONTROL * PortEntry); -void * AXIPExtInit(struct PORTCONTROL * PortEntry); -void * SCSExtInit(struct PORTCONTROL * PortEntry); -void * AEAExtInit(struct PORTCONTROL * PortEntry); -void * KAMExtInit(struct PORTCONTROL * PortEntry); -void * HALExtInit(struct PORTCONTROL * PortEntry); -void * ETHERExtInit(struct PORTCONTROL * PortEntry); -void * AGWExtInit(struct PORTCONTROL * PortEntry); -void * WinmorExtInit(EXTPORTDATA * PortEntry); -void * TelnetExtInit(EXTPORTDATA * PortEntry); -//void * SoundModemExtInit(EXTPORTDATA * PortEntry); -void * TrackerExtInit(EXTPORTDATA * PortEntry); -void * TrackerMExtInit(EXTPORTDATA * PortEntry); -void * V4ExtInit(EXTPORTDATA * PortEntry); -void * UZ7HOExtInit(EXTPORTDATA * PortEntry); -void * MPSKExtInit(EXTPORTDATA * PortEntry); -void * FLDigiExtInit(EXTPORTDATA * PortEntry); -void * UIARQExtInit(EXTPORTDATA * PortEntry); -void * SerialExtInit(EXTPORTDATA * PortEntry); -void * ARDOPExtInit(EXTPORTDATA * PortEntry); -void * VARAExtInit(EXTPORTDATA * PortEntry); -void * KISSHFExtInit(EXTPORTDATA * PortEntry); -void * WinRPRExtInit(EXTPORTDATA * PortEntry); -void * HSMODEMExtInit(EXTPORTDATA * PortEntry); -void * FreeDataExtInit(EXTPORTDATA * PortEntry); -void * SIXPACKExtInit(EXTPORTDATA * PortEntry); - -extern char * ConfigBuffer; // Config Area -VOID REMOVENODE(dest_list * DEST); -DllExport int ConvFromAX25(unsigned char * incall,unsigned char * outcall); -DllExport int ConvToAX25(unsigned char * incall,unsigned char * outcall); -VOID GetUIConfig(); -VOID ADIFWriteFreqList(); -void SaveAIS(); -void initAIS(); -void initADSB(); - -extern BOOL ADIFLogEnabled; - -int CloseOnError = 0; - -char UIClassName[]="UIMAINWINDOW"; // the main window class name - -HWND UIhWnd; - -extern char AUTOSAVE; -extern char AUTOSAVEMH; - -extern char MYNODECALL; // 10 chars,not null terminated - -extern QCOUNT; -extern BPQVECSTRUC BPQHOSTVECTOR[]; -#define BPQHOSTSTREAMS 64 -#define IPHOSTVECTOR BPQHOSTVECTOR[BPQHOSTSTREAMS + 3] - -extern char * CONFIGFILENAME; - -DllExport BPQVECSTRUC * BPQHOSTVECPTR; - -extern int DATABASESTART; - -extern struct ROUTE * NEIGHBOURS; -extern int ROUTE_LEN; -extern int MAXNEIGHBOURS; - -extern struct DEST_LIST * DESTS; // NODE LIST -extern int DEST_LIST_LEN; -extern int MAXDESTS; // MAX NODES IN SYSTEM - -extern struct _LINKTABLE * LINKS; -extern int LINK_TABLE_LEN; -extern int MAXLINKS; - -extern double LatFromLOC; -extern double LonFromLOC; - - -extern int BPQHOSTAPI(); -extern int INITIALISEPORTS(); -extern int TIMERINTERRUPT(); -extern int MONDECODE(); -extern int BPQMONOPTIONS(); -extern char PWTEXT[]; -extern char PWLen; - -extern int FINDFREEDESTINATION(); -extern int RAWTX(); -extern int RELBUFF(); -extern int SENDNETFRAME(); -extern char MYCALL[]; // 7 chars, ax.25 format - -extern HWND hIPResWnd; -extern BOOL IPMinimized; - -extern int NODESINPROGRESS; -extern VOID * CURRENTNODE; - - -BOOL Start(); - -VOID SaveWindowPos(int port); -VOID SaveAXIPWindowPos(int port); -VOID SetupRTFHddr(); -DllExport VOID APIENTRY CreateNewTrayIcon(); -int DoReceivedData(int Stream); -int DoStateChange(int Stream); -int DoMonData(int Stream); -struct ConsoleInfo * CreateChildWindow(int Stream, BOOL DuringInit); -CloseHostSessions(); -SaveHostSessions(); -VOID SaveBPQ32Windows(); -VOID CloseDriverWindow(int port); -VOID CheckWL2KReportTimer(); -VOID SetApplPorts(); -VOID WriteMiniDump(); -VOID FindLostBuffers(); -BOOL InitializeTNCEmulator(); -VOID TNCTimer(); -char * strlop(char * buf, char delim); - -DllExport int APIENTRY Get_APPLMASK(int Stream); -DllExport int APIENTRY GetStreamPID(int Stream); -DllExport int APIENTRY GetApplFlags(int Stream); -DllExport int APIENTRY GetApplNum(int Stream); -DllExport BOOL APIENTRY GetAllocationState(int Stream); -DllExport int APIENTRY GetMsg(int stream, char * msg, int * len, int * count ); -DllExport int APIENTRY RXCount(int Stream); -DllExport int APIENTRY TXCount(int Stream); -DllExport int APIENTRY MONCount(int Stream); -DllExport int APIENTRY GetCallsign(int stream, char * callsign); -DllExport VOID APIENTRY RelBuff(VOID * Msg); -void SaveMH(); -void DRATSPoll(); - -#define C_Q_ADD(s, b) _C_Q_ADD(s, b, __FILE__, __LINE__); -int _C_Q_ADD(VOID *PQ, VOID *PBUFF, char * File, int Line); - -VOID SetWindowTextSupport(); -int WritetoConsoleSupport(char * buff); -VOID PMClose(); -VOID MySetWindowText(HWND hWnd, char * Msg); -BOOL CreateMonitorWindow(char * MonSize); -VOID FormatTime3(char * Time, time_t cTime); - -char EXCEPTMSG[80] = ""; - -char SIGNONMSG[128] = ""; -char SESSIONHDDR[80] = ""; -int SESSHDDRLEN = 0; - -BOOL IncludesMail = FALSE; -BOOL IncludesChat = FALSE; // Set if pgram is running - used for Web Page Index - - -char WL2KCall[10]; -char WL2KLoc[7]; - -extern char LOCATOR[]; // Locator for Reporting - may be Maidenhead or LAT:LON -extern char MAPCOMMENT[]; // Locator for Reporting - may be Maidenhead or LAT:LON -extern char LOC[7]; // Maidenhead Locator for Reporting -extern char ReportDest[7]; - -extern UCHAR ConfigDirectory[260]; - -extern uint64_t timeLoadedMS; - -VOID __cdecl Debugprintf(const char * format, ...); -VOID __cdecl Consoleprintf(const char * format, ...); - -DllExport int APIENTRY CloseBPQ32(); -DllExport char * APIENTRY GetLOC(); -DllExport int APIENTRY SessionControl(int stream, int command, int param); - -int DoRefreshWebMailIndex(); - -BOOL APIENTRY Init_IP(); -BOOL APIENTRY Poll_IP(); - -BOOL APIENTRY Init_PM(); -BOOL APIENTRY Poll_PM(); - -BOOL APIENTRY Init_APRS(); -BOOL APIENTRY Poll_APRS(); -VOID HTTPTimer(); - -BOOL APIENTRY Rig_Init(); -BOOL APIENTRY Rig_Close(); -BOOL Rig_Poll(); - -VOID IPClose(); -VOID APRSClose(); -VOID CloseTNCEmulator(); - -VOID Poll_AGW(); -void RHPPoll(); -BOOL AGWAPIInit(); -int AGWAPITerminate(); - -int * Flag = (int *)&Flag; // for Dump Analysis -int MAJORVERSION=4; -int MINORVERSION=9; - -struct SEM Semaphore = {0, 0, 0, 0}; -struct SEM APISemaphore = {0, 0, 0, 0}; -int SemHeldByAPI = 0; -int LastSemGets = 0; -UINT Sem_eax = 0; -UINT Sem_ebx = 0; -UINT Sem_ecx = 0; -UINT Sem_edx = 0; -UINT Sem_esi = 0; -UINT Sem_edi = 0; - - -#define GetSemaphore(Semaphore,ID) _GetSemaphore(Semaphore, ID, __FILE__, __LINE__) -void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line); -void FreeSemaphore(struct SEM * Semaphore); - -DllExport void * BPQHOSTAPIPTR = &BPQHOSTAPI; -//DllExport long MONDECODEPTR = (long)&MONDECODE; - -extern UCHAR BPQDirectory[]; -extern UCHAR LogDirectory[]; -extern UCHAR BPQProgramDirectory[]; - -static char BPQWinMsg[] = "BPQWindowMessage"; - -static char ClassName[] = "BPQMAINWINDOW"; - -HKEY REGTREE = HKEY_CURRENT_USER; -char REGTREETEXT[100] = "HKEY_CURRENT_USER"; - -UINT BPQMsg=0; - -#define MAXLINELEN 120 -#define MAXSCREENLEN 50 - -#define BGCOLOUR RGB(236,233,216) - -HBRUSH bgBrush = NULL; - -//int LINELEN=120; -//int SCREENLEN=50; - -//char Screen[MAXLINELEN*MAXSCREENLEN]={0}; - -//int lineno=0; -//int col=0; - -#define REPORTINTERVAL 15 * 549; // Magic Ticks Per Minute for PC's nominal 100 ms timer -int ReportTimer = 0; - -HANDLE OpenConfigFile(char * file); - -VOID SetupBPQDirectory(); -VOID SendLocation(); - -//uintptr_t _beginthread(void(*start_address)(), unsigned stack_size, int arglist); - -#define TRAY_ICON_ID 1 // ID number for the Notify Icon -#define MY_TRAY_ICON_MESSAGE WM_APP // the message ID sent to our window - -NOTIFYICONDATA niData; - -int SetupConsoleWindow(); - -BOOL StartMinimized=FALSE; -BOOL MinimizetoTray=TRUE; - -BOOL StatusMinimized = FALSE; -BOOL ConsoleMinimized = FALSE; - -HMENU trayMenu=0; - -HWND hConsWnd = NULL, hWndCons = NULL, hWndBG = NULL, ClientWnd = NULL, FrameWnd = NULL, StatusWnd = NULL; - -BOOL FrameMaximized = FALSE; - -BOOL IGateEnabled = TRUE; -extern int ISDelayTimer; // Time before trying to reopen APRS-IS link -extern int ISPort; - -UINT * WINMORTraceQ = NULL; -UINT * SetWindowTextQ = NULL; - -static RECT Rect = {100,100,400,400}; // Console Window Position -RECT FRect = {100,100,800,600}; // Frame -static RECT StatusRect = {100,100,850,500}; // Status Window - -DllExport int APIENTRY DumpSystem(); -DllExport int APIENTRY SaveNodes (); -DllExport int APIENTRY ClearNodes (); -DllExport int APIENTRY SetupTrayIcon(); - -#define Q_REM(s) _Q_REM(s, __FILE__, __LINE__) - -VOID * _Q_REM(VOID *Q, char * File, int Line); - -UINT ReleaseBuffer(UINT *BUFF); - - -VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime ); - -DllExport int APIENTRY DeallocateStream(int stream); - -int VECTORLENGTH = sizeof (struct _BPQVECSTRUC); - -int FirstEntry = 1; -BOOL CloseLast = TRUE; // If the user started BPQ32.exe, don't close it when other programs close -BOOL Closing = FALSE; // Set if Close All called - prevents respawning bpq32.exe - -BOOL BPQ32_EXE; // Set if Process is running BPQ32.exe. Not initialised. - // Used to Kill surplus BPQ32.exe processes - -DWORD Our_PID; // Our Process ID - local variable - -void * InitDone = 0; -int FirstInitDone = 0; -int PerlReinit = 0; -UINT_PTR TimerHandle = 0; -UINT_PTR SessHandle = 0; - -BOOL EventsEnabled = 0; - -unsigned int TimerInst = 0xffffffff; - -HANDLE hInstance = 0; - -int AttachedProcesses = 0; -int AttachingProcess = 0; -HINSTANCE hIPModule = 0; -HINSTANCE hRigModule = 0; - -BOOL ReconfigFlag = FALSE; -BOOL RigReconfigFlag = FALSE; -BOOL APRSReconfigFlag = FALSE; -BOOL CloseAllNeeded = FALSE; -BOOL NeedWebMailRefresh = FALSE; - -int AttachedPIDList[100] = {0}; - -HWND hWndArray[100] = {0}; -int PIDArray[100] = {0}; -char PopupText[30][100] = {""}; - -// Next 3 should be uninitialised so they are local to each process - -UCHAR MCOM; -UCHAR MTX; // Top bit indicates use local time -uint64_t MMASK; -UCHAR MUIONLY; - -UCHAR AuthorisedProgram; // Local Variable. Set if Program is on secure list - -char pgm[256]; // Uninitialised so per process - -HANDLE Mutex; - -BOOL PartLine = FALSE; -int pindex = 0; -DWORD * WritetoConsoleQ; - - -LARGE_INTEGER lpFrequency = {0}; -LARGE_INTEGER lastRunTime; -LARGE_INTEGER currentTime; - -int ticksPerMillisec; -int interval; - - -VOID CALLBACK SetupTermSessions(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime); - - -TIMERPROC lpTimerFunc = (TIMERPROC) TimerProc; -TIMERPROC lpSetupTermSessions = (TIMERPROC) SetupTermSessions; - - -BOOL ProcessConfig(); -VOID FreeConfig(); - -DllExport int APIENTRY WritetoConsole(char * buff); - -BOOLEAN CheckifBPQ32isLoaded(); -BOOLEAN StartBPQ32(); -DllExport VOID APIENTRY Send_AX(VOID * Block, DWORD len, UCHAR Port); -BOOL LoadIPDriver(); -BOOL Send_IP(VOID * Block, DWORD len); -VOID CheckforLostProcesses(); -BOOL LoadRigDriver(); -VOID SaveConfig(); -VOID CreateRegBackup(); -VOID ResolveUpdateThread(); -VOID OpenReportingSockets(); -DllExport VOID APIENTRY CloseAllPrograms(); -DllExport BOOL APIENTRY SaveReg(char * KeyIn, HANDLE hFile); -int upnpClose(); - -BOOL IPActive = FALSE; -extern BOOL IPRequired; -BOOL PMActive = FALSE; -extern BOOL PMRequired; -BOOL RigRequired = TRUE; -BOOL RigActive = FALSE; -BOOL APRSActive = FALSE; -BOOL AGWActive = FALSE; -BOOL needAIS = FALSE; -int needADSB = 0; - -extern int AGWPort; - -Tell_Sessions(); - - -typedef int (WINAPI FAR *FARPROCX)(); - -FARPROCX CreateToolHelp32SnapShotPtr; -FARPROCX Process32Firstptr; -FARPROCX Process32Nextptr; - -void LoadToolHelperRoutines() -{ - HINSTANCE ExtDriver=0; - int err; - char msg[100]; - - ExtDriver=LoadLibrary("kernel32.dll"); - - if (ExtDriver == NULL) - { - err=GetLastError(); - sprintf(msg,"BPQ32 Error loading kernel32.dll - Error code %d\n", err); - OutputDebugString(msg); - return; - } - - CreateToolHelp32SnapShotPtr = (FARPROCX)GetProcAddress(ExtDriver,"CreateToolhelp32Snapshot"); - Process32Firstptr = (FARPROCX)GetProcAddress(ExtDriver,"Process32First"); - Process32Nextptr = (FARPROCX)GetProcAddress(ExtDriver,"Process32Next"); - - if (CreateToolHelp32SnapShotPtr == 0) - { - err=GetLastError(); - sprintf(msg,"BPQ32 Error getting CreateToolhelp32Snapshot entry point - Error code %d\n", err); - OutputDebugString(msg); - return; - } -} - -BOOL GetProcess(int ProcessID, char * Program) -{ - HANDLE hProcessSnap; - PROCESSENTRY32 pe32; - int p; - - if (CreateToolHelp32SnapShotPtr==0) - { - return (TRUE); // Routine not available - } - // Take a snapshot of all processes in the system. - hProcessSnap = (HANDLE)CreateToolHelp32SnapShotPtr(TH32CS_SNAPPROCESS, 0); - if( hProcessSnap == INVALID_HANDLE_VALUE ) - { - OutputDebugString( "CreateToolhelp32Snapshot (of processes) Failed\n" ); - return( FALSE ); - } - - // Set the size of the structure before using it. - pe32.dwSize = sizeof( PROCESSENTRY32 ); - - // Retrieve information about the first process, - // and exit if unsuccessful - if( !Process32Firstptr( hProcessSnap, &pe32 ) ) - { - OutputDebugString( "Process32First Failed\n" ); // Show cause of failure - CloseHandle( hProcessSnap ); // Must clean up the snapshot object! - return( FALSE ); - } - - // Now walk the snapshot of processes, and - // display information about each process in turn - do - { - if (ProcessID==pe32.th32ProcessID) - { - // if running on 98, program contains the full path - remove it - - for (p = (int)strlen(pe32.szExeFile); p >= 0; p--) - { - if (pe32.szExeFile[p]=='\\') - { - break; - } - } - p++; - - sprintf(Program,"%s", &pe32.szExeFile[p]); - CloseHandle( hProcessSnap ); - return( TRUE ); - } - - } while( Process32Nextptr( hProcessSnap, &pe32 ) ); - - - sprintf(Program,"PID %d Not Found", ProcessID); - CloseHandle( hProcessSnap ); - return(FALSE); -} - -BOOL IsProcess(int ProcessID) -{ - // Check that Process exists - - HANDLE hProcessSnap; - PROCESSENTRY32 pe32; - - if (CreateToolHelp32SnapShotPtr==0) return (TRUE); // Routine not available - - hProcessSnap = (HANDLE)CreateToolHelp32SnapShotPtr(TH32CS_SNAPPROCESS, 0); - - if( hProcessSnap == INVALID_HANDLE_VALUE ) - { - OutputDebugString( "CreateToolhelp32Snapshot (of processes) Failed\n" ); - return(TRUE); // Don't know, so assume ok - } - - pe32.dwSize = sizeof( PROCESSENTRY32 ); - - if( !Process32Firstptr( hProcessSnap, &pe32 ) ) - { - OutputDebugString( "Process32First Failed\n" ); // Show cause of failure - CloseHandle( hProcessSnap ); // Must clean up the snapshot object! - return(TRUE); // Don't know, so assume ok - } - - do - { - if (ProcessID==pe32.th32ProcessID) - { - CloseHandle( hProcessSnap ); - return( TRUE ); - } - - } while( Process32Nextptr( hProcessSnap, &pe32 ) ); - - CloseHandle( hProcessSnap ); - return(FALSE); -} - -#include "DbgHelp.h" - -VOID MonitorThread(int x) -{ - // Thread to detect killed processes. Runs in process owning timer. - - // Obviously can't detect loss of timer owning thread! - - do - { - if (Semaphore.Gets == LastSemGets && Semaphore.Flag) - { - // It is stuck - try to release - - Debugprintf ("Semaphore locked - Process ID = %d, Held By %d from %s Line %d", - Semaphore.SemProcessID, SemHeldByAPI, Semaphore.File, Semaphore.Line); - - // Write a minidump - - WriteMiniDump(); - - Semaphore.Flag = 0; - } - - LastSemGets = Semaphore.Gets; - - Sleep(30000); - CheckforLostProcesses(); - - } while (TRUE); -} - -VOID CheckforLostProcesses() -{ - UCHAR buff[100]; - char Log[80]; - int i, n, ProcessID; - - for (n=0; n < AttachedProcesses; n++) - { - ProcessID=AttachedPIDList[n]; - - if (!IsProcess(ProcessID)) - { - // Process has died - Treat as a detach - - sprintf(Log,"BPQ32 Process %d Died\n", ProcessID); - OutputDebugString(Log); - - // Remove Tray Icon Entry - - for( i = 0; i < 100; ++i ) - { - if (PIDArray[i] == ProcessID) - { - hWndArray[i] = 0; - sprintf(Log,"BPQ32 Removing Tray Item %s\n", PopupText[i]); - OutputDebugString(Log); - DeleteMenu(trayMenu,TRAYBASEID+i,MF_BYCOMMAND); - } - } - - // If process had the semaphore, release it - - if (Semaphore.Flag == 1 && ProcessID == Semaphore.SemProcessID) - { - OutputDebugString("BPQ32 Process was holding Semaphore - attempting recovery\r\n"); - Debugprintf("Last Sem Call %d %x %x %x %x %x %x", SemHeldByAPI, - Sem_eax, Sem_ebx, Sem_ecx, Sem_edx, Sem_esi, Sem_edi); - - Semaphore.Flag = 0; - SemHeldByAPI = 0; - } - - for (i=1;i<65;i++) - { - if (BPQHOSTVECTOR[i-1].STREAMOWNER == AttachedPIDList[n]) - { - DeallocateStream(i); - } - } - - if (TimerInst == ProcessID) - { - KillTimer(NULL,TimerHandle); - TimerHandle=0; - TimerInst=0xffffffff; -// Tell_Sessions(); - OutputDebugString("BPQ32 Process was running timer \n"); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - - } - - // Remove this entry from PID List - - for (i=n; i< AttachedProcesses; i++) - { - AttachedPIDList[i]=AttachedPIDList[i+1]; - } - AttachedProcesses--; - - sprintf(buff,"BPQ32 Lost Process - %d Process(es) Attached\n", AttachedProcesses); - OutputDebugString(buff); - } - } -} -VOID MonitorTimerThread(int x) -{ - // Thread to detect killed timer process. Runs in all other BPQ32 processes. - - do { - - Sleep(60000); - - if (TimerInst != 0xffffffff && !IsProcess(TimerInst)) - { - // Timer owning Process has died - Force a new timer to be created - // New timer thread will detect lost process and tidy up - - Debugprintf("BPQ32 Process %d with Timer died", TimerInst); - - // If process was holding the semaphore, release it - - if (Semaphore.Flag == 1 && TimerInst == Semaphore.SemProcessID) - { - OutputDebugString("BPQ32 Process was holding Semaphore - attempting recovery\r\n"); - Debugprintf("Last Sem Call %d %x %x %x %x %x %x", SemHeldByAPI, - Sem_eax, Sem_ebx, Sem_ecx, Sem_edx, Sem_esi, Sem_edi); - Semaphore.Flag = 0; - SemHeldByAPI = 0; - } - -// KillTimer(NULL,TimerHandle); -// TimerHandle=0; -// TimerInst=0xffffffff; -// Tell_Sessions(); - - CheckforLostProcesses(); // Normally only done in timer thread, which is now dead - - // Timer can only run in BPQ32.exe - - TimerInst=0xffffffff; // So we dont keep doing it - TimerHandle = 0; // So new process attaches - - if (Closing == FALSE && AttachingProcess == FALSE) - { - OutputDebugString("BPQ32 Reloading BPQ32.exe\n"); - StartBPQ32(); - } - -// if (MinimizetoTray) -// Shell_NotifyIcon(NIM_DELETE,&niData); - } - - } while (TRUE); -} - -VOID WritetoTraceSupport(struct TNCINFO * TNC, char * Msg, int Len); - -VOID TimerProcX(); - -VOID CALLBACK TimerProc( - HWND hwnd, // handle of window for timer messages - UINT uMsg, // WM_TIMER message - UINT idEvent, // timer identifier - DWORD dwTime) // current system time -{ - KillTimer(NULL,TimerHandle); - TimerProcX(); - TimerHandle = SetTimer(NULL,0,100,lpTimerFunc); -} -VOID TimerProcX() -{ - struct _EXCEPTION_POINTERS exinfo; - - // - // Get semaphore before proceeeding - // - - GetSemaphore(&Semaphore, 2); - - // Get time since last run - - QueryPerformanceCounter(¤tTime); - - interval = (int)(currentTime.QuadPart - lastRunTime.QuadPart) / ticksPerMillisec; - lastRunTime.QuadPart = currentTime.QuadPart; - - //Debugprintf("%d", interval); - - // Process WINMORTraceQ - - while (WINMORTraceQ) - { - UINT * Buffer = Q_REM(&WINMORTraceQ); - struct TNCINFO * TNC = (struct TNCINFO * )Buffer[1]; - int Len = Buffer[2]; - char * Msg = (char *)&Buffer[3]; - - WritetoTraceSupport(TNC, Msg, Len); - RelBuff(Buffer); - } - - if (SetWindowTextQ) - SetWindowTextSupport(); - - while (WritetoConsoleQ) - { - UINT * Buffer = Q_REM(&WritetoConsoleQ); - WritetoConsoleSupport((char *)&Buffer[2]); - RelBuff(Buffer); - } - - strcpy(EXCEPTMSG, "Timer ReconfigProcessing"); - - __try - { - - if (trayMenu == NULL) - SetupTrayIcon(); - - // See if reconfigure requested - - if (CloseAllNeeded) - { - CloseAllNeeded = FALSE; - CloseAllPrograms(); - } - - if (ReconfigFlag) - { - // Only do it it timer owning process, or we could get in a real mess! - - if(TimerInst == GetCurrentProcessId()) - { - int i; - BPQVECSTRUC * HOSTVEC; - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - WSADATA WsaData; // receives data from WSAStartup - RECT cRect; - - ReconfigFlag = FALSE; - - SetupBPQDirectory(); - - WritetoConsole("Reconfiguring ...\n\n"); - OutputDebugString("BPQ32 Reconfiguring ...\n"); - - GetWindowRect(FrameWnd, &FRect); - - SaveWindowPos(70); // Rigcontrol - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { - SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - CloseDriverWindow(PORTVEC->PORTCONTROL.PORTNUMBER); - PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); // Close External Ports - } - } - PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL); - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - IPClose(); - PMClose(); - APRSClose(); - Rig_Close(); - CloseTNCEmulator(); - if (AGWActive) - AGWAPITerminate(); - - WSACleanup(); - - WL2KReports = NULL; - - Sleep(2000); - - WSAStartup(MAKEWORD(2, 0), &WsaData); - - Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - Consoleprintf(VerCopyright); - - Start(); - - INITIALISEPORTS(); // Restart Ports - - SetApplPorts(); - - FreeConfig(); - - for (i=1; i<68; i++) // Include Telnet, APRS and IP Vec - { - HOSTVEC=&BPQHOSTVECTOR[i-1]; - - HOSTVEC->HOSTTRACEQ=0; // Clear header (pool has been reinitialized - - if (HOSTVEC->HOSTSESSION !=0) - { - // Had a connection - - HOSTVEC->HOSTSESSION=0; - HOSTVEC->HOSTFLAGS |=3; // Disconnected - - PostMessage(HOSTVEC->HOSTHANDLE, BPQMsg, i, 4); - } - } - - // Free the APRS Appl Q - - APPL_Q = 0; - - OpenReportingSockets(); - - WritetoConsole("\n\nReconfiguration Complete\n"); - - if (IPRequired) IPActive = Init_IP(); - if (PMRequired) PMActive = Init_PM(); - - APRSActive = Init_APRS(); - - if (ISPort == 0) - IGateEnabled = 0; - - CheckDlgButton(hConsWnd, IDC_ENIGATE, IGateEnabled); - - GetClientRect(hConsWnd, &cRect); - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - { - ShowWindow(GetDlgItem(hConsWnd, IDC_GPS), SW_HIDE); - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - } - InvalidateRect(hConsWnd, NULL, TRUE); - - RigActive = Rig_Init(); - - if (NUMBEROFTNCPORTS) - { - FreeSemaphore(&Semaphore); - InitializeTNCEmulator(); - GetSemaphore(&Semaphore, 0); - } - - FreeSemaphore(&Semaphore); - AGWActive = AGWAPIInit(); - GetSemaphore(&Semaphore, 0); - - OutputDebugString("BPQ32 Reconfiguration Complete\n"); - } - } - - - if (RigReconfigFlag) - { - // Only do it it timer owning process, or we could get in a real mess! - - if(TimerInst == GetCurrentProcessId()) - { - RigReconfigFlag = FALSE; - CloseDriverWindow(70); - Rig_Close(); - Sleep(6000); // Allow any CATPTT, HAMLIB and FLRIG threads to close - RigActive = Rig_Init(); - - WritetoConsole("Rigcontrol Reconfiguration Complete\n"); - } - } - - if (APRSReconfigFlag) - { - // Only do it it timer owning process, or we could get in a real mess! - - if(TimerInst == GetCurrentProcessId()) - { - APRSReconfigFlag = FALSE; - APRSClose(); - APRSActive = Init_APRS(); - - WritetoConsole("APRS Reconfiguration Complete\n"); - } - } - - } - #include "StdExcept.c" - - if (Semaphore.Flag && Semaphore.SemProcessID == GetCurrentProcessId()) - FreeSemaphore(&Semaphore); - - } - - strcpy(EXCEPTMSG, "Timer Processing"); - - __try - { - if (IPActive) Poll_IP(); - if (PMActive) Poll_PM(); - if (RigActive) Rig_Poll(); - - if (NeedWebMailRefresh) - DoRefreshWebMailIndex(); - - CheckGuardZone(); - - if (APRSActive) - { - Poll_APRS(); - CheckGuardZone(); - } - - CheckWL2KReportTimer(); - - CheckGuardZone(); - - TIMERINTERRUPT(); - - CheckGuardZone(); - - FreeSemaphore(&Semaphore); // SendLocation needs to get the semaphore - - if (NUMBEROFTNCPORTS) - TNCTimer(); - - if (AGWActive) - Poll_AGW(); - - DRATSPoll(); - RHPPoll(); - - CheckGuardZone(); - - strcpy(EXCEPTMSG, "HTTP Timer Processing"); - - HTTPTimer(); - - CheckGuardZone(); - - strcpy(EXCEPTMSG, "WL2K Report Timer Processing"); - - if (ReportTimer) - { - ReportTimer--; - - if (ReportTimer == 0) - { - ReportTimer = REPORTINTERVAL; - SendLocation(); - } - } - } - - #include "StdExcept.c" - - if (Semaphore.Flag && Semaphore.SemProcessID == GetCurrentProcessId()) - FreeSemaphore(&Semaphore); - - } - - CheckGuardZone(); - - return; -} - -HANDLE NPHandle; - -int (WINAPI FAR *GetModuleFileNameExPtr)() = NULL; -int (WINAPI FAR *EnumProcessesPtr)() = NULL; - -FirstInit() -{ - WSADATA WsaData; // receives data from WSAStartup - HINSTANCE ExtDriver=0; - RECT cRect; - - - // First Time Ports and Timer init - - // Moved from DLLINIT to sort out perl problem, and meet MS Guidelines on minimising DLLMain - - // Call wsastartup - most systems need winsock, and duplicate statups could be a problem - - WSAStartup(MAKEWORD(2, 0), &WsaData); - - // Load Psapi.dll if possible - - ExtDriver=LoadLibrary("Psapi.dll"); - - SetupTrayIcon(); - - if (ExtDriver) - { - GetModuleFileNameExPtr = (FARPROCX)GetProcAddress(ExtDriver,"GetModuleFileNameExA"); - EnumProcessesPtr = (FARPROCX)GetProcAddress(ExtDriver,"EnumProcesses"); - } - - timeLoadedMS = GetTickCount(); - - INITIALISEPORTS(); - - OpenReportingSockets(); - - WritetoConsole("\n"); - WritetoConsole("Port Initialisation Complete\n"); - - if (IPRequired) IPActive = Init_IP(); - if (PMRequired) PMActive = Init_PM(); - - APRSActive = Init_APRS(); - - if (APRSActive) - { - hWndBG = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 0,0,40,546, hConsWnd, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Enable IGate", WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, - 8,0,90,24, hConsWnd, (HMENU)-1, hInstance, NULL); - - CreateWindowEx(0, "BUTTON", "", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP, - 95,1,18,24, hConsWnd, (HMENU)IDC_ENIGATE, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "IGate State - Disconnected", - WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 125, 0, 195, 24, hConsWnd, (HMENU)IGATESTATE, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "IGATE Stats - Msgs 0 Local Stns 0", - WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 320, 0, 240, 24, hConsWnd, (HMENU)IGATESTATS, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "GPS Off", - WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 560, 0, 80, 24, hConsWnd, (HMENU)IDC_GPS, hInstance, NULL); - } - - if (ISPort == 0) - IGateEnabled = 0; - - CheckDlgButton(hConsWnd, IDC_ENIGATE, IGateEnabled); - - GetClientRect(hConsWnd, &cRect); - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - { - ShowWindow(GetDlgItem(hConsWnd, IDC_GPS), SW_HIDE); - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - } - InvalidateRect(hConsWnd, NULL, TRUE); - - RigActive = Rig_Init(); - - _beginthread(MonitorThread,0,0); - - TimerHandle=SetTimer(NULL,0,100,lpTimerFunc); - TimerInst=GetCurrentProcessId(); - SessHandle = SetTimer(NULL, 0, 5000, lpSetupTermSessions); - - // If ARIF reporting is enabled write a Trimode Like ini for RMS Analyser - - if (ADIFLogEnabled) - ADIFWriteFreqList(); - - OutputDebugString("BPQ32 Port Initialisation Complete\n"); - - if (needAIS) - initAIS(); - - if (needADSB) - initADSB(); - - return 0; -} - -Check_Timer() -{ - if (Closing) - return 0; - - if (Semaphore.Flag) - return 0; - - if (InitDone == (void *)-1) - { - GetSemaphore(&Semaphore, 3); - Sleep(15000); - FreeSemaphore(&Semaphore); - exit (0); - } - - if (FirstInitDone == 0) - { - GetSemaphore(&Semaphore, 3); - - if (_stricmp(pgm, "bpq32.exe") == 0) - { - FirstInit(); - FreeSemaphore(&Semaphore); - if (NUMBEROFTNCPORTS) - InitializeTNCEmulator(); - - AGWActive = AGWAPIInit(); - FirstInitDone=1; // Only init in BPQ32.exe - return 0; - } - else - { - FreeSemaphore(&Semaphore); - return 0; - } - } - - if (TimerHandle == 0 && FirstInitDone == 1) - { - WSADATA WsaData; // receives data from WSAStartup - HINSTANCE ExtDriver=0; - RECT cRect; - - // Only attach timer to bpq32.exe - - if (_stricmp(pgm, "bpq32.exe") != 0) - { - return 0; - } - - GetSemaphore(&Semaphore, 3); - OutputDebugString("BPQ32 Reinitialising External Ports and Attaching Timer\n"); - - if (!ProcessConfig()) - { - ShowWindow(hConsWnd, SW_RESTORE); - SendMessage(hConsWnd, WM_PAINT, 0, 0); - SetForegroundWindow(hConsWnd); - - InitDone = (void *)-1; - FreeSemaphore(&Semaphore); - - MessageBox(NULL,"Configuration File Error","BPQ32",MB_ICONSTOP); - - exit (0); - } - - GetVersionInfo("bpq32.dll"); - - SetupConsoleWindow(); - - Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - Consoleprintf(VerCopyright); - Consoleprintf("Reinitialising..."); - - SetupBPQDirectory(); - - Sleep(1000); // Allow time for sockets to close - - WSAStartup(MAKEWORD(2, 0), &WsaData); - - // Load Psapi.dll if possible - - ExtDriver = LoadLibrary("Psapi.dll"); - - SetupTrayIcon(); - - if (ExtDriver) - { - GetModuleFileNameExPtr = (FARPROCX)GetProcAddress(ExtDriver,"GetModuleFileNameExA"); - EnumProcessesPtr = (FARPROCX)GetProcAddress(ExtDriver,"EnumProcesses"); - } - - Start(); - - INITIALISEPORTS(); - - OpenReportingSockets(); - - NODESINPROGRESS = 0; - CURRENTNODE = 0; - - SetApplPorts(); - - WritetoConsole("\n\nPort Reinitialisation Complete\n"); - - BPQMsg = RegisterWindowMessage(BPQWinMsg); - - CreateMutex(NULL,TRUE,"BPQLOCKMUTEX"); - -// NPHandle=CreateNamedPipe("\\\\.\\pipe\\BPQ32pipe", -// PIPE_ACCESS_DUPLEX,0,64,4096,4096,1000,NULL); - - if (IPRequired) IPActive = Init_IP(); - if (PMRequired) PMActive = Init_PM(); - - RigActive = Rig_Init(); - APRSActive = Init_APRS(); - - if (ISPort == 0) - IGateEnabled = 0; - - CheckDlgButton(hConsWnd, IDC_ENIGATE, IGateEnabled); - - GetClientRect(hConsWnd, &cRect); - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - { - ShowWindow(GetDlgItem(hConsWnd, IDC_GPS), SW_HIDE); - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - } - InvalidateRect(hConsWnd, NULL, TRUE); - - FreeConfig(); - - _beginthread(MonitorThread,0,0); - - ReportTimer = 0; - - OpenReportingSockets(); - - FreeSemaphore(&Semaphore); - - if (NUMBEROFTNCPORTS) - InitializeTNCEmulator(); - - AGWActive = AGWAPIInit(); - - if (StartMinimized) - if (MinimizetoTray) - ShowWindow(FrameWnd, SW_HIDE); - else - ShowWindow(FrameWnd, SW_SHOWMINIMIZED); - else - ShowWindow(FrameWnd, SW_RESTORE); - - TimerHandle=SetTimer(NULL,0,100,lpTimerFunc); - TimerInst=GetCurrentProcessId(); - SessHandle = SetTimer(NULL, 0, 5000, lpSetupTermSessions); - - return (1); - } - - return (0); -} - -DllExport INT APIENTRY CheckTimer() -{ - return Check_Timer(); -} - -Tell_Sessions() -{ - // - // Post a message to all listening sessions, so they call the - // API, and cause a new timer to be allocated - // - HWND hWnd; - int i; - - for (i=1;i<65;i++) - { - if (BPQHOSTVECTOR[i-1].HOSTFLAGS & 0x80) - { - hWnd = BPQHOSTVECTOR[i-1].HOSTHANDLE; - PostMessage(hWnd, BPQMsg,i, 1); - PostMessage(hWnd, BPQMsg,i, 2); - } - } - return (0); -} - -BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved) -{ - DWORD n; - char buf[350]; - - int i; - unsigned int ProcessID; - - OSVERSIONINFO osvi; - - memset(&osvi, 0, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - - GetVersionEx(&osvi); - - - switch( ul_reason_being_called ) - { - case DLL_PROCESS_ATTACH: - - if (sizeof(HDLCDATA) > PORTENTRYLEN + 200) // 200 bytes of Hardwaredata - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"BPQ32 Too much HDLC data - Recompile","BPQ32", MB_OK); - return 0; - } - - if (sizeof(struct KISSINFO) > PORTENTRYLEN + 200) // 200 bytes of Hardwaredata - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"BPQ32 Too much KISS data - Recompile","BPQ32", MB_OK); - return 0; - } - - if (sizeof(struct _EXTPORTDATA) > PORTENTRYLEN + 200) // 200 bytes of Hardwaredata - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"BPQ32 Too much _EXTPORTDATA data - Recompile","BPQ32", MB_OK); - return 0; - } - - if (sizeof(LINKTABLE) != LINK_TABLE_LEN) - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"L2 LINK Table .c and .asm mismatch - fix and rebuild","BPQ32", MB_OK); - return 0; - } - if (sizeof(struct ROUTE) != ROUTE_LEN) - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"ROUTE Table .c and .asm mismatch - fix and rebuild", "BPQ32", MB_OK); - return 0; - } - - if (sizeof(struct DEST_LIST) != DEST_LIST_LEN) - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"NODES Table .c and .asm mismatch - fix and rebuild", "BPQ32", MB_OK); - return 0; - } - - GetSemaphore(&Semaphore, 4); - - BPQHOSTVECPTR = &BPQHOSTVECTOR[0]; - - LoadToolHelperRoutines(); - - Our_PID = GetCurrentProcessId(); - - QueryPerformanceFrequency(&lpFrequency); - - ticksPerMillisec = (int)lpFrequency.QuadPart / 1000; - - lastRunTime.QuadPart = lpFrequency.QuadPart; - - GetProcess(Our_PID, pgm); - - if (_stricmp(pgm, "regsvr32.exe") == 0 || _stricmp(pgm, "bpqcontrol.exe") == 0) - { - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 1; - } - - if (_stricmp(pgm,"BPQ32.exe") == 0) - BPQ32_EXE = TRUE; - - if (_stricmp(pgm,"BPQMailChat.exe") == 0) - IncludesMail = TRUE; - - if (_stricmp(pgm,"BPQMail.exe") == 0) - IncludesMail = TRUE; - - if (_stricmp(pgm,"BPQChat.exe") == 0) - IncludesChat = TRUE; - - if (FirstEntry) // If loaded by BPQ32.exe, dont close it at end - { - FirstEntry = 0; - if (BPQ32_EXE) - CloseLast = FALSE; - } - else - { - if (BPQ32_EXE && AttachingProcess == 0) - { - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - MessageBox(NULL,"BPQ32.exe is already running\r\n\r\nIt should only be run once", "BPQ32", MB_OK); - return 0; - } - } - - if (_stricmp(pgm,"BPQTelnetServer.exe") == 0) - { - MessageBox(NULL,"BPQTelnetServer is no longer supported\r\n\r\nUse the TelnetServer in BPQ32.dll", "BPQ32", MB_OK); - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 0; - } - - if (_stricmp(pgm,"BPQUIUtil.exe") == 0) - { - MessageBox(NULL,"BPQUIUtil is now part of BPQ32.dll\r\nBPQUIUtil.exe cannot be run\r\n", "BPQ32", MB_OK); - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 0; - } - - if (_stricmp(pgm,"BPQMailChat.exe") == 0) - { - MessageBox(NULL,"BPQMailChat is obsolete. Run BPQMail.exe and/or BPQChat.exe instead", "BPQ32", MB_OK); - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 0; - } - AuthorisedProgram = TRUE; - - if (InitDone == 0) - { -// #pragma warning(push) -// #pragma warning(disable : 4996) - -// if (_winver < 0x0600) -// #pragma warning(pop) -// { -// // Below Vista -// -// REGTREE = HKEY_LOCAL_MACHINE; -// strcpy(REGTREETEXT, "HKEY_LOCAL_MACHINE"); -// } - - hInstance=hInst; - - Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"BPQLOCKMUTEX"); - - if (Mutex != NULL) - { - OutputDebugString("Another BPQ32.dll is loaded\n"); - i=MessageBox(NULL,"BPQ32 DLL already loaded from another directory\nIf you REALLY want this, hit OK, else hit Cancel","BPQ32",MB_OKCANCEL); - FreeSemaphore(&Semaphore); - - if (i != IDOK) return (0); - - CloseHandle(Mutex); - } - - if (!BPQ32_EXE) - { - if (CheckifBPQ32isLoaded() == FALSE) // Start BPQ32.exe if needed - { - // Wasn't Loaded, so we have started it, and should let it init system - - goto SkipInit; - } - } - - GetVersionInfo("bpq32.dll"); - - sprintf (SIGNONMSG, "G8BPQ AX25 Packet Switch System Version %s %s\r\n%s\r\n", - TextVerstring, Datestring, VerCopyright); - - SESSHDDRLEN = sprintf(SESSIONHDDR, "G8BPQ Network System %s for Win32 (", TextVerstring); - - SetupConsoleWindow(); - SetupBPQDirectory(); - - if (!ProcessConfig()) - { - StartMinimized = FALSE; - MinimizetoTray = FALSE; - ShowWindow(FrameWnd, SW_MAXIMIZE); - ShowWindow(hConsWnd, SW_MAXIMIZE); - ShowWindow(StatusWnd, SW_HIDE); - - SendMessage(hConsWnd, WM_PAINT, 0, 0); - SetForegroundWindow(hConsWnd); - - InitDone = (void *)-1; - FreeSemaphore(&Semaphore); - - MessageBox(NULL,"Configuration File Error\r\nProgram will close in 15 seconds","BPQ32",MB_ICONSTOP); - - return (0); - } - - Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - Consoleprintf(VerCopyright); - - if (Start() !=0) - { - Sleep(3000); - FreeSemaphore(&Semaphore); - return (0); - } - else - { - SetApplPorts(); - - GetUIConfig(); - - InitDone = &InitDone; - BPQMsg = RegisterWindowMessage(BPQWinMsg); -// TimerHandle=SetTimer(NULL,0,100,lpTimerFunc); -// TimerInst=GetCurrentProcessId(); - -/* Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"BPQLOCKMUTEX"); - - if (Mutex != NULL) - { - OutputDebugString("Another BPQ32.dll is loaded\n"); - MessageBox(NULL,"BPQ32 DLL already loaded from another directory","BPQ32",MB_ICONSTOP); - FreeSemaphore(&Semaphore); - return (0); - } - -*/ - Mutex=CreateMutex(NULL,TRUE,"BPQLOCKMUTEX"); - -// CreatePipe(&H1,&H2,NULL,1000); - -// GetLastError(); - -// NPHandle=CreateNamedPipe("\\\\.\\pipe\\BPQ32pipe", -// PIPE_ACCESS_DUPLEX,0,64,4096,4096,1000,NULL); - -// GetLastError(); - -/* - // - // Read SYSOP password - // - - if (PWTEXT[0] == 0) - { - handle = OpenConfigFile("PASSWORD.BPQ"); - - if (handle == INVALID_HANDLE_VALUE) - { - WritetoConsole("Can't open PASSWORD.BPQ\n"); - PWLen=0; - PWTEXT[0]=0; - } - else - { - ReadFile(handle,PWTEXT,78,&n,NULL); - CloseHandle(handle); - } - } -*/ - for (i=0;PWTEXT[i] > 0x20;i++); //Scan for cr or null - PWLen=i; - - } - } - else - { - if (InitDone != &InitDone) - { - MessageBox(NULL,"BPQ32 DLL already loaded at another address","BPQ32",MB_ICONSTOP); - FreeSemaphore(&Semaphore); - return (0); - } - } - - // Run timer monitor thread in all processes - it is possible for the TImer thread not to be the first thread -SkipInit: - - _beginthread(MonitorTimerThread,0,0); - - FreeSemaphore(&Semaphore); - - AttachedPIDList[AttachedProcesses++] = GetCurrentProcessId(); - - if (_stricmp(pgm,"bpq32.exe") == 0 && AttachingProcess == 1) AttachingProcess = 0; - - GetProcess(GetCurrentProcessId(),pgm); - n=sprintf(buf,"BPQ32 DLL Attach complete - Program %s - %d Process(es) Attached\n",pgm,AttachedProcesses); - OutputDebugString(buf); - - // Set up local variables - - MCOM=1; - MTX=1; - MMASK=0xffffffffffffffff; - -// if (StartMinimized) -// if (MinimizetoTray) -// ShowWindow(FrameWnd, SW_HIDE); -// else -// ShowWindow(FrameWnd, SW_SHOWMINIMIZED); -// else -// ShowWindow(FrameWnd, SW_RESTORE); - - return 1; - - case DLL_THREAD_ATTACH: - - return 1; - - case DLL_THREAD_DETACH: - - return 1; - - case DLL_PROCESS_DETACH: - - if (_stricmp(pgm,"BPQMailChat.exe") == 0) - IncludesMail = FALSE; - - if (_stricmp(pgm,"BPQChat.exe") == 0) - IncludesChat = FALSE; - - ProcessID=GetCurrentProcessId(); - - Debugprintf("BPQ32 Process %d Detaching", ProcessID); - - // Release any streams that the app has failed to release - - for (i=1;i<65;i++) - { - if (BPQHOSTVECTOR[i-1].STREAMOWNER == ProcessID) - { - // If connected, disconnect - - SessionControl(i, 2, 0); - DeallocateStream(i); - } - } - - // Remove any Tray Icon Entries - - for( i = 0; i < 100; ++i ) - { - if (PIDArray[i] == ProcessID) - { - char Log[80]; - hWndArray[i] = 0; - sprintf(Log,"BPQ32 Removing Tray Item %s\n", PopupText[i]); - OutputDebugString(Log); - DeleteMenu(trayMenu,TRAYBASEID+i,MF_BYCOMMAND); - } - } - - if (Mutex) CloseHandle(Mutex); - - // Remove our entry from PID List - - for (i=0; i< AttachedProcesses; i++) - if (AttachedPIDList[i] == ProcessID) - break; - - for (; i< AttachedProcesses; i++) - { - AttachedPIDList[i]=AttachedPIDList[i+1]; - } - - AttachedProcesses--; - - if (TimerInst == ProcessID) - { - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - - OutputDebugString("BPQ32 Process with Timer closing\n"); - - // Call Port Close Routines - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR && PORTVEC->DLLhandle == NULL) // Don't call if real .dll - it's not there! - { - SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); // Close External Ports - } - } - - PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL); - - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - - IPClose(); - PMClose(); - APRSClose(); - Rig_Close(); - CloseTNCEmulator(); - if (AGWActive) - AGWAPITerminate(); - - upnpClose(); - - WSACleanup(); - WSAGetLastError(); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - if (hConsWnd) DestroyWindow(hConsWnd); - - KillTimer(NULL,TimerHandle); - TimerHandle=0; - TimerInst=0xffffffff; - - if (AttachedProcesses && Closing == FALSE && AttachingProcess == 0) // Other processes - { - OutputDebugString("BPQ32 Reloading BPQ32.exe\n"); - StartBPQ32(); - } - } - else - { - // Not Timer Process - - if (AttachedProcesses == 1 && CloseLast) // Only bpq32.exe left - { - Debugprintf("Only BPQ32.exe running - close it"); - CloseAllNeeded = TRUE; - } - } - - if (AttachedProcesses < 2) - { - if (AUTOSAVE) - SaveNodes(); - if (AUTOSAVEMH) - SaveMH(); - - if (needAIS) - SaveAIS(); - } - if (AttachedProcesses == 0) - { - Closing = TRUE; - KillTimer(NULL,TimerHandle); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - // Unload External Drivers - - { - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10 && PORTVEC->DLLhandle) - FreeLibrary(PORTVEC->DLLhandle); - - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - } - } - - GetProcess(GetCurrentProcessId(),pgm); - n=sprintf(buf,"BPQ32 DLL Detach complete - Program %s - %d Process(es) Attached\n",pgm,AttachedProcesses); - OutputDebugString(buf); - - return 1; - } - return 1; -} - -DllExport int APIENTRY CloseBPQ32() -{ - // Unload External Drivers - - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - int i; - int ProcessID = GetCurrentProcessId(); - - if (Semaphore.Flag == 1 && ProcessID == Semaphore.SemProcessID) - { - OutputDebugString("BPQ32 Process holding Semaphore called CloseBPQ32 - attempting recovery\r\n"); - Debugprintf("Last Sem Call %d %x %x %x %x %x %x", SemHeldByAPI, - Sem_eax, Sem_ebx, Sem_ecx, Sem_edx, Sem_esi, Sem_edi); - - Semaphore.Flag = 0; - SemHeldByAPI = 0; - } - - if (TimerInst == ProcessID) - { - OutputDebugString("BPQ32 Process with Timer called CloseBPQ32\n"); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { - PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); - } - } - PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL); - - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - KillTimer(NULL,TimerHandle); - TimerHandle=0; - TimerInst=0xffffffff; - - IPClose(); - PMClose(); - APRSClose(); - Rig_Close(); - if (AGWActive) - AGWAPITerminate(); - - upnpClose(); - - CloseTNCEmulator(); - WSACleanup(); - - if (hConsWnd) DestroyWindow(hConsWnd); - - Debugprintf("AttachedProcesses %d ", AttachedProcesses); - - if (AttachedProcesses > 1 && Closing == FALSE && AttachingProcess == 0) // Other processes - { - OutputDebugString("BPQ32 Reloading BPQ32.exe\n"); - StartBPQ32(); - } - } - - return 0; -} - -BOOL CopyReg(HKEY hKeyIn, HKEY hKeyOut); - -VOID SetupBPQDirectory() -{ - HKEY hKey = 0; - HKEY hKeyIn = 0; - HKEY hKeyOut = 0; - int disp; - int retCode,Type,Vallen=MAX_PATH,i; - char msg[512]; - char ValfromReg[MAX_PATH] = ""; - char DLLName[256]="Not Known"; - char LogDir[256]; - char Time[64]; - -/* -•NT4 was/is '4' -•Win 95 is 4.00.950 -•Win 98 is 4.10.1998 -•Win 98 SE is 4.10.2222 -•Win ME is 4.90.3000 -•2000 is NT 5.0.2195 -•XP is actually 5.1 -•Vista is 6.0 -•Win7 is 6.1 - - i = _osver; / Build - i = _winmajor; - i = _winminor; -*/ -/* -#pragma warning(push) -#pragma warning(disable : 4996) - -if (_winver < 0x0600) -#pragma warning(pop) - { - // Below Vista - - REGTREE = HKEY_LOCAL_MACHINE; - strcpy(REGTREETEXT, "HKEY_LOCAL_MACHINE"); - ValfromReg[0] = 0; - } - else -*/ - { - if (_stricmp(pgm, "regsvr32.exe") == 0) - { - Debugprintf("BPQ32 loaded by regsvr32.exe - Registry not copied"); - } - else - { - // If necessary, move reg from HKEY_LOCAL_MACHINE to HKEY_CURRENT_USER - - retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_READ, - &hKeyIn); - - retCode = RegCreateKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\G8BPQ\\BPQ32", 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKeyOut, &disp); - - // See if Version Key exists in HKEY_CURRENT_USER - if it does, we have already done the copy - - Vallen = MAX_PATH; - retCode = RegQueryValueEx(hKeyOut, "Version" ,0 , &Type,(UCHAR *)&msg, &Vallen); - - if (retCode != ERROR_SUCCESS) - if (hKeyIn) - CopyReg(hKeyIn, hKeyOut); - - RegCloseKey(hKeyIn); - RegCloseKey(hKeyOut); - } - } - - GetModuleFileName(hInstance,DLLName,256); - - BPQDirectory[0]=0; - - retCode = RegOpenKeyEx (REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (retCode == ERROR_SUCCESS) - { - // Try "BPQ Directory" - - Vallen = MAX_PATH; - retCode = RegQueryValueEx(hKey,"BPQ Directory",0, - &Type,(UCHAR *)&ValfromReg,&Vallen); - - if (retCode == ERROR_SUCCESS) - { - if (strlen(ValfromReg) == 2 && ValfromReg[0] == '"' && ValfromReg[1] == '"') - ValfromReg[0]=0; - } - - if (ValfromReg[0] == 0) - { - // BPQ Directory absent or = "" - try "Config File Location" - - Vallen = MAX_PATH; - - retCode = RegQueryValueEx(hKey,"Config File Location",0, - &Type,(UCHAR *)&ValfromReg,&Vallen); - - if (retCode == ERROR_SUCCESS) - { - if (strlen(ValfromReg) == 2 && ValfromReg[0] == '"' && ValfromReg[1] == '"') - ValfromReg[0]=0; - } - } - - if (ValfromReg[0] == 0) GetCurrentDirectory(MAX_PATH, ValfromReg); - - // Get StartMinimized and MinimizetoTray flags - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Start Minimized", 0, &Type, (UCHAR *)&StartMinimized, &Vallen); - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Minimize to Tray", 0, &Type, (UCHAR *)&MinimizetoTray, &Vallen); - - ExpandEnvironmentStrings(ValfromReg, BPQDirectory, MAX_PATH); - - // Also get "BPQ Program Directory" - - ValfromReg[0] = 0; - Vallen = MAX_PATH; - - retCode = RegQueryValueEx(hKey, "BPQ Program Directory",0 , &Type, (UCHAR *)&ValfromReg, &Vallen); - - if (retCode == ERROR_SUCCESS) - ExpandEnvironmentStrings(ValfromReg, BPQProgramDirectory, MAX_PATH); - - // And Log Directory - - ValfromReg[0] = 0; - Vallen = MAX_PATH; - - retCode = RegQueryValueEx(hKey, "Log Directory",0 , &Type, (UCHAR *)&ValfromReg, &Vallen); - - if (retCode == ERROR_SUCCESS) - ExpandEnvironmentStrings(ValfromReg, LogDirectory, MAX_PATH); - - RegCloseKey(hKey); - } - - strcpy(ConfigDirectory, BPQDirectory); - - if (LogDirectory[0] == 0) - strcpy(LogDirectory, BPQDirectory); - - if (BPQProgramDirectory[0] == 0) - strcpy(BPQProgramDirectory, BPQDirectory); - - sprintf(msg,"BPQ32 Ver %s Loaded from: %s by %s\n", VersionString, DLLName, pgm); - WritetoConsole(msg); - OutputDebugString(msg); - FormatTime3(Time, time(NULL)); - sprintf(msg,"Loaded %s\n", Time); - WritetoConsole(msg); - OutputDebugString(msg); - -#pragma warning(push) -#pragma warning(disable : 4996) - -#if _MSC_VER >= 1400 - -#define _winmajor 6 -#define _winminor 0 - -#endif - - i=sprintf(msg,"Windows Ver %d.%d, Using Registry Key %s\n" ,_winmajor, _winminor, REGTREETEXT); - -#pragma warning(pop) - - WritetoConsole(msg); - OutputDebugString(msg); - - i=sprintf(msg,"BPQ32 Using config from: %s\n\n",BPQDirectory); - WritetoConsole(&msg[6]); - msg[i-1]=0; - OutputDebugString(msg); - - // Don't write the Version Key if loaded by regsvr32.exe (Installer is running with Admin rights, - // so will write the wrong tree on ) - - if (_stricmp(pgm, "regsvr32.exe") == 0) - { - Debugprintf("BPQ32 loaded by regsvr32.exe - Version String not written"); - } - else - { - retCode = RegCreateKeyEx(REGTREE, "SOFTWARE\\G8BPQ\\BPQ32", 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - sprintf(msg,"%d,%d,%d,%d", Ver[0], Ver[1], Ver[2], Ver[3]); - retCode = RegSetValueEx(hKey, "Version",0, REG_SZ,(BYTE *)msg, strlen(msg) + 1); - - RegCloseKey(hKey); - } - - // Make sure Logs Directory exists - - sprintf(LogDir, "%s/Logs", LogDirectory); - - CreateDirectory(LogDir, NULL); - - return; -} - -HANDLE OpenConfigFile(char *fn) -{ - HANDLE handle; - UCHAR Value[MAX_PATH]; - FILETIME LastWriteTime; - SYSTEMTIME Time; - char Msg[256]; - - - // If no directory, use current - if (BPQDirectory[0] == 0) - { - strcpy(Value,fn); - } - else - { - strcpy(Value,BPQDirectory); - strcat(Value,"\\"); - strcat(Value,fn); - } - - handle = CreateFile(Value, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - GetFileTime(handle, NULL, NULL, &LastWriteTime); - FileTimeToSystemTime(&LastWriteTime, &Time); - - sprintf(Msg,"BPQ32 Config File %s Created %.2d:%.2d %d/%.2d/%.2d\n", Value, - Time.wHour, Time.wMinute, Time.wYear, Time.wMonth, Time.wDay); - - OutputDebugString(Msg); - - return(handle); -} - -#ifdef _WIN64 -int BPQHOSTAPI() -{ - return 0; -} -#endif - - -DllExport int APIENTRY GETBPQAPI() -{ - return (int)BPQHOSTAPI; -} - -//DllExport UINT APIENTRY GETMONDECODE() -//{ -// return (UINT)MONDECODE; -//} - - -DllExport INT APIENTRY BPQAPI(int Fn, char * params) -{ - -/* -; -; BPQ HOST MODE SUPPORT CODE -; -; 22/11/95 -; -; MOVED FROM TNCODE.ASM COS CONITIONALS WERE GETTING TOO COMPLICATED -; (OS2 VERSION HAD UPSET KANT VERISON -; -; -*/ - - -/* - - BPQHOSTPORT: -; -; SPECIAL INTERFACE, MAINLY FOR EXTERNAL HOST MODE SUPPORT PROGS -; -; COMMANDS SUPPORTED ARE -; -; AH = 0 Get node/switch version number and description. On return -; AH='B',AL='P',BH='Q',BL=' ' -; DH = major version number and DL = minor version number. -; -; -; AH = 1 Set application mask to value in DL (or even DX if 16 -; applications are ever to be supported). -; -; Set application flag(s) to value in CL (or CX). -; whether user gets connected/disconnected messages issued -; by the node etc. -; -; -; AH = 2 Send frame in ES:SI (length CX) -; -; -; AH = 3 Receive frame into buffer at ES:DI, length of frame returned -; in CX. BX returns the number of outstanding frames still to -; be received (ie. after this one) or zero if no more frames -; (ie. this is last one). -; -; -; -; AH = 4 Get stream status. Returns: -; -; CX = 0 if stream disconnected or CX = 1 if stream connected -; DX = 0 if no change of state since last read, or DX = 1 if -; the connected/disconnected state has changed since -; last read (ie. delta-stream status). -; -; -; -; AH = 6 Session control. -; -; CX = 0 Conneect - _APPLMASK in DL -; CX = 1 connect -; CX = 2 disconnect -; CX = 3 return user to node -; -; -; AH = 7 Get buffer counts for stream. Returns: -; -; AX = number of status change messages to be received -; BX = number of frames queued for receive -; CX = number of un-acked frames to be sent -; DX = number of buffers left in node -; SI = number of trace frames queued for receive -; -;AH = 8 Port control/information. Called with a stream number -; in AL returns: -; -; AL = Radio port on which channel is connected (or zero) -; AH = SESSION TYPE BITS -; BX = L2 paclen for the radio port -; CX = L2 maxframe for the radio port -; DX = L4 window size (if L4 circuit, or zero) -; ES:DI = CALLSIGN - -;AH = 9 Fetch node/application callsign & alias. AL = application -; number: -; -; 0 = node -; 1 = BBS -; 2 = HOST -; 3 = SYSOP etc. etc. -; -; Returns string with alias & callsign or application name in -; user's buffer pointed to by ES:SI length CX. For example: -; -; "WORCS:G8TIC" or "TICPMS:G8TIC-10". -; -; -; AH = 10 Unproto transmit frame. Data pointed to by ES:SI, of -; length CX, is transmitted as a HDLC frame on the radio -; port (not stream) in AL. -; -; -; AH = 11 Get Trace (RAW Data) Frame into ES:DI, -; Length to CX, Timestamp to AX -; -; -; AH = 12 Update Switch. At the moment only Beacon Text may be updated -; DX = Function -; 1=update BT. ES:SI, Len CX = Text -; 2=kick off nodes broadcast -; -; AH = 13 Allocate/deallocate stream -; If AL=0, return first free stream -; If AL>0, CL=1, Allocate stream. If aleady allocated, -; return CX nonzero, else allocate, and return CX=0 -; If AL>0, CL=2, Release stream -; -; -; AH = 14 Internal Interface for IP Router -; -; Send frame - to NETROM L3 if DL=0 -; to L2 Session if DL<>0 -; -; -; AH = 15 Get interval timer - - -*/ - - - switch(Fn) - { - - case CHECKLOADED: - - params[0]=MAJORVERSION; - params[1]=MINORVERSION; - params[2]=QCOUNT; - - return (1); - } - return 0; -} - -DllExport int APIENTRY InitSwitch() -{ - return (0); -} - -/*DllExport int APIENTRY SwitchTimer() -{ - GetSemaphore((&Semaphore); - - TIMERINTERRUPT(); - - FreeSemaphore(&Semaphore); - - return (0); -} -*/ -DllExport int APIENTRY GetFreeBuffs() -{ -// Returns number of free buffers -// (BPQHOST function 7 (part)). - return (QCOUNT); -} - -DllExport UCHAR * APIENTRY GetNodeCall() -{ - return (&MYNODECALL); -} - - -DllExport UCHAR * APIENTRY GetNodeAlias() -{ - return (&MYALIASTEXT[0]); -} - -DllExport UCHAR * APIENTRY GetBBSCall() -{ - return (UCHAR *)(&APPLCALLTABLE[0].APPLCALL_TEXT); -} - - -DllExport UCHAR * APIENTRY GetBBSAlias() -{ - return (UCHAR *)(&APPLCALLTABLE[0].APPLALIAS_TEXT); -} - -DllExport VOID APIENTRY GetApplCallVB(int Appl, char * ApplCall) -{ - if (Appl < 1 || Appl > NumberofAppls ) return; - - strncpy(ApplCall,(char *)&APPLCALLTABLE[Appl-1].APPLCALL_TEXT, 10); -} - -BOOL UpdateNodesForApp(int Appl); - -DllExport BOOL APIENTRY SetApplCall(int Appl, char * NewCall) -{ - char Call[10]=" "; - int i; - - if (Appl < 1 || Appl > NumberofAppls ) return FALSE; - - i=strlen(NewCall); - - if (i > 10) i=10; - - strncpy(Call,NewCall,i); - - strncpy((char *)&APPLCALLTABLE[Appl-1].APPLCALL_TEXT,Call,10); - - if (!ConvToAX25(Call,APPLCALLTABLE[Appl-1].APPLCALL)) return FALSE; - - UpdateNodesForApp(Appl); - - return TRUE; - -} - -DllExport BOOL APIENTRY SetApplAlias(int Appl, char * NewCall) -{ - char Call[10]=" "; - int i; - - if (Appl < 1 || Appl > NumberofAppls ) return FALSE; - - i=strlen(NewCall); - - if (i > 10) i=10; - - strncpy(Call,NewCall,i); - - strncpy((char *)&APPLCALLTABLE[Appl-1].APPLALIAS_TEXT,Call,10); - - if (!ConvToAX25(Call,APPLCALLTABLE[Appl-1].APPLALIAS)) return FALSE; - - UpdateNodesForApp(Appl); - - return TRUE; - -} - - - -DllExport BOOL APIENTRY SetApplQual(int Appl, int NewQual) -{ - if (Appl < 1 || Appl > NumberofAppls ) return FALSE; - - APPLCALLTABLE[Appl-1].APPLQUAL=NewQual; - - UpdateNodesForApp(Appl); - - return TRUE; - -} - - -BOOL UpdateNodesForApp(int Appl) -{ - int App=Appl-1; - int DestLen = sizeof (struct DEST_LIST); - int n = MAXDESTS; - - struct DEST_LIST * DEST = APPLCALLTABLE[App].NODEPOINTER; - APPLCALLS * APPL=&APPLCALLTABLE[App]; - - if (DEST == NULL) - { - // No dest at the moment. If we have valid call and Qual, create an entry - - if (APPLCALLTABLE[App].APPLQUAL == 0) return FALSE; - - if (APPLCALLTABLE[App].APPLCALL[0] < 41) return FALSE; - - - GetSemaphore(&Semaphore, 5); - - DEST = DESTS; - - while (n--) - { - if (DEST->DEST_CALL[0] == 0) // Spare - break; - } - - if (n == 0) - { - // no dests - - FreeSemaphore(&Semaphore); - return FALSE; - } - - NUMBEROFNODES++; - APPL->NODEPOINTER = DEST; - - memmove (DEST->DEST_CALL,APPL->APPLCALL,13); - - DEST->DEST_STATE=0x80; // SPECIAL ENTRY - - DEST->NRROUTE[0].ROUT_QUALITY = (BYTE)APPL->APPLQUAL; - DEST->NRROUTE[0].ROUT_OBSCOUNT = 255; - - FreeSemaphore(&Semaphore); - - return TRUE; - } - - // We have a destination. If Quality is zero, remove it, else update it - - if (APPLCALLTABLE[App].APPLQUAL == 0) - { - GetSemaphore(&Semaphore, 6); - - REMOVENODE(DEST); // Clear buffers, Remove from Sorted Nodes chain, and zap entry - - APPL->NODEPOINTER=NULL; - - FreeSemaphore(&Semaphore); - return FALSE; - - } - - if (APPLCALLTABLE[App].APPLCALL[0] < 41) return FALSE; - - GetSemaphore(&Semaphore, 7); - - memmove (DEST->DEST_CALL,APPL->APPLCALL,13); - - DEST->DEST_STATE=0x80; // SPECIAL ENTRY - - DEST->NRROUTE[0].ROUT_QUALITY = (BYTE)APPL->APPLQUAL; - DEST->NRROUTE[0].ROUT_OBSCOUNT = 255; - - FreeSemaphore(&Semaphore); - return TRUE; - -} - - -DllExport UCHAR * APIENTRY GetSignOnMsg() -{ - return (&SIGNONMSG[0]); -} - - -DllExport HKEY APIENTRY GetRegistryKey() -{ - return REGTREE; -} - -DllExport char * APIENTRY GetRegistryKeyText() -{ - return REGTREETEXT;; -} - -DllExport UCHAR * APIENTRY GetBPQDirectory() -{ - while (BPQDirectory[0] == 0) - { - Debugprintf("BPQ Directory not set up - waiting"); - Sleep(1000); - } - return (&BPQDirectory[0]); -} - -DllExport UCHAR * APIENTRY GetProgramDirectory() -{ - return (&BPQProgramDirectory[0]); -} - -DllExport UCHAR * APIENTRY GetLogDirectory() -{ - return (&LogDirectory[0]); -} - -// Version for Visual Basic - -DllExport char * APIENTRY CopyBPQDirectory(char * dir) -{ - return (strcpy(dir,BPQDirectory)); -} - -DllExport int APIENTRY GetMsgPerl(int stream, char * msg) -{ - int len,count; - - GetMsg(stream, msg, &len, &count ); - - return len; -} - -int Rig_Command(int Session, char * Command); - -BOOL Rig_CommandInt(int Session, char * Command) -{ - return Rig_Command(Session, Command); -} - -DllExport int APIENTRY BPQSetHandle(int Stream, HWND hWnd) -{ - BPQHOSTVECTOR[Stream-1].HOSTHANDLE=hWnd; - return (0); -} - -#define L4USER 0 - -BPQVECSTRUC * PORTVEC ; - -VOID * InitializeExtDriver(PEXTPORTDATA PORTVEC) -{ - HINSTANCE ExtDriver=0; - char msg[128]; - int err=0; - HKEY hKey=0; - UCHAR Value[MAX_PATH]; - - // If no directory, use current - - if (BPQDirectory[0] == 0) - { - strcpy(Value,PORTVEC->PORT_DLL_NAME); - } - else - { - strcpy(Value,BPQDirectory); - strcat(Value,"\\"); - strcat(Value,PORTVEC->PORT_DLL_NAME); - } - - // Several Drivers are now built into bpq32.dll - - _strupr(Value); - - if (strstr(Value, "BPQVKISS")) - return VCOMExtInit; - - if (strstr(Value, "BPQAXIP")) - return AXIPExtInit; - - if (strstr(Value, "BPQETHER")) - return ETHERExtInit; - - if (strstr(Value, "BPQTOAGW")) - return AGWExtInit; - - if (strstr(Value, "AEAPACTOR")) - return AEAExtInit; - - if (strstr(Value, "HALDRIVER")) - return HALExtInit; - - if (strstr(Value, "KAMPACTOR")) - return KAMExtInit; - - if (strstr(Value, "SCSPACTOR")) - return SCSExtInit; - - if (strstr(Value, "WINMOR")) - return WinmorExtInit; - - if (strstr(Value, "V4")) - return V4ExtInit; - - if (strstr(Value, "TELNET")) - return TelnetExtInit; - -// if (strstr(Value, "SOUNDMODEM")) -// return SoundModemExtInit; - - if (strstr(Value, "SCSTRACKER")) - return TrackerExtInit; - - if (strstr(Value, "TRKMULTI")) - return TrackerMExtInit; - - if (strstr(Value, "UZ7HO")) - return UZ7HOExtInit; - - if (strstr(Value, "MULTIPSK")) - return MPSKExtInit; - - if (strstr(Value, "FLDIGI")) - return FLDigiExtInit; - - if (strstr(Value, "UIARQ")) - return UIARQExtInit; - -// if (strstr(Value, "BAYCOM")) -// return (UINT) BaycomExtInit; - - if (strstr(Value, "VARA")) - return VARAExtInit; - - if (strstr(Value, "ARDOP")) - return ARDOPExtInit; - - if (strstr(Value, "SERIAL")) - return SerialExtInit; - - if (strstr(Value, "KISSHF")) - return KISSHFExtInit; - - if (strstr(Value, "WINRPR")) - return WinRPRExtInit; - - if (strstr(Value, "HSMODEM")) - return HSMODEMExtInit; - - if (strstr(Value, "FREEDATA")) - return FreeDataExtInit; - - if (strstr(Value, "6PACK")) - return SIXPACKExtInit; - - ExtDriver = LoadLibrary(Value); - - if (ExtDriver == NULL) - { - err=GetLastError(); - - sprintf(msg,"Error loading Driver %s - Error code %d", - PORTVEC->PORT_DLL_NAME,err); - - MessageBox(NULL,msg,"BPQ32",MB_ICONSTOP); - - return(0); - } - - PORTVEC->DLLhandle=ExtDriver; - - return (GetProcAddress(ExtDriver,"_ExtInit@4")); - -} - -/* -_DATABASE LABEL BYTE - -FILLER DB 14 DUP (0) ; PROTECTION AGENST BUFFER PROBLEMS! - DB MAJORVERSION,MINORVERSION -_NEIGHBOURS DD 0 - DW TYPE ROUTE -_MAXNEIGHBOURS DW 20 ; MAX ADJACENT NODES - -_DESTS DD 0 ; NODE LIST - DW TYPE DEST_LIST -MAXDESTS DW 100 ; MAX NODES IN SYSTEM -*/ - - -DllExport int APIENTRY GetAttachedProcesses() -{ - return (AttachedProcesses); -} - -DllExport int * APIENTRY GetAttachedProcessList() -{ - return (&AttachedPIDList[0]); -} - -DllExport int * APIENTRY SaveNodesSupport() -{ - return (&DATABASESTART); -} - -// -// Internal BPQNODES support -// - -#define UCHAR unsigned char - -/* -ROUTE ADD G1HTL-1 2 200 0 0 0 -ROUTE ADD G4IRX-3 2 200 0 0 0 -NODE ADD MAPPLY:G1HTL-1 G1HTL-1 2 200 G4IRX-3 2 98 -NODE ADD NOT:GB7NOT G1HTL-1 2 199 G4IRX-3 2 98 - -*/ - -struct DEST_LIST * Dests; -struct ROUTE * Routes; - -int MaxNodes; -int MaxRoutes; -int NodeLen; -int RouteLen; - -int count; -int cursor; - -int len,i; - -ULONG cnt; -char Normcall[10]; -char Portcall[10]; -char Alias[7]; - -char line[100]; - -HANDLE handle; - -int APIENTRY Restart() -{ - int i, Count = AttachedProcesses; - HANDLE hProc; - DWORD PID; - - for (i = 0; i < Count; i++) - { - PID = AttachedPIDList[i]; - - // Kill Timer Owner last - - if (TimerInst != PID) - { - hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID); - - if (hProc) - { - TerminateProcess(hProc, 0); - CloseHandle(hProc); - } - } - } - - hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, TimerInst); - - if (hProc) - { - TerminateProcess(hProc, 0); - CloseHandle(hProc); - } - - - return 0; -} - -int APIENTRY Reboot() -{ - // Run shutdown -r -f - - STARTUPINFO SInfo; - PROCESS_INFORMATION PInfo; - char Cmd[] = "shutdown -r -f"; - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - return CreateProcess(NULL, Cmd, NULL, NULL, FALSE,0 ,NULL ,NULL, &SInfo, &PInfo); -} -/* -int APIENTRY Reconfig() -{ - if (!ProcessConfig()) - { - return (0); - } - SaveNodes(); - WritetoConsole("Nodes Saved\n"); - ReconfigFlag=TRUE; - WritetoConsole("Reconfig requested ... Waiting for Timer Poll\n"); - return 1; -} -*/ -// Code to support minimizing all BPQ Apps to a single Tray ICON - -// As we can't minimize the console window to the tray, I'll use an ordinary -// window instead. This also gives me somewhere to post the messages to - - -char AppName[] = "BPQ32"; -char Title[80] = "BPQ32.dll Console"; - -int NewLine(); - -char FrameClassName[] = TEXT("MdiFrame"); - -HWND ClientWnd; //This stores the MDI client area window handle - -LOGFONT LFTTYFONT ; - -HFONT hFont ; - -HMENU hPopMenu, hWndMenu; -HMENU hMainFrameMenu = NULL; -HMENU hBaseMenu = NULL; -HMENU hConsMenu = NULL; -HMENU hTermMenu = NULL; -HMENU hMonMenu = NULL; -HMENU hTermActMenu, hTermCfgMenu, hTermEdtMenu, hTermHlpMenu; -HMENU hMonActMenu, hMonCfgMenu, hMonEdtMenu, hMonHlpMenu; - - -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - -DllExport int APIENTRY DeleteTrayMenuItem(HWND hWnd); - -#define BPQMonitorAvail 1 -#define BPQDataAvail 2 -#define BPQStateChange 4 - -VOID GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value); -SOCKET OpenWL2KHTTPSock(); -SendHTTPRequest(SOCKET sock, char * Request, char * Params, int Len, char * Return); - -BOOL GetWL2KSYSOPInfo(char * Call, char * _REPLYBUFFER); -BOOL UpdateWL2KSYSOPInfo(char * Call, char * SQL); - - -static INT_PTR CALLBACK ConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_INITDIALOG: - { - char _REPLYBUFFER[1000] = ""; - char Value[1000]; - - if (GetWL2KSYSOPInfo(WL2KCall, _REPLYBUFFER)) - { -// if (strstr(_REPLYBUFFER, "\"ErrorMessage\":") == 0) - - GetJSONValue(_REPLYBUFFER, "\"SysopName\":", Value); - SetDlgItemText(hDlg, NAME, Value); - - GetJSONValue(_REPLYBUFFER, "\"GridSquare\":", Value); - SetDlgItemText(hDlg, IDC_Locator, Value); - - GetJSONValue(_REPLYBUFFER, "\"StreetAddress1\":", Value); - SetDlgItemText(hDlg, ADDR1, Value); - - GetJSONValue(_REPLYBUFFER, "\"StreetAddress2\":", Value); - SetDlgItemText(hDlg, ADDR2, Value); - - GetJSONValue(_REPLYBUFFER, "\"City\":", Value); - SetDlgItemText(hDlg, CITY, Value); - - GetJSONValue(_REPLYBUFFER, "\"State\":", Value); - SetDlgItemText(hDlg, STATE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Country\":", Value); - SetDlgItemText(hDlg, COUNTRY, Value); - - GetJSONValue(_REPLYBUFFER, "\"PostalCode\":", Value); - SetDlgItemText(hDlg, POSTCODE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Email\":", Value); - SetDlgItemText(hDlg, EMAIL, Value); - - GetJSONValue(_REPLYBUFFER, "\"Website\":", Value); - SetDlgItemText(hDlg, WEBSITE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Phones\":", Value); - SetDlgItemText(hDlg, PHONE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Comments\":", Value); - SetDlgItemText(hDlg, ADDITIONALDATA, Value); - - } - - return (INT_PTR)TRUE; - } - case WM_COMMAND: - - switch(LOWORD(wParam)) - { - - case ID_SAVE: - { - char Name[100]; - char PasswordText[100]; - char LocatorText[100]; - char Addr1[100]; - char Addr2[100]; - char City[100]; - char State[100]; - char Country[100]; - char PostCode[100]; - char Email[100]; - char Website[100]; - char Phone[100]; - char Data[100]; - - SOCKET sock; - - int Len; - char Message[2048]; - char Reply[2048] = ""; - - - GetDlgItemText(hDlg, NAME, Name, 99); - GetDlgItemText(hDlg, IDC_Password, PasswordText, 99); - GetDlgItemText(hDlg, IDC_Locator, LocatorText, 99); - GetDlgItemText(hDlg, ADDR1, Addr1, 99); - GetDlgItemText(hDlg, ADDR2, Addr2, 99); - GetDlgItemText(hDlg, CITY, City, 99); - GetDlgItemText(hDlg, STATE, State, 99); - GetDlgItemText(hDlg, COUNTRY, Country, 99); - GetDlgItemText(hDlg, POSTCODE, PostCode, 99); - GetDlgItemText(hDlg, EMAIL, Email, 99); - GetDlgItemText(hDlg, WEBSITE, Website, 99); - GetDlgItemText(hDlg, PHONE, Phone, 99); - GetDlgItemText(hDlg, ADDITIONALDATA, Data, 99); - - -//{"Callsign":"String","GridSquare":"String","SysopName":"String", -//"StreetAddress1":"String","StreetAddress2":"String","City":"String", -//"State":"String","Country":"String","PostalCode":"String","Email":"String", -//"Phones":"String","Website":"String","Comments":"String"} - - Len = sprintf(Message, - "\"Callsign\":\"%s\"," - "\"Password\":\"%s\"," - "\"GridSquare\":\"%s\"," - "\"SysopName\":\"%s\"," - "\"StreetAddress1\":\"%s\"," - "\"StreetAddress2\":\"%s\"," - "\"City\":\"%s\"," - "\"State\":\"%s\"," - "\"Country\":\"%s\"," - "\"PostalCode\":\"%s\"," - "\"Email\":\"%s\"," - "\"Phones\":\"%s\"," - "\"Website\":\"%s\"," - "\"Comments\":\"%s\"", - - WL2KCall, PasswordText, LocatorText, Name, Addr1, Addr2, City, State, Country, PostCode, Email, Phone, Website, Data); - - Debugprintf("Sending %s", Message); - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - char * ptr; - - SendHTTPRequest(sock, - "/sysop/add", Message, Len, Reply); - - ptr = strstr(Reply, "\"ErrorCode\":"); - - if (ptr) - { - ptr = strstr(ptr, "Message"); - if (ptr) - { - ptr += 10; - strlop(ptr, '"'); - MessageBox(NULL ,ptr, "Error", MB_OK); - } - } - else - MessageBox(NULL, "Sysop Record Updated", "BPQ32", MB_OK); - - } - closesocket(sock); - } - - case ID_CANCEL: - { - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - } - break; - } - } - return (INT_PTR)FALSE; -} - - - -LRESULT CALLBACK UIWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -VOID WINAPI OnTabbedDialogInit(HWND hDlg); - -LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - POINT pos; - BOOL ret; - - CLIENTCREATESTRUCT MDIClientCreateStruct; // Structure to be used for MDI client area - //HWND m_hwndSystemInformation = 0; - - if (message == BPQMsg) - { - if (lParam & BPQDataAvail) - DoReceivedData(wParam); - - if (lParam & BPQMonitorAvail) - DoMonData(wParam); - - if (lParam & BPQStateChange) - DoStateChange(wParam); - - return (0); - } - - switch (message) - { - case MY_TRAY_ICON_MESSAGE: - - switch(lParam) - { - case WM_RBUTTONUP: - case WM_LBUTTONUP: - - GetCursorPos(&pos); - - // SetForegroundWindow(FrameWnd); - - TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, FrameWnd, 0); - return 0; - } - - break; - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - case WM_SIZING: - case WM_SIZE: - - SendMessage(ClientWnd, WM_MDIICONARRANGE, 0 ,0); - break; - - case WM_NCCREATE: - - ret = DefFrameProc(hWnd, ClientWnd, message, wParam, lParam); - return TRUE; - - case WM_CREATE: - - // On creation of main frame, create the MDI client area - - MDIClientCreateStruct.hWindowMenu = NULL; - MDIClientCreateStruct.idFirstChild = IDM_FIRSTCHILD; - - ClientWnd = CreateWindow(TEXT("MDICLIENT"), // predefined value for MDI client area - NULL, // no caption required - WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, - 0, // No need to give any x/y or height/width since this client - // will just be used to get client windows created, effectively - // in the main window we will be seeing the mainframe window client area itself. - 0, - 0, - 0, - hWnd, - NULL, - hInstance, - (void *) &MDIClientCreateStruct); - - - return 0; - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - if (wmId >= TRAYBASEID && wmId < (TRAYBASEID + 100)) - { - handle=hWndArray[wmId-TRAYBASEID]; - - if (handle == FrameWnd) - ShowWindow(handle, SW_NORMAL); - - if (handle == FrameWnd && FrameMaximized == TRUE) - PostMessage(handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); - else - PostMessage(handle, WM_SYSCOMMAND, SC_RESTORE, 0); - - SetForegroundWindow(handle); - return 0; - } - - switch(wmId) - { - struct ConsoleInfo * Cinfo = NULL; - - case ID_NEWWINDOW: - Cinfo = CreateChildWindow(0, FALSE); - if (Cinfo) - SendMessage(ClientWnd, WM_MDIACTIVATE, (WPARAM)Cinfo->hConsole, 0); - break; - - case ID_WINDOWS_CASCADE: - SendMessage(ClientWnd, WM_MDICASCADE, 0, 0); - return 0; - - case ID_WINDOWS_TILE: - SendMessage(ClientWnd, WM_MDITILE , MDITILE_HORIZONTAL, 0); - return 0; - - case BPQCLOSEALL: - CloseAllPrograms(); - // SendMessage(ClientWnd, WM_MDIICONARRANGE, 0 ,0); - - return 0; - - case BPQUICONFIG: - { - int err, i=0; - char Title[80]; - WNDCLASS wc; - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = UIWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON) ); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = bgBrush; - - wc.lpszMenuName = NULL; - wc.lpszClassName = UIClassName; - - RegisterClass(&wc); - - UIhWnd = CreateDialog(hInstance, UIClassName, 0, NULL); - - if (!UIhWnd) - { - err=GetLastError(); - return FALSE; - } - - wsprintf(Title,"BPQ32 Beacon Configuration"); - MySetWindowText(UIhWnd, Title); - ShowWindow(UIhWnd, SW_NORMAL); - - OnTabbedDialogInit(UIhWnd); // Set up pages - - // UpdateWindow(UIhWnd); - return 0; - } - - - case IDD_WL2KSYSOP: - - if (WL2KCall[0] == 0) - { - MessageBox(NULL,"WL2K Reporting is not configured","BPQ32", MB_OK); - break; - } - - DialogBox(hInstance, MAKEINTRESOURCE(IDD_WL2KSYSOP), hWnd, ConfigWndProc); - break; - - - // Handle MDI Window commands - - default: - { - if(wmId >= IDM_FIRSTCHILD) - { - DefFrameProc(hWnd, ClientWnd, message, wParam, lParam); - } - else - { - HWND hChild = (HWND)SendMessage(ClientWnd, WM_MDIGETACTIVE,0,0); - - if(hChild) - SendMessage(hChild, WM_COMMAND, wParam, lParam); - } - } - } - - break; - - case WM_INITMENUPOPUP: - { - HWND hChild = (HWND)SendMessage(ClientWnd, WM_MDIGETACTIVE,0,0); - - if(hChild) - SendMessage(hChild, WM_INITMENUPOPUP, wParam, lParam); - } - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_MAXIMIZE: - - FrameMaximized = TRUE; - break; - - case SC_RESTORE: - - FrameMaximized = FALSE; - break; - - case SC_MINIMIZE: - - if (MinimizetoTray) - { - ShowWindow(hWnd, SW_HIDE); - return TRUE; - } - } - - return (DefFrameProc(hWnd, ClientWnd, message, wParam, lParam)); - - case WM_CLOSE: - - PostQuitMessage(0); - - if (MinimizetoTray) - DeleteTrayMenuItem(hWnd); - - break; - - default: - return (DefFrameProc(hWnd, ClientWnd, message, wParam, lParam)); - - } - return (DefFrameProc(hWnd, ClientWnd, message, wParam, lParam)); -} - -int OffsetH, OffsetW; - -int SetupConsoleWindow() -{ - WNDCLASS wc; - int i; - int retCode, Type, Vallen; - HKEY hKey=0; - char Size[80]; - WNDCLASSEX wndclassMainFrame; - RECT CRect; - - retCode = RegOpenKeyEx (REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"FrameWindowSize",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size,"%d,%d,%d,%d",&FRect.left,&FRect.right,&FRect.top,&FRect.bottom); - - if (FRect.top < - 500 || FRect.left < - 500) - { - FRect.left = 0; - FRect.top = 0; - FRect.right = 600; - FRect.bottom = 400; - } - - - Vallen=80; - retCode = RegQueryValueEx(hKey,"WindowSize",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size,"%d,%d,%d,%d,%d",&Rect.left,&Rect.right,&Rect.top,&Rect.bottom, &ConsoleMinimized); - - if (Rect.top < - 500 || Rect.left < - 500) - { - Rect.left = 0; - Rect.top = 0; - Rect.right = 600; - Rect.bottom = 400; - } - - Vallen=80; - - retCode = RegQueryValueEx(hKey,"StatusWindowSize",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size, "%d,%d,%d,%d,%d", &StatusRect.left, &StatusRect.right, - &StatusRect.top, &StatusRect.bottom, &StatusMinimized); - - if (StatusRect.top < - 500 || StatusRect.left < - 500) - { - StatusRect.left = 0; - StatusRect.top = 0; - StatusRect.right = 850; - StatusRect.bottom = 500; - } - - - // Get StartMinimized and MinimizetoTray flags - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Start Minimized", 0, &Type, (UCHAR *)&StartMinimized, &Vallen); - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Minimize to Tray", 0, &Type, (UCHAR *)&MinimizetoTray, &Vallen); - } - - wndclassMainFrame.cbSize = sizeof(WNDCLASSEX); - wndclassMainFrame.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wndclassMainFrame.lpfnWndProc = FrameWndProc; - wndclassMainFrame.cbClsExtra = 0; - wndclassMainFrame.cbWndExtra = 0; - wndclassMainFrame.hInstance = hInstance; - wndclassMainFrame.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON)); - wndclassMainFrame.hCursor = LoadCursor(NULL, IDC_ARROW); - wndclassMainFrame.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH); - wndclassMainFrame.lpszMenuName = NULL; - wndclassMainFrame.lpszClassName = FrameClassName; - wndclassMainFrame.hIconSm = NULL; - - if(!RegisterClassEx(&wndclassMainFrame)) - { - return 0; - } - - pindex = 0; - PartLine = FALSE; - - bgBrush = CreateSolidBrush(BGCOLOUR); - -// hMainFrameMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MAINFRAME_MENU)); - - hBaseMenu = LoadMenu(hInstance, MAKEINTRESOURCE(CONS_MENU)); - hConsMenu = GetSubMenu(hBaseMenu, 1); - hWndMenu = GetSubMenu(hBaseMenu, 0); - - hTermMenu = LoadMenu(hInstance, MAKEINTRESOURCE(TERM_MENU)); - hTermActMenu = GetSubMenu(hTermMenu, 1); - hTermCfgMenu = GetSubMenu(hTermMenu, 2); - hTermEdtMenu = GetSubMenu(hTermMenu, 3); - hTermHlpMenu = GetSubMenu(hTermMenu, 4); - - hMonMenu = LoadMenu(hInstance, MAKEINTRESOURCE(MON_MENU)); - hMonCfgMenu = GetSubMenu(hMonMenu, 1); - hMonEdtMenu = GetSubMenu(hMonMenu, 2); - hMonHlpMenu = GetSubMenu(hMonMenu, 3); - - hMainFrameMenu = CreateMenu(); - AppendMenu(hMainFrameMenu, MF_STRING + MF_POPUP, (UINT)hWndMenu, "Window"); - - //Create the main MDI frame window - - ClientWnd = NULL; - - FrameWnd = CreateWindow(FrameClassName, - "BPQ32 Console", - WS_OVERLAPPEDWINDOW |WS_CLIPCHILDREN, - FRect.left, - FRect.top, - FRect.right - FRect.left, - FRect.bottom - FRect.top, - NULL, // handle to parent window - hMainFrameMenu, // handle to menu - hInstance, // handle to the instance of module - NULL); // Long pointer to a value to be passed to the window through the - // CREATESTRUCT structure passed in the lParam parameter the WM_CREATE message - - - // Get Client Params - - if (FrameWnd == 0) - { - Debugprintf("SetupConsoleWindow Create Frame failed %d", GetLastError()); - return 0; - } - - ShowWindow(FrameWnd, SW_RESTORE); - - - GetWindowRect(FrameWnd, &FRect); - OffsetH = FRect.bottom - FRect.top; - OffsetW = FRect.right - FRect.left; - GetClientRect(FrameWnd, &CRect); - OffsetH -= CRect.bottom; - OffsetW -= CRect.right; - OffsetH -= 4; - - // Create Console Window - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = 0; - wc.lpszClassName = ClassName; - - i=RegisterClass(&wc); - - sprintf (Title, "BPQ32.dll Console Version %s", VersionString); - - hConsWnd = CreateMDIWindow(ClassName, "Console", 0, - 0,0,0,0, ClientWnd, hInstance, 1234); - - i = GetLastError(); - - if (!hConsWnd) { - return (FALSE); - } - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)StatusWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = 0; - wc.lpszClassName = "Status"; - - i=RegisterClass(&wc); - - if (StatusRect.top < OffsetH) // Make sure not off top of MDI frame - { - int Error = OffsetH - StatusRect.top; - StatusRect.top += Error; - StatusRect.bottom += Error; - } - - StatusWnd = CreateMDIWindow("Status", "Stream Status", 0, - StatusRect.left, StatusRect.top, StatusRect.right - StatusRect.left, - StatusRect.bottom - StatusRect.top, ClientWnd, hInstance, 1234); - - SetTimer(StatusWnd, 1, 1000, NULL); - - hPopMenu = GetSubMenu(hBaseMenu, 1) ; - - if (MinimizetoTray) - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_UNCHECKED); - - if (StartMinimized) - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_UNCHECKED); - - DrawMenuBar(hConsWnd); - - // setup default font information - - LFTTYFONT.lfHeight = 12; - LFTTYFONT.lfWidth = 8 ; - LFTTYFONT.lfEscapement = 0 ; - LFTTYFONT.lfOrientation = 0 ; - LFTTYFONT.lfWeight = 0 ; - LFTTYFONT.lfItalic = 0 ; - LFTTYFONT.lfUnderline = 0 ; - LFTTYFONT.lfStrikeOut = 0 ; - LFTTYFONT.lfCharSet = 0; - LFTTYFONT.lfOutPrecision = OUT_DEFAULT_PRECIS ; - LFTTYFONT.lfClipPrecision = CLIP_DEFAULT_PRECIS ; - LFTTYFONT.lfQuality = DEFAULT_QUALITY ; - LFTTYFONT.lfPitchAndFamily = FIXED_PITCH; - lstrcpy(LFTTYFONT.lfFaceName, "FIXEDSYS" ) ; - - hFont = CreateFontIndirect(&LFTTYFONT) ; - - SetWindowText(hConsWnd,Title); - - if (Rect.right < 100 || Rect.bottom < 100) - { - GetWindowRect(hConsWnd, &Rect); - } - - if (Rect.top < OffsetH) // Make sure not off top of MDI frame - { - int Error = OffsetH - Rect.top; - Rect.top += Error; - Rect.bottom += Error; - } - - - MoveWindow(hConsWnd, Rect.left - (OffsetW /2), Rect.top - OffsetH, Rect.right-Rect.left, Rect.bottom-Rect.top, TRUE); - - MoveWindow(StatusWnd, StatusRect.left - (OffsetW /2), StatusRect.top - OffsetH, - StatusRect.right-StatusRect.left, StatusRect.bottom-StatusRect.top, TRUE); - - hWndCons = CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "", - WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | LBS_NOSEL | WS_VSCROLL | WS_HSCROLL, - Rect.left, Rect.top, Rect.right - Rect.left, Rect.bottom - Rect.top, - hConsWnd, NULL, hInstance, NULL); - -// SendMessage(hWndCons, WM_SETFONT, hFont, 0); - - SendMessage(hWndCons, LB_SETHORIZONTALEXTENT , 1000, 0); - - if (ConsoleMinimized) - ShowWindow(hConsWnd, SW_SHOWMINIMIZED); - else - ShowWindow(hConsWnd, SW_RESTORE); - - if (StatusMinimized) - ShowWindow(StatusWnd, SW_SHOWMINIMIZED); - else - ShowWindow(StatusWnd, SW_RESTORE); - - ShowWindow(FrameWnd, SW_RESTORE); - - - LoadLibrary("riched20.dll"); - - if (StartMinimized) - if (MinimizetoTray) - ShowWindow(FrameWnd, SW_HIDE); - else - ShowWindow(FrameWnd, SW_SHOWMINIMIZED); - else - ShowWindow(FrameWnd, SW_RESTORE); - - CreateMonitorWindow(Size); - - return 0; -} - -DllExport int APIENTRY SetupTrayIcon() -{ - if (MinimizetoTray == 0) - return 0; - - trayMenu = CreatePopupMenu(); - - for( i = 0; i < 100; ++i ) - { - if (strcmp(PopupText[i],"BPQ32 Console") == 0) - { - hWndArray[i] = FrameWnd; - goto doneit; - } - } - - for( i = 0; i < 100; ++i ) - { - if (hWndArray[i] == 0) - { - hWndArray[i] = FrameWnd; - strcpy(PopupText[i],"BPQ32 Console"); - break; - } - } -doneit: - - for( i = 0; i < 100; ++i ) - { - if (hWndArray[i] != 0) - AppendMenu(trayMenu,MF_STRING,TRAYBASEID+i,PopupText[i]); - } - - // Set up Tray ICON - - ZeroMemory(&niData,sizeof(NOTIFYICONDATA)); - - niData.cbSize = sizeof(NOTIFYICONDATA); - - // the ID number can be any UINT you choose and will - // be used to identify your icon in later calls to - // Shell_NotifyIcon - - niData.uID = TRAY_ICON_ID; - - // state which structure members are valid - // here you can also choose the style of tooltip - // window if any - specifying a balloon window: - // NIF_INFO is a little more complicated - - strcpy(niData.szTip,"BPQ32 Windows"); - - niData.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; - - // load the icon note: you should destroy the icon - // after the call to Shell_NotifyIcon - - niData.hIcon = - - //LoadIcon(NULL, IDI_APPLICATION); - - (HICON)LoadImage( hInstance, - MAKEINTRESOURCE(BPQICON), - IMAGE_ICON, - GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - LR_DEFAULTCOLOR); - - - // set the window you want to receive event messages - - niData.hWnd = FrameWnd; - - // set the message to send - // note: the message value should be in the - // range of WM_APP through 0xBFFF - - niData.uCallbackMessage = MY_TRAY_ICON_MESSAGE; - - // Call Shell_NotifyIcon. NIM_ADD adds a new tray icon - - if (Shell_NotifyIcon(NIM_ADD,&niData)) - Debugprintf("BPQ32 Create Tray Icon Ok"); -// else -// Debugprintf("BPQ32 Create Tray Icon failed %d", GetLastError()); - - return 0; -} - -VOID SaveConfig() -{ - HKEY hKey=0; - int retCode, disp; - - retCode = RegCreateKeyEx(REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, // Reserved - 0, // Class - 0, // Options - KEY_ALL_ACCESS, - NULL, // Security Attrs - &hKey, - &disp); - - if (retCode == ERROR_SUCCESS) - { - retCode = RegSetValueEx(hKey, "Start Minimized", 0, REG_DWORD, (UCHAR *)&StartMinimized, 4); - retCode = RegSetValueEx(hKey, "Minimize to Tray", 0, REG_DWORD, (UCHAR *)&MinimizetoTray, 4); - } -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - POINT pos; - HWND handle; - RECT cRect; - - switch (message) - { - case WM_MDIACTIVATE: - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - // GetSubMenu function should retrieve a handle to the drop-down menu or submenu. - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)hConsMenu, "Actions"); - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - DrawMenuBar(FrameWnd); - - return TRUE; //DefMDIChildProc(hWnd, message, wParam, lParam); - - case MY_TRAY_ICON_MESSAGE: - - switch(lParam) - { - case WM_RBUTTONUP: - case WM_LBUTTONUP: - - GetCursorPos(&pos); - - SetForegroundWindow(hWnd); - - TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, hWnd, 0); - return 0; - } - - break; - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - if (wmId == IDC_ENIGATE) - { - int retCode, disp; - HKEY hKey=0; - - IGateEnabled = IsDlgButtonChecked(hWnd, IDC_ENIGATE); - - if (IGateEnabled) - ISDelayTimer = 60; - - retCode = RegCreateKeyEx(REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, // Reserved - 0, // Class - 0, // Options - KEY_ALL_ACCESS, - NULL, // Security Attrs - &hKey, - &disp); - - if (retCode == ERROR_SUCCESS) - { - retCode = RegSetValueEx(hKey,"IGateEnabled", 0 , REG_DWORD,(BYTE *)&IGateEnabled, 4); - RegCloseKey(hKey); - } - - return 0; - } - - if (wmId == BPQSAVENODES) - { - SaveNodes(); - WritetoConsole("Nodes Saved\n"); - return 0; - } - if (wmId == BPQCLEARRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - - ClearNodes(); - WritetoConsole("Nodes file Cleared\n"); - ReconfigFlag=TRUE; - WritetoConsole("Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - if (wmId == BPQRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - SaveNodes(); - WritetoConsole("Nodes Saved\n"); - ReconfigFlag=TRUE; - WritetoConsole("Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - - if (wmId == SCANRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - - RigReconfigFlag = TRUE; - WritetoConsole("Rigcontrol Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - - if (wmId == APRSRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - - APRSReconfigFlag=TRUE; - WritetoConsole("APRS Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - if (wmId == BPQDUMP) - { - DumpSystem(); - return 0; - } - - if (wmId == BPQCLOSEALL) - { - CloseAllPrograms(); - return 0; - } - - if (wmId == BPQUICONFIG) - { - int err, i=0; - char Title[80]; - WNDCLASS wc; - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = UIWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON) ); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = bgBrush; - - wc.lpszMenuName = NULL; - wc.lpszClassName = UIClassName; - - RegisterClass(&wc); - - UIhWnd = CreateDialog(hInstance, UIClassName,0,NULL); - - if (!UIhWnd) - { - err=GetLastError(); - return FALSE; - } - - wsprintf(Title,"BPQ32 Beacon Utility Version"); - MySetWindowText(UIhWnd, Title); - return 0; - } - - if (wmId == BPQSAVEREG) - { - CreateRegBackup(); - return 0; - } - - if (wmId == BPQMINTOTRAY) - { - MinimizetoTray = !MinimizetoTray; - - if (MinimizetoTray) - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_UNCHECKED); - - SaveConfig(); - return 0; - } - - if (wmId == BPQSTARTMIN) - { - StartMinimized = !StartMinimized; - - if (StartMinimized) - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_UNCHECKED); - - SaveConfig(); - return 0; - } - - if (wmId >= TRAYBASEID && wmId < (TRAYBASEID + 100)) - { - handle=hWndArray[wmId-TRAYBASEID]; - - if (handle == FrameWnd && FrameMaximized == TRUE) - PostMessage(handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); - else - PostMessage(handle, WM_SYSCOMMAND, SC_RESTORE, 0); - - SetForegroundWindow(handle); - return 0; - } - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_MINIMIZE: - - ConsoleMinimized = TRUE; - break; - - case SC_RESTORE: - - ConsoleMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - - case WM_SIZE: - - GetClientRect(hWnd, &cRect); - - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - -// InvalidateRect(hWnd, NULL, TRUE); - break; - -/* - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - - hOldFont = SelectObject( hdc, hFont) ; - - for (i=0; i 300) - len = 300; - - memcpy(&buffptr[2], buff, len + 1); - - C_Q_ADD(&WritetoConsoleQ, buffptr); - - return 0; -} - -int WritetoConsoleSupport(char * buff) -{ - - int len=strlen(buff); - char Temp[2000]= ""; - char * ptr; - - if (PartLine) - { - SendMessage(hWndCons, LB_GETTEXT, pindex, (LPARAM)(LPCTSTR) Temp); - SendMessage(hWndCons, LB_DELETESTRING, pindex, 0); - PartLine = FALSE; - } - - if ((strlen(Temp) + strlen(buff)) > 1990) - Temp[0] = 0; // Should never have anything this long - - strcat(Temp, buff); - - ptr = strchr(Temp, '\n'); - - if (ptr) - *ptr = 0; - else - PartLine = TRUE; - - pindex=SendMessage(hWndCons, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR) Temp); - return 0; - } - -DllExport VOID APIENTRY BPQOutputDebugString(char * String) -{ - OutputDebugString(String); - return; - } - -HANDLE handle; -char fn[]="BPQDUMP"; -ULONG cnt; -char * stack; -//char screen[1920]; -//COORD ReadCoord; - -#define DATABYTES 400000 - -extern UCHAR DATAAREA[]; - -DllExport int APIENTRY DumpSystem() -{ - char fn[200]; - char Msg[250]; - - sprintf(fn,"%s\\BPQDUMP",BPQDirectory); - - handle = CreateFile(fn, - GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - -#ifndef _WIN64 - - _asm { - - mov stack,esp - } - - WriteFile(handle,stack,128,&cnt,NULL); -#endif - -// WriteFile(handle,Screen,MAXLINELEN*MAXSCREENLEN,&cnt,NULL); - - WriteFile(handle,DATAAREA, DATABYTES,&cnt,NULL); - - CloseHandle(handle); - - sprintf(Msg, "Dump to %s Completed\n", fn); - WritetoConsole(Msg); - - FindLostBuffers(); - - return (0); -} - -BOOLEAN CheckifBPQ32isLoaded() -{ - HANDLE Mutex; - - // See if BPQ32 is running - if we create it in the NTVDM address space by - // loading bpq32.dll it will not work. - - Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"BPQLOCKMUTEX"); - - if (Mutex == NULL) - { - if (AttachingProcess == 0) // Already starting BPQ32 - { - OutputDebugString("BPQ32 No other bpq32 programs running - Loading BPQ32.exe\n"); - StartBPQ32(); - } - return FALSE; - } - - CloseHandle(Mutex); - - return TRUE; -} - -BOOLEAN StartBPQ32() -{ - UCHAR Value[100]; - - char bpq[]="BPQ32.exe"; - char *fn=(char *)&bpq; - HKEY hKey=0; - int ret,Type,Vallen=99; - - char Errbuff[100]; - char buff[20]; - - STARTUPINFO StartupInfo; // pointer to STARTUPINFO - PROCESS_INFORMATION ProcessInformation; // pointer to PROCESS_INFORMATION - - AttachingProcess = 1; - -// Get address of BPQ Directory - - Value[0]=0; - - ret = RegOpenKeyEx (REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (ret == ERROR_SUCCESS) - { - ret = RegQueryValueEx(hKey, "BPQ Program Directory", 0, &Type,(UCHAR *)&Value, &Vallen); - - if (ret == ERROR_SUCCESS) - { - if (strlen(Value) == 2 && Value[0] == '"' && Value[1] == '"') - Value[0]=0; - } - - - if (Value[0] == 0) - { - - // BPQ Directory absent or = "" - "try Config File Location" - - ret = RegQueryValueEx(hKey,"BPQ Directory",0, - &Type,(UCHAR *)&Value,&Vallen); - - if (ret == ERROR_SUCCESS) - { - if (strlen(Value) == 2 && Value[0] == '"' && Value[1] == '"') - Value[0]=0; - } - - } - RegCloseKey(hKey); - } - - if (Value[0] == 0) - { - strcpy(Value,fn); - } - else - { - strcat(Value,"\\"); - strcat(Value,fn); - } - - StartupInfo.cb=sizeof(StartupInfo); - StartupInfo.lpReserved=NULL; - StartupInfo.lpDesktop=NULL; - StartupInfo.lpTitle=NULL; - StartupInfo.dwFlags=0; - StartupInfo.cbReserved2=0; - StartupInfo.lpReserved2=NULL; - - if (!CreateProcess(Value,NULL,NULL,NULL,FALSE, - CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, - NULL,NULL,&StartupInfo,&ProcessInformation)) - { - ret=GetLastError(); - - _itoa(ret,buff,10); - - strcpy(Errbuff, "BPQ32 Load "); - strcat(Errbuff,Value); - strcat(Errbuff," failed "); - strcat(Errbuff,buff); - OutputDebugString(Errbuff); - AttachingProcess = 0; - return FALSE; - } - - return TRUE; -} - - -DllExport BPQVECSTRUC * APIENTRY GetIPVectorAddr() -{ - return &IPHOSTVECTOR; -} - -DllExport UINT APIENTRY GETSENDNETFRAMEADDR() -{ - return (UINT)&SENDNETFRAME; -} - -DllExport VOID APIENTRY RelBuff(VOID * Msg) -{ - UINT * pointer, * BUFF = Msg; - - if (Semaphore.Flag == 0) - Debugprintf("ReleaseBuffer called without semaphore"); - - pointer = FREE_Q; - - *BUFF =(UINT)pointer; - - FREE_Q = BUFF; - - QCOUNT++; - - return; -} - -extern int MINBUFFCOUNT; - -DllExport VOID * APIENTRY GetBuff() -{ - UINT * Temp = Q_REM(&FREE_Q); - - if (Semaphore.Flag == 0) - Debugprintf("GetBuff called without semaphore"); - - if (Temp) - { - QCOUNT--; - - if (QCOUNT < MINBUFFCOUNT) - MINBUFFCOUNT = QCOUNT; - } - - return Temp; -} - - -VOID __cdecl Debugprintf(const char * format, ...) -{ - char Mess[10000]; - va_list(arglist); - - va_start(arglist, format); - vsprintf(Mess, format, arglist); - strcat(Mess, "\r\n"); - OutputDebugString(Mess); - - return; -} - -unsigned short int compute_crc(unsigned char *buf, int txlen); - -extern SOCKADDR_IN reportdest; - -extern SOCKET ReportSocket; - -extern SOCKADDR_IN Chatreportdest; - -DllExport VOID APIENTRY SendChatReport(SOCKET ChatReportSocket, char * buff, int txlen) -{ - unsigned short int crc = compute_crc(buff, txlen); - - crc ^= 0xffff; - - buff[txlen++] = (crc&0xff); - buff[txlen++] = (crc>>8); - - sendto(ChatReportSocket, buff, txlen, 0, (LPSOCKADDR)&Chatreportdest, sizeof(Chatreportdest)); -} - -VOID CreateRegBackup() -{ - char Backup1[MAX_PATH]; - char Backup2[MAX_PATH]; - char RegFileName[MAX_PATH]; - char Msg[80]; - HANDLE handle; - int len, written; - char RegLine[300]; - -// SHELLEXECUTEINFO sei; -// STARTUPINFO SInfo; -// PROCESS_INFORMATION PInfo; - - sprintf(RegFileName, "%s\\BPQ32.reg", BPQDirectory); - - // Keep 4 Generations - - strcpy(Backup2, RegFileName); - strcat(Backup2, ".bak.3"); - - strcpy(Backup1, RegFileName); - strcat(Backup1, ".bak.2"); - - DeleteFile(Backup2); // Remove old .bak.3 - MoveFile(Backup1, Backup2); // Move .bak.2 to .bak.3 - - strcpy(Backup2, RegFileName); - strcat(Backup2, ".bak.1"); - - MoveFile(Backup2, Backup1); // Move .bak.1 to .bak.2 - - strcpy(Backup1, RegFileName); - strcat(Backup1, ".bak"); - - MoveFile(Backup1, Backup2); //Move .bak to .bak.1 - - strcpy(Backup2, RegFileName); - strcat(Backup2, ".bak"); - - CopyFile(RegFileName, Backup2, FALSE); // Copy to .bak - - handle = CreateFile(RegFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if (handle == INVALID_HANDLE_VALUE) - { - sprintf(Msg, "Failed to open Registry Save File\n"); - WritetoConsole(Msg); - return; - } - - len = sprintf(RegLine, "Windows Registry Editor Version 5.00\r\n\r\n"); - WriteFile(handle, RegLine, len, &written, NULL); - - if (SaveReg("Software\\G8BPQ\\BPQ32", handle)) - WritetoConsole("Registry Save complete\n"); - else - WritetoConsole("Registry Save failed\n"); - - CloseHandle(handle); - return ; -/* - - if (REGTREE == HKEY_LOCAL_MACHINE) // < Vista - { - sprintf(cmd, - "regedit /E \"%s\\BPQ32.reg\" %s\\Software\\G8BPQ\\BPQ32", BPQDirectory, REGTREETEXT); - - ZeroMemory(&SInfo, sizeof(SInfo)); - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0 ,NULL, NULL, &SInfo, &PInfo) == 0) - { - sprintf(Msg, "Error: CreateProcess for regedit failed 0%d\n", GetLastError() ); - WritetoConsole(Msg); - return; - } - } - else - { - - sprintf(cmd, - "/E \"%s\\BPQ32.reg\" %s\\Software\\G8BPQ\\BPQ32", BPQDirectory, REGTREETEXT); - - ZeroMemory(&sei, sizeof(sei)); - - sei.cbSize = sizeof(SHELLEXECUTEINFOW); - sei.hwnd = hWnd; - sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI; - sei.lpVerb = "runas"; - sei.lpFile = "regedit.exe"; - sei.lpParameters = cmd; - sei.nShow = SW_SHOWNORMAL; - - if (!ShellExecuteEx(&sei)) - { - sprintf(Msg, "Error: ShellExecuteEx for regedit failed %d\n", GetLastError() ); - WritetoConsole(Msg); - return; - } - } - - sprintf(Msg, "Registry Save Initiated\n", fn); - WritetoConsole(Msg); - - return ; -*/ -} - -BOOL CALLBACK EnumForCloseProc(HWND hwnd, LPARAM lParam) -{ - struct TNCINFO * TNC = (struct TNCINFO *)lParam; - UINT ProcessId; - - GetWindowThreadProcessId(hwnd, &ProcessId); - - for (i=0; i< AttachedProcesses; i++) - { - if (AttachedPIDList[i] == ProcessId) - { - Debugprintf("BPQ32 Close All Closing PID %d", ProcessId); - PostMessage(hwnd, WM_CLOSE, 1, 1); - // AttachedPIDList[i] = 0; // So we don't do it again - break; - } - } - - return (TRUE); -} -DllExport BOOL APIENTRY RestoreFrameWindow() -{ - return ShowWindow(FrameWnd, SW_RESTORE); -} - -DllExport VOID APIENTRY CreateNewTrayIcon() -{ - Shell_NotifyIcon(NIM_DELETE,&niData); - trayMenu = NULL; -} - -DllExport VOID APIENTRY CloseAllPrograms() -{ -// HANDLE hProc; - - // Close all attached BPQ32 programs - - Closing = TRUE; - - ShowWindow(FrameWnd, SW_RESTORE); - - GetWindowRect(FrameWnd, &FRect); - - SaveBPQ32Windows(); - CloseHostSessions(); - - if (AttachedProcesses == 1) - CloseBPQ32(); - - Debugprintf("BPQ32 Close All Processes %d PIDS %d %d %d %d", AttachedProcesses, AttachedPIDList[0], - AttachedPIDList[1], AttachedPIDList[2], AttachedPIDList[3]); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - EnumWindows(EnumForCloseProc, (LPARAM)NULL); -} - -#define MAX_KEY_LENGTH 255 -#define MAX_VALUE_NAME 16383 -#define MAX_VALUE_DATA 65536 - -BOOL CopyReg(HKEY hKeyIn, HKEY hKeyOut) -{ - TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name - DWORD cbName; // size of name string - TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name - DWORD cchClassName = MAX_PATH; // size of class string - DWORD cSubKeys=0; // number of subkeys - DWORD cbMaxSubKey; // longest subkey size - DWORD cchMaxClass; // longest class string - DWORD cValues; // number of values for key - DWORD cchMaxValue; // longest value name - DWORD cbMaxValueData; // longest value data - DWORD cbSecurityDescriptor; // size of security descriptor - FILETIME ftLastWriteTime; // last write time - - DWORD i, retCode; - - TCHAR achValue[MAX_VALUE_NAME]; - DWORD cchValue = MAX_VALUE_NAME; - - // Get the class name and the value count. - retCode = RegQueryInfoKey( - hKeyIn, // key handle - achClass, // buffer for class name - &cchClassName, // size of class string - NULL, // reserved - &cSubKeys, // number of subkeys - &cbMaxSubKey, // longest subkey size - &cchMaxClass, // longest class string - &cValues, // number of values for this key - &cchMaxValue, // longest value name - &cbMaxValueData, // longest value data - &cbSecurityDescriptor, // security descriptor - &ftLastWriteTime); // last write time - - // Enumerate the subkeys, until RegEnumKeyEx fails. - - if (cSubKeys) - { - Debugprintf( "\nNumber of subkeys: %d\n", cSubKeys); - - for (i=0; i 76) - { - len = sprintf(RegLine, "%s\\\r\n", RegLine); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - len = 2; - } - - len = sprintf(RegLine, "%s%02x,", RegLine, Value[k]); - } - RegLine[--len] = 0x0d; - RegLine[++len] = 0x0a; - len++; - - break; - - case REG_DWORD: //( 4 ) // 32-bit number -// case REG_DWORD_LITTLE_ENDIAN: //( 4 ) // 32-bit number (same as REG_DWORD) - - memcpy(&Intval, Value, 4); - len = sprintf(RegLine, "\"%s\"=dword:%08x\r\n", achValue, Intval); - break; - - case REG_DWORD_BIG_ENDIAN: //( 5 ) // 32-bit number - break; - case REG_LINK: //( 6 ) // Symbolic Link (unicode) - break; - case REG_MULTI_SZ: //( 7 ) // Multiple Unicode strings - - len = sprintf(RegLine, "\"%s\"=hex(7):%02x,00,", achValue, Value[0]); - for (k = 1; k < ValLen; k++) - { - if (len > 76) - { - len = sprintf(RegLine, "%s\\\r\n", RegLine); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - len = 2; - } - len = sprintf(RegLine, "%s%02x,", RegLine, Value[k]); - if (len > 76) - { - len = sprintf(RegLine, "%s\\\r\n", RegLine); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - } - len = sprintf(RegLine, "%s00,", RegLine); - } - - RegLine[--len] = 0x0d; - RegLine[++len] = 0x0a; - len++; - break; - - case REG_RESOURCE_LIST: //( 8 ) // Resource list in the resource map - break; - case REG_FULL_RESOURCE_DESCRIPTOR: //( 9 ) // Resource list in the hardware description - break; - case REG_RESOURCE_REQUIREMENTS_LIST://( 10 ) - break; - case REG_QWORD: //( 11 ) // 64-bit number -// case REG_QWORD_LITTLE_ENDIAN: //( 11 ) // 64-bit number (same as REG_QWORD) - break; - - } - - WriteFile(hFile, RegLine, len, &written, NULL); - } - } - } - - WriteFile(hFile, "\r\n", 2, &written, NULL); - - // Enumerate the subkeys, until RegEnumKeyEx fails. - - if (cSubKeys) - { - for (i=0; i> 1; - } - - Flags=GetApplFlags(i); - - if (OneBits > 1) - sprintf(&NewScreen[(i+1)*54],"%2d%s%3d %3d %3d %03x %3x %10s%-20s", - i, flag, RXCount(i), TXCount(i), MONCount(i), Mask, Flags, callsign, - BPQHOSTVECTOR[i-1].PgmName); - else - sprintf(&NewScreen[(i+1)*54],"%2d%s%3d %3d %3d %3d %3x %10s%-20s", - i, flag, RXCount(i), TXCount(i), MONCount(i), AppNumber, Flags, callsign, - BPQHOSTVECTOR[i-1].PgmName); - - } - } - - #include "StdExcept.c" - - if (Semaphore.Flag && Semaphore.SemProcessID == GetCurrentProcessId()) - FreeSemaphore(&Semaphore); - - } - - if (memcmp(Screen, NewScreen, 33 * 108) == 0) // No Change - return 0; - - memcpy(Screen, NewScreen, 33 * 108); - InvalidateRect(StatusWnd,NULL,FALSE); - - return(0); -} - -LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - PAINTSTRUCT ps; - HDC hdc; - HFONT hOldFont ; - HGLOBAL hMem; - MINMAXINFO * mmi; - int i; - - switch (message) - { - case WM_TIMER: - - if (Semaphore.Flag == 0) - DoStatus(); - break; - - case WM_MDIACTIVATE: - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)hConsMenu, "Actions"); - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - } - else - { - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - DrawMenuBar(FrameWnd); - - return TRUE; //DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_GETMINMAXINFO: - - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = 850; - mmi->ptMaxSize.y = 500; - mmi->ptMaxTrackSize.x = 850; - mmi->ptMaxTrackSize.y = 500; - - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - //Parse the menu selections: - - switch (wmId) - { - -/* - case BPQSTREAMS: - - CheckMenuItem(hMenu,BPQSTREAMS,MF_CHECKED); - CheckMenuItem(hMenu,BPQIPSTATUS,MF_UNCHECKED); - - StreamDisplay = TRUE; - - break; - - case BPQIPSTATUS: - - CheckMenuItem(hMenu,BPQSTREAMS,MF_UNCHECKED); - CheckMenuItem(hMenu,BPQIPSTATUS,MF_CHECKED); - - StreamDisplay = FALSE; - memset(Screen, ' ', 4000); - - - break; - -*/ - - case BPQCOPY: - - // - // Copy buffer to clipboard - // - hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 33*110); - - if (hMem != 0) - { - if (OpenClipboard(hWnd)) - { -// CopyScreentoBuffer(GlobalLock(hMem)); - GlobalUnlock(hMem); - EmptyClipboard(); - SetClipboardData(CF_TEXT,hMem); - CloseClipboard(); - } - else - { - GlobalFree(hMem); - } - - } - - break; - - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_MAXIMIZE: - - break; - - case SC_MINIMIZE: - - StatusMinimized = TRUE; - break; - - case SC_RESTORE: - - StatusMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - - hOldFont = SelectObject( hdc, hFont) ; - - for (i=0; i<33; i++) - { - TextOut(hdc,0,i*14,&Screen[i*108],108); - } - - SelectObject( hdc, hOldFont ) ; - EndPaint (hWnd, &ps); - - break; - - case WM_DESTROY: - -// PostQuitMessage(0); - - break; - - - default: - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - } - return (0); -} - -VOID SaveMDIWindowPos(HWND hWnd, char * RegKey, char * Value, BOOL Minimized) -{ - HKEY hKey=0; - char Size[80]; - char Key[80]; - int retCode, disp; - RECT Rect; - - if (IsWindow(hWnd) == FALSE) - return; - - ShowWindow(hWnd, SW_RESTORE); - - if (GetWindowRect(hWnd, &Rect) == FALSE) - return; - - // Make relative to Frame - - Rect.top -= FRect.top ; - Rect.left -= FRect.left; - Rect.bottom -= FRect.top; - Rect.right -= FRect.left; - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\%s", RegKey); - - retCode = RegCreateKeyEx(REGTREE, Key, 0, 0, 0, - KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - sprintf(Size,"%d,%d,%d,%d,%d", Rect.left, Rect.right, Rect.top ,Rect.bottom, Minimized); - retCode = RegSetValueEx(hKey, Value, 0, REG_SZ,(BYTE *)&Size, strlen(Size)); - RegCloseKey(hKey); - } -} - -extern int GPSPort; -extern char LAT[]; // in standard APRS Format -extern char LON[]; // in standard APRS Format - -VOID SaveBPQ32Windows() -{ - HKEY hKey=0; - char Size[80]; - int retCode, disp; - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - int i; - - retCode = RegCreateKeyEx(REGTREE, "SOFTWARE\\G8BPQ\\BPQ32", 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - sprintf(Size,"%d,%d,%d,%d", FRect.left, FRect.right, FRect.top, FRect.bottom); - retCode = RegSetValueEx(hKey, "FrameWindowSize", 0, REG_SZ, (BYTE *)&Size, strlen(Size)); - - // Save GPS Position - - if (GPSPort) - { - sprintf(Size, "%s, %s", LAT, LON); - retCode = RegSetValueEx(hKey, "GPS", 0, REG_SZ,(BYTE *)&Size, strlen(Size)); - } - - RegCloseKey(hKey); - } - - SaveMDIWindowPos(StatusWnd, "", "StatusWindowSize", StatusMinimized); - SaveMDIWindowPos(hConsWnd, "", "WindowSize", ConsoleMinimized); - - for (i=0; iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { - SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - } - } - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - SaveWindowPos(70); // Rigcontrol - - - if (hIPResWnd) - SaveMDIWindowPos(hIPResWnd, "", "IPResSize", IPMinimized); - - SaveHostSessions(); -} - -DllExport BOOL APIENTRY CheckIfOwner() -{ - // - // Returns TRUE if current process is root process - // that loaded the DLL - // - - if (TimerInst == GetCurrentProcessId()) - - return (TRUE); - else - return (FALSE); -} - -VOID GetParam(char * input, char * key, char * value) -{ - char * ptr = strstr(input, key); - char Param[2048]; - char * ptr1, * ptr2; - char c; - - - if (ptr) - { - ptr2 = strchr(ptr, '&'); - if (ptr2) *ptr2 = 0; - strcpy(Param, ptr + strlen(key)); - if (ptr2) *ptr2 = '&'; // Restore string - - // Undo any % transparency - - ptr1 = Param; - ptr2 = Param; - - 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; - - strcpy(value, Param); - } -} - -int GetListeningPortsPID(int Port) -{ - MIB_TCPTABLE_OWNER_PID * TcpTable = NULL; - PMIB_TCPROW_OWNER_PID Row; - int dwSize = 0; - DWORD n; - - // Get PID of process for this TCP Port - - // Get Length of table - - GetExtendedTcpTable(TcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0); - - TcpTable = malloc(dwSize); - - if (TcpTable == NULL) - return 0; - - GetExtendedTcpTable(TcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0); - - for (n = 0; n < TcpTable->dwNumEntries; n++) - { - Row = &TcpTable->table[n]; - - if (Row->dwLocalPort == Port && Row->dwState == MIB_TCP_STATE_LISTEN) - { - return Row->dwOwningPid; - break; - } - } - return 0; // Not found -} - -DllExport char * APIENTRY GetLOC() -{ - return LOC; -} - -DllExport void APIENTRY GetLatLon(double * lat, double * lon) -{ - *lat = LatFromLOC; - *lon = LonFromLOC; - return; -} - - -// UZ7HO Dll PTT interface - -// 1 ext_PTT_info -// 2 ext_PTT_settings -// 3 ext_PTT_OFF -// 4 ext_PTT_ON -// 5 ext_PTT_close -// 6 ext_PTT_open - -extern struct RIGINFO * DLLRIG; // Rig record for dll PTT interface (currently only for UZ7HO); - -VOID Rig_PTT(struct TNCINFO * TNC, BOOL PTTState); -VOID Rig_PTTEx(struct RIGINFO * RIG, BOOL PTTState, struct TNCINFO * TNC); - -int WINAPI ext_PTT_info() -{ - return 0; -} - -int WINAPI ext_PTT_settings() -{ - return 0; -} - -int WINAPI ext_PTT_OFF(int Port) -{ - if (DLLRIG) - Rig_PTTEx(DLLRIG, 0, 0); - - return 0; -} - -int WINAPI ext_PTT_ON(int Port) -{ - if (DLLRIG) - Rig_PTTEx(DLLRIG, 1, 0); - - return 0; -} -int WINAPI ext_PTT_close() -{ - if (DLLRIG) - Rig_PTTEx(DLLRIG, 0, 0); - - return 0; -} - -DllExport INT WINAPI ext_PTT_open() -{ - return 1; -} - -char * stristr (char *ch1, char *ch2) -{ - char *chN1, *chN2; - char *chNdx; - char *chRet = NULL; - - chN1 = _strdup(ch1); - chN2 = _strdup(ch2); - - if (chN1 && chN2) - { - chNdx = chN1; - while (*chNdx) - { - *chNdx = (char) tolower(*chNdx); - chNdx ++; - } - chNdx = chN2; - - while (*chNdx) - { - *chNdx = (char) tolower(*chNdx); - chNdx ++; - } - - chNdx = strstr(chN1, chN2); - - if (chNdx) - chRet = ch1 + (chNdx - chN1); - } - - free (chN1); - free (chN2); - return chRet; -} - diff --git a/Bpq32.c b/Bpq32.c index b6acf29..944010b 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1243,11 +1243,16 @@ 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 RHP 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) +// Add L4 RESET (Paula G8PZT's extension to NETROM) +// Fix problem using SENDRAW from BPQMail (63) +// Fix compatibility with latest ardopcf (64) +// Fix bug in RHP socket timeout code (65) #define CKernel diff --git a/Cmd.c b/Cmd.c index c5f43dd..9ff56fe 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)); @@ -4144,7 +3988,7 @@ VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struc if (ret & 0x8000) // Disconnecting { - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port in use\r"); + Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port in use (Disconnecting)\r"); SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); return; } @@ -4195,14 +4039,25 @@ VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struc - if (EXTPORT->ATTACHEDSESSIONS[sess] || PORT->PortSuspended) + if (EXTPORT->ATTACHEDSESSIONS[sess]) { // In use - Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port in use\r"); + Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port in use (Session Attached\r"); SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); return; } + + if (PORT->PortSuspended) + { + // In use + + Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port Suspended\r"); + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; + } + + // GET CIRCUIT TABLE ENTRY FOR OTHER END OF LINK NewSess = SetupNewSession(Session, Bufferptr); diff --git a/CommonCode-skigdebian.c b/CommonCode-skigdebian.c deleted file mode 100644 index 90e6a08..0000000 --- a/CommonCode-skigdebian.c +++ /dev/null @@ -1,5647 +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 -*/ - - - -// General C Routines common to bpq32 and linbpq. Mainly moved from BPQ32.c - -#pragma data_seg("_BPQDATA") - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include -#include -#include "mqtt.h" - -#pragma data_seg("_BPQDATA") - -#include "cheaders.h" -#include "tncinfo.h" -#include "configstructs.h" - -extern struct CONFIGTABLE xxcfg; - -#define LIBCONFIG_STATIC -#include "libconfig.h" - -#ifndef LINBPQ - -//#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. - -#include "commctrl.h" -#include "Commdlg.h" - -#endif - -struct TNCINFO * TNCInfo[71]; // Records are Malloc'd - -extern int ReportTimer; - -Dll VOID APIENTRY Send_AX(UCHAR * Block, DWORD Len, UCHAR Port); -TRANSPORTENTRY * SetupSessionFromHost(PBPQVECSTRUC HOST, UINT ApplMask); -int Check_Timer(); -VOID SENDUIMESSAGE(struct DATAMESSAGE * Msg); -DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot); -VOID APIENTRY md5 (char *arg, unsigned char * checksum); -VOID COMSetDTR(HANDLE fd); -VOID COMClearDTR(HANDLE fd); -VOID COMSetRTS(HANDLE fd); -VOID COMClearRTS(HANDLE fd); - -VOID WriteMiniDump(); -void printStack(void); -char * FormatMH(PMHSTRUC MH, char Format); -void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode); -void SendDataToPktMap(); - -extern BOOL LogAllConnects; -extern BOOL M0LTEMap; - -char * stristr (char *ch1, char *ch2); - -extern VOID * ENDBUFFERPOOL; - - -// Read/Write length field in a buffer header - -// Needed for Big/LittleEndian and ARM5 (unaligned operation problem) portability - - -VOID PutLengthinBuffer(PDATAMESSAGE buff, USHORT datalen) -{ - if (datalen <= sizeof(void *) + 4) - datalen = sizeof(void *) + 4; // Protect - - memcpy(&buff->LENGTH, &datalen, 2); -} - -int GetLengthfromBuffer(PDATAMESSAGE buff) -{ - USHORT Length; - - memcpy(&Length, &buff->LENGTH, 2); - return Length; -} - -BOOL CheckQHeadder(UINT * Q) -{ -#ifdef WIN32 - UINT Test; - - __try - { - Test = *Q; - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - Debugprintf("Invalid Q Header %p", Q); - printStack(); - return FALSE; - } -#endif - return TRUE; -} - -// Get buffer from Queue - - -VOID * _Q_REM(VOID **PQ, char * File, int Line) -{ - void ** Q; - void ** first; - VOID * next; - PMESSAGE Test; - - // PQ may not be word aligned, so copy as bytes (for ARM5) - - Q = PQ; - - if (Semaphore.Flag == 0) - Debugprintf("Q_REM called without semaphore from %s Line %d", File, Line); - - if (CheckQHeadder((UINT *) Q) == 0) - return(0); - - first = Q[0]; - - if (first == 0) - return (0); // Empty - - next = first[0]; // Address of next buffer - - Q[0] = next; - - // Make sure guard zone is zeros - - Test = (PMESSAGE)first; - - if (Test->GuardZone != 0) - { - Debugprintf("Q_REM %p GUARD ZONE CORRUPT %x Called from %s Line %d", first, Test->GuardZone, File, Line); - printStack(); - } - - return first; -} - -// Non=pool version (for IPGateway) - -VOID * _Q_REM_NP(VOID *PQ, char * File, int Line) -{ - void ** Q; - void ** first; - void * next; - - // PQ may not be word aligned, so copy as bytes (for ARM5) - - Q = PQ; - - if (CheckQHeadder((UINT *)Q) == 0) - return(0); - - first = Q[0]; - - if (first == 0) return (0); // Empty - - next = first[0]; // Address of next buffer - - Q[0] = next; - - return first; -} - -// Return Buffer to Free Queue - -extern VOID * BUFFERPOOL; -extern void ** Bufferlist[1000]; -void printStack(void); - -void _CheckGuardZone(char * File, int Line) -{ - int n = 0, i, offset = 0; - PMESSAGE Test; - UINT CodeDump[8]; - unsigned char * ptr; - - n = NUMBEROFBUFFERS; - - while (n--) - { - Test = (PMESSAGE)Bufferlist[n]; - - if (Test && Test->GuardZone) - { - Debugprintf("CheckGuardZone %p GUARD ZONE CORRUPT %d Called from %s Line %d", Test, Test->Process, File, Line); - - offset = 0; - ptr = (unsigned char *)Test; - - while (offset < 400) - { - memcpy(CodeDump, &ptr[offset], 32); - - for (i = 0; i < 8; i++) - CodeDump[i] = htonl(CodeDump[i]); - - Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ", - &ptr[offset], CodeDump[0], CodeDump[1], CodeDump[2], CodeDump[3], CodeDump[4], CodeDump[5], CodeDump[6], CodeDump[7]); - - offset += 32; - } - WriteMiniDump(); -#ifdef MDIKERNEL - CloseAllNeeded = 1; -#endif - } - - } -} - -UINT _ReleaseBuffer(VOID *pBUFF, char * File, int Line) -{ - void ** pointer, ** BUFF = pBUFF; - int n = 0; - void ** debug; - PMESSAGE Test; - UINT CodeDump[16]; - int i; - unsigned int rev; - - if (Semaphore.Flag == 0) - Debugprintf("ReleaseBuffer called without semaphore from %s Line %d", File, Line); - - // Make sure address is within pool - - if ((uintptr_t)BUFF < (uintptr_t)BUFFERPOOL || (uintptr_t)BUFF > (uintptr_t)ENDBUFFERPOOL) - { - // Not pointing to a buffer . debug points to the buffer that this is chained from - - // Dump first chunk and source tag - - memcpy(CodeDump, BUFF, 64); - - Debugprintf("Releasebuffer Buffer not in pool from %s Line %d, ptr %p prev %d", File, Line, BUFF, 0); - - for (i = 0; i < 16; i++) - { - rev = (CodeDump[i] & 0xff) << 24; - rev |= (CodeDump[i] & 0xff00) << 8; - rev |= (CodeDump[i] & 0xff0000) >> 8; - rev |= (CodeDump[i] & 0xff000000) >> 24; - - CodeDump[i] = rev; - } - - Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ", - Bufferlist[n], CodeDump[0], CodeDump[1], CodeDump[2], CodeDump[3], CodeDump[4], CodeDump[5], CodeDump[6], CodeDump[7]); - - Debugprintf(" %08x %08x %08x %08x %08x %08x %08x %08x", - CodeDump[8], CodeDump[9], CodeDump[10], CodeDump[11], CodeDump[12], CodeDump[13], CodeDump[14], CodeDump[15]); - - - return 0; - } - - Test = (PMESSAGE)pBUFF; - - if (Test->GuardZone != 0) - { - Debugprintf("_ReleaseBuffer %p GUARD ZONE CORRUPT %x Called from %s Line %d", pBUFF, Test->GuardZone, File, Line); - } - - while (n <= NUMBEROFBUFFERS) - { - if (BUFF == Bufferlist[n++]) - goto BOK1; - } - - Debugprintf("ReleaseBuffer %X not in Pool called from %s Line %d", BUFF, File, Line); - printStack(); - - return 0; - -BOK1: - - n = 0; - - // validate free Queue - - pointer = FREE_Q; - debug = &FREE_Q; - - while (pointer) - { - // Validate pointer to make sure it is in pool - it may be a duff address if Q is corrupt - - Test = (PMESSAGE)pointer; - - if (Test->GuardZone || (uintptr_t)pointer < (uintptr_t)BUFFERPOOL || (uintptr_t)pointer > (uintptr_t)ENDBUFFERPOOL) - { - // Not pointing to a buffer . debug points to the buffer that this is chained from - - // Dump first chunk and source tag - - memcpy(CodeDump, debug, 64); - - Debugprintf("Releasebuffer Pool Corruption n = %d, ptr %p prev %p", n, pointer, debug); - - for (i = 0; i < 16; i++) - { - rev = (CodeDump[i] & 0xff) << 24; - rev |= (CodeDump[i] & 0xff00) << 8; - rev |= (CodeDump[i] & 0xff0000) >> 8; - rev |= (CodeDump[i] & 0xff000000) >> 24; - - CodeDump[i] = rev; - } - - Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ", - Bufferlist[n], CodeDump[0], CodeDump[1], CodeDump[2], CodeDump[3], CodeDump[4], CodeDump[5], CodeDump[6], CodeDump[7]); - - Debugprintf(" %08x %08x %08x %08x %08x %08x %08x %08x", - CodeDump[8], CodeDump[9], CodeDump[10], CodeDump[11], CodeDump[12], CodeDump[13], CodeDump[14], CodeDump[15]); - - if (debug[400]) - Debugprintf(" %s", &debug[400]); - - } - - // See if already on free Queue - - if (pointer == BUFF) - { - Debugprintf("Trying to free buffer %p when already on FREE_Q called from %s Line %d", BUFF, File, Line); -// WriteMiniDump(); - return 0; - } - -// if (pointer[0] && pointer == pointer[0]) -// { -// Debugprintf("Buffer chained to itself"); -// return 0; -// } - - debug = pointer; - pointer = pointer[0]; - n++; - - if (n > 1000) - { - Debugprintf("Loop searching free chain - pointer = %p %p", debug, pointer); - return 0; - } - } - - pointer = FREE_Q; - - *BUFF = pointer; - - FREE_Q = BUFF; - - QCOUNT++; - - return 0; -} - -int _C_Q_ADD(VOID *PQ, VOID *PBUFF, char * File, int Line) -{ - void ** Q; - void ** BUFF = PBUFF; - void ** next; - PMESSAGE Test; - - - int n = 0; - -// PQ may not be word aligned, so copy as bytes (for ARM5) - - Q = PQ; - - if (Semaphore.Flag == 0) - Debugprintf("C_Q_ADD called without semaphore from %s Line %d", File, Line); - - if (CheckQHeadder((UINT *)Q) == 0) // Make sure Q header is readable - return(0); - - // Make sure guard zone is zeros - - Test = (PMESSAGE)PBUFF; - - if (Test->GuardZone != 0) - { - Debugprintf("C_Q_ADD %p GUARD ZONE CORRUPT %x Called from %s Line %d", PBUFF, Test->GuardZone, File, Line); - } - - Test = (PMESSAGE)Q; - - - - // Make sure address is within pool - - while (n <= NUMBEROFBUFFERS) - { - if (BUFF == Bufferlist[n++]) - goto BOK2; - } - - Debugprintf("C_Q_ADD %X not in Pool called from %s Line %d", BUFF, File, Line); - printStack(); - - return 0; - -BOK2: - - BUFF[0] = 0; // Clear chain in new buffer - - if (Q[0] == 0) // Empty - { - Q[0]=BUFF; // New one on front - return(0); - } - - next = Q[0]; - - while (next[0] != 0) - { - next = next[0]; // Chain to end of queue - } - next[0] = BUFF; // New one on end - - return(0); -} - -// Non-pool version - -int C_Q_ADD_NP(VOID *PQ, VOID *PBUFF) -{ - void ** Q; - void ** BUFF = PBUFF; - void ** next; - int n = 0; - -// PQ may not be word aligned, so copy as bytes (for ARM5) - - Q = PQ; - - if (CheckQHeadder((UINT *)Q) == 0) // Make sure Q header is readable - return(0); - - BUFF[0]=0; // Clear chain in new buffer - - if (Q[0] == 0) // Empty - { - Q[0]=BUFF; // New one on front -// memcpy(PQ, &BUFF, 4); - return 0; - } - next = Q[0]; - - while (next[0] != 0) - next=next[0]; // Chain to end of queue - - next[0] = BUFF; // New one on end - - return(0); -} - - -int C_Q_COUNT(VOID *PQ) -{ - void ** Q; - int count = 0; - -// PQ may not be word aligned, so copy as bytes (for ARM5) - - Q = PQ; - - if (CheckQHeadder((UINT *)Q) == 0) // Make sure Q header is readable - return(0); - - // SEE HOW MANY BUFFERS ATTACHED TO Q HEADER - - while (*Q) - { - count++; - if ((count + QCOUNT) > MAXBUFFS) - { - Debugprintf("C_Q_COUNT Detected corrupt Q %p len %d", PQ, count); - return count; - } - Q = *Q; - } - - return count; -} - -VOID * _GetBuff(char * File, int Line) -{ - UINT * Temp; - MESSAGE * Msg; - char * fptr = 0; - unsigned char * byteaddr; - - Temp = Q_REM(&FREE_Q); - -// FindLostBuffers(); - - if (Semaphore.Flag == 0) - Debugprintf("GetBuff called without semaphore from %s Line %d", File, Line); - - if (Temp) - { - QCOUNT--; - - if (QCOUNT < MINBUFFCOUNT) - MINBUFFCOUNT = QCOUNT; - - Msg = (MESSAGE *)Temp; - fptr = File + (int)strlen(File); - while (*fptr != '\\' && *fptr != '/') - fptr--; - fptr++; - - // Buffer Length is BUFFLEN, but buffers are allocated 512 - // So add file info in gap between - - byteaddr = (unsigned char *)Msg; - - - memset(&byteaddr[0], 0, 64); // simplify debugging lost buffers - memset(&byteaddr[400], 0, 64); // simplify debugging lost buffers - sprintf(&byteaddr[400], "%s %d", fptr, Line); - - Msg->Process = (short)GetCurrentProcessId(); - Msg->Linkptr = NULL; - Msg->Padding[0] = 0; // Used for modem status info - } - else - Debugprintf("Warning - Getbuff returned NULL"); - - return Temp; -} - -void * zalloc(int len) -{ - // malloc and clear - - void * ptr; - - ptr=malloc(len); - - if (ptr) - memset(ptr, 0, len); - - return ptr; -} - -char * strlop(char * buf, char delim) -{ - // Terminate buf at delim, and return rest of string - - char * ptr; - - if (buf == NULL) return NULL; // Protect - - ptr = strchr(buf, delim); - - if (ptr == NULL) return NULL; - - *(ptr)++=0; - - return ptr; -} - -VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer) -{ - UCHAR Type = L4->L4CIRCUITTYPE; - struct PORTCONTROL * PORT; - struct _LINKTABLE * LINK; - BPQVECSTRUC * VEC; - struct DEST_LIST * DEST; - - char Normcall[20] = ""; // Could be alias:call - char Normcall2[11] = ""; - char Alias[11] = ""; - - Buffer[0] = 0; - - switch (Type) - { - case PACTOR+UPLINK: - - PORT = L4->L4TARGET.PORT; - - ConvFromAX25(L4->L4USER, Normcall); - strlop(Normcall, ' '); - - if (PORT) - sprintf(Buffer, "%s %d/%d(%s)", "TNC Uplink Port", PORT->PORTNUMBER, L4->KAMSESSION, Normcall); - - return; - - - case PACTOR+DOWNLINK: - - PORT = L4->L4TARGET.PORT; - - if (PORT) - sprintf(Buffer, "%s %d/%d", "Attached to Port", PORT->PORTNUMBER, L4->KAMSESSION); - return; - - - case L2LINK+UPLINK: - - LINK = L4->L4TARGET.LINK; - - ConvFromAX25(L4->L4USER, Normcall); - strlop(Normcall, ' '); - - if (LINK &&LINK->LINKPORT) - sprintf(Buffer, "%s %d(%s)", "Uplink", LINK->LINKPORT->PORTNUMBER, Normcall); - - return; - - case L2LINK+DOWNLINK: - - LINK = L4->L4TARGET.LINK; - - if (LINK == NULL) - return; - - ConvFromAX25(LINK->OURCALL, Normcall); - strlop(Normcall, ' '); - - ConvFromAX25(LINK->LINKCALL, Normcall2); - strlop(Normcall2, ' '); - - sprintf(Buffer, "%s %d(%s %s)", "Downlink", LINK->LINKPORT->PORTNUMBER, Normcall, Normcall2); - return; - - case BPQHOST + UPLINK: - case BPQHOST + DOWNLINK: - - // if the call has a Level 4 address display ALIAS:CALL, else just Call - - if (FindDestination(L4->L4USER, &DEST)) - Normcall[DecodeNodeName(DEST->DEST_CALL, Normcall)] = 0; // null terminate - else - Normcall[ConvFromAX25(L4->L4USER, Normcall)] = 0; - - VEC = L4->L4TARGET.HOST; - sprintf(Buffer, "%s%02d(%s)", "Host", (int)(VEC - BPQHOSTVECTOR) + 1, Normcall); - return; - - case SESSION + DOWNLINK: - case SESSION + UPLINK: - - ConvFromAX25(L4->L4USER, Normcall); - strlop(Normcall, ' '); - - DEST = L4->L4TARGET.DEST; - - if (DEST == NULL) - return; - - ConvFromAX25(DEST->DEST_CALL, Normcall2); - strlop(Normcall2, ' '); - - memcpy(Alias, DEST->DEST_ALIAS, 6); - strlop(Alias, ' '); - - sprintf(Buffer, "Circuit(%s:%s %s)", Alias, Normcall2, Normcall); - - return; - } -} - -VOID CheckForDetach(struct TNCINFO * TNC, int Stream, struct STREAMINFO * STREAM, - VOID TidyCloseProc(struct TNCINFO * TNC, int Stream), VOID ForcedCloseProc(struct TNCINFO * TNC, int Stream), VOID CloseComplete(struct TNCINFO * TNC, int Stream)) -{ - void ** buffptr; - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] == 0) - { - // Node has disconnected - clear any connection - - if (STREAM->Disconnecting) - { - // Already detected the detach, and have started to close - - STREAM->DisconnectingTimeout--; - - if (STREAM->DisconnectingTimeout) - return; // Give it a bit longer - - // Close has timed out - force a disc, and clear - - ForcedCloseProc(TNC, Stream); // Send Tidy Disconnect - - goto NotConnected; - } - - // New Disconnect - - Debugprintf("New Disconnect Port %d Q %x", TNC->Port, STREAM->BPQtoPACTOR_Q); - - if (STREAM->Connected || STREAM->Connecting) - { - - // Need to do a tidy close - - STREAM->Connecting = FALSE; - STREAM->Disconnecting = TRUE; - STREAM->DisconnectingTimeout = 300; // 30 Secs - - if (Stream == 0) - SetWindowText(TNC->xIDC_TNCSTATE, "Disconnecting"); - - // Create a traffic record - - hookL4SessionDeleted(TNC, STREAM); - - if (STREAM->BPQtoPACTOR_Q) // Still data to send? - return; // Will close when all acked - -// if (STREAM->FramesOutstanding && TNC->Hardware == H_UZ7HO) -// return; // Will close when all acked - - TidyCloseProc(TNC, Stream); // Send Tidy Disconnect - - return; - } - - // Not connected -NotConnected: - - STREAM->Disconnecting = FALSE; - STREAM->Attached = FALSE; - STREAM->Connecting = FALSE; - STREAM->Connected = FALSE; - - if (Stream == 0) - SetWindowText(TNC->xIDC_TNCSTATE, "Free"); - - STREAM->FramesQueued = 0; - STREAM->FramesOutstanding = 0; - - CloseComplete(TNC, Stream); - - if (TNC->DefaultRXFreq && TNC->RXRadio) - { - char Msg[128]; - - sprintf(Msg, "R%d %f", TNC->RXRadio, TNC->DefaultRXFreq); - Rig_Command( (TRANSPORTENTRY *) -1, Msg); - } - - if (TNC->DefaultTXFreq && TNC->TXRadio && TNC->TXRadio != TNC->RXRadio) - { - char Msg[128]; - - sprintf(Msg, "R%d %f", TNC->TXRadio, TNC->DefaultTXFreq); - Rig_Command( (TRANSPORTENTRY *) -1, Msg); - } - - while(STREAM->BPQtoPACTOR_Q) - { - buffptr=Q_REM(&STREAM->BPQtoPACTOR_Q); - ReleaseBuffer(buffptr); - } - - while(STREAM->PACTORtoBPQ_Q) - { - buffptr=Q_REM(&STREAM->PACTORtoBPQ_Q); - ReleaseBuffer(buffptr); - } - } -} - -char * CheckAppl(struct TNCINFO * TNC, char * Appl) -{ - APPLCALLS * APPL; - BPQVECSTRUC * PORTVEC; - int Allocated = 0, Available = 0; - int App, Stream; - struct TNCINFO * APPLTNC; - -// Debugprintf("Checking if %s is running", Appl); - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - - if (_memicmp(APPL->APPLCMD, Appl, 12) == 0) - { - int _APPLMASK = 1 << App; - - // If App has an alias, assume it is running , unless a CMS alias - then check CMS - - if (APPL->APPLHASALIAS) - { - if (_memicmp(APPL->APPLCMD, "RELAY ", 6) == 0) - return APPL->APPLCALL_TEXT; // Assume people using RELAY know what they are doing - - if (APPL->APPLPORT && (_memicmp(APPL->APPLCMD, "RMS ", 4) == 0)) - { - APPLTNC = TNCInfo[APPL->APPLPORT]; - { - if (APPLTNC) - { - if (APPLTNC->TCPInfo && !APPLTNC->TCPInfo->CMSOK && !APPLTNC->TCPInfo->FallbacktoRelay) - return NULL; - } - } - } - return APPL->APPLCALL_TEXT; - } - - // See if App is running - - PORTVEC = &BPQHOSTVECTOR[0]; - - for (Stream = 0; Stream < 64; Stream++) - { - if (PORTVEC->HOSTAPPLMASK & _APPLMASK) - { - Allocated++; - - if (PORTVEC->HOSTSESSION == 0 && (PORTVEC->HOSTFLAGS & 3) == 0) - { - // Free and no outstanding report - - return APPL->APPLCALL_TEXT; // Running - } - } - PORTVEC++; - } - } - } - - return NULL; // Not Running -} - -VOID SetApplPorts() -{ - // If any appl has an alias, get port number - - struct APPLCONFIG * App; - APPLCALLS * APPL; - - char C[80]; - char Port[80]; - char Call[80]; - - int i, n; - - App = &xxcfg.C_APPL[0]; - - for (i=0; i < NumberofAppls; i++) - { - APPL=&APPLCALLTABLE[i]; - - if (APPL->APPLHASALIAS) - { - n = sscanf(App->CommandAlias, "%s %s %s", &C[0], &Port[0], &Call[0]); - if (n == 3) - APPL->APPLPORT = atoi(Port); - } - App++; - } -} - - -char Modenames[19][10] = {"WINMOR", "SCS", "KAM", "AEA", "HAL", "TELNET", "TRK", - "V4", "UZ7HO", "MPSK", "FLDIGI", "UIARQ", "ARDOP", "VARA", - "SERIAL", "KISSHF", "WINRPR", "HSMODEM", "FREEDATA"}; - -BOOL ProcessIncommingConnect(struct TNCINFO * TNC, char * Call, int Stream, BOOL SENDCTEXT) -{ - return ProcessIncommingConnectEx(TNC, Call, Stream, SENDCTEXT, FALSE); -} - -BOOL ProcessIncommingConnectEx(struct TNCINFO * TNC, char * Call, int Stream, BOOL SENDCTEXT, BOOL AllowTR) -{ - TRANSPORTENTRY * Session; - int Index = 0; - PMSGWITHLEN buffptr; - int Totallen = 0; - UCHAR * ptr; - struct PORTCONTROL * PORT = (struct PORTCONTROL *)TNC->PortRecord; - struct STREAMINFO * STREAM = &TNC->Streams[Stream]; - - // Stop Scanner - - if (Stream == 0 || TNC->Hardware == H_UZ7HO) - { - char Msg[80]; - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command( (TRANSPORTENTRY *) -1, Msg); - - UpdateMH(TNC, Call, '+', 'I'); - } - - Session = L4TABLE; - - // Find a free Circuit Entry - - while (Index < MAXCIRCUITS) - { - if (Session->L4USER[0] == 0) - break; - - Session++; - Index++; - } - - if (Index == MAXCIRCUITS) - return FALSE; // Tables Full - - memset(Session, 0, sizeof(TRANSPORTENTRY)); - - memcpy(STREAM->RemoteCall, Call, 9); // Save Text Callsign - - // May be subsequently rejected but a good place to capture calls - - hookL4SessionAccepted(STREAM, Call, TNC->TargetCall); - - if (AllowTR) - ConvToAX25Ex(Call, Session->L4USER); // Allow -T and -R SSID's for MPS - else - ConvToAX25(Call, Session->L4USER); - ConvToAX25(MYNODECALL, Session->L4MYCALL); - Session->CIRCUITINDEX = Index; - Session->CIRCUITID = NEXTID; - NEXTID++; - if (NEXTID == 0) NEXTID++; // Keep non-zero - - TNC->PortRecord->ATTACHEDSESSIONS[Stream] = Session; - STREAM->Attached = TRUE; - - Session->L4TARGET.EXTPORT = TNC->PortRecord; - - Session->L4CIRCUITTYPE = UPLINK+PACTOR; - Session->L4WINDOW = L4DEFAULTWINDOW; - Session->L4STATE = 5; - Session->SESSIONT1 = L4T1; - Session->SESSPACLEN = TNC->PortRecord->PORTCONTROL.PORTPACLEN; - Session->KAMSESSION = Stream; - - STREAM->Connected = TRUE; // Subsequent data to data channel - - if (LogAllConnects) - { - if (TNC->TargetCall[0]) - WriteConnectLog(Call, TNC->TargetCall, Modenames[TNC->Hardware - 1]); - else - WriteConnectLog(Call, MYNODECALL, Modenames[TNC->Hardware - 1]); - } - - if (SENDCTEXT == 0) - return TRUE; - - // if Port CTEXT defined, use it - - if (PORT->CTEXT) - { - Totallen = strlen(PORT->CTEXT); - ptr = PORT->CTEXT; - } - else if (HFCTEXTLEN > 0) - { - Totallen = HFCTEXTLEN; - ptr = HFCTEXT; - } - else - return TRUE; - - while (Totallen > 0) - { - int sendLen = TNC->PortRecord->ATTACHEDSESSIONS[Stream]->SESSPACLEN; - - if (sendLen == 0) - sendLen = 80; - - if (Totallen < sendLen) - sendLen = Totallen; - - buffptr = (PMSGWITHLEN)GetBuff(); - if (buffptr == 0) return TRUE; // No buffers - - buffptr->Len = sendLen; - memcpy(&buffptr->Data[0], ptr, sendLen); - C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr); - Totallen -= sendLen; - ptr += sendLen; - } - return TRUE; -} - -char * Config; -static char * ptr1, * ptr2; - -BOOL ReadConfigFile(int Port, int ProcLine(char * buf, int Port)) -{ - char buf[256],errbuf[256]; - - if (TNCInfo[Port]) // If restarting, free old config - free(TNCInfo[Port]); - - TNCInfo[Port] = NULL; - - Config = PortConfig[Port]; - - if (Config) - { - // Using config from bpq32.cfg - - if (strlen(Config) == 0) - { - // Empty Config File - OK for most types - - struct TNCINFO * TNC = TNCInfo[Port] = zalloc(sizeof(struct TNCINFO)); - - TNC->InitScript = malloc(2); - TNC->InitScript[0] = 0; - - return TRUE; - } - - ptr1 = Config; - - ptr2 = strchr(ptr1, 13); - while(ptr2) - { - memcpy(buf, ptr1, ptr2 - ptr1 + 1); - buf[ptr2 - ptr1 + 1] = 0; - ptr1 = ptr2 + 2; - ptr2 = strchr(ptr1, 13); - - strcpy(errbuf,buf); // save in case of error - - if (!ProcLine(buf, Port)) - { - WritetoConsoleLocal("\n"); - WritetoConsoleLocal("Bad config record "); - WritetoConsoleLocal(errbuf); - } - } - } - else - { - sprintf(buf," ** Error - No Configuration info in bpq32.cfg"); - WritetoConsoleLocal(buf); - } - - return (TRUE); -} -int GetLine(char * buf) -{ -loop: - - if (ptr2 == NULL) - return 0; - - memcpy(buf, ptr1, ptr2 - ptr1 + 2); - buf[ptr2 - ptr1 + 2] = 0; - ptr1 = ptr2 + 2; - ptr2 = strchr(ptr1, 13); - - if (buf[0] < 0x20) goto loop; - if (buf[0] == '#') goto loop; - if (buf[0] == ';') goto loop; - - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - buf[strlen(buf)] = 13; - - return 1; -} -VOID DigiToMultiplePorts(struct PORTCONTROL * PORTVEC, PMESSAGE Msg) -{ - USHORT Mask=PORTVEC->DIGIMASK; - int i; - - for (i=1; i<=NUMBEROFPORTS; i++) - { - if (Mask & 1) - { - // Block includes the Msg Header (7/11 bytes), Len Does not! - - Msg->PORT = i; - Send_AX((UCHAR *)&Msg, Msg->LENGTH - MSGHDDRLEN, i); - Mask>>=1; - } - } -} - -int CompareAlias(struct DEST_LIST ** a, struct DEST_LIST ** b) -{ - return memcmp(a[0]->DEST_ALIAS, b[0]->DEST_ALIAS, 6); - /* strcmp functions works exactly as expected from comparison function */ -} - - -int CompareNode(struct DEST_LIST ** a, struct DEST_LIST ** b) -{ - return memcmp(a[0]->DEST_CALL, b[0]->DEST_CALL, 7); -} - -DllExport int APIENTRY CountFramesQueuedOnStream(int Stream) -{ - BPQVECSTRUC * PORTVEC = &BPQHOSTVECTOR[Stream-1]; // API counts from 1 - TRANSPORTENTRY * L4 = PORTVEC->HOSTSESSION; - - int Count = 0; - - if (L4) - { - if (L4->L4CROSSLINK) // CONNECTED? - Count = CountFramesQueuedOnSession(L4->L4CROSSLINK); - else - Count = CountFramesQueuedOnSession(L4); - } - return Count; -} - -DllExport int APIENTRY ChangeSessionCallsign(int Stream, unsigned char * AXCall) -{ - // Equivalent to "*** linked to" command - - memcpy(BPQHOSTVECTOR[Stream-1].HOSTSESSION->L4USER, AXCall, 7); - return (0); -} - -DllExport int APIENTRY ChangeSessionPaclen(int Stream, int Paclen) -{ - BPQHOSTVECTOR[Stream-1].HOSTSESSION->SESSPACLEN = Paclen; - return (0); -} - -DllExport int APIENTRY ChangeSessionIdletime(int Stream, int idletime) -{ - if (BPQHOSTVECTOR[Stream-1].HOSTSESSION) - BPQHOSTVECTOR[Stream-1].HOSTSESSION->L4LIMIT = idletime; - return (0); -} - -DllExport int APIENTRY Get_APPLMASK(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].HOSTAPPLMASK; -} -DllExport int APIENTRY GetStreamPID(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].STREAMOWNER; -} - -DllExport int APIENTRY GetApplFlags(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].HOSTAPPLFLAGS; -} - -DllExport int APIENTRY GetApplNum(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].HOSTAPPLNUM; -} - -DllExport int APIENTRY GetApplMask(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].HOSTAPPLMASK; -} - -DllExport BOOL APIENTRY GetAllocationState(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].HOSTFLAGS & 0x80; -} - -VOID Send_AX_Datagram(PDIGIMESSAGE Block, DWORD Len, UCHAR Port); - -extern int InitDone; -extern int SemHeldByAPI; -extern char pgm[256]; // Uninitialised so per process -extern int BPQHOSTAPI(); - - -VOID POSTSTATECHANGE(BPQVECSTRUC * SESS) -{ - // Post a message if requested -#ifndef LINBPQ - if (SESS->HOSTHANDLE) - PostMessage(SESS->HOSTHANDLE, BPQMsg, SESS->HOSTSTREAM, 4); -#endif - return; -} - - -DllExport int APIENTRY SessionControl(int stream, int command, int Mask) -{ - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return (0); - - SESS = &BPQHOSTVECTOR[stream]; - - // Send Session Control command (BPQHOST function 6) - //; CL=0 CONNECT USING APPL MASK IN DL - //; CL=1, CONNECT. CL=2 - DISCONNECT. CL=3 RETURN TO NODE - - if (command > 1) - { - // Disconnect - - if (SESS->HOSTSESSION == 0) - { - SESS->HOSTFLAGS |= 1; // State Change - POSTSTATECHANGE(SESS); - return 0; // NOT CONNECTED - } - - if (command == 3) - SESS->HOSTFLAGS |= 0x20; // Set Stay - - SESS->HOSTFLAGS |= 0x40; // SET 'DISC REQ' FLAG - - return 0; - } - - // 0 or 1 - connect - - if (SESS->HOSTSESSION) // ALREADY CONNECTED - { - SESS->HOSTFLAGS |= 1; // State Change - POSTSTATECHANGE(SESS); - return 0; - } - - // SET UP A SESSION FOR THE CONSOLE - - SESS->HOSTFLAGS |= 0x80; // SET ALLOCATED BIT - - if (command == 1) // Zero is mask supplied by caller - Mask = SESS->HOSTAPPLMASK; // SO WE GET CORRECT CALLSIGN - - L4 = SetupSessionFromHost(SESS, Mask); - - if (L4 == 0) // tables Full - { - SESS->HOSTFLAGS |= 3; // State Change - POSTSTATECHANGE(SESS); - return 0; - } - - SESS->HOSTSESSION = L4; - L4->L4CIRCUITTYPE = BPQHOST | UPLINK; - L4->Secure_Session = AuthorisedProgram; // Secure Host Session - - SESS->HOSTFLAGS |= 1; // State Change - POSTSTATECHANGE(SESS); - return 0; // ALREADY CONNECTED -} - -int FindFreeStreamEx(int GetSem); - -int FindFreeStreamNoSem() -{ - return FindFreeStreamEx(0); -} - -DllExport int APIENTRY FindFreeStream() -{ - return FindFreeStreamEx(1); -} - -int FindFreeStreamEx(int GetSem) -{ - int stream, n; - BPQVECSTRUC * PORTVEC; - -// Returns number of first unused BPQHOST stream. If none available, -// returns 255. See API function 13. - - // if init has not yet been run, wait. - - while (InitDone == 0) - { - Debugprintf("Waiting for init to complete"); - Sleep(1000); - } - - if (InitDone == -1) // Init failed - exit(0); - - if (GetSem) - GetSemaphore(&Semaphore, 9); - - stream = 0; - n = 64; - - while (n--) - { - PORTVEC = &BPQHOSTVECTOR[stream++]; - if ((PORTVEC->HOSTFLAGS & 0x80) == 0) - { - PORTVEC->STREAMOWNER=GetCurrentProcessId(); - PORTVEC->HOSTFLAGS = 128; // SET ALLOCATED BIT, clear others - memcpy(&PORTVEC->PgmName[0], pgm, 31); - if (GetSem) - FreeSemaphore(&Semaphore); - return stream; - } - } - - if (GetSem) - FreeSemaphore(&Semaphore); - - return 255; -} - -DllExport int APIENTRY AllocateStream(int stream) -{ -// Allocate stream. If stream is already allocated, return nonzero. -// Otherwise allocate stream, and return zero. - - BPQVECSTRUC * PORTVEC = &BPQHOSTVECTOR[stream -1]; // API counts from 1 - - if ((PORTVEC->HOSTFLAGS & 0x80) == 0) - { - PORTVEC->STREAMOWNER=GetCurrentProcessId(); - PORTVEC->HOSTFLAGS = 128; // SET ALLOCATED BIT, clear others - memcpy(&PORTVEC->PgmName[0], pgm, 31); - FreeSemaphore(&Semaphore); - return 0; - } - - return 1; // Already allocated -} - - -DllExport int APIENTRY DeallocateStream(int stream) -{ - BPQVECSTRUC * PORTVEC; - UINT * monbuff; - BOOL GotSem = Semaphore.Flag; - -// Release stream. - - stream--; - - if (stream < 0 || stream > 63) - return (0); - - PORTVEC=&BPQHOSTVECTOR[stream]; - - PORTVEC->STREAMOWNER=0; - PORTVEC->PgmName[0] = 0; - PORTVEC->HOSTAPPLFLAGS=0; - PORTVEC->HOSTAPPLMASK=0; - PORTVEC->HOSTHANDLE=0; - - // Clear Trace Queue - - if (PORTVEC->HOSTSESSION) - SessionControl(stream + 1, 2, 0); - - if (GotSem == 0) - GetSemaphore(&Semaphore, 0); - - while (PORTVEC->HOSTTRACEQ) - { - monbuff = Q_REM((void *)&PORTVEC->HOSTTRACEQ); - ReleaseBuffer(monbuff); - } - - if (GotSem == 0) - FreeSemaphore(&Semaphore); - - PORTVEC->HOSTFLAGS &= 0x60; // Clear Allocated. Must leave any DISC Pending bits - - return(0); -} -DllExport int APIENTRY SessionState(int stream, int * state, int * change) -{ - // Get current Session State. Any state changed is ACK'ed - // automatically. See BPQHOST functions 4 and 5. - - BPQVECSTRUC * HOST = &BPQHOSTVECTOR[stream -1]; // API counts from 1 - - Check_Timer(); // In case Appl doesnt call it often ehough - - GetSemaphore(&Semaphore, 20); - - // CX = 0 if stream disconnected or CX = 1 if stream connected - // DX = 0 if no change of state since last read, or DX = 1 if - // the connected/disconnected state has changed since - // last read (ie. delta-stream status). - - // HOSTFLAGS = Bit 80 = Allocated - // Bit 40 = Disc Request - // Bit 20 = Stay Flag - // Bit 02 and 01 State Change Bits - - if ((HOST->HOSTFLAGS & 3) == 0) - // No Chaange - *change = 0; - else - *change = 1; - - if (HOST->HOSTSESSION) // LOCAL SESSION - // Connected - *state = 1; - else - *state = 0; - - HOST->HOSTFLAGS &= 0xFC; // Clear Change Bitd - - FreeSemaphore(&Semaphore); - return 0; -} - -DllExport int APIENTRY SessionStateNoAck(int stream, int * state) -{ - // Get current Session State. Dont ACK any change - // See BPQHOST function 4 - - BPQVECSTRUC * HOST = &BPQHOSTVECTOR[stream -1]; // API counts from 1 - - Check_Timer(); // In case Appl doesnt call it often ehough - - if (HOST->HOSTSESSION) // LOCAL SESSION - // Connected - *state = 1; - else - *state = 0; - - return 0; -} - - -int SendMsgEx(int stream, char * msg, int len, int GetSem); - -int SendMsgNoSem(int stream, char * msg, int len) -{ - return SendMsgEx(stream, msg, len, 0); -} - -DllExport int APIENTRY SendMsg(int stream, char * msg, int len) -{ - return SendMsgEx(stream, msg, len, 1); -} - - -int SendMsgEx(int stream, char * msg, int len, int GetSem) -{ - // Send message to stream (BPQHOST Function 2) - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - TRANSPORTENTRY * Partner; - PDATAMESSAGE MSG; - - Check_Timer(); - - if (len > 256) - return 0; // IGNORE - - if (stream == 0) - { - // Send UNPROTO - SEND FRAME TO ALL RADIO PORTS - - // COPY DATA TO A BUFFER IN OUR SEGMENTS - SIMPLFIES THINGS LATER - - if (QCOUNT < 50) - return 0; // Dont want to run out - - if (GetSem) - GetSemaphore(&Semaphore, 10); - - if ((MSG = GetBuff()) == 0) - { - if (GetSem) - FreeSemaphore(&Semaphore); - return 0; - } - - MSG->PID = 0xF0; // Normal Data PID - - memcpy(&MSG->L2DATA[0], msg, len); - MSG->LENGTH = (len + MSGHDDRLEN + 1); - - SENDUIMESSAGE(MSG); - ReleaseBuffer(MSG); - if (GetSem) - FreeSemaphore(&Semaphore); - return 0; - } - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - if (L4 == 0) - return 0; - - if (GetSem) - GetSemaphore(&Semaphore, 22); - - SESS->HOSTFLAGS |= 0x80; // SET ALLOCATED BIT - - if (QCOUNT < 40) // PLENTY FREE? - { - if (GetSem) - FreeSemaphore(&Semaphore); - return 1; - } - - // Dont allow massive queues to form - - if (QCOUNT < 100) - { - int n = CountFramesQueuedOnStream(stream + 1); - - if (n > 100) - { - Debugprintf("Stream %d QCOUNT %d Q Len %d - discarding", stream, QCOUNT, n); - if (GetSem) - FreeSemaphore(&Semaphore); - return 1; - } - } - - if ((MSG = GetBuff()) == 0) - { - if (GetSem) - FreeSemaphore(&Semaphore); - return 1; - } - - MSG->PID = 0xF0; // Normal Data PID - - memcpy(&MSG->L2DATA[0], msg, len); - MSG->LENGTH = len + MSGHDDRLEN + 1; - - // IF CONNECTED, PASS MESSAGE TO TARGET CIRCUIT - FLOW CONTROL AND - // DELAYED DISC ONLY WORK ON ONE SIDE - - Partner = L4->L4CROSSLINK; - - L4->L4KILLTIMER = 0; // RESET SESSION TIMEOUT - - if (Partner && Partner->L4STATE > 4) // Partner and link up - { - // Connected - - Partner->L4KILLTIMER = 0; // RESET SESSION TIMEOUT - C_Q_ADD(&Partner->L4TX_Q, MSG); - PostDataAvailable(Partner); - } - else - C_Q_ADD(&L4->L4RX_Q, MSG); - - if (GetSem) - FreeSemaphore(&Semaphore); - return 0; -} -DllExport int APIENTRY SendRaw(int port, char * msg, int len) -{ - struct PORTCONTROL * PORT; - MESSAGE * MSG; - - Check_Timer(); - - // Send Raw (KISS mode) frame to port (BPQHOST function 10) - - if (len > (MAXDATA - (MSGHDDRLEN + 8))) - return 0; - - if (QCOUNT < 50) - return 1; - - // GET A BUFFER - - PORT = GetPortTableEntryFromSlot(port); - - if (PORT == 0) - return 0; - - GetSemaphore(&Semaphore, 24); - - MSG = GetBuff(); - - if (MSG == 0) - { - FreeSemaphore(&Semaphore); - return 1; - } - - memcpy(MSG->DEST, msg, len); - - MSG->LENGTH = len + MSGHDDRLEN; - - if (PORT->PROTOCOL == 10 && PORT->TNC && PORT->TNC->Hardware != H_KISSHF) // PACTOR/WINMOR Style - { - // Pactor Style. Probably will only be used for Tracker unless we do APRS over V4 or WINMOR - - EXTPORTDATA * EXTPORT = (EXTPORTDATA *) PORT; - - C_Q_ADD(&EXTPORT->UI_Q, MSG); - - FreeSemaphore(&Semaphore); - return 0; - } - - MSG->PORT = PORT->PORTNUMBER; - - PUT_ON_PORT_Q(PORT, MSG); - - FreeSemaphore(&Semaphore); - return 0; -} - -DllExport time_t APIENTRY GetRaw(int stream, char * msg, int * len, int * count) -{ - time_t Stamp; - BPQVECSTRUC * SESS; - PMESSAGE MSG; - int Msglen; - - Check_Timer(); - - *len = 0; - *count = 0; - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - - GetSemaphore(&Semaphore, 26); - - if (SESS->HOSTTRACEQ == 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - MSG = Q_REM((void *)&SESS->HOSTTRACEQ); - - Msglen = MSG->LENGTH; - - if (Msglen < 0 || Msglen > 350) - { - FreeSemaphore(&Semaphore); - return 0; - } - - Stamp = MSG->Timestamp; - - memcpy(msg, MSG, BUFFLEN - sizeof(void *)); // To c - - *len = Msglen; - - ReleaseBuffer(MSG); - - *count = C_Q_COUNT(&SESS->HOSTTRACEQ); - FreeSemaphore(&Semaphore); - - return Stamp; -} - -DllExport int APIENTRY GetMsg(int stream, char * msg, int * len, int * count ) -{ -// Get message from stream. Returns length, and count of frames -// still waiting to be collected. (BPQHOST function 3) -// AH = 3 Receive frame into buffer at ES:DI, length of frame returned -// in CX. BX returns the number of outstanding frames still to -// be received (ie. after this one) or zero if no more frames -// (ie. this is last one). -// - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - PDATAMESSAGE MSG; - int Msglen; - - Check_Timer(); - - *len = 0; - *count = 0; - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - GetSemaphore(&Semaphore, 25); - - if (L4 == 0 || L4->L4TX_Q == 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - L4->L4KILLTIMER = 0; // RESET SESSION TIMEOUT - - if(L4->L4CROSSLINK) - L4->L4CROSSLINK->L4KILLTIMER = 0; - - MSG = Q_REM((void *)&L4->L4TX_Q); - - Msglen = MSG->LENGTH - (MSGHDDRLEN + 1); // Dont want PID - - if (Msglen < 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - if (Msglen > 256) - Msglen = 256; - - memcpy(msg, &MSG->L2DATA[0], Msglen); - - *len = Msglen; - - ReleaseBuffer(MSG); - - *count = C_Q_COUNT(&L4->L4TX_Q); - FreeSemaphore(&Semaphore); - - return 0; -} - - -DllExport int APIENTRY RXCount(int stream) -{ -// Returns count of packets waiting on stream -// (BPQHOST function 7 (part)). - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - - Check_Timer(); - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - if (L4 == 0) - return 0; // NOT CONNECTED - - return C_Q_COUNT(&L4->L4TX_Q); -} - -DllExport int APIENTRY TXCount(int stream) -{ -// Returns number of packets on TX queue for stream -// (BPQHOST function 7 (part)). - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - - Check_Timer(); - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - if (L4 == 0) - return 0; // NOT CONNECTED - - L4 = L4->L4CROSSLINK; - - if (L4 == 0) - return 0; // NOTHING ro Q on - - return (CountFramesQueuedOnSession(L4)); -} - -DllExport int APIENTRY MONCount(int stream) -{ -// Returns number of monitor frames available -// (BPQHOST function 7 (part)). - - BPQVECSTRUC * SESS; - - Check_Timer(); - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - - return C_Q_COUNT(&SESS->HOSTTRACEQ); -} - - -DllExport int APIENTRY GetCallsign(int stream, char * callsign) -{ - // Returns call connected on stream (BPQHOST function 8 (part)). - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - TRANSPORTENTRY * Partner; - UCHAR Call[11] = "SWITCH "; - UCHAR * AXCall = NULL; - Check_Timer(); - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - GetSemaphore(&Semaphore, 26); - - if (L4 == 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - Partner = L4->L4CROSSLINK; - - if (Partner) - { - // CONNECTED OUT - GET TARGET SESSION - - if (Partner->L4CIRCUITTYPE & BPQHOST) - { - AXCall = &Partner->L4USER[0]; - } - else if (Partner->L4CIRCUITTYPE & L2LINK) - { - struct _LINKTABLE * LINK = Partner->L4TARGET.LINK; - - if (LINK) - AXCall = LINK->LINKCALL; - - if (Partner->L4CIRCUITTYPE & UPLINK) - { - // IF UPLINK, SHOULD USE SESSION CALL, IN CASE *** LINKED HAS BEEN USED - - AXCall = &Partner->L4USER[0]; - } - } - else if (Partner->L4CIRCUITTYPE & PACTOR) - { - // PACTOR Type - Frames are queued on the Port Entry - - EXTPORTDATA * EXTPORT = Partner->L4TARGET.EXTPORT; - - if (EXTPORT) - AXCall = &EXTPORT->ATTACHEDSESSIONS[Partner->KAMSESSION]->L4USER[0]; - - } - else - { - // MUST BE NODE SESSION - - // ANOTHER NODE - - // IF THE HOST IS THE UPLINKING STATION, WE NEED THE TARGET CALL - - if (L4->L4CIRCUITTYPE & UPLINK) - { - struct DEST_LIST *DEST = Partner->L4TARGET.DEST; - - if (DEST) - AXCall = &DEST->DEST_CALL[0]; - } - else - AXCall = Partner->L4USER; - } - if (AXCall) - ConvFromAX25(AXCall, Call); - } - - memcpy(callsign, Call, 10); - - FreeSemaphore(&Semaphore); - return 0; -} - -DllExport int APIENTRY GetConnectionInfo(int stream, char * callsign, - int * port, int * sesstype, int * paclen, - int * maxframe, int * l4window) -{ - // Return the Secure Session Flag rather than not connected - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - TRANSPORTENTRY * Partner; - UCHAR Call[11] = "SWITCH "; - UCHAR * AXCall; - Check_Timer(); - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - GetSemaphore(&Semaphore, 27); - - if (L4 == 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - Partner = L4->L4CROSSLINK; - - // Return the Secure Session Flag rather than not connected - - // AL = Radio port on which channel is connected (or zero) - // AH = SESSION TYPE BITS - // EBX = L2 paclen for the radio port - // ECX = L2 maxframe for the radio port - // EDX = L4 window size (if L4 circuit, or zero) or -1 if not connected - // ES:DI = CALLSIGN - - *port = 0; - *sesstype = 0; - *paclen = 0; - *maxframe = 0; - *l4window = 0; - if (L4->SESSPACLEN) - *paclen = L4->SESSPACLEN; - else - *paclen = 256; - - if (Partner) - { - // CONNECTED OUT - GET TARGET SESSION - - *l4window = Partner->L4WINDOW; - *sesstype = Partner->L4CIRCUITTYPE; - - if (Partner->L4CIRCUITTYPE & BPQHOST) - { - AXCall = &Partner->L4USER[0]; - } - else if (Partner->L4CIRCUITTYPE & L2LINK) - { - struct _LINKTABLE * LINK = Partner->L4TARGET.LINK; - - // EXTRACT PORT AND MAXFRAME - - *port = LINK->LINKPORT->PORTNUMBER; - *maxframe = LINK->LINKWINDOW; - *l4window = 0; - - AXCall = LINK->LINKCALL; - - if (Partner->L4CIRCUITTYPE & UPLINK) - { - // IF UPLINK, SHOULD USE SESSION CALL, IN CASE *** LINKED HAS BEEN USED - - AXCall = &Partner->L4USER[0]; - } - } - else if (Partner->L4CIRCUITTYPE & PACTOR) - { - // PACTOR Type - Frames are queued on the Port Entry - - EXTPORTDATA * EXTPORT = Partner->L4TARGET.EXTPORT; - - *port = EXTPORT->PORTCONTROL.PORTNUMBER; - AXCall = &EXTPORT->ATTACHEDSESSIONS[Partner->KAMSESSION]->L4USER[0]; - - } - else - { - // MUST BE NODE SESSION - - // ANOTHER NODE - - // IF THE HOST IS THE UPLINKING STATION, WE NEED THE TARGET CALL - - if (L4->L4CIRCUITTYPE & UPLINK) - { - struct DEST_LIST *DEST = Partner->L4TARGET.DEST; - - AXCall = &DEST->DEST_CALL[0]; - } - else - AXCall = Partner->L4USER; - } - ConvFromAX25(AXCall, Call); - } - - memcpy(callsign, Call, 10); - - FreeSemaphore(&Semaphore); - - if (Partner) - return Partner->Secure_Session; - - return 0; -} - - -DllExport int APIENTRY SetAppl(int stream, int flags, int mask) -{ -// Sets Application Flags and Mask for stream. (BPQHOST function 1) -// AH = 1 Set application mask to value in EDX (or even DX if 16 -// applications are ever to be supported). -// -// Set application flag(s) to value in CL (or CX). -// whether user gets connected/disconnected messages issued -// by the node etc. - - - BPQVECSTRUC * PORTVEC; - stream--; - - if (stream < 0 || stream > 63) - return (0); - - PORTVEC=&BPQHOSTVECTOR[stream]; - - PORTVEC->HOSTAPPLFLAGS = flags; - PORTVEC->HOSTAPPLMASK = mask; - - // If either is non-zero, set allocated and Process. This gets round problem with - // stations that don't call allocate stream - - if (flags || mask) - { - if ((PORTVEC->HOSTFLAGS & 128) == 0) // Not allocated - { - PORTVEC->STREAMOWNER=GetCurrentProcessId(); - memcpy(&PORTVEC->PgmName[0], pgm, 31); - PORTVEC->HOSTFLAGS = 128; // SET ALLOCATED BIT, clear others - } - } - - return (0); -} - -DllExport struct PORTCONTROL * APIENTRY GetPortTableEntry(int portslot) // Kept for Legacy apps -{ - struct PORTCONTROL * PORTVEC=PORTTABLE; - - if (portslot>NUMBEROFPORTS) - portslot=NUMBEROFPORTS; - - while (--portslot > 0) - PORTVEC=PORTVEC->PORTPOINTER; - - return PORTVEC; -} - -// Proc below renamed to avoid confusion with GetPortTableEntryFromPortNum - -DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot) -{ - struct PORTCONTROL * PORTVEC=PORTTABLE; - - if (portslot>NUMBEROFPORTS) - portslot=NUMBEROFPORTS; - - while (--portslot > 0) - PORTVEC=PORTVEC->PORTPOINTER; - - return PORTVEC; -} - -int CanPortDigi(int Port) -{ - struct PORTCONTROL * PORTVEC = GetPortTableEntryFromPortNum(Port); - struct TNCINFO * TNC; - - if (PORTVEC == NULL) - return FALSE; - - TNC = PORTVEC->TNC; - - if (TNC == NULL) - return TRUE; - - if (TNC->Hardware == H_SCS || TNC->Hardware == H_TRK || TNC->Hardware == H_TRKM || TNC->Hardware == H_WINRPR) - return FALSE; - - return TRUE; -} - -struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum) -{ - struct PORTCONTROL * PORTVEC = PORTTABLE; - - do - { - if (PORTVEC->PORTNUMBER == portnum) - return PORTVEC; - - PORTVEC=PORTVEC->PORTPOINTER; - } - while (PORTVEC); - - return NULL; -} - -DllExport UCHAR * APIENTRY GetPortDescription(int portslot, char * Desc) -{ - struct PORTCONTROL * PORTVEC=PORTTABLE; - - if (portslot>NUMBEROFPORTS) - portslot=NUMBEROFPORTS; - - while (--portslot > 0) - PORTVEC=PORTVEC->PORTPOINTER; - - memcpy(Desc, PORTVEC->PORTDESCRIPTION, 30); - Desc[30]=0; - - return 0; -} - -// Standard serial port handling routines, used by lots of modules. - -int OpenCOMMPort(struct TNCINFO * conn, char * Port, int Speed, BOOL Quiet) -{ - if (conn->WEB_COMMSSTATE == NULL) - conn->WEB_COMMSSTATE = zalloc(100); - - if (Port == NULL) - return (FALSE); - - conn->hDevice = OpenCOMPort(Port, Speed, TRUE, TRUE, Quiet, 0); - - if (conn->hDevice == 0) - { - sprintf(conn->WEB_COMMSSTATE,"%s Open failed - Error %d", Port, GetLastError()); - if (conn->xIDC_COMMSSTATE) - SetWindowText(conn->xIDC_COMMSSTATE, conn->WEB_COMMSSTATE); - - return (FALSE); - } - - sprintf(conn->WEB_COMMSSTATE,"%s Open", Port); - - if (conn->xIDC_COMMSSTATE) - SetWindowText(conn->xIDC_COMMSSTATE, conn->WEB_COMMSSTATE); - - return TRUE; -} - - - -#ifdef WIN32 - -HANDLE OpenCOMPort(char * pPort, int speed, BOOL SetDTR, BOOL SetRTS, BOOL Quiet, int Stopbits) -{ - char szPort[256]; - BOOL fRetVal ; - COMMTIMEOUTS CommTimeOuts ; - int Err; - char buf[100]; - HANDLE fd; - DCB dcb; - - // if Port Name starts COM, convert to \\.\COM or ports above 10 wont work - - if (_memicmp(pPort, "COM", 3) == 0) - { - char * pp = (char *)pPort; - int p = atoi(&pp[3]); - sprintf( szPort, "\\\\.\\COM%d", p); - } - else - strcpy(szPort, pPort); - - // open COMM device - - fd = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (fd == (HANDLE) -1) - { - if (Quiet == 0) - { - Debugprintf("%s could not be opened %d", pPort, GetLastError()); - } - return (FALSE); - } - - Err = GetFileType(fd); - - // setup device buffers - - SetupComm(fd, 4096, 4096 ) ; - - // purge any information in the buffer - - PurgeComm(fd, PURGE_TXABORT | PURGE_RXABORT | - PURGE_TXCLEAR | PURGE_RXCLEAR ) ; - - // set up for overlapped I/O - - CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ; - CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ; - CommTimeOuts.ReadTotalTimeoutConstant = 0 ; - CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ; -// CommTimeOuts.WriteTotalTimeoutConstant = 0 ; - CommTimeOuts.WriteTotalTimeoutConstant = 500 ; - SetCommTimeouts(fd, &CommTimeOuts ) ; - - dcb.DCBlength = sizeof( DCB ) ; - - GetCommState(fd, &dcb ) ; - - dcb.BaudRate = speed; - dcb.ByteSize = 8; - dcb.Parity = 0; - dcb.StopBits = TWOSTOPBITS; - dcb.StopBits = Stopbits; - - // setup hardware flow control - - dcb.fOutxDsrFlow = 0; - dcb.fDtrControl = DTR_CONTROL_DISABLE ; - - dcb.fOutxCtsFlow = 0; - dcb.fRtsControl = RTS_CONTROL_DISABLE ; - - // setup software flow control - - dcb.fInX = dcb.fOutX = 0; - dcb.XonChar = 0; - dcb.XoffChar = 0; - dcb.XonLim = 100 ; - dcb.XoffLim = 100 ; - - // other various settings - - dcb.fBinary = TRUE ; - dcb.fParity = FALSE; - - fRetVal = SetCommState(fd, &dcb); - - if (fRetVal) - { - if (SetDTR) - EscapeCommFunction(fd, SETDTR); - else - EscapeCommFunction(fd, CLRDTR); - - if (SetRTS) - EscapeCommFunction(fd, SETRTS); - else - EscapeCommFunction(fd, CLRRTS); - } - else - { - sprintf(buf,"%s Setup Failed %d ", pPort, GetLastError()); - - WritetoConsoleLocal(buf); - OutputDebugString(buf); - CloseHandle(fd); - return 0; - } - - return fd; - -} - -int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error); - -int ReadCOMBlock(HANDLE fd, char * Block, int MaxLength) -{ - BOOL Error; - return ReadCOMBlockEx(fd, Block, MaxLength, &Error); -} - -// version to pass read error back to caller - -int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error) -{ - BOOL fReadStat ; - COMSTAT ComStat ; - DWORD dwErrorFlags; - DWORD dwLength; - BOOL ret; - - if (fd == NULL) - return 0; - - // only try to read number of bytes in queue - - ret = ClearCommError(fd, &dwErrorFlags, &ComStat); - - if (ret == 0) - { - int Err = GetLastError(); - *Error = TRUE; - return 0; - } - - - dwLength = min((DWORD) MaxLength, ComStat.cbInQue); - - if (dwLength > 0) - { - fReadStat = ReadFile(fd, Block, dwLength, &dwLength, NULL) ; - - if (!fReadStat) - { - dwLength = 0 ; - ClearCommError(fd, &dwErrorFlags, &ComStat ) ; - } - } - - *Error = FALSE; - - return dwLength; -} - - -BOOL WriteCOMBlock(HANDLE fd, char * Block, int BytesToWrite) -{ - BOOL fWriteStat; - DWORD BytesWritten; - DWORD ErrorFlags; - COMSTAT ComStat; - DWORD Mask = 0; - int Err; - - Err = GetCommModemStatus(fd, &Mask); - -// if ((Mask & MS_CTS_ON) == 0) // trap com0com other end not open -// return TRUE; - - fWriteStat = WriteFile(fd, Block, BytesToWrite, - &BytesWritten, NULL ); - - if ((!fWriteStat) || (BytesToWrite != BytesWritten)) - { - int Err = GetLastError(); - ClearCommError(fd, &ErrorFlags, &ComStat); - return FALSE; - } - return TRUE; -} - -VOID CloseCOMPort(HANDLE fd) -{ - if (fd == NULL) - return; - - SetCommMask(fd, 0); - - // drop DTR - - COMClearDTR(fd); - - // purge any outstanding reads/writes and close device handle - - PurgeComm(fd, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ; - - CloseHandle(fd); - fd = NULL; -} - - -VOID COMSetDTR(HANDLE fd) -{ - EscapeCommFunction(fd, SETDTR); -} - -VOID COMClearDTR(HANDLE fd) -{ - EscapeCommFunction(fd, CLRDTR); -} - -VOID COMSetRTS(HANDLE fd) -{ - EscapeCommFunction(fd, SETRTS); -} - -VOID COMClearRTS(HANDLE fd) -{ - EscapeCommFunction(fd, CLRRTS); -} - - -#else - -static struct speed_struct -{ - int user_speed; - speed_t termios_speed; -} speed_table[] = { - {300, B300}, - {600, B600}, - {1200, B1200}, - {2400, B2400}, - {4800, B4800}, - {9600, B9600}, - {19200, B19200}, - {38400, B38400}, - {57600, B57600}, - {115200, B115200}, - {-1, B0} -}; - - -HANDLE OpenCOMPort(VOID * pPort, int speed, BOOL SetDTR, BOOL SetRTS, BOOL Quiet, int Stopbits) -{ - char Port[256]; - char buf[512]; - - // Linux Version. - - int fd; - int hwflag = 0; - u_long param=1; - struct termios term; - struct speed_struct *s; - - if ((uintptr_t)pPort < 256) - sprintf(Port, "%s/com%d", BPQDirectory, (int)(uintptr_t)pPort); - else - strcpy(Port, pPort); - - if ((fd = open(Port, O_RDWR | O_NDELAY)) == -1) - { - if (Quiet == 0) - { - perror("Com Open Failed"); - sprintf(buf," %s could not be opened \n", Port); - WritetoConsoleLocal(buf); - Debugprintf(buf); - } - return 0; - } - - // Validate Speed Param - - for (s = speed_table; s->user_speed != -1; s++) - if (s->user_speed == speed) - break; - - if (s->user_speed == -1) - { - fprintf(stderr, "tty_speed: invalid speed %d\n", speed); - return FALSE; - } - - if (tcgetattr(fd, &term) == -1) - { - perror("tty_speed: tcgetattr"); - return FALSE; - } - - cfmakeraw(&term); - cfsetispeed(&term, s->termios_speed); - cfsetospeed(&term, s->termios_speed); - - if (tcsetattr(fd, TCSANOW, &term) == -1) - { - perror("tty_speed: tcsetattr"); - return FALSE; - } - - ioctl(fd, FIONBIO, ¶m); - - Debugprintf("LinBPQ Port %s fd %d", Port, fd); - - if (SetDTR) - { - COMSetDTR(fd); - } - else - { - COMClearDTR(fd); - } - - if (SetRTS) - { - COMSetRTS(fd); - } - else - { - COMClearRTS(fd); - } - return fd; -} - -int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error); - -int ReadCOMBlock(HANDLE fd, char * Block, int MaxLength) -{ - BOOL Error; - return ReadCOMBlockEx(fd, Block, MaxLength, &Error); -} - -// version to pass read error back to caller - -int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error) -{ - int Length; - - if (fd == 0) - { - *Error = 1; - return 0; - } - - errno = 22222; // to catch zero read (?? file closed ??) - - Length = read(fd, Block, MaxLength); - - *Error = 0; - - if (Length == 0 && errno == 22222) // seems to be result of unpluging USB - { -// printf("KISS read returned zero len and no errno\n"); - *Error = 1; - return 0; - } - - if (Length < 0) - { - if (errno != 11 && errno != 35) // Would Block - { - perror("read"); - printf("Handle %d Errno %d Len %d\n", fd, errno, Length); - *Error = errno; - } - return 0; - } - - return Length; -} - -BOOL WriteCOMBlock(HANDLE fd, char * Block, int BytesToWrite) -{ - // Some systems seem to have a very small max write size - - int ToSend = BytesToWrite; - int Sent = 0, ret; - int loops = 100; - - while (ToSend && loops-- > 0) - { - ret = write(fd, &Block[Sent], ToSend); - - if (ret >= ToSend) - return TRUE; - - if (ret == -1) - { - if (errno != 11 && errno != 35) // Would Block - return FALSE; - - usleep(10000); - ret = 0; - } - - Sent += ret; - ToSend -= ret; - } - -// if (ToSend) -// { -// // Send timed out. Close and reopen device -// -// } - return TRUE; -} - -VOID CloseCOMPort(HANDLE fd) -{ - if (fd == 0) - return; - - close(fd); - fd = 0; -} - -VOID COMSetDTR(HANDLE fd) -{ - int status; - - ioctl(fd, TIOCMGET, &status); - status |= TIOCM_DTR; - ioctl(fd, TIOCMSET, &status); -} - -VOID COMClearDTR(HANDLE fd) -{ - int status; - - ioctl(fd, TIOCMGET, &status); - status &= ~TIOCM_DTR; - ioctl(fd, TIOCMSET, &status); -} - -VOID COMSetRTS(HANDLE fd) -{ - int status; - - ioctl(fd, TIOCMGET, &status); - status |= TIOCM_RTS; - ioctl(fd, TIOCMSET, &status); -} - -VOID COMClearRTS(HANDLE fd) -{ - int status; - - ioctl(fd, TIOCMGET, &status); - status &= ~TIOCM_RTS; - ioctl(fd, TIOCMSET, &status); -} - -#endif - - -int MaxNodes; -int MaxRoutes; -int NodeLen; -int RouteLen; -struct DEST_LIST * Dests; -struct ROUTE * Routes; - -FILE *file; - -int DoRoutes() -{ - char digis[30] = ""; - int count, len; - char Normcall[10], Portcall[10]; - char line[80]; - - for (count=0; countNEIGHBOUR_CALL[0] != 0) - { - len=ConvFromAX25(Routes->NEIGHBOUR_CALL,Normcall); - Normcall[len]=0; - - if (Routes->NEIGHBOUR_DIGI1[0] != 0) - { - memcpy(digis," VIA ",5); - - len=ConvFromAX25(Routes->NEIGHBOUR_DIGI1,Portcall); - Portcall[len]=0; - strcpy(&digis[5],Portcall); - - if (Routes->NEIGHBOUR_DIGI2[0] != 0) - { - len=ConvFromAX25(Routes->NEIGHBOUR_DIGI2,Portcall); - Portcall[len]=0; - strcat(digis," "); - strcat(digis,Portcall); - } - } - else - digis[0] = 0; - - len=sprintf(line, - "ROUTE ADD %s %d %d %s %d %d %d %d %d\n", - Normcall, - Routes->NEIGHBOUR_PORT, - Routes->NEIGHBOUR_QUAL, digis, - Routes->NBOUR_MAXFRAME, - Routes->NBOUR_FRACK, - Routes->NBOUR_PACLEN, - Routes->INP3Node | (Routes->NoKeepAlive << 2), - Routes->OtherendsRouteQual); - - fputs(line, file); - } - - Routes+=1; - } - - return (0); -} - -int DoNodes() -{ - int count, len, cursor, i; - char Normcall[10], Portcall[10]; - char line[80]; - char Alias[7]; - - Dests-=1; - - for (count=0; countNRROUTE[0].ROUT_NEIGHBOUR == 0) - continue; - - { - len=ConvFromAX25(Dests->DEST_CALL,Normcall); - Normcall[len]=0; - - memcpy(Alias,Dests->DEST_ALIAS,6); - - Alias[6]=0; - - for (i=0;i<6;i++) - { - if (Alias[i] == ' ') - Alias[i] = 0; - } - - cursor=sprintf(line,"NODE ADD %s:%s ", Alias,Normcall); - - if (Dests->NRROUTE[0].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[0].ROUT_NEIGHBOUR->INP3Node == 0) - { - len=ConvFromAX25( - Dests->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); - Portcall[len]=0; - - len=sprintf(&line[cursor],"%s %d %d ", - Portcall, - Dests->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, - Dests->NRROUTE[0].ROUT_QUALITY); - - cursor+=len; - - if (Dests->NRROUTE[0].ROUT_OBSCOUNT > 127) - { - len=sprintf(&line[cursor],"! "); - cursor+=len; - } - } - - if (Dests->NRROUTE[1].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[1].ROUT_NEIGHBOUR->INP3Node == 0) - { - len=ConvFromAX25( - Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); - Portcall[len]=0; - - len=sprintf(&line[cursor],"%s %d %d ", - Portcall, - Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, - Dests->NRROUTE[1].ROUT_QUALITY); - - cursor+=len; - - if (Dests->NRROUTE[1].ROUT_OBSCOUNT > 127) - { - len=sprintf(&line[cursor],"! "); - cursor+=len; - } - } - - if (Dests->NRROUTE[2].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[2].ROUT_NEIGHBOUR->INP3Node == 0) - { - len=ConvFromAX25( - Dests->NRROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); - Portcall[len]=0; - - len=sprintf(&line[cursor],"%s %d %d ", - Portcall, - Dests->NRROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, - Dests->NRROUTE[2].ROUT_QUALITY); - - cursor+=len; - - if (Dests->NRROUTE[2].ROUT_OBSCOUNT > 127) - { - len=sprintf(&line[cursor],"! "); - cursor+=len; - } - } - - if (cursor > 30) - { - line[cursor++]='\n'; - line[cursor++]=0; - fputs(line, file); - } - } - } - return (0); -} - -void SaveMH() -{ - char FN[250]; - struct PORTCONTROL * PORT = PORTTABLE; - FILE *file; - - if (BPQDirectory[0] == 0) - { - strcpy(FN, "MHSave.txt"); - } - else - { - strcpy(FN,BPQDirectory); - strcat(FN,"/"); - strcat(FN,"MHSave.txt"); - } - - if ((file = fopen(FN, "w")) == NULL) - return; - - while (PORT) - { - int Port = 0; - char * ptr; - - MHSTRUC * MH = PORT->PORTMHEARD; - - int count = MHENTRIES; - int n; - char Normcall[20]; - char From[10]; - char DigiList[100]; - char * Output; - int len; - char Digi = 0; - - - // Note that the MHDIGIS field may contain rubbish. You have to check End of Address bit to find - // how many digis there are - - if (MH == NULL) - continue; - - fprintf(file, "Port:%d\n", PORT->PORTNUMBER); - - while (count--) - { - if (MH->MHCALL[0] == 0) - break; - - Digi = 0; - - len = ConvFromAX25(MH->MHCALL, Normcall); - Normcall[len] = 0; - - n = 8; // Max number of digi-peaters - - ptr = &MH->MHCALL[6]; // End of Address bit - - Output = &DigiList[0]; - - if ((*ptr & 1) == 0) - { - // at least one digi - - strcpy(Output, "via "); - Output += 4; - - while ((*ptr & 1) == 0) - { - // MORE TO COME - - From[ConvFromAX25(ptr + 1, From)] = 0; - Output += sprintf((char *)Output, "%s", From); - - ptr += 7; - n--; - - if (n == 0) - break; - - // See if digi actioned - put a * on last actioned - - if (*ptr & 0x80) - { - if (*ptr & 1) // if last address, must need * - { - *(Output++) = '*'; - Digi = '*'; - } - - else - if ((ptr[7] & 0x80) == 0) // Repeased by next? - { - *(Output++) = '*'; // No, so need * - Digi = '*'; - } - - - } - *(Output++) = ','; - } - *(--Output) = 0; // remove last comma - } - else - *(Output) = 0; - - // if we used a digi set * on call and display via string - - - if (Digi) - Normcall[len++] = Digi; - else - DigiList[0] = 0; // Dont show list if not used - - Normcall[len++] = 0; - - ptr = FormatMH(MH, 'U'); - - ptr[15] = 0; - - if (MH->MHDIGI) - fprintf(file, "%d %6d %-10s%c %s %s|%s|%s\n", (int)MH->MHTIME, MH->MHCOUNT, Normcall, MH->MHDIGI, ptr, DigiList, MH->MHLocator, MH->MHFreq); - else - fprintf(file, "%d %6d %-10s%c %s %s|%s|%s\n", (int)MH->MHTIME, MH->MHCOUNT, Normcall, ' ', ptr, DigiList, MH->MHLocator, MH->MHFreq); - - MH++; - } - PORT = PORT->PORTPOINTER; - } - - fclose(file); - - return; -} - - -int APIENTRY SaveNodes () -{ - char FN[250]; - - Routes = NEIGHBOURS; - RouteLen = ROUTE_LEN; - MaxRoutes = MAXNEIGHBOURS; - - Dests = DESTS; - NodeLen = DEST_LIST_LEN; - MaxNodes = MAXDESTS; - - // Set up pointer to BPQNODES file - - if (BPQDirectory[0] == 0) - { - strcpy(FN,"BPQNODES.dat"); - } - else - { - strcpy(FN,BPQDirectory); - strcat(FN,"/"); - strcat(FN,"BPQNODES.dat"); - } - - if ((file = fopen(FN, "w")) == NULL) - return FALSE; - - DoRoutes(); - DoNodes(); - - fclose(file); - - return (0); -} - -DllExport int APIENTRY ClearNodes () -{ - char FN[250]; - - // Set up pointer to BPQNODES file - - if (BPQDirectory[0] == 0) - { - strcpy(FN,"BPQNODES.dat"); - } - else - { - strcpy(FN,BPQDirectory); - strcat(FN,"/"); - strcat(FN,"BPQNODES.dat"); - } - - if ((file = fopen(FN, "w")) == NULL) - return FALSE; - - fclose(file); - - return (0); -} - - -static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - - -char * FormatMH(PMHSTRUC MH, char Format) -{ - struct tm * TM; - static char MHTime[50]; - time_t szClock; - char LOC[7]; - - memcpy(LOC, MH->MHLocator, 6); - LOC[6] = 0; - - if (Format == 'U' || Format =='L') - szClock = MH->MHTIME; - else - szClock = time(NULL) - MH->MHTIME; - - if (Format == 'L') - TM = localtime(&szClock); - else - TM = gmtime(&szClock); - - if (Format == 'U' || Format =='L') - sprintf(MHTime, "%s %02d %.2d:%.2d:%.2d %s %s", - month[TM->tm_mon], TM->tm_mday, TM->tm_hour, TM->tm_min, TM->tm_sec, MH->MHFreq, LOC); - else - sprintf(MHTime, "%.2d:%.2d:%.2d:%.2d %s %s", - TM->tm_yday, TM->tm_hour, TM->tm_min, TM->tm_sec, MH->MHFreq, LOC); - - return MHTime; - -} - - -Dll VOID APIENTRY CreateOneTimePassword(char * Password, char * KeyPhrase, int TimeOffset) -{ - // Create a time dependent One Time Password from the KeyPhrase - // TimeOffset is used when checking to allow for slight variation in clocks - - time_t NOW = time(NULL); - UCHAR Hash[16]; - char Key[1000]; - int i, chr; - - NOW = NOW/30 + TimeOffset; // Only Change every 30 secs - - sprintf(Key, "%s%x", KeyPhrase, (int)NOW); - - md5(Key, Hash); - - for (i=0; i<16; i++) - { - chr = (Hash[i] & 31); - if (chr > 9) chr += 7; - - Password[i] = chr + 48; - } - - Password[16] = 0; - return; -} - -Dll BOOL APIENTRY CheckOneTimePassword(char * Password, char * KeyPhrase) -{ - char CheckPassword[17]; - int Offsets[10] = {0, -1, 1, -2, 2, -3, 3, -4, 4}; - int i, Pass; - - if (strlen(Password) < 16) - Pass = atoi(Password); - - for (i = 0; i < 9; i++) - { - CreateOneTimePassword(CheckPassword, KeyPhrase, Offsets[i]); - - if (strlen(Password) < 16) - { - // Using a numeric extract - - long long Val; - - memcpy(&Val, CheckPassword, 8); - Val = Val %= 1000000; - - if (Pass == Val) - return TRUE; - } - else - if (memcmp(Password, CheckPassword, 16) == 0) - return TRUE; - } - - return FALSE; -} - - -DllExport BOOL ConvToAX25Ex(unsigned char * callsign, unsigned char * ax25call) -{ - // Allows SSID's of 'T and 'R' - - int i; - - memset(ax25call,0x40,6); // in case short - ax25call[6]=0x60; // default SSID - - for (i=0;i<7;i++) - { - if (callsign[i] == '-') - { - // - // process ssid and return - // - - if (callsign[i+1] == 'T') - { - ax25call[6]=0x42; - return TRUE; - } - - if (callsign[i+1] == 'R') - { - ax25call[6]=0x44; - return TRUE; - } - i = atoi(&callsign[i+1]); - - if (i < 16) - { - ax25call[6] |= i<<1; - return (TRUE); - } - return (FALSE); - } - - if (callsign[i] == 0 || callsign[i] == 13 || callsign[i] == ' ' || callsign[i] == ',') - { - // - // End of call - no ssid - // - return (TRUE); - } - - ax25call[i] = callsign[i] << 1; - } - - // - // Too many chars - // - - return (FALSE); -} - - -DllExport BOOL ConvToAX25(unsigned char * callsign, unsigned char * ax25call) -{ - int i; - - memset(ax25call,0x40,6); // in case short - ax25call[6]=0x60; // default SSID - - for (i=0;i<7;i++) - { - if (callsign[i] == '-') - { - // - // process ssid and return - // - i = atoi(&callsign[i+1]); - - if (i < 16) - { - ax25call[6] |= i<<1; - return (TRUE); - } - return (FALSE); - } - - if (callsign[i] == 0 || callsign[i] == 13 || callsign[i] == ' ' || callsign[i] == ',') - { - // - // End of call - no ssid - // - return (TRUE); - } - - ax25call[i] = callsign[i] << 1; - } - - // - // Too many chars - // - - return (FALSE); -} - - -DllExport int ConvFromAX25(unsigned char * incall,unsigned char * outcall) -{ - int in,out=0; - unsigned char chr; - - memset(outcall,0x20,10); - - for (in=0;in<6;in++) - { - chr=incall[in]; - if (chr == 0x40) - break; - chr >>= 1; - outcall[out++]=chr; - } - - chr=incall[6]; // ssid - - if (chr == 0x42) - { - outcall[out++]='-'; - outcall[out++]='T'; - return out; - } - - if (chr == 0x44) - { - outcall[out++]='-'; - outcall[out++]='R'; - return out; - } - - chr >>= 1; - chr &= 15; - - if (chr > 0) - { - outcall[out++]='-'; - if (chr > 9) - { - chr-=10; - outcall[out++]='1'; - } - chr+=48; - outcall[out++]=chr; - } - return (out); -} - -unsigned short int compute_crc(unsigned char *buf, int txlen); - -SOCKADDR_IN reportdest = {0}; - -SOCKET ReportSocket = 0; - -SOCKADDR_IN Chatreportdest = {0}; - -extern char LOCATOR[]; // Locator for Reporting - may be Maidenhead or LAT:LON -extern char MAPCOMMENT[]; // Locator for Reporting - may be Maidenhead or LAT:LON -extern char LOC[7]; // Maidenhead Locator for Reporting -extern char ReportDest[7]; - - -VOID SendReportMsg(char * buff, int txlen) -{ - unsigned short int crc = compute_crc(buff, txlen); - - crc ^= 0xffff; - - buff[txlen++] = (crc&0xff); - buff[txlen++] = (crc>>8); - - sendto(ReportSocket, buff, txlen, 0, (struct sockaddr *)&reportdest, sizeof(reportdest)); - -} -VOID SendLocation() -{ - MESSAGE AXMSG = {0}; - PMESSAGE AXPTR = &AXMSG; - char Msg[512]; - int Len; - - Len = sprintf(Msg, "%s %s
%s", LOCATOR, VersionString, MAPCOMMENT); - -#ifdef LINBPQ - Len = sprintf(Msg, "%s L%s
%s", LOCATOR, VersionString, MAPCOMMENT); -#endif -#ifdef MACBPQ - Len = sprintf(Msg, "%s M%s
%s", LOCATOR, VersionString, MAPCOMMENT); -#endif -#ifdef FREEBSD - Len = sprintf(Msg, "%s F%s
%s", LOCATOR, VersionString, MAPCOMMENT); -#endif - - if (Len > 256) - Len = 256; - - // Block includes the Msg Header (7 bytes), Len Does not! - - memcpy(AXPTR->DEST, ReportDest, 7); - memcpy(AXPTR->ORIGIN, MYCALL, 7); - AXPTR->DEST[6] &= 0x7e; // Clear End of Call - AXPTR->DEST[6] |= 0x80; // set Command Bit - - AXPTR->ORIGIN[6] |= 1; // Set End of Call - AXPTR->CTL = 3; //UI - AXPTR->PID = 0xf0; - memcpy(AXPTR->L2DATA, Msg, Len); - - SendReportMsg((char *)&AXMSG.DEST, Len + 16); - - if (M0LTEMap) - SendDataToPktMap(); - - return; - -} - - - -VOID SendMH(struct TNCINFO * TNC, char * call, char * freq, char * LOC, char * Mode) -{ - MESSAGE AXMSG; - PMESSAGE AXPTR = &AXMSG; - char Msg[100]; - int Len; - - if (ReportSocket == 0 || LOCATOR[0] == 0) - return; - - Len = sprintf(Msg, "MH %s,%s,%s,%s", call, freq, LOC, Mode); - - // Block includes the Msg Header (7 bytes), Len Does not! - - memcpy(AXPTR->DEST, ReportDest, 7); - - if (TNC && TNC->PortRecord->PORTCONTROL.PORTCALL[0]) - memcpy(AXPTR->ORIGIN, TNC->PortRecord->PORTCONTROL.PORTCALL, 7); - else - memcpy(AXPTR->ORIGIN, MYCALL, 7); - AXPTR->DEST[6] &= 0x7e; // Clear End of Call - AXPTR->DEST[6] |= 0x80; // set Command Bit - - AXPTR->ORIGIN[6] |= 1; // Set End of Call - AXPTR->CTL = 3; //UI - AXPTR->PID = 0xf0; - memcpy(AXPTR->L2DATA, Msg, Len); - - SendReportMsg((char *)&AXMSG.DEST, Len + 16) ; - - return; - -} - -time_t TimeLastNRRouteSent = 0; - -char NRRouteMessage[256]; -int NRRouteLen = 0; - - -VOID SendNETROMRoute(struct PORTCONTROL * PORT, unsigned char * axcall) -{ - // Called to update Link Map when a NODES Broadcast is received - // Batch to reduce Load - - MESSAGE AXMSG; - PMESSAGE AXPTR = &AXMSG; - char Msg[300]; - int Len; - char Call[10]; - char Report[16]; - time_t Now = time(NULL); - int NeedSend = FALSE; - - - if (ReportSocket == 0 || LOCATOR[0] == 0) - return; - - Call[ConvFromAX25(axcall, Call)] = 0; - - sprintf(Report, "%s,%d,", Call, PORT->PORTTYPE); - - if (Now - TimeLastNRRouteSent > 60) - NeedSend = TRUE; - - if (strstr(NRRouteMessage, Report) == 0) // reported recently - strcat(NRRouteMessage, Report); - - if (strlen(NRRouteMessage) > 230 || NeedSend) - { - Len = sprintf(Msg, "LINK %s", NRRouteMessage); - - // Block includes the Msg Header (7 bytes), Len Does not! - - memcpy(AXPTR->DEST, ReportDest, 7); - memcpy(AXPTR->ORIGIN, MYCALL, 7); - AXPTR->DEST[6] &= 0x7e; // Clear End of Call - AXPTR->DEST[6] |= 0x80; // set Command Bit - - AXPTR->ORIGIN[6] |= 1; // Set End of Call - AXPTR->CTL = 3; //UI - AXPTR->PID = 0xf0; - memcpy(AXPTR->L2DATA, Msg, Len); - - SendReportMsg((char *)&AXMSG.DEST, Len + 16) ; - - TimeLastNRRouteSent = Now; - NRRouteMessage[0] = 0; - } - - return; - -} - -DllExport char * APIENTRY GetApplCall(int Appl) -{ - if (Appl < 1 || Appl > NumberofAppls ) return NULL; - - return (UCHAR *)(&APPLCALLTABLE[Appl-1].APPLCALL_TEXT); -} -DllExport char * APIENTRY GetApplAlias(int Appl) -{ - if (Appl < 1 || Appl > NumberofAppls ) return NULL; - - return (UCHAR *)(&APPLCALLTABLE[Appl-1].APPLALIAS_TEXT); -} - -DllExport int32_t APIENTRY GetApplQual(int Appl) -{ - if (Appl < 1 || Appl > NumberofAppls ) return 0; - - return (APPLCALLTABLE[Appl-1].APPLQUAL); -} - -char * GetApplCallFromName(char * App) -{ - int i; - char PaddedAppl[13] = " "; - - memcpy(PaddedAppl, App, (int)strlen(App)); - - for (i = 0; i < NumberofAppls; i++) - { - if (memcmp(&APPLCALLTABLE[i].APPLCMD, PaddedAppl, 12) == 0) - return &APPLCALLTABLE[i].APPLCALL_TEXT[0]; - } - return NULL; -} - - -DllExport char * APIENTRY GetApplName(int Appl) -{ - if (Appl < 1 || Appl > NumberofAppls ) return NULL; - - return (UCHAR *)(&APPLCALLTABLE[Appl-1].APPLCMD); -} - -DllExport int APIENTRY GetNumberofPorts() -{ - return (NUMBEROFPORTS); -} - -DllExport int APIENTRY GetPortNumber(int portslot) -{ - struct PORTCONTROL * PORTVEC=PORTTABLE; - - if (portslot>NUMBEROFPORTS) - portslot=NUMBEROFPORTS; - - while (--portslot > 0) - PORTVEC=PORTVEC->PORTPOINTER; - - return PORTVEC->PORTNUMBER; - -} - -DllExport char * APIENTRY GetVersionString() -{ -// return ((char *)&VersionStringWithBuild); - return ((char *)&VersionString); -} - -#ifdef MACBPQ - -//Fiddle till I find a better solution - -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1060 -int __sync_lock_test_and_set(int * ptr, int val) -{ - *ptr = val; - return 0; -} -#endif // __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ -#endif // MACBPQ - - -#define GetSemaphore(Semaphore,ID) _GetSemaphore(Semaphore, ID, __FILE__, __LINE__) - - -void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line) -{ - // - // Wait for it to be free - // - - if (Semaphore->Flag != 0) - { - Semaphore->Clashes++; - } - -loop1: - - while (Semaphore->Flag != 0) - { - Sleep(10); - } - - // - // try to get semaphore - // - -#ifdef WIN32 - - { - if (InterlockedExchange(&Semaphore->Flag, 1) != 0) // Failed to get it - goto loop1; // try again;; - } - -#else - - if (__sync_lock_test_and_set(&Semaphore->Flag, 1) != 0) - - // Failed to get it - goto loop1; // try again; - -#endif - - //Ok. got it - - Semaphore->Gets++; - Semaphore->SemProcessID = GetCurrentProcessId(); - Semaphore->SemThreadID = GetCurrentThreadId(); - SemHeldByAPI = ID; - Semaphore->Line = Line; - strcpy(Semaphore->File, File); - - return; -} - -void FreeSemaphore(struct SEM * Semaphore) -{ - if (Semaphore->Flag == 0) - Debugprintf("Free Semaphore Called when Sem not held"); - - Semaphore->Rels++; - Semaphore->Flag = 0; - - return; -} - -#ifdef WIN32 - -#include "DbgHelp.h" -/* -USHORT WINAPI RtlCaptureStackBackTrace( - __in ULONG FramesToSkip, - __in ULONG FramesToCapture, - __out PVOID *BackTrace, - __out_opt PULONG BackTraceHash -); -*/ -#endif - -void printStack(void) -{ -#ifdef WIN32 -#ifdef _DEBUG // So we can use on 98/2K - - unsigned int i; - void * stack[ 100 ]; - unsigned short frames; - SYMBOL_INFO * symbol; - HANDLE process; - - Debugprintf("Stack Backtrace"); - - process = GetCurrentProcess(); - - SymInitialize( process, NULL, TRUE ); - - frames = RtlCaptureStackBackTrace( 0, 60, stack, NULL ); - symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 ); - symbol->MaxNameLen = 255; - symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); - - for( i = 0; i < frames; i++ ) - { - SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol ); - - Debugprintf( "%i: %s - %p", frames - i - 1, symbol->Name, symbol->Address ); - } - - free(symbol); - -#endif -#endif -} - -pthread_t ResolveUpdateThreadId = 0; - -char NodeMapServer[80] = "update.g8bpq.net"; -char ChatMapServer[80] = "chatupdate.g8bpq.net"; - -VOID ResolveUpdateThread(void * Unused) -{ - struct hostent * HostEnt1; - struct hostent * HostEnt2; - - ResolveUpdateThreadId = GetCurrentThreadId(); - - while (TRUE) - { - if (pthread_equal(ResolveUpdateThreadId, GetCurrentThreadId()) == FALSE) - { - Debugprintf("Resolve Update thread %x redundant - closing", GetCurrentThreadId()); - return; - } - - // Resolve name to address - - Debugprintf("Resolving %s", NodeMapServer); - HostEnt1 = gethostbyname (NodeMapServer); -// HostEnt1 = gethostbyname ("192.168.1.64"); - - if (HostEnt1) - memcpy(&reportdest.sin_addr.s_addr,HostEnt1->h_addr,4); - - Debugprintf("Resolving %s", ChatMapServer); - HostEnt2 = gethostbyname (ChatMapServer); -// HostEnt2 = gethostbyname ("192.168.1.64"); - - if (HostEnt2) - memcpy(&Chatreportdest.sin_addr.s_addr,HostEnt2->h_addr,4); - - if (HostEnt1 && HostEnt2) - { - Sleep(1000 * 60 * 30); - continue; - } - - Debugprintf("Resolve Failed for update.g8bpq.net or chatmap.g8bpq.net"); - Sleep(1000 * 60 * 5); - } -} - - -VOID OpenReportingSockets() -{ - u_long param=1; - BOOL bcopt=TRUE; - - if (LOCATOR[0]) - { - // Enable Node Map Reports - - ReportTimer = 1200; // 2 mins - Give Rigcontrol time to start - - ReportSocket = socket(AF_INET,SOCK_DGRAM,0); - - if (ReportSocket == INVALID_SOCKET) - { - Debugprintf("Failed to create Reporting socket"); - ReportSocket = 0; - return; - } - - ioctlsocket (ReportSocket, FIONBIO, ¶m); - setsockopt (ReportSocket, SOL_SOCKET, SO_BROADCAST, (const char FAR *)&bcopt,4); - - reportdest.sin_family = AF_INET; - reportdest.sin_port = htons(81); - ConvToAX25("DUMMY-1", ReportDest); - } - - // Set up Chat Report even if no LOCATOR reportdest.sin_family = AF_INET; - // Socket must be opened in MailChat Process - - Chatreportdest.sin_family = AF_INET; - Chatreportdest.sin_port = htons(81); - - _beginthread(ResolveUpdateThread, 0, NULL); - - printf("MQTT Enabled %d\n", MQTT); - - if (MQTT) - MQTTConnect(MQTT_HOST, MQTT_PORT, MQTT_USER, MQTT_PASS); -} - -VOID WriteMiniDumpThread(); - -time_t lastMiniDump = 0; - -void WriteMiniDump() -{ -#ifdef WIN32 - - _beginthread(WriteMiniDumpThread, 0, 0); - Sleep(3000); -} - -VOID WriteMiniDumpThread() -{ - HANDLE hFile; - BOOL ret; - char FN[256]; - struct tm * TM; - time_t Now = time(NULL); - - if (lastMiniDump == Now) // Not more than one per second - { - Debugprintf("minidump suppressed"); - return; - } - - lastMiniDump = Now; - - TM = gmtime(&Now); - - sprintf(FN, "%s/Logs/MiniDump%d%02d%02d%02d%02d%02d.dmp", BPQDirectory, - TM->tm_year + 1900, TM->tm_mon +1, TM->tm_mday, TM->tm_hour, TM->tm_min, TM->tm_sec); - - hFile = CreateFile(FN, GENERIC_READ | GENERIC_WRITE, - 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) - { - // Create the minidump - - ret = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), - hFile, MiniDumpNormal, 0, 0, 0 ); - - if(!ret) - Debugprintf("MiniDumpWriteDump failed. Error: %u", GetLastError()); - else - Debugprintf("Minidump %s created.", FN); - CloseHandle(hFile); - } -#endif -} - -// UI Util Code - -#pragma pack(1) - -typedef struct _MESSAGEX -{ -// BASIC LINK LEVEL MESSAGE BUFFER LAYOUT - - struct _MESSAGEX * CHAIN; - - UCHAR PORT; - USHORT LENGTH; - - UCHAR DEST[7]; - UCHAR ORIGIN[7]; - -// MAY BE UP TO 56 BYTES OF DIGIS - - UCHAR CTL; - UCHAR PID; - UCHAR DATA[256]; - UCHAR PADDING[56]; // In case he have Digis - -}MESSAGEX, *PMESSAGEX; - -#pragma pack() - - -int PortNum[MaxBPQPortNo + 1] = {0}; // Tab nunber to port - -char * UIUIDigi[MaxBPQPortNo + 1]= {0}; -char * UIUIDigiAX[MaxBPQPortNo + 1] = {0}; // ax.25 version of digistring -int UIUIDigiLen[MaxBPQPortNo + 1] = {0}; // Length of AX string - -char UIUIDEST[MaxBPQPortNo + 1][11] = {0}; // Dest for Beacons - -char UIAXDEST[MaxBPQPortNo + 1][7] = {0}; - - -UCHAR FN[MaxBPQPortNo + 1][256]; // Filename -int Interval[MaxBPQPortNo + 1]; // Beacon Interval (Mins) -int MinCounter[MaxBPQPortNo + 1]; // Interval Countdown - -BOOL SendFromFile[MaxBPQPortNo + 1]; -char Message[MaxBPQPortNo + 1][1000]; // Beacon Text - -VOID SendUIBeacon(int Port); - -BOOL RunUI = TRUE; - -VOID UIThread(void * Unused) -{ - int Port, MaxPorts = GetNumberofPorts(); - - Sleep(60000); - - while (RunUI) - { - int sleepInterval = 60000; - - for (Port = 1; Port <= MaxPorts; Port++) - { - if (MinCounter[Port]) - { - MinCounter[Port]--; - - if (MinCounter[Port] == 0) - { - MinCounter[Port] = Interval[Port]; - SendUIBeacon(Port); - - // pause beteen beacons but adjust sleep interval to suit - - Sleep(10000); - sleepInterval -= 10000; - } - } - } - - while (sleepInterval <= 0) // just in case we have a crazy config - sleepInterval += 60000; - - Sleep(sleepInterval); - } -} - -int UIRemoveLF(char * Message, int len) -{ - // Remove lf chars - - char * ptr1, * ptr2; - - ptr1 = ptr2 = Message; - - while (len-- > 0) - { - *ptr2 = *ptr1; - - if (*ptr1 == '\r') - if (*(ptr1+1) == '\n') - { - ptr1++; - len--; - } - ptr1++; - ptr2++; - } - - return (int)(ptr2 - Message); -} - - - - -VOID UISend_AX_Datagram(UCHAR * Msg, DWORD Len, UCHAR Port, UCHAR * HWADDR, BOOL Queue) -{ - MESSAGEX AXMSG; - PMESSAGEX AXPTR = &AXMSG; - int DataLen = Len; - struct PORTCONTROL * PORT = GetPortTableEntryFromSlot(Port); - - // Block includes the Msg Header (7 or 11 bytes), Len Does not! - - memcpy(AXPTR->DEST, HWADDR, 7); - - // Get BCALL or PORTCALL if set - - if (PORT && PORT->PORTBCALL[0]) - memcpy(AXPTR->ORIGIN, PORT->PORTBCALL, 7); - else if (PORT && PORT->PORTCALL[0]) - memcpy(AXPTR->ORIGIN, PORT->PORTCALL, 7); - else - memcpy(AXPTR->ORIGIN, MYCALL, 7); - - AXPTR->DEST[6] &= 0x7e; // Clear End of Call - AXPTR->DEST[6] |= 0x80; // set Command Bit - - if (UIUIDigi[Port]) - { - // This port has a digi string - - int DigiLen = UIUIDigiLen[Port]; - UCHAR * ptr; - - memcpy(&AXPTR->CTL, UIUIDigiAX[Port], DigiLen); - - ptr = (UCHAR *)AXPTR; - ptr += DigiLen; - AXPTR = (PMESSAGEX)ptr; - - Len += DigiLen; - } - - AXPTR->ORIGIN[6] |= 1; // Set End of Call - AXPTR->CTL = 3; //UI - AXPTR->PID = 0xf0; - memcpy(AXPTR->DATA, Msg, DataLen); - -// if (Queue) -// QueueRaw(Port, &AXMSG, Len + 16); -// else - SendRaw(Port, (char *)&AXMSG.DEST, Len + 16); - - return; - -} - - - -VOID SendUIBeacon(int Port) -{ - char UIMessage[1024]; - int Len = (int)strlen(Message[Port]); - int Index = 0; - - if (SendFromFile[Port]) - { - FILE * hFile; - - hFile = fopen(FN[Port], "rb"); - - if (hFile == 0) - return; - - Len = (int)fread(UIMessage, 1, 1024, hFile); - - fclose(hFile); - - } - else - strcpy(UIMessage, Message[Port]); - - Len = UIRemoveLF(UIMessage, Len); - - while (Len > 256) - { - UISend_AX_Datagram(&UIMessage[Index], 256, Port, UIAXDEST[Port], TRUE); - Index += 256; - Len -= 256; - Sleep(2000); - } - UISend_AX_Datagram(&UIMessage[Index], Len, Port, UIAXDEST[Port], TRUE); -} - -#ifndef LINBPQ - -typedef struct tag_dlghdr -{ - HWND hwndTab; // tab control - HWND hwndDisplay; // current child dialog box - RECT rcDisplay; // display rectangle for the tab control - - DLGTEMPLATE *apRes[MaxBPQPortNo + 1]; - -} DLGHDR; - -DLGTEMPLATE * WINAPI DoLockDlgRes(LPCSTR lpszResName); - -#endif - -HWND hwndDlg; -int PageCount; -int CurrentPage=0; // Page currently on show in tabbed Dialog - - -VOID WINAPI OnSelChanged(HWND hwndDlg); -VOID WINAPI OnChildDialogInit(HWND hwndDlg); - -#define ICC_STANDARD_CLASSES 0x00004000 - -HWND hwndDisplay; - -#define ID_TEST 102 -#define IDD_DIAGLOG1 103 -#define IDC_FROMFILE 1022 -#define IDC_EDIT1 1054 -#define IDC_FILENAME 1054 -#define IDC_EDIT2 1055 -#define IDC_MESSAGE 1055 -#define IDC_EDIT3 1056 -#define IDC_INTERVAL 1056 -#define IDC_EDIT4 1057 -#define IDC_UIDEST 1057 -#define IDC_FILE 1058 -#define IDC_TAB1 1059 -#define IDC_UIDIGIS 1059 -#define IDC_PORTNAME 1060 - -extern HKEY REGTREE; -HBRUSH bgBrush; - -VOID SetupUI(int Port) -{ - char DigiString[100], * DigiLeft; - - ConvToAX25(UIUIDEST[Port], &UIAXDEST[Port][0]); - - UIUIDigiLen[Port] = 0; - - if (UIUIDigi[Port]) - { - UIUIDigiAX[Port] = zalloc(100); - strcpy(DigiString, UIUIDigi[Port]); - DigiLeft = strlop(DigiString,','); - - while(DigiString[0]) - { - ConvToAX25(DigiString, &UIUIDigiAX[Port][UIUIDigiLen[Port]]); - UIUIDigiLen[Port] += 7; - - if (DigiLeft) - { - memmove(DigiString, DigiLeft, (int)strlen(DigiLeft) + 1); - DigiLeft = strlop(DigiString,','); - } - else - DigiString[0] = 0; - } - } -} - -#ifndef LINBPQ - -VOID SaveIntValue(config_setting_t * group, char * name, int value) -{ - config_setting_t *setting; - - setting = config_setting_add(group, name, CONFIG_TYPE_INT); - if(setting) - config_setting_set_int(setting, value); -} - -VOID SaveStringValue(config_setting_t * group, char * name, char * value) -{ - config_setting_t *setting; - - setting = config_setting_add(group, name, CONFIG_TYPE_STRING); - if (setting) - config_setting_set_string(setting, value); - -} - -#endif - -config_t cfg; - -VOID SaveUIConfig() -{ - config_setting_t *root, *group, *UIGroup; - int Port, MaxPort = GetNumberofPorts(); - char ConfigName[256]; - - if (BPQDirectory[0] == 0) - { - strcpy(ConfigName,"UIUtil.cfg"); - } - else - { - strcpy(ConfigName,BPQDirectory); - strcat(ConfigName,"/"); - strcat(ConfigName,"UIUtil.cfg"); - } - - // Get rid of old config before saving - - config_init(&cfg); - - root = config_root_setting(&cfg); - - group = config_setting_add(root, "main", CONFIG_TYPE_GROUP); - - UIGroup = config_setting_add(group, "UIUtil", CONFIG_TYPE_GROUP); - - for (Port = 1; Port <= MaxPort; Port++) - { - char Key[20]; - - sprintf(Key, "Port%d", Port); - group = config_setting_add(UIGroup, Key, CONFIG_TYPE_GROUP); - - SaveStringValue(group, "UIDEST", &UIUIDEST[Port][0]); - SaveStringValue(group, "FileName", &FN[Port][0]); - SaveStringValue(group, "Message", &Message[Port][0]); - SaveStringValue(group, "Digis", UIUIDigi[Port]); - - SaveIntValue(group, "Interval", Interval[Port]); - SaveIntValue(group, "SendFromFile", SendFromFile[Port]); - } - - if(!config_write_file(&cfg, ConfigName)) - { - fprintf(stderr, "Error while writing file.\n"); - config_destroy(&cfg); - return; - } - - config_destroy(&cfg); -} - -int GetRegConfig(); - -VOID GetUIConfig() -{ - char Key[100]; - char CfgFN[256]; - char Digis[100]; - struct stat STAT; - - config_t cfg; - config_setting_t *group; - int Port, MaxPort = GetNumberofPorts(); - - memset((void *)&cfg, 0, sizeof(config_t)); - - config_init(&cfg); - - if (BPQDirectory[0] == 0) - { - strcpy(CfgFN,"UIUtil.cfg"); - } - else - { - strcpy(CfgFN,BPQDirectory); - strcat(CfgFN,"/"); - strcat(CfgFN,"UIUtil.cfg"); - } - - if (stat(CfgFN, &STAT) == -1) - { - // No file. If Windows try to read from registy - -#ifndef LINBPQ - GetRegConfig(); -#else - Debugprintf("UIUtil Config File not found\n"); -#endif - return; - } - - if(!config_read_file(&cfg, CfgFN)) - { - fprintf(stderr, "UI Util Config Error Line %d - %s\n", config_error_line(&cfg), config_error_text(&cfg)); - - config_destroy(&cfg); - return; - } - - group = config_lookup(&cfg, "main"); - - if (group) - { - for (Port = 1; Port <= MaxPort; Port++) - { - sprintf(Key, "main.UIUtil.Port%d", Port); - - group = config_lookup (&cfg, Key); - - if (group) - { - GetStringValue(group, "UIDEST", &UIUIDEST[Port][0], 11); - GetStringValue(group, "FileName", &FN[Port][0], 256); - GetStringValue(group, "Message", &Message[Port][0], 1000); - GetStringValue(group, "Digis", Digis, 100); - UIUIDigi[Port] = _strdup(Digis); - - Interval[Port] = GetIntValue(group, "Interval"); - MinCounter[Port] = Interval[Port]; - - SendFromFile[Port] = GetIntValue(group, "SendFromFile"); - - SetupUI(Port); - } - } - } - - - _beginthread(UIThread, 0, NULL); - -} - -#ifndef LINBPQ - -int GetIntValue(config_setting_t * group, char * name) -{ - config_setting_t *setting; - - setting = config_setting_get_member (group, name); - if (setting) - return config_setting_get_int (setting); - - return 0; -} - -BOOL GetStringValue(config_setting_t * group, char * name, char * value, int maxlen) -{ - char * str; - config_setting_t *setting; - - setting = config_setting_get_member (group, name); - if (setting) - { - str = (char *)config_setting_get_string(setting); - - if (strlen(str) > maxlen) - { - Debugprintf("Suspect config record %s", str); - str[maxlen] = 0; - } - strcpy(value, str); - return TRUE; - } - value[0] = 0; - return FALSE; -} - -int GetRegConfig() -{ - int retCode, Vallen, Type, i; - char Key[80]; - char Size[80]; - HKEY hKey; - RECT Rect; - - wsprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\UIUtil"); - - retCode = RegOpenKeyEx (REGTREE, Key, 0, KEY_QUERY_VALUE, &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"Size",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size,"%d,%d,%d,%d",&Rect.left,&Rect.right,&Rect.top,&Rect.bottom); - - RegCloseKey(hKey); - } - - for (i=1; i<=32; i++) - { - wsprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\UIUtil\\UIPort%d", i); - - retCode = RegOpenKeyEx (REGTREE, - Key, - 0, - KEY_QUERY_VALUE, - &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=0; - RegQueryValueEx(hKey,"Digis",0, - (ULONG *)&Type, NULL, (ULONG *)&Vallen); - - if (Vallen) - { - UIUIDigi[i] = malloc(Vallen); - RegQueryValueEx(hKey,"Digis",0, - (ULONG *)&Type, UIUIDigi[i], (ULONG *)&Vallen); - } - - Vallen=4; - retCode = RegQueryValueEx(hKey, "Interval", 0, - (ULONG *)&Type, (UCHAR *)&Interval[i], (ULONG *)&Vallen); - - MinCounter[i] = Interval[i]; - - Vallen=4; - retCode = RegQueryValueEx(hKey, "SendFromFile", 0, - (ULONG *)&Type, (UCHAR *)&SendFromFile[i], (ULONG *)&Vallen); - - - Vallen=10; - retCode = RegQueryValueEx(hKey, "UIDEST", 0, &Type, &UIUIDEST[i][0], &Vallen); - - Vallen=255; - retCode = RegQueryValueEx(hKey, "FileName", 0, &Type, &FN[i][0], &Vallen); - - Vallen=999; - retCode = RegQueryValueEx(hKey, "Message", 0, &Type, &Message[i][0], &Vallen); - - SetupUI(i); - - RegCloseKey(hKey); - } - } - - SaveUIConfig(); - - return TRUE; -} - -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 = BPQDirectory; - - if (GetOpenFileName(&ofn)) - SetDlgItemText(hDlg, IDC_FILENAME, &FN[Port][0]); - - break; - - - case IDOK: - - GetDlgItemText(hDlg, IDC_UIDEST, &UIUIDEST[Port][0], 10); - - if (UIUIDigi[Port]) - { - free(UIUIDigi[Port]); - UIUIDigi[Port] = NULL; - } - - if (UIUIDigiAX[Port]) - { - free(UIUIDigiAX[Port]); - UIUIDigiAX[Port] = NULL; - } - - GetDlgItemText(hDlg, IDC_UIDIGIS, Digis, 99); - - UIUIDigi[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); - - wsprintf(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 *)&UIUIDEST[Port][0], (int)strlen(&UIUIDEST[Port][0])); - retCode = RegSetValueEx(hKey, "FileName", 0, REG_SZ,(BYTE *)&FN[Port][0], (int)strlen(&FN[Port][0])); - retCode = RegSetValueEx(hKey, "Message", 0, REG_SZ,(BYTE *)&Message[Port][0], (int)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, "Digis",0, REG_SZ, Digis, (int)strlen(Digis)); - - RegCloseKey(hKey); - } - - SetupUI(Port); - - SaveUIConfig(); - - return (INT_PTR)TRUE; - - - case IDCANCEL: - - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - - case ID_TEST: - - SendUIBeacon(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. - -#define GWL_USERDATA (-21) - - 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, hInstance, 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 <= NUMBEROFPORTS; i++) - { - // Only allow UI on ax.25 ports - - PORTVEC = (struct _EXTPORTDATA * )GetPortTableEntryFromSlot(i); - - if (PORTVEC->PORTCONTROL.PORTTYPE == 16) // EXTERNAL - if (PORTVEC->PORTCONTROL.PROTOCOL == 10) // Pactor/WINMOR - if (PORTVEC->PORTCONTROL.UICAPABLE == 0) - continue; - - wsprintf(PortNo, "Port %2d", GetPortNumber(i)); - PortNum[tab] = 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(hInstance, lpszResName, RT_DIALOG); - HGLOBAL hglb = LoadResource(hInstance, 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(hInstance, 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, &UIUIDEST[Port][0]); - SetDlgItemText(hwndDisplay, IDC_UIDIGIS, UIUIDigi[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); -} - - - -LRESULT CALLBACK UIWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - HKEY hKey=0; - - switch (message) { - - case WM_INITDIALOG: - OnTabbedDialogInit(hWnd); - return (INT_PTR)TRUE; - - case WM_NOTIFY: - - switch (((LPNMHDR)lParam)->code) - { - case TCN_SELCHANGE: - OnSelChanged(hWnd); - return TRUE; - // More cases on WM_NOTIFY switch. - case NM_CHAR: - return TRUE; - } - - break; - - - 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: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) { - - case IDOK: - - return TRUE; - - default: - - return 0; - } - - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_RESTORE: - - return (DefWindowProc(hWnd, message, wParam, lParam)); - - case SC_MINIMIZE: - - if (MinimizetoTray) - return ShowWindow(hWnd, SW_HIDE); - else - return (DefWindowProc(hWnd, message, wParam, lParam)); - - break; - - default: - return (DefWindowProc(hWnd, message, wParam, lParam)); - } - - case WM_CLOSE: - return(DestroyWindow(hWnd)); - - default: - return (DefWindowProc(hWnd, message, wParam, lParam)); - - } - - return (0); -} - -#endif - -extern struct DATAMESSAGE * REPLYBUFFER; -char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char * format, ...); - -void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) -{ - char FN[250]; - FILE *hFile; - struct stat STAT; - struct PORTCONTROL * PORT = PORTTABLE; - char PortList[256] = ""; - - while (PORT) - { - if (PORT->CTEXT) - { - free(PORT->CTEXT); - PORT->CTEXT = 0; - } - - if (BPQDirectory[0] == 0) - sprintf(FN, "Port%dCTEXT.txt", PORT->PORTNUMBER); - else - sprintf(FN, "%s/Port%dCTEXT.txt", BPQDirectory, PORT->PORTNUMBER); - - if (stat(FN, &STAT) == -1) - { - PORT = PORT->PORTPOINTER; - continue; - } - - hFile = fopen(FN, "rb"); - - if (hFile) - { - char * ptr; - - PORT->CTEXT = zalloc(STAT.st_size + 1); - fread(PORT->CTEXT , 1, STAT.st_size, hFile); - fclose(hFile); - - // convert CRLF or LF to CR - - while (ptr = strstr(PORT->CTEXT, "\r\n")) - memmove(ptr, ptr + 1, strlen(ptr)); - - // Now has LF - - while (ptr = strchr(PORT->CTEXT, '\n')) - *ptr = '\r'; - - - sprintf(PortList, "%s,%d", PortList, PORT->PORTNUMBER); - } - - PORT = PORT->PORTPOINTER; - } - - if (Session) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "CTEXT Read for ports %s\r", &PortList[1]); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - } - else - Debugprintf("CTEXT Read for ports %s\r", &PortList[1]); -} - -// Get the current frequency for a port. This can get a bit complicated, especially if looking for centre freq -// rather than dial freq (as this depends on mode). -// -// Used for various reporting functions - MH, Maps, BBS New User message, - -// I think I'll try PORT "PortFreq" setting first then if that isn't available via rigcontrol. -// -// For now at least will report dial freq if using RIGCONTROL - -DllExport uint64_t APIENTRY GetPortFrequency(int PortNo, char * FreqString) -{ - struct PORTCONTROL * PORT = GetPortTableEntryFromPortNum(PortNo); - double freq = 0.0; - uint64_t freqint = 0; - - char * ptr; - int n = 3; - - FreqString[0] = 0; - - if (PORT == 0) - return 0; - - if (PORT->PortFreq) - { - freqint = PORT->PortFreq; - freq = freqint / 1000000.0; - } - else - { - // Try rigcontrol - - - struct TNCINFO * TNC; - struct RIGINFO * RIG = 0; - - if (PORT->RIGPort) - TNC = TNCInfo[PORT->RIGPort]; - else - TNC = TNCInfo[PortNo]; - - if (TNC) - RIG = TNC->RIG; - - if (RIG == 0) - return 0; - - // Frequency should be in valchar - - if (RIG->Valchar[0] == 0) - return 0; - - freq = atof(TNC->RIG->Valchar); - freqint = (int64_t)(freq * 1000000.0); - } - - sprintf(FreqString, "%.6f", freq); - - // Return 3 digits after . (KHz) unless more are significant - - ptr = &FreqString[strlen(FreqString) - 1]; - - while (n-- && *(ptr) == '0') - *ptr-- = 0; - - return freqint; -} - -SOCKET OpenHTTPSock(char * Host) -{ - SOCKET sock = 0; - struct sockaddr_in destaddr; - struct sockaddr_in sinx; - int addrlen=sizeof(sinx); - struct hostent * HostEnt; - int err; - u_long param=1; - BOOL bcopt=TRUE; - - destaddr.sin_family = AF_INET; - destaddr.sin_port = htons(80); - - // Resolve name to address - - HostEnt = gethostbyname (Host); - - if (!HostEnt) - { - err = WSAGetLastError(); - - Debugprintf("Resolve Failed for %s %d %x", Host, err, err); - return 0 ; // Resolve failed - } - - memcpy(&destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - - // Allocate a Socket entry - - sock = socket(AF_INET,SOCK_STREAM,0); - - if (sock == INVALID_SOCKET) - return 0; - - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - if (bind(sock, (struct sockaddr *) &sinx, addrlen) != 0 ) - return FALSE; - - if (connect(sock,(struct sockaddr *) &destaddr, sizeof(destaddr)) != 0) - { - err=WSAGetLastError(); - closesocket(sock); - return 0; - } - - return sock; -} - -static char HeaderTemplate[] = "POST %s HTTP/1.1\r\n" - "Accept: app N B lication/json\r\n" -// "Accept-Encoding: gzip,deflate,gzip, deflate\r\n" - "Content-Type: application/json\r\n" - "Host: %s:%d\r\n" - "Content-Length: %d\r\n" - "User-Agent: %s%s\r\n" -// "Expect: 100-continue\r\n" - "\r\n"; - - -DllExport VOID WINAPI SendWebRequest(char * Host, char * Request, char * Params, char * Return) -{ - SOCKET sock; - int InputLen = 0; - int inptr = 0; - char Buffer[4096]; - char Header[256]; - char * ptr, * ptr1; - int Sent; - int Len = strlen(Params); - - if (M0LTEMap == 0) - return; - - sock = OpenHTTPSock(Host); - - if (sock == 0) - return; - -#ifdef LINBPQ - sprintf(Header, HeaderTemplate, Request, Host, 80, Len, "linbpq/", VersionString, Params); -#else - sprintf(Header, HeaderTemplate, Request, Host, 80, Len, "bpq32/", VersionString, Params); -#endif - Sent = send(sock, Header, (int)strlen(Header), 0); - Sent = send(sock, Params, (int)strlen(Params), 0); - - if (Sent == -1) - { - int Err = WSAGetLastError(); - Debugprintf("Error %d from Web Update send()", Err); - closesocket(sock); - return; - } - - while (InputLen != -1) - { - InputLen = recv(sock, &Buffer[inptr], 4095 - inptr, 0); - - if (InputLen == -1 || InputLen == 0) - { - int Err = WSAGetLastError(); - Debugprintf("Error %d from Web Update recv()", Err); - closesocket(sock); - return; - } - - inptr += InputLen; - - Buffer[inptr] = 0; - - ptr = strstr(Buffer, "\r\n\r\n"); - - if (ptr) - { - // got header - - int Hddrlen = (int)(ptr - Buffer); - - ptr1 = strstr(Buffer, "Content-Length:"); - - if (ptr1) - { - // Have content length - - int ContentLen = atoi(ptr1 + 16); - - if (ContentLen + Hddrlen + 4 == inptr) - { - // got whole response - - if (strstr(Buffer, " 200 OK")) - { - if (Return) - { - memcpy(Return, ptr + 4, ContentLen); - Return[ContentLen] = 0; - } - else - Debugprintf("Map Database update ok"); - - } - else - { - strlop(Buffer, 13); - Debugprintf("Map Update failed - %s", Buffer); - } - closesocket(sock); - return; - } - } - else - { - ptr1 = strstr(_strlwr(Buffer), "transfer-encoding:"); - - if (ptr1) - { - // Just accept anything until I've sorted things with Lee - - closesocket(sock); - Debugprintf("Web Database update ok"); - return; - } - } - } - } -} - -// https://packetnodes.spots.radio/api/NodeData/{callsign} - -//SendHTTPRequest(sock, "/account/exists", Message, Len, Response); - -#include "kiss.h" - -extern char MYALIASLOPPED[10]; -extern int MasterPort[MAXBPQPORTS+1]; - - -// G7TAJ // -/* - {"mheard": [ - { - "Callsign": "GB7CIP-7", - "Port": "VHF", - "Packets": 70369, - "LastHeard": "2024-12-29 20:26:32" - }, -*/ - -void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT) -{ - struct tm * TM; - static char MHTIME[50]; - time_t szClock; - MHSTRUC * MH = PORT->PORTMHEARD; - int count = MHENTRIES; - char Normcall[20]; - int len; - char * ptr; - char mhstr[400]; - int i; - char c; - - if (MH == NULL) - return; - - while (count--) - { - if (MH->MHCALL[0] == 0) - break; - - len = ConvFromAX25(MH->MHCALL, Normcall); - Normcall[len] = 0; - - ptr = &MH->MHCALL[6]; // End of Address bit - - if ((*ptr & 1) == 0) - { - // at least one digi - which we are not going to include - MH++; - continue; - } - - // validate call to prevent corruption of json - - for (i=0; i < len; i++) - { - c = Normcall[i]; - - if (!isalnum(c) && !(c == '#') && !(c == ' ') && !(c == '-')) - goto skipit; - } - - - //format TIME - - szClock = MH->MHTIME; - TM = gmtime(&szClock); - sprintf(MHTIME, "%d-%d-%d %02d:%02d:%02d", - TM->tm_year+1900, TM->tm_mon + 1, TM->tm_mday, TM->tm_hour, TM->tm_min, TM->tm_sec); - - sprintf(mhstr, "{\"callSign\": \"%s\", \"port\": \"%d\", \"packets\": %d, \"lastHeard\": \"%s\" },\r\n" , - Normcall, PORT->PORTNUMBER, MH->MHCOUNT, MHTIME); - - strcat( MHJSON, mhstr ); -skipit: - MH++; - } -} - -void SendDataToPktMapThread(); - -void SendDataToPktMap() -{ - _beginthread(SendDataToPktMapThread,2048000,0); -} - -void SendDataToPktMapThread() -{ - char Return[256] = ""; - char Request[64]; - char Params[50000]; - - struct PORTCONTROL * PORT = PORTTABLE; - struct PORTCONTROL * SAVEPORT; - struct ROUTE * Routes = NEIGHBOURS; - int MaxRoutes = MAXNEIGHBOURS; - - int PortNo; - int Active; - uint64_t Freq; - int Baud; - int Bitrate; - char * Mode; - char * Use; - char * Type; - char * Modulation; - char * Usage; - - char locked[] = " ! "; - int Percent = 0; - int Port = 0; - char Normcall[10]; - char Copy[20]; - char ID[33]; - - char * ptr = Params; - -// G7TAJ // - char MHJSON[50000]; - char * mhptr; - char * b4Routesptr; - - MHJSON[0]=0; -// G7TAJ // - -// printf("Sending to new map\n"); - - sprintf(Request, "/api/NodeData/%s", MYNODECALL); - -// https://packetnodes.spots.radio/swagger/index.html - - // This builds the request and sends it - - // Minimum header seems to be - - // "nodeAlias": "BPQ", - // "location": {"locator": "IO68VL"}, - // "software": {"name": "BPQ32","version": "6.0.24.3"}, - - ptr += sprintf(ptr, "{\"nodeAlias\": \"%s\",\r\n", MYALIASLOPPED); - - if (strlen(LOCATOR) == 6) - ptr += sprintf(ptr, "\"location\": {\"locator\": \"%s\"},\r\n", LOCATOR); - else - { - // Lat Lon - - double myLat, myLon; - char LocCopy[80]; - char * context; - - strcpy(LocCopy, LOCATOR); - - myLat = atof(strtok_s(LocCopy, ",:; ", &context)); - myLon = atof(context); - - ptr += sprintf(ptr, "\"location\": {\"coords\": {\"lat\": %f, \"lon\": %f}},\r\n", - myLat, myLon); - - } - -#ifdef LINBPQ - ptr += sprintf(ptr, "\"software\": {\"name\": \"LINBPQ\",\"version\": \"%s\"},\r\n", VersionString); -#else - ptr += sprintf(ptr, "\"software\": {\"name\": \"BPQ32\",\"version\": \"%s\"},\r\n", VersionString); -#endif - ptr += sprintf(ptr, "\"source\": \"ReportedByNode\",\r\n"); - -// G7TAJ // - sprintf(MHJSON, ",\"mheard\": ["); -// G7TAJ // - - - //Ports - - ptr += sprintf(ptr, "\"ports\": ["); - - // Get active ports - - while (PORT) - { - PortNo = PORT->PORTNUMBER; - - if (PORT->Hide) - { - PORT = PORT->PORTPOINTER; - continue; - } - - if (PORT->SendtoM0LTEMap == 0) - { - PORT = PORT->PORTPOINTER; - continue; - } - - // Try to get port status - may not be possible with some - - if (PORT->PortStopped) - { - PORT = PORT->PORTPOINTER; - continue; - } - - Active = 0; - Freq = 0; - Baud = 0; - Mode = "ax.25"; - Use = ""; - Type = "RF"; - Bitrate = 0; - Modulation = "FSK"; - Usage = "Access"; - - if (PORT->PortFreq) - Freq = PORT->PortFreq; - - if (PORT->PORTTYPE == 0) - { - struct KISSINFO * KISS = (struct KISSINFO *)PORT; - NPASYINFO Port; - - SAVEPORT = PORT; - - if (KISS->FIRSTPORT && KISS->FIRSTPORT != KISS) - { - // Not first port on device - - PORT = (struct PORTCONTROL *)KISS->FIRSTPORT; - Port = KISSInfo[PortNo]; - } - - Port = KISSInfo[PORT->PORTNUMBER]; - - if (Port) - { - // KISS like - see if connected - - if (PORT->PORTIPADDR.s_addr || PORT->KISSSLAVE) - { - // KISS over UDP or TCP - - if (PORT->KISSTCP) - { - if (Port->Connected) - Active = 1; - } - else - Active = 1; // UDP - Cant tell - } - else - if (Port->idComDev) // Serial port Open - Active = 1; - - PORT = SAVEPORT; - } - } - else if (PORT->PORTTYPE == 14) // Loopback - Active = 0; - - else if (PORT->PORTTYPE == 16) // External - { - if (PORT->PROTOCOL == 10) // 'HF' Port - { - struct TNCINFO * TNC = TNCInfo[PortNo]; - struct AGWINFO * AGW; - - if (TNC == NULL) - { - PORT = PORT->PORTPOINTER; - continue; - } - - if (Freq == 0 && TNC->RIG) - Freq = TNC->RIG->RigFreq * 1000000; - - switch (TNC->Hardware) // Hardware Type - { - case H_KAM: - case H_AEA: - case H_HAL: - case H_SERIAL: - - // Serial - - if (TNC->hDevice) - Active = 1; - - break; - - case H_SCS: - case H_TRK: - case H_WINRPR: - - if (TNC->HostMode) - Active = 1; - - break; - - - case H_UZ7HO: - - if (TNCInfo[MasterPort[PortNo]]->CONNECTED) - Active = 1; - - // Try to get mode and frequency - - AGW = TNC->AGWInfo; - - if (AGW && AGW->isQTSM) - { - if (AGW->ModemName[0]) - { - char * ptr1, * ptr2, *Context; - - strcpy(Copy, AGW->ModemName); - ptr1 = strtok_s(Copy, " ", & Context); - ptr2 = strtok_s(NULL, " ", & Context); - - if (Context) - { - Modulation = Copy; - - if (strstr(ptr1, "BPSK") || strstr(ptr1, "AFSK")) - { - Baud = Bitrate = atoi(Context); - } - else if (strstr(ptr1, "QPSK")) - { - Modulation = "QPSK"; - Bitrate = atoi(Context); - Baud = Bitrate /2; - } - } - } - } - - break; - - case H_KISSHF: - - // Try to get mode from ID then drop through - - if (stristr(PORT->PORTDESCRIPTION, "BPSK")) - { - Modulation = "BPSK"; - } - - case H_WINMOR: - case H_V4: - - case H_MPSK: - case H_FLDIGI: - case H_UIARQ: - case H_ARDOP: - case H_VARA: - - case H_FREEDATA: - - // TCP - - Mode = Modenames[TNC->Hardware - 1]; - - if (TNC->CONNECTED) - Active = 1; - - break; - - case H_TELNET: - - Active = 1; - Type = "Internet"; - Mode = ""; - } - } - else - { - // External but not HF - AXIP, BPQETHER VKISS, ?? - - struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)PORT; - Type = "Internet"; - Active = 1; - } - } - - if (Active) - { - char * ptr2 = &ID[29]; - strcpy(ID, PORT->PORTDESCRIPTION); - while (*(ptr2) == ' ' && ptr2 != ID) - *(ptr2--) = 0; - - if (PORT->M0LTEMapInfo) - { - // Override with user configured values - RF,7.045,BPSK,300,300,Access - - char param[256]; - char *p1, *p2, *p3, *p4, *p5; - - strcpy(param, PORT->M0LTEMapInfo); - - p1 = strlop(param, ','); - p2 = strlop(p1, ','); - p3 = strlop(p2, ','); - p4 = strlop(p3, ','); - p5 = strlop(p4, ','); - - // int n = sscanf(PORT->M0LTEMapInfo, "%s,%s,%s,%s,%s,%s", &p1, &p2, &p3, &p4, &p5, &p6); - - if (p5) - { - if (param[0]) Type = param; - - if (p1[0]) - { - // if set to DIAL+=n and frequency set from config or rigcontrol modify it - - uint64_t offset = 0; - - if (_memicmp(p1, "DIAL+", 5) == 0) - offset = atoi(&p1[5]); - else if (_memicmp(p1, "DIAL-", 5) == 0) - offset = -atoi(&p1[5]); - else - Freq = atof(p1) * 1000000; - - if (Freq != 0) - Freq += offset; - - } - - if (p2[0]) Modulation = p2; - if (p3[0]) Baud = atoi(p3); - if (p4[0]) Bitrate = atoi(p4); - if (p5[0]) Usage = p5; - } - } - - ptr += sprintf(ptr, "{\"id\": \"%d\",\"linkType\": \"%s\"," - "\"freq\": \"%lld\",\"mode\": \"%s\",\"modulation\": \"%s\"," - "\"baud\": \"%d\",\"bitrate\": \"%d\",\"usage\": \"%s\",\"comment\": \"%s\"},\r\n", - PortNo, Type, - Freq, Mode, Modulation, - Baud, Bitrate, Usage, ID); - -// G7TAJ // - // make MH list to be added later - BuildPortMH(MHJSON, PORT); - -// G7TAJ // - - - } - - PORT = PORT->PORTPOINTER; - } - - ptr -= 3; - ptr += sprintf(ptr, "],\r\n"); - - // Neighbours - -// G7TAJ // - b4Routesptr = ptr-3; -// G7TAJ // - - ptr += sprintf(ptr, "\"neighbours\": [\r\n"); - - while (MaxRoutes--) - { - if (Routes->NEIGHBOUR_CALL[0] != 0) - if (Routes->NEIGHBOUR_LINK && Routes->NEIGHBOUR_LINK->L2STATE >= 5) - { - ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall); - strlop(Normcall, ' '); - - ptr += sprintf(ptr, - "{\"node\": \"%s\", \"port\": \"%d\", \"quality\": \"%d\"},\r\n", - Normcall, Routes->NEIGHBOUR_PORT, Routes->NEIGHBOUR_QUAL); - } - - Routes++; - } - -// G7TAJ // - - // if !strstr quality, then there are none, so remove neighbours portion - if ( strstr(Params, "quality") == NULL ) { - ptr = b4Routesptr; - } else { - ptr -= 3; - ptr += sprintf(ptr, "]"); - } - - if ( strlen(MHJSON) > 15 ) { - mhptr = MHJSON + strlen(MHJSON); - mhptr -= 3; - sprintf(mhptr, "]\r\n"); - ptr += sprintf(ptr, "\r\n%s", MHJSON); - - } - - ptr += sprintf(ptr, "}"); - - - -// G7TAJ // - - -/* -{ - "nodeAlias": "BPQ", - "location": {"locator": "IO92KX"}, - "software": {"name": "BPQ32","version": "6.0.24.11 Debug Build "}, - "contact": "G8BPQ", - "sysopComment": "Testing", - "source": "ReportedByNode" -} - - "ports": [ - { - "id": "string", - "linkType": "RF", - "freq": 0, - "mode": "string", - "modulation": "string", - "baud": 0, - "bitrate": 0, - "usage": "Access", - "comment": "string" - } - ], - -*/ - // "contact": "string", - // "neighbours": [{"node": "G7TAJ","port": "30"}] - - SendWebRequest("packetnodes.spots.radio", Request, Params, 0); -} - -// ="{\"neighbours\": [{\"node\": \"G7TAJ\",\"port\": \"30\"}]}"; - -//'POST' \ -// 'https://packetnodes.spots.radio/api/NodeData/GM8BPQ' \ -// -H 'accept: */*' \ -// -H 'Content-Type: application/json' \ -// -d '{ -// "nodeAlias": "BPQ", -// "location": {"locator": "IO68VL"}, -// "software": {"name": "BPQ32","version": "6.0.24.3"}, -// "contact": "string", -// "neighbours": [{"node": "G7TAJ","port": "30"}] -//}' - - - - - - - - - diff --git a/CommonCode.c b/CommonCode.c index 18d412c..0866980 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -18,7 +18,6 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses */ - // General C Routines common to bpq32 and linbpq. Mainly moved from BPQ32.c #pragma data_seg("_BPQDATA") @@ -914,7 +913,7 @@ BOOL ProcessIncommingConnectEx(struct TNCINFO * TNC, char * Call, int Stream, BO sprintf(Msg, "%d SCANSTOP", TNC->Port); - Rig_Command( (TRANSPORTENTRY *) -1, Msg); + Rig_Command((TRANSPORTENTRY *) -1, Msg); UpdateMH(TNC, Call, '+', 'I'); } @@ -1493,8 +1492,8 @@ int SendMsgEx(int stream, char * msg, int len, int GetSem) if (QCOUNT < 50) return 0; // Dont want to run out - if (GetSem) - GetSemaphore(&Semaphore, 10); + if (GetSem) + GetSemaphore(&Semaphore, 10); if ((MSG = GetBuff()) == 0) { @@ -1623,7 +1622,7 @@ DllExport int APIENTRY SendRaw(int port, char * msg, int len) MSG->LENGTH = len + MSGHDDRLEN; - if (PORT->PROTOCOL == 10 && PORT->TNC && PORT->TNC->Hardware != H_KISSHF) // PACTOR/WINMOR Style + if (PORT->PROTOCOL == 10 && PORT->HWType != H_KISSHF) // PACTOR/WINMOR Style { // Pactor Style. Probably will only be used for Tracker unless we do APRS over V4 or WINMOR @@ -2687,6 +2686,14 @@ int DoRoutes() { if (Routes->NEIGHBOUR_CALL[0] != 0) { + // Dont save routes from config file here or they are difficult to get rid of + + if (Routes->NEIGHBOUR_FLAG & LOCKEDBYCONFIG) + { + Routes++; + continue; + } + len=ConvFromAX25(Routes->NEIGHBOUR_CALL,Normcall); Normcall[len]=0; @@ -2710,7 +2717,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 +2725,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/FLDigi.c b/FLDigi.c index 480a443..8c97113 100644 --- a/FLDigi.c +++ b/FLDigi.c @@ -1180,7 +1180,6 @@ VOID * FLDigiExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; - TNC->PortRecord = PortEntry; if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) @@ -1211,7 +1210,7 @@ VOID * FLDigiExtInit(EXTPORTDATA * PortEntry) ptr=strchr(TNC->NodeCall, ' '); if (ptr) *(ptr) = 0; // Null Terminate - TNC->Hardware = H_FLDIGI; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_FLDIGI; if (TNC->BusyWait == 0) TNC->BusyWait = 10; diff --git a/FreeDATA.c b/FreeDATA.c index 66ff40a..0af1375 100644 --- a/FreeDATA.c +++ b/FreeDATA.c @@ -1393,14 +1393,14 @@ VOID * FreeDataExtInit(EXTPORTDATA * PortEntry) Consoleprintf("FreeData Host %s %d", TNC->HostName, TNC->TCPPort); TNC->Port = port; - TNC->Hardware = H_FREEDATA; + TNC->PortRecord = PortEntry; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_FREEDATA; TNC->WeStartedTNC = 1; TNC->ARDOPDataBuffer = malloc(MAXRXSIZE); TNC->ARDOPBuffer = malloc(FREEDATABUFLEN); - TNC->PortRecord = PortEntry; if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); diff --git a/HALDriver.c b/HALDriver.c index a914a38..408ff97 100644 --- a/HALDriver.c +++ b/HALDriver.c @@ -499,15 +499,15 @@ VOID * HALExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; + TNC->PortRecord = PortEntry; - TNC->Hardware = H_HAL; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_HAL; if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; PortEntry->MAXHOSTMODESESSIONS = 1; // Default - TNC->PortRecord = PortEntry; if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) { diff --git a/HFCommon.c b/HFCommon.c index c0f82d7..1ecd775 100644 --- a/HFCommon.c +++ b/HFCommon.c @@ -336,7 +336,8 @@ LRESULT CALLBACK PacWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPara } #endif -BOOL CreatePactorWindow(struct TNCINFO * TNC, char * ClassName, char * WindowTitle, int RigControlRow, WNDPROC WndProc, int Width, int Height, VOID ForcedCloseProc()) +BOOL CreatePactorWindow(struct TNCINFO * TNC, char * ClassName, char * WindowTitle, int RigControlRow, WNDPROC WndProc, int Width, int Height, + VOID ForcedCloseProc(struct TNCINFO * TNC, int Stream)) { #ifdef LINBPQ return FALSE; diff --git a/HSMODEM.c b/HSMODEM.c index 4efdb80..d3430d7 100644 --- a/HSMODEM.c +++ b/HSMODEM.c @@ -1177,10 +1177,10 @@ VOID * HSMODEMExtInit(EXTPORTDATA * PortEntry) Consoleprintf("HSMODEM Host %s %d", TNC->HostName, TNC->TCPPort); TNC->Port = port; - TNC->Hardware = H_HSMODEM; - TNC->PortRecord = PortEntry; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_HSMODEM; + if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); else diff --git a/HTTPcode-skigdebian.c b/HTTPcode-skigdebian.c deleted file mode 100644 index ac0a3ff..0000000 --- a/HTTPcode-skigdebian.c +++ /dev/null @@ -1,5175 +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 -*/ - - -//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - -#define _CRT_SECURE_NO_DEPRECATE - -#define DllImport - -#include "cheaders.h" -#include - -#include "tncinfo.h" -#include "time.h" -#include "bpq32.h" -#include "telnetserver.h" - -// This is needed to link with a lib built from source - -#ifdef WIN32 -#define ZEXPORT __stdcall -#endif - -#include - -#define CKernel -#include "httpconnectioninfo.h" - -extern int MAXBUFFS, QCOUNT, MINBUFFCOUNT, NOBUFFCOUNT, BUFFERWAITS, L3FRAMES; -extern int NUMBEROFNODES, MAXDESTS, L4CONNECTSOUT, L4CONNECTSIN, L4FRAMESTX, L4FRAMESRX, L4FRAMESRETRIED, OLDFRAMES; -extern int STATSTIME; -extern TRANSPORTENTRY * L4TABLE; -extern BPQVECSTRUC BPQHOSTVECTOR[]; -extern BOOL APRSApplConnected; -extern char VersionString[]; -VOID FormatTime3(char * Time, time_t cTime); -DllExport int APIENTRY Get_APPLMASK(int Stream); -VOID SaveUIConfig(); -int ProcessNodeSignon(SOCKET sock, struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, int LOCAL); -VOID SetupUI(int Port); -VOID SendUIBeacon(int Port); -VOID GetParam(char * input, char * key, char * value); -VOID ARDOPAbort(struct TNCINFO * TNC); -VOID WriteMiniDump(); -BOOL KillTNC(struct TNCINFO * TNC); -BOOL RestartTNC(struct TNCINFO * TNC); -int GetAISPageInfo(char * Buffer, int ais, int adsb); -int GetAPRSPageInfo(char * Buffer, double N, double S, double W, double E, int aprs, int ais, int adsb); -unsigned char * Compressit(unsigned char * In, int Len, int * OutLen); -char * stristr (char *ch1, char *ch2); -int GetAPRSIcon(unsigned char * _REPLYBUFFER, char * NodeURL); -char * GetStandardPage(char * FN, int * Len); -BOOL SHA1PasswordHash(char * String, char * Hash); -char * byte_base64_encode(char *str, int len); -int APIProcessHTTPMessage(char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE); -int RHPProcessHTTPMessage(struct ConnectionInfo * conn, char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE); - -extern struct ROUTE * NEIGHBOURS; -extern int ROUTE_LEN; -extern int MAXNEIGHBOURS; - -extern struct DEST_LIST * DESTS; // NODE LIST -extern int DEST_LIST_LEN; -extern int MAXDESTS; // MAX NODES IN SYSTEM - -extern struct _LINKTABLE * LINKS; -extern int LINK_TABLE_LEN; -extern int MAXLINKS; -extern char * RigWebPage; -extern COLORREF Colours[256]; - -extern BOOL IncludesMail; -extern BOOL IncludesChat; - -extern BOOL APRSWeb; -extern BOOL RigActive; - -extern HKEY REGTREE; - -extern BOOL APRSActive; - -extern UCHAR LogDirectory[]; - -extern struct RIGPORTINFO * PORTInfo[34]; -extern int NumberofPorts; - -extern UCHAR ConfigDirectory[260]; - -VOID sendandcheck(SOCKET sock, const char * Buffer, int Len); -int CompareNode(const void *a, const void *b); -int CompareAlias(const void *a, const void *b); -void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen, char * Token); -void ProcessChatHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen); -struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot); -int SetupNodeMenu(char * Buff, int SYSOP); -int StatusProc(char * Buff); -int ProcessMailSignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, BOOL WebMail, int LOCAL); -int ProcessMailAPISignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, BOOL WebMail, int LOCAL); -int ProcessChatSignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, int LOCAL); -VOID APRSProcessHTTPMessage(SOCKET sock, char * MsgPtr, BOOL LOCAL, BOOL COOKIE); - - -static struct HTTPConnectionInfo * SessionList; // active term mode sessions - -char Mycall[10]; - -char MAILPipeFileName[] = "\\\\.\\pipe\\BPQMAILWebPipe"; -char CHATPipeFileName[] = "\\\\.\\pipe\\BPQCHATWebPipe"; - -char Index[] = "%s's BPQ32 Web Server

" -"" -"" -"
Node PagesAPRS Pages
"; - -char IndexNoAPRS[] = "" -""; - -//char APRSBit[] = "APRS Pages"; - -//char MailBit[] = "Mail Mgmt" -// "WebMail"; -//char ChatBit[] = "Chat Mgmt"; - -char Tail[] = ""; - -char RouteHddr[] = "

Routes

" -""; - -char RouteLine[] = ""; -char xNodeHddr[] = "
" -"
PortCallQualityNode CountFrame CountRetriesPercentMaxframeFrackLast HeardQueuedRem Qual
%s%d%s%c%d%d%d%d%d%%d%d%02d:%02d%d%d
" -"
" -"" -"
" -"

Nodes %s

"; - -char NodeHddr[] = "
" -"" -"" -"
" -"

Nodes %s

"; - -char NodeLine[] = ""; - - -char StatsHddr[] = "

Node Stats

%s:%s
" -""; - -char PortStatsHddr[] = "

Stats for Port %d

"; - -char PortStatsLine[] = ""; - - -char Beacons[] = "

Beacon Configuration for Port %d

You need to be signed in to save changes

%s %d
" -"" -"
" -"" -"" -"" -"" -"" -"
Send Interval (Minutes)
To
Path
Send From File
Text
" -"" - -"

" -""; - - -char LinkHddr[] = "

Links

" -""; - -char LinkLine[] = ""; - -char UserHddr[] = "

Sessions

Far CallOur CallPortax.25 stateLink Typeax.25 Version
%s%s%d%s%s%d
"; - -char UserLine[] = ""; - -char TermSignon[] = "BPQ32 Node %s Terminal Access" -"

BPQ32 Node %s Terminal Access

" -"

Please enter username and password to access the node

" -"" -"
%s%s%s
" -"" -"
User
Password
" -"

" -""; - - -char PassError[] = "

Sorry, User or Password is invalid - please try again

"; - -char BusyError[] = "

Sorry, No sessions available - please try later

"; - -char LostSession[] = "Sorry, Session had been lost - refresh page to sign in again"; -char NoSessions[] = "Sorry, No Sessions available - refresh page to try again"; - -char TermPage[] = "" -"BPQ32 Node %s" -"" -"" -"

BPQ32 Node %s

" -"
" -"

" -"" -"" -""; - -char TermOutput[] = "" -"" -"" -"" -"" -"" -"" -"
\""; - - -// font-family:monospace;background-color:black;color:lawngreen;font-size:12px - -char TermOutputTail[] = "
"; - -/* -char InputLine[] = "" -"
" -"" -"
"; -*/ -char InputLine[] = "" -"
" -"\" id=inp type=text text width=100%% name=input />" -"
"; - -static char NodeSignon[] = "BPQ32 Node SYSOP Access" -"

BPQ32 Node %s SYSOP Access

" -"

This page sets Cookies. Don't continue if you object to this

" -"

Please enter Callsign and Password to access the Node

" -"
" -"" -"" -"
User
Password
" -"

"; - - -static char MailSignon[] = "BPQ32 Mail Server Access" -"

BPQ32 Mail Server %s Access

" -"

Please enter Callsign and Password to access the BBS

" -"
" -"" -"" -"
User
Password
" -"

"; - -static char ChatSignon[] = "BPQ32 Chat Server Access" -"

BPQ32 Chat Server %s Access

" -"

Please enter Callsign and Password to access the Chat Server

" -"
" -"" -"" -"
User
Password
" -"

"; - - -static char MailLostSession[] = "" -"
" -"Sorry, Session had been lost

    " -"
"; - - -static char ConfigEditPage[] = "" -"Edit Config" -"
" -"

" -"
"; - -static char EXCEPTMSG[80] = ""; - - -void UndoTransparency(char * input) -{ - char * ptr1, * ptr2; - char c; - int hex; - - if (input == NULL) - return; - - ptr1 = ptr2 = input; - - // Convert any %xx constructs - - while (1) - { - c = *(ptr1++); - - if (c == 0) - break; - - if (c == '%') - { - c = *(ptr1++); - if(isdigit(c)) - hex = (c - '0') << 4; - else - hex = (tolower(c) - 'a' + 10) << 4; - - c = *(ptr1++); - if(isdigit(c)) - hex += (c - '0'); - else - hex += (tolower(c) - 'a' + 10); - - *(ptr2++) = hex; - } - else if (c == '+') - *(ptr2++) = 32; - else - *(ptr2++) = c; - } - *ptr2 = 0; -} - - - - -VOID PollSession(struct HTTPConnectionInfo * Session) -{ - int state, change; - int count, len; - char Msg[400] = ""; - char Formatted[8192]; - char * ptr1, * ptr2; - char c; - int Line; - - // Poll Node - - SessionState(Session->Stream, &state, &change); - - if (change == 1) - { - int Line = Session->LastLine++; - free(Session->ScreenLines[Line]); - - if (state == 1)// Connected - Session->ScreenLines[Line] = _strdup("*** Connected
\r\n"); - else - Session->ScreenLines[Line] = _strdup("*** Disconnected
\r\n"); - - if (Line == 99) - Session->LastLine = 0; - - Session->Changed = TRUE; - } - - if (RXCount(Session->Stream) > 0) - { - int realLen = 0; - - do - { - GetMsg(Session->Stream, &Msg[0], &len, &count); - - // replace cr with
and space with   - - - ptr1 = Msg; - ptr2 = &Formatted[0]; - - if (Session->PartLine) - { - // Last line was incomplete - append to it - - realLen = Session->PartLine; - - Line = Session->LastLine - 1; - - if (Line < 0) - Line = 99; - - strcpy(Formatted, Session->ScreenLines[Line]); - ptr2 += strlen(Formatted); - - Session->LastLine = Line; - Session->PartLine = FALSE; - } - - while (len--) - { - c = *(ptr1++); - realLen++; - - if (c == 13) - { - int LineLen; - - strcpy(ptr2, "
\r\n"); - - // Write to screen - - Line = Session->LastLine++; - free(Session->ScreenLines[Line]); - - LineLen = (int)strlen(Formatted); - - // if line starts with a colour code, process it - - if (Formatted[0] == 0x1b && LineLen > 1) - { - int ColourCode = Formatted[1] - 10; - COLORREF Colour = Colours[ColourCode]; - char ColString[30]; - - memmove(&Formatted[20], &Formatted[2], LineLen); - sprintf(ColString, "", GetRValue(Colour), GetGValue(Colour), GetBValue(Colour)); - memcpy(Formatted, ColString, 20); - strcat(Formatted, ""); - LineLen =+ 28; - } - - Session->ScreenLineLen[Line] = LineLen; - Session->ScreenLines[Line] = _strdup(Formatted); - - if (Line == 99) - Session->LastLine = 0; - - ptr2 = &Formatted[0]; - realLen = 0; - - } - else if (c == 32) - { - memcpy(ptr2, " ", 6); - ptr2 += 6; - - // Make sure line isn't too long - // but beware of spaces expanded to   - count chars in line - - if ((realLen) > 100) - { - strcpy(ptr2, "
\r\n"); - - Line = Session->LastLine++; - free(Session->ScreenLines[Line]); - - Session->ScreenLines[Line] = _strdup(Formatted); - - if (Line == 99) - Session->LastLine = 0; - - ptr2 = &Formatted[0]; - realLen = 0; - } - } - else if (c == '>') - { - memcpy(ptr2, ">", 4); - ptr2 += 4; - } - else if (c == '<') - { - memcpy(ptr2, "<", 4); - ptr2 += 4; - } - else - *(ptr2++) = c; - - } - - *ptr2 = 0; - - if (ptr2 != &Formatted[0]) - { - // Incomplete line - - // Save to screen - - Line = Session->LastLine++; - free(Session->ScreenLines[Line]); - - Session->ScreenLines[Line] = _strdup(Formatted); - - if (Line == 99) - Session->LastLine = 0; - - Session->PartLine = realLen; - } - - // strcat(Session->ScreenBuffer, Formatted); - Session->Changed = TRUE; - - } while (count > 0); - } -} - - -VOID HTTPTimer() -{ - // Run every tick. Check for status change and data available - - struct HTTPConnectionInfo * Session = SessionList; // active term mode sessions - struct HTTPConnectionInfo * PreviousSession = NULL; - -// inf(); - - while (Session) - { - Session->KillTimer++; - - if (Session->Key[0] != 'T') - { - PreviousSession = Session; - Session = Session->Next; - continue; - } - - if (Session->KillTimer > 3000) // Around 5 mins - { - int i; - int Stream = Session->Stream; - - for (i = 0; i < 100; i++) - { - free(Session->ScreenLines[i]); - } - - SessionControl(Stream, 2, 0); - SessionState(Stream, &i, &i); - DeallocateStream(Stream); - - if (PreviousSession) - PreviousSession->Next = Session->Next; // Remove from chain - else - SessionList = Session->Next; - - free(Session); - - break; - } - - PollSession(Session); - - // if (Session->ResponseTimer == 0 && Session->Changed) - // Debugprintf("Data to send but no outstanding GET"); - - if (Session->ResponseTimer) - { - Session->ResponseTimer--; - - if (Session->ResponseTimer == 0 || Session->Changed) - { - SOCKET sock = Session->sock; - char _REPLYBUFFER[100000]; - int ReplyLen; - char Header[256]; - int HeaderLen; - int Last = Session->LastLine; - int n; - struct TNCINFO * TNC = Session->TNC; - struct TCPINFO * TCP = 0; - - if (TNC) - TCP = TNC->TCPInfo; - - if (TCP && TCP->WebTermCSS) - sprintf(_REPLYBUFFER, TermOutput, TCP->WebTermCSS); - else - sprintf(_REPLYBUFFER, TermOutput, ""); - - for (n = Last;;) - { - if ((strlen(Session->ScreenLines[n]) + strlen(_REPLYBUFFER)) < 99999) - strcat(_REPLYBUFFER, Session->ScreenLines[n]); - - if (n == 99) - n = -1; - - if (++n == Last) - break; - } - - ReplyLen = (int)strlen(_REPLYBUFFER); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", TermOutputTail); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, _REPLYBUFFER, ReplyLen); - - Session->ResponseTimer = Session->Changed = 0; - } - } - PreviousSession = Session; - Session = Session->Next; - } -} - -struct HTTPConnectionInfo * AllocateSession(SOCKET sock, char Mode) -{ - time_t KeyVal; - struct HTTPConnectionInfo * Session = zalloc(sizeof(struct HTTPConnectionInfo)); - int i; - - if (Session == NULL) - return NULL; - - if (Mode == 'T') - { - // Terminal - - for (i = 0; i < 20; i++) - Session->ScreenLines[i] = _strdup("Scroll to end
"); - - for (i = 20; i < 100; i++) - Session->ScreenLines[i] = _strdup("
\r\n"); - - Session->Stream = FindFreeStream(); - - if (Session->Stream == 0) - return NULL; - - SessionControl(Session->Stream, 1, 0); - } - - KeyVal = (int)sock * time(NULL); - - sprintf(Session->Key, "%c%012X", Mode, (int)KeyVal); - - if (SessionList) - Session->Next = SessionList; - - SessionList = Session; - - return Session; -} - -struct HTTPConnectionInfo * FindSession(char * Key) -{ - struct HTTPConnectionInfo * Session = SessionList; - - while (Session) - { - if (strcmp(Session->Key, Key) == 0) - return Session; - - Session = Session->Next; - } - - return NULL; -} - -void ProcessTermInput(SOCKET sock, char * MsgPtr, int MsgLen, char * Key) -{ - char _REPLYBUFFER[2048]; - int ReplyLen; - char Header[256]; - int HeaderLen; - int State; - struct HTTPConnectionInfo * Session = FindSession(Key); - int Stream; - int maxlen = 1000; - - - if (Session == NULL) - { - ReplyLen = sprintf(_REPLYBUFFER, "%s", LostSession); - } - else - { - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * end = &MsgPtr[MsgLen]; - int Line = Session->LastLine++; - char * ptr1, * ptr2; - char c; - UCHAR hex; - - int msglen = end - input; - - struct TNCINFO * TNC = Session->TNC; - struct TCPINFO * TCP = 0; - - if (TNC) - TCP = TNC->TCPInfo; - - if (TCP && TCP->WebTermCSS) - maxlen -= strlen(TCP->WebTermCSS); - - if (MsgLen > maxlen) - { - Session->KillTimer = 99999; // close session - return; - } - - - if (TCP && TCP->WebTermCSS) - ReplyLen = sprintf(_REPLYBUFFER, InputLine, Key, TCP->WebTermCSS); - else - ReplyLen = sprintf(_REPLYBUFFER, InputLine, Key, ""); - - - Stream = Session->Stream; - - input += 10; - ptr1 = ptr2 = input; - - // Convert any %xx constructs - - while (ptr1 != end) - { - c = *(ptr1++); - if (c == '%') - { - c = *(ptr1++); - if(isdigit(c)) - hex = (c - '0') << 4; - else - hex = (tolower(c) - 'a' + 10) << 4; - - c = *(ptr1++); - if(isdigit(c)) - hex += (c - '0'); - else - hex += (tolower(c) - 'a' + 10); - - *(ptr2++) = hex; - } - else if (c == '+') - *(ptr2++) = 32; - else - *(ptr2++) = c; - } - - end = ptr2; - - *ptr2 = 0; - - strcat(input, "
\r\n"); - - free(Session->ScreenLines[Line]); - - Session->ScreenLines[Line] = _strdup(input); - - if (Line == 99) - Session->LastLine = 0; - - *end++ = 13; - *end = 0; - - SessionStateNoAck(Stream, &State); - - if (State == 0) - { - char AXCall[10]; - SessionControl(Stream, 1, 0); - if (BPQHOSTVECTOR[Session->Stream -1].HOSTSESSION == NULL) - { - //No L4 sessions free - - ReplyLen = sprintf(_REPLYBUFFER, "%s", NoSessions); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - return; - } - - ConvToAX25(Session->HTTPCall, AXCall); - ChangeSessionCallsign(Stream, AXCall); - if (Session->USER) - BPQHOSTVECTOR[Session->Stream -1].HOSTSESSION->Secure_Session = Session->USER->Secure; - else - Debugprintf("HTTP Term Session->USER is NULL"); - } - - SendMsg(Stream, input, (int)(end - input)); - Session->Changed = TRUE; - Session->KillTimer = 0; - } - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); -} - - -void ProcessTermClose(SOCKET sock, char * MsgPtr, int MsgLen, char * Key, int LOCAL) -{ - char _REPLYBUFFER[8192]; - int ReplyLen = sprintf(_REPLYBUFFER, InputLine, Key, ""); - char Header[256]; - int HeaderLen; - struct HTTPConnectionInfo * Session = FindSession(Key); - - if (Session) - { - Session->KillTimer = 99999; - } - - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n" - "\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); -} - -int ProcessTermSignon(struct TNCINFO * TNC, SOCKET sock, char * MsgPtr, int MsgLen, int LOCAL) -{ - char _REPLYBUFFER[8192]; - int ReplyLen; - char Header[256]; - int HeaderLen; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * user, * password, * Context, * Appl; - char NoApp[] = ""; - struct TCPINFO * TCP = TNC->TCPInfo; - - if (input) - { - int i; - struct UserRec * USER; - - UndoTransparency(input); - - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - goto Sendit; - } - user = strtok_s(&input[9], "&", &Context); - password = strtok_s(NULL, "=", &Context); - password = strtok_s(NULL, "&", &Context); - - Appl = strtok_s(NULL, "=", &Context); - Appl = strtok_s(NULL, "&", &Context); - - if (Appl == 0) - Appl = NoApp; - - if (password == NULL) - { - ReplyLen = sprintf(_REPLYBUFFER, TermSignon, Mycall, Mycall, Appl); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", PassError); - goto Sendit; - } - - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if ((strcmp(password, USER->Password) == 0) && - ((_stricmp(user, USER->UserName) == 0 ) || (_stricmp(USER->UserName, "ANON") == 0))) - { - // ok - - struct HTTPConnectionInfo * Session = AllocateSession(sock, 'T'); - - if (Session) - { - char AXCall[10]; - ReplyLen = sprintf(_REPLYBUFFER, TermPage, Mycall, Mycall, Session->Key, Session->Key, Session->Key); - if (_stricmp(USER->UserName, "ANON") == 0) - strcpy(Session->HTTPCall, _strupr(user)); - else - strcpy(Session->HTTPCall, USER->Callsign); - ConvToAX25(Session->HTTPCall, AXCall); - ChangeSessionCallsign(Session->Stream, AXCall); - BPQHOSTVECTOR[Session->Stream -1].HOSTSESSION->Secure_Session = USER->Secure; - Session->USER = USER; - - if (USER->Appl[0]) - SendMsg(Session->Stream, USER->Appl, (int)strlen(USER->Appl)); - } - else - { - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", BusyError); - } - break; - } - } - - if (i == TCP->NumberofUsers) - { - // Not found - - ReplyLen = sprintf(_REPLYBUFFER, TermSignon, Mycall, Mycall, Appl); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", PassError); - } - - } - -Sendit: - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 1; -} - -char * LookupKey(char * Key) -{ - if (strcmp(Key, "##MY_CALLSIGN##") == 0) - { - char Mycall[10]; - memcpy(Mycall, &MYNODECALL, 10); - strlop(Mycall, ' '); - - return _strdup(Mycall); - } - return NULL; -} - - -int ProcessSpecialPage(char * Buffer, int FileSize) -{ - // replaces ##xxx### constructs with the requested data - - char * NewMessage = malloc(100000); - char * ptr1 = Buffer, * ptr2, * ptr3, * ptr4, * NewPtr = NewMessage; - int PrevLen; - int BytesLeft = FileSize; - int NewFileSize = FileSize; - char * StripPtr = ptr1; - - // strip comments blocks - - while (ptr4 = strstr(ptr1, ""); - if (ptr2) - { - PrevLen = (int)(ptr4 - ptr1); - memcpy(StripPtr, ptr1, PrevLen); - StripPtr += PrevLen; - ptr1 = ptr2 + 3; - BytesLeft = (int)(FileSize - (ptr1 - Buffer)); - } - } - - memcpy(StripPtr, ptr1, BytesLeft); - StripPtr += BytesLeft; - - BytesLeft = (int)(StripPtr - Buffer); - - FileSize = BytesLeft; - NewFileSize = FileSize; - ptr1 = Buffer; - ptr1[FileSize] = 0; - -loop: - ptr2 = strstr(ptr1, "##"); - - if (ptr2) - { - PrevLen = (int)(ptr2 - ptr1); // Bytes before special text - - ptr3 = strstr(ptr2+2, "##"); - - if (ptr3) - { - char Key[80] = ""; - int KeyLen; - char * NewText; - int NewTextLen; - - ptr3 += 2; - KeyLen = (int)(ptr3 - ptr2); - - if (KeyLen < 80) - memcpy(Key, ptr2, KeyLen); - - NewText = LookupKey(Key); - - if (NewText) - { - NewTextLen = (int)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 = (int)(Buffer + FileSize - ptr3); - } - else // Unmatched ## - { - memcpy(NewPtr, ptr1, PrevLen + 2); - NewPtr += (PrevLen + 2); - ptr1 = ptr2 + 2; - } - goto loop; - } - - // Copy Rest - - memcpy(NewPtr, ptr1, BytesLeft); - NewMessage[NewFileSize] = 0; - - strcpy(Buffer, NewMessage); - free(NewMessage); - - return NewFileSize; -} - -int SendMessageFile(SOCKET sock, char * FN, BOOL OnlyifExists, int allowDeflate) -{ - int FileSize = 0, Sent, Loops = 0; - char * MsgBytes; - char MsgFile[512]; - FILE * hFile; - int ReadLen; - BOOL Special = FALSE; - int Len; - int HeaderLen; - char Header[256]; - char TimeString[64]; - char FileTimeString[64]; - struct stat STAT; - char * ptr; - char * Compressed = 0; - char Encoding[] = "Content-Encoding: deflate\r\n"; - char Type[64] = "Content-Type: text/html\r\n"; - -#ifdef WIN32 - - struct _EXCEPTION_POINTERS exinfo; - strcpy(EXCEPTMSG, "SendMessageFile"); - - __try { -#endif - - UndoTransparency(FN); - - if (strstr(FN, "..")) - { - FN[0] = '/'; - FN[1] = 0; - } - - if (strlen(FN) > 256) - { - FN[256] = 0; - Debugprintf("HTTP File Name too long %s", FN); - } - - if (strcmp(FN, "/") == 0) - if (APRSActive) - sprintf(MsgFile, "%s/HTML/index.html", BPQDirectory); - else - sprintf(MsgFile, "%s/HTML/indexnoaprs.html", BPQDirectory); - else - sprintf(MsgFile, "%s/HTML%s", BPQDirectory, FN); - - - // First see if file exists so we can override standard ones in code - - if (stat(MsgFile, &STAT) == 0 && (hFile = fopen(MsgFile, "rb"))) - { - FileSize = STAT.st_size; - - MsgBytes = zalloc(FileSize + 1); - - ReadLen = (int)fread(MsgBytes, 1, FileSize, hFile); - - fclose(hFile); - - // ft.QuadPart -= 116444736000000000; - // ft.QuadPart /= 10000000; - - // ctime = ft.LowPart; - - FormatTime3(FileTimeString, STAT.st_ctime); - } - else - { - // See if it is a hard coded file - - MsgBytes = GetStandardPage(&FN[1], &FileSize); - - if (MsgBytes) - { - if (FileSize == 0) - FileSize = strlen(MsgBytes); - - FormatTime3(FileTimeString, 0); - } - else - { - if (OnlyifExists) // Set if we dont want an error response if missing - return -1; - - Len = sprintf(Header, "HTTP/1.1 404 Not Found\r\nContent-Length: 16\r\n\r\nPage not found\r\n"); - send(sock, Header, Len, 0); - return 0; - } - } - - // if HTML file, look for ##...## substitutions - - if ((strcmp(FN, "/") == 0 || strstr(FN, "htm" ) || strstr(FN, "HTM")) && strstr(MsgBytes, "##" )) - { - FileSize = ProcessSpecialPage(MsgBytes, FileSize); - FormatTime3(FileTimeString, time(NULL)); - - } - - FormatTime3(TimeString, time(NULL)); - - ptr = FN; - - while (strchr(ptr, '.')) - { - ptr = strchr(ptr, '.'); - ++ptr; - } - - if (_stricmp(ptr, "js") == 0) - strcpy(Type, "Content-Type: text/javascript\r\n"); - - if (_stricmp(ptr, "css") == 0) - strcpy(Type, "Content-Type: text/css\r\n"); - - if (_stricmp(ptr, "pdf") == 0) - strcpy(Type, "Content-Type: application/pdf\r\n"); - - if (allowDeflate) - { - Compressed = Compressit(MsgBytes, FileSize, &FileSize); - } - else - { - Encoding[0] = 0; - Compressed = MsgBytes; - } - - if (_stricmp(ptr, "jpg") == 0 || _stricmp(ptr, "jpeg") == 0 || _stricmp(ptr, "png") == 0 || - _stricmp(ptr, "gif") == 0 || _stricmp(ptr, "bmp") == 0 || _stricmp(ptr, "ico") == 0) - strcpy(Type, "Content-Type: image\r\n"); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n" - "Date: %s\r\n" - "Last-Modified: %s\r\n" - "%s%s" - "\r\n", FileSize, TimeString, FileTimeString, Type, Encoding); - - send(sock, Header, HeaderLen, 0); - - Sent = send(sock, Compressed, FileSize, 0); - - while (Sent != FileSize && Loops++ < 3000) // 100 secs max - { - if (Sent > 0) // something sent - { -// Debugprintf("%d out of %d sent", Sent, FileSize); - FileSize -= Sent; - memmove(Compressed, &Compressed[Sent], FileSize); - } - - Sleep(30); - Sent = send(sock, Compressed, FileSize, 0); - } - -// Debugprintf("%d out of %d sent %d loops", Sent, FileSize, Loops); - - - free (MsgBytes); - if (allowDeflate) - free (Compressed); - -#ifdef WIN32 - } -#include "StdExcept.c" - Debugprintf("Sending FIle %s", FN); -} -#endif - -return 0; -} - -VOID sendandcheck(SOCKET sock, const char * Buffer, int Len) -{ - int Loops = 0; - int Sent = send(sock, Buffer, Len, 0); - char * Copy = NULL; - - while (Sent != Len && Loops++ < 300) // 10 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, Len, Loops); - - if (Copy == NULL) - { - Copy = malloc(Len); - memcpy(Copy, Buffer, Len); - } - - if (Sent > 0) // something sent - { - Len -= Sent; - memmove(Copy, &Copy[Sent], Len); - } - - Sleep(30); - Sent = send(sock, Copy, Len, 0); - } - - if (Copy) - free(Copy); - - return; -} - -int RefreshTermWindow(struct TCPINFO * TCP, struct HTTPConnectionInfo * Session, char * _REPLYBUFFER) -{ - char Msg[400] = ""; - int HeaderLen, ReplyLen; - char Header[256]; - - PollSession(Session); // See if anything received - - if (Session->Changed) - { - int Last = Session->LastLine; - int n; - - if (TCP && TCP->WebTermCSS) - sprintf(_REPLYBUFFER, TermOutput, TCP->WebTermCSS); - else - sprintf(_REPLYBUFFER, TermOutput, ""); - - for (n = Last;;) - { - strcat(_REPLYBUFFER, Session->ScreenLines[n]); - - if (n == 99) - n = -1; - - if (++n == Last) - break; - } - - Session->Changed = 0; - - ReplyLen = (int)strlen(_REPLYBUFFER); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", TermOutputTail); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen); - sendandcheck(Session->sock, Header, HeaderLen); - sendandcheck(Session->sock, _REPLYBUFFER, ReplyLen); - - return 1; - } - else - return 0; -} - -int SetupNodeMenu(char * Buff, int LOCAL) -{ - int Len = 0, i; - struct TNCINFO * TNC; - int top = 0, left = 0; - - char NodeMenuHeader[] = "%s's BPQ32 Web Server" - "" - - "" - "

BPQ32 Node %s

" - "

" - "" - "" - "" - "" - "" - "" - "%s%s%s%s%s%s"; - - char DriverBit[] = "" - ""; - - char APRSBit[] = ""; - - char MailBit[] = "" - ""; - - char ChatBit[] = ""; - char SigninBit[] = ""; - - char NodeTail[] = - "" - "
RoutesNodesPortsLinksUsersStatsTerminalDriver WindowsStream StatusAPRS PagesMail MgmtWebMailChat MgmtSYSOP SigninEdit Config" - "
"; - - - Len = sprintf(Buff, NodeMenuHeader, Mycall); - - for (i=1; i <= MAXBPQPORTS; i++) - { - TNC = TNCInfo[i]; - if (TNC == NULL) - continue; - - if (TNC->WebWindowProc) - { - Len += sprintf(&Buff[Len], NodeMenuLine, i, TNC->WebWinX, TNC->WebWinY, top, left); - top += 22; - left += 22; - } - } - - Len += sprintf(&Buff[Len], NodeMenuRest, Mycall, - DriverBit, - (APRSWeb)?APRSBit:"", - (IncludesMail)?MailBit:"", (IncludesChat)?ChatBit:"", (LOCAL)?"":SigninBit, NodeTail); - - return Len; -} - -VOID SaveConfigFile(SOCKET sock , char * MsgPtr, char * Rest, int LOCAL) -{ - int ReplyLen = 0; - char * ptr, * ptr1, * ptr2, *input; - char c; - int MsgLen, WriteLen = 0; - char inputname[250]="bpq32.cfg"; - FILE *fp1; - char Header[256]; - int HeaderLen; - char Reply[4096]; - char Mess[256]; - char Backup1[MAX_PATH]; - char Backup2[MAX_PATH]; - struct stat STAT; - - input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - - if (input) - { - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - // ReplyLen = sprintf(Reply, "%s", ""); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - return; - } - - ptr = strstr(input, "&Save="); - - if (ptr) - { - *ptr = 0; - - // Undo any % transparency - - ptr1 = ptr2 = input + 8; - - 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; - - c = m * 16 + n; - } - else if (c == '+') - c = ' '; - -#ifndef WIN32 - if (c != 13) // Strip CR if Linux -#endif - *(ptr2++) = c; - - c = *(ptr1++); - - } - - *(ptr2++) = 0; - - MsgLen = (int)strlen(input + 8); - - if (ConfigDirectory[0] == 0) - { - strcpy(inputname, "bpq32.cfg"); - } - else - { - strcpy(inputname,ConfigDirectory); - strcat(inputname,"/"); - strcat(inputname, "bpq32.cfg"); - } - - // Make a backup of the config - - // Keep 4 Generations - - strcpy(Backup2, inputname); - strcat(Backup2, ".bak.3"); - - strcpy(Backup1, inputname); - strcat(Backup1, ".bak.2"); - - DeleteFile(Backup2); // Remove old .bak.3 - MoveFile(Backup1, Backup2); // Move .bak.2 to .bak.3 - - strcpy(Backup2, inputname); - strcat(Backup2, ".bak.1"); - - MoveFile(Backup2, Backup1); // Move .bak.1 to .bak.2 - - strcpy(Backup1, inputname); - strcat(Backup1, ".bak"); - - MoveFile(Backup1, Backup2); // Move .bak to .bak.1 - - CopyFile(inputname, Backup1, FALSE); // Copy to .bak - - // Get length to compare with new length - - stat(inputname, &STAT); - - fp1 = fopen(inputname, "wb"); - - if (fp1) - { - WriteLen = (int)fwrite(input + 8, 1, MsgLen, fp1); - fclose(fp1); - } - - if (WriteLen != MsgLen) - sprintf_s(Mess, sizeof(Mess), "Failed to write Config File"); - else - sprintf_s(Mess, sizeof(Mess), "Configuration Saved, Orig Length %d New Length %d", - STAT.st_size, MsgLen); - } - - ReplyLen = sprintf(Reply, "", Mess); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - } - return; -} - -// Compress using deflate. Caller must free output buffer after use - -unsigned char * Compressit(unsigned char * In, int Len, int * OutLen) -{ - z_stream defstream; - int maxSize; - unsigned char * Out; - - defstream.zalloc = Z_NULL; - defstream.zfree = Z_NULL; - defstream.opaque = Z_NULL; - - defstream.avail_in = Len; // size of input - defstream.next_in = (Bytef *)In; // input char array - - deflateInit(&defstream, Z_BEST_COMPRESSION); - maxSize = deflateBound(&defstream, Len); - - Out = malloc(maxSize); - - defstream.avail_out = maxSize; // size of output - defstream.next_out = (Bytef *)Out; // output char array - - deflate(&defstream, Z_FINISH); - deflateEnd(&defstream); - - *OutLen = defstream.total_out; - - return Out; -} - - -int InnerProcessHTTPMessage(struct ConnectionInfo * conn) -{ - struct TCPINFO * TCP = conn->TNC->TCPInfo; - SOCKET sock = conn->socket; - char * MsgPtr = conn->InputBuffer; - int MsgLen = conn->InputLen; - int InputLen = 0; - int OutputLen = 0; - int Bufferlen; - struct HTTPConnectionInfo CI; - struct HTTPConnectionInfo * sockptr = &CI; - struct HTTPConnectionInfo * Session = NULL; - - char URL[100000]; - char * ptr; - char * encPtr = 0; - int allowDeflate = 0; - char * Compressed = 0; - char * HostPtr = 0; - - char * Context, * Method, * NodeURL = 0, * Key; - char _REPLYBUFFER[250000]; - char Reply[250000]; - - int ReplyLen = 0; - char Header[256]; - int HeaderLen; - char TimeString[64]; - BOOL LOCAL = FALSE; - BOOL COOKIE = FALSE; - int Len; - char * WebSock = 0; - - char PortsHddr[] = "

Ports

" - ""; - -// char PortLine[] = ""; - - char PortLineWithBeacon[] = "" - "\r\n"; - - char SessionPortLine[] = "" - "\r\n"; - - char PortLineWithDriver[] = "" - "\r\n"; - - - char PortLineWithBeaconAndDriver[] = "" - "" - "\r\n"; - - char RigControlLine[] = "" - "\r\n"; - - - char Encoding[] = "Content-Encoding: deflate\r\n"; - -#ifdef WIN32xx - - struct _EXCEPTION_POINTERS exinfo; - strcpy(EXCEPTMSG, "ProcessHTTPMessage"); - - __try { -#endif - - Len = (int)strlen(MsgPtr); - if (Len > 100000) - return 0; - - strcpy(URL, MsgPtr); - - HostPtr = strstr(MsgPtr, "Host: "); - - WebSock = strstr(MsgPtr, "Upgrade: websocket"); - - if (HostPtr) - { - uint32_t Host; - char Hostname[32]= ""; - struct LOCALNET * LocalNet = conn->TNC->TCPInfo->LocalNets; - - HostPtr += 6; - memcpy(Hostname, HostPtr, 31); - strlop(Hostname, ':'); - Host = inet_addr(Hostname); - - if (strcmp(Hostname, "127.0.0.1") == 0) - LOCAL = TRUE; - else - { - if (conn->sin.sin_family != AF_INET6) - { - while(LocalNet) - { - uint32_t MaskedHost = conn->sin.sin_addr.s_addr & LocalNet->Mask; - if (MaskedHost == LocalNet->Network) - { - LOCAL = 1; - break; - } - LocalNet = LocalNet->Next; - } - } - } - } - - encPtr = stristr(MsgPtr, "Accept-Encoding:"); - - if (encPtr && stristr(encPtr, "deflate")) - allowDeflate = 1; - else - Encoding[0] = 0; - - ptr = strstr(MsgPtr, "BPQSessionCookie=N"); - - if (ptr) - { - COOKIE = TRUE; - Key = ptr + 17; - ptr = strchr(Key, ','); - if (ptr) - { - *ptr = 0; - Session = FindSession(Key); - *ptr = ','; - } - else - { - ptr = strchr(Key, 13); - if (ptr) - { - *ptr = 0; - Session = FindSession(Key); - *ptr = 13; - } - } - } - - if (WebSock) - { - // Websock connection request - Reply and remember state. - - char KeyMsg[128]; - char Webx[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // Fixed UID - char Hash[64] = ""; - char * Hash64; // base 64 version - char * ptr; - - //Sec-WebSocket-Key: l622yZS3n+zI+hR6SVWkPw== - - char ReplyMsg[] = - "HTTP/1.1 101 Switching Protocols\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Accept: %s\r\n" -// "Sec-WebSocket-Protocol: chat\r\n" - "\r\n"; - - ptr = strstr(MsgPtr, "Sec-WebSocket-Key:"); - - if (ptr) - { - ptr += 18; - while (*ptr == ' ') - ptr++; - - memcpy(KeyMsg, ptr, 40); - strlop(KeyMsg, 13); - strlop(KeyMsg, ' '); - strcat(KeyMsg, Webx); - - SHA1PasswordHash(KeyMsg, Hash); - Hash64 = byte_base64_encode(Hash, 20); - - conn->WebSocks = 1; - strlop(&URL[4], ' '); - strcpy(conn->WebURL, &URL[4]); - - ReplyLen = sprintf(Reply, ReplyMsg, Hash64); - - free(Hash64); - goto Returnit; - - } - } - - - ptr = strstr(URL, " HTTP"); - - if (ptr) - *ptr = 0; - - Method = strtok_s(URL, " ", &Context); - - memcpy(Mycall, &MYNODECALL, 10); - strlop(Mycall, ' '); - - - // Look for API messages - - if (_memicmp(Context, "/api/", 5) == 0 || _stricmp(Context, "/api") == 0) - { - char * Compressed; - - // if for mail api process signon here and rearrange url from - // api/v1/mail to mail/api/v1 so it goes to mail handler later - - if (_memicmp(Context, "/api/v1/mail/", 13) == 0) - { - memcpy(MsgPtr, "GET /mail/api/v1/", 17); - - if (memcmp(&Context[13], "login", 5) == 0) - { - ReplyLen = ProcessMailAPISignon(TCP, MsgPtr, "M", Reply, &Session, FALSE, LOCAL); - memcpy(MsgPtr, "GET /mail/api/v1/", 17); - - if (ReplyLen) // Error message - goto Returnit; - } - - memcpy(Context, "/mail/api/v1/", 13); - goto doHeader; - } - else - { - ReplyLen = APIProcessHTTPMessage(_REPLYBUFFER, Method, Context, MsgPtr, LOCAL, COOKIE); - - if (memcmp(_REPLYBUFFER, "HTTP", 4) == 0) - { - // Full Message - just send it - - sendandcheck(sock, _REPLYBUFFER, ReplyLen); - - return 0; - } - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = _REPLYBUFFER; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\n" - "Content-Length: %d\r\n" - "Content-Type: application/json\r\n" - "Connection: close\r\n" - "Access-Control-Allow-Origin: *\r\n" - "%s\r\n", ReplyLen, Encoding); - - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - } - } - - if (_memicmp(Context, "/rhp/", 5) == 0 || _stricmp(Context, "/rhp") == 0) - { - { - ReplyLen = RHPProcessHTTPMessage(conn, _REPLYBUFFER, Method, Context, MsgPtr, LOCAL, COOKIE); - - if (memcmp(_REPLYBUFFER, "HTTP", 4) == 0) - { - // Full Message - just send it - - sendandcheck(sock, _REPLYBUFFER, ReplyLen); - - return 0; - } - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = _REPLYBUFFER; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\n" - "Content-Length: %d\r\n" - "Content-Type: application/json\r\n" - "Connection: close\r\n" - "Access-Control-Allow-Origin: *\r\n" - "%s\r\n", ReplyLen, Encoding); - - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - } - } - - - // APRS process internally - - if (_memicmp(Context, "/APRS/", 6) == 0 || _stricmp(Context, "/APRS") == 0) - { - APRSProcessHTTPMessage(sock, MsgPtr, LOCAL, COOKIE); - return 0; - } - - - if (_stricmp(Context, "/Node/Signon?Node") == 0) - { - char * IContext; - - NodeURL = strtok_s(Context, "?", &IContext); - Key = strtok_s(NULL, "?", &IContext); - - ProcessNodeSignon(sock, TCP, MsgPtr, Key, Reply, &Session, LOCAL); - return 0; - - } - - // If for Mail or Chat, check for a session, and send login screen if necessary - - // Moved here to simplify operation with both internal and external clients - - if (_memicmp(Context, "/Mail/", 6) == 0) - { - int RLen = 0; - char Appl; - char * input; - char * IContext; - - NodeURL = strtok_s(Context, "?", &IContext); - Key = strtok_s(NULL, "?", &IContext); - - if (_stricmp(NodeURL, "/Mail/Signon") == 0) - { - ReplyLen = ProcessMailSignon(TCP, MsgPtr, Key, Reply, &Session, FALSE, LOCAL); - - if (ReplyLen) - { - goto Returnit; - } - -#ifdef LINBPQ - strcpy(Context, "/Mail/Header"); -#else - strcpy(MsgPtr, "POST /Mail/Header"); -#endif - goto doHeader; - } - - if (_stricmp(NodeURL, "/Mail/Lost") == 0) - { - input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - - if (input && strstr(input, "Cancel=Exit")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - RLen = ReplyLen; - goto Returnit; - } - if (Key) - Appl = Key[0]; - - Key = 0; - } - - if (Key == 0 || Key[0] == 0) - { - // No Session - - // if not local send a signon screen, else create a user session - - if (LOCAL || COOKIE) - { - Session = AllocateSession(sock, 'M'); - - if (Session) - { - strcpy(Context, "/Mail/Header"); - goto doHeader; - } - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); - } - RLen = ReplyLen; - - goto Returnit; - - } - - ReplyLen = sprintf(Reply, MailSignon, Mycall, Mycall); - - RLen = ReplyLen; - goto Returnit; - } - - Session = FindSession(Key); - - - if (Session == NULL && _memicmp(Context, "/Mail/API/", 10) != 0) - { - ReplyLen = sprintf(Reply, MailLostSession, Key); - RLen = ReplyLen; - goto Returnit; - } - } - - if (_memicmp(Context, "/Chat/", 6) == 0) - { - int RLen = 0; - char Appl; - char * input; - char * IContext; - - - HostPtr = strstr(MsgPtr, "Host: "); - - if (HostPtr) - { - uint32_t Host; - char Hostname[32]= ""; - struct LOCALNET * LocalNet = conn->TNC->TCPInfo->LocalNets; - - HostPtr += 6; - memcpy(Hostname, HostPtr, 31); - strlop(Hostname, ':'); - Host = inet_addr(Hostname); - - if (strcmp(Hostname, "127.0.0.1") == 0) - LOCAL = TRUE; - else while(LocalNet) - { - uint32_t MaskedHost = Host & LocalNet->Mask; - if (MaskedHost == LocalNet->Network) - { - char * rest; - LOCAL = 1; - rest = strchr(HostPtr, 13); - if (rest) - { - memmove(HostPtr + 9, rest, strlen(rest) + 1); - memcpy(HostPtr, "127.0.0.1", 9); - break; - } - } - LocalNet = LocalNet->Next; - } - } - - NodeURL = strtok_s(Context, "?", &IContext); - Key = strtok_s(NULL, "?", &IContext); - - if (_stricmp(NodeURL, "/Chat/Signon") == 0) - { - ReplyLen = ProcessChatSignon(TCP, MsgPtr, Key, Reply, &Session, LOCAL); - - if (ReplyLen) - { - goto Returnit; - } - -#ifdef LINBPQ - strcpy(Context, "/Chat/Header"); -#else - strcpy(MsgPtr, "POST /Chat/Header"); -#endif - goto doHeader; - } - - if (_stricmp(NodeURL, "/Chat/Lost") == 0) - { - input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - - if (input && strstr(input, "Cancel=Exit")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - RLen = ReplyLen; - goto Returnit; - } - if (Key) - Appl = Key[0]; - - Key = 0; - } - - if (Key == 0 || Key[0] == 0) - { - // No Session - - // if not local send a signon screen, else create a user session - - if (LOCAL || COOKIE) - { - Session = AllocateSession(sock, 'C'); - - if (Session) - { - strcpy(Context, "/Chat/Header"); - goto doHeader; - } - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); - } - RLen = ReplyLen; - - goto Returnit; - - } - - ReplyLen = sprintf(Reply, ChatSignon, Mycall, Mycall); - - RLen = ReplyLen; - goto Returnit; - } - - Session = FindSession(Key); - - if (Session == NULL) - { - int Sent, Loops = 0; - ReplyLen = sprintf(Reply, MailLostSession, Key); - RLen = ReplyLen; -Returnit: - if (memcmp(Reply, "HTTP", 4) == 0) - { - // Full Header provided by appl - just send it - - // Send may block - - Sent = send(sock, Reply, ReplyLen, 0); - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(Reply, &Reply[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sock, Reply, ReplyLen, 0); - } - - return 0; - } - - if (NodeURL && _memicmp(NodeURL, "/mail/api/", 10) != 0) - { - // Add tail - - strcpy(&Reply[ReplyLen], Tail); - ReplyLen += strlen(Tail); - } - - // compress if allowed - - if (allowDeflate) - Compressed = Compressit(Reply, ReplyLen, &ReplyLen); - else - Compressed = Reply; - - if (NodeURL && _memicmp(NodeURL, "/mail/api/", 10) == 0) - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: application/json\r\nConnection: close\r\n%s\r\n", ReplyLen, Encoding); - else - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n%s\r\n", ReplyLen, Encoding); - - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - } - } - -doHeader: - -#ifdef LINBPQ - - if ((_memicmp(Context, "/MAIL/", 6) == 0) || (_memicmp(Context, "/WebMail", 8) == 0)) - { - char _REPLYBUFFER[250000]; - struct HTTPConnectionInfo Dummy = {0}; - int Sent, Loops = 0; - char token[16] = ""; - - // look for auth header - - const char * auth_header = "Authorization: Bearer "; - char * token_begin = strstr(MsgPtr, auth_header); - int Flags = 0, n; - - char * Tok; - char * param; - - if (token_begin) - { - // Using Auth Header - - // Extract the token from the request (assuming it's present in the request headers) - - token_begin += strlen(auth_header); // Move to the beginning of the token - strncpy(token, token_begin, 13); - token[13] = '\0'; // Null-terminate the token - } - - ReplyLen = 0; - - if (Session == 0) - Session = &Dummy; - - if (LOCAL) - Session->TNC = (void *)1; // TNC only used for Web Terminal Sessions - else - Session->TNC = (void *)0; - - ProcessMailHTTPMessage(Session, Method, Context, MsgPtr, _REPLYBUFFER, &ReplyLen, MsgLen, token); - - if (Context && _memicmp(Context, "/mail/api/", 10) == 0) - { - if (memcmp(_REPLYBUFFER, "HTTP", 4) == 0) - { - // Full Header provided by appl - just send it - - // Send may block - - Sent = send(sock, _REPLYBUFFER, ReplyLen, 0); - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(_REPLYBUFFER, &_REPLYBUFFER[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sock, _REPLYBUFFER, ReplyLen, 0); - } - return 0; - } - - // compress if allowed - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = _REPLYBUFFER; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: application/json\r\nConnection: close\r\n%s\r\n", ReplyLen, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - } - - if (memcmp(_REPLYBUFFER, "HTTP", 4) == 0) - { - // Full Header provided by appl - just send it - - // Send may block - - Sent = send(sock, _REPLYBUFFER, ReplyLen, 0); - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(_REPLYBUFFER, &_REPLYBUFFER[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sock, _REPLYBUFFER, ReplyLen, 0); - } - return 0; - } - - if (Context && _memicmp(Context, "/mail/api/", 10) != 0) - { - - // Add tail - - strcpy(&_REPLYBUFFER[ReplyLen], Tail); - ReplyLen += strlen(Tail); - - } - - // compress if allowed - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = Reply; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n%s\r\n", ReplyLen, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - - -/* - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - - // Send may block - - Sent = send(sock, _REPLYBUFFER, ReplyLen, 0); - - if (Sent == -1) - return 0; - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(_REPLYBUFFER, &_REPLYBUFFER[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sock, _REPLYBUFFER, ReplyLen, 0); - } - - send(sock, Tail, (int)strlen(Tail), 0); - return 0; -*/ - } - - if (_memicmp(Context, "/CHAT/", 6) == 0) - { - char _REPLYBUFFER[100000]; - - ReplyLen = 0; - - ProcessChatHTTPMessage(Session, Method, Context, MsgPtr, _REPLYBUFFER, &ReplyLen); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 0; - - } - - - /* - Sent = send(sock, _REPLYBUFFER, InputLen, 0); - - while (Sent != InputLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(_REPLYBUFFER, &_REPLYBUFFER[Sent], InputLen); - } - - Sleep(30); - Sent = send(sock, _REPLYBUFFER, InputLen, 0); - } - return 0; - } - */ -#else - - // Pass to MailChat if active - - NodeURL = Context; - - if ((_memicmp(Context, "/MAIL/", 6) == 0) || (_memicmp(Context, "/WebMail", 8) == 0)) - { - // If for Mail, Pass to Mail Server via Named Pipe - - HANDLE hPipe; - - hPipe = CreateFile(MAILPipeFileName, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (hPipe == (HANDLE)-1) - { - InputLen = sprintf(Reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 28\r\n\r\nMail Data is not available\r\n"); - send(sock, Reply, InputLen, 0); - } - else - { - // int Sent; - int Loops = 0; - struct HTTPConnectionInfo Dummy = {0}; - - if (Session == 0) - Session = &Dummy; - - Session->TNC = LOCAL; // TNC is only used on Web Terminal Sessions so can reuse as LOCAL flag - - WriteFile(hPipe, Session, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - WriteFile(hPipe, MsgPtr, MsgLen, &InputLen, NULL); - - - ReadFile(hPipe, Session, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - ReadFile(hPipe, Reply, 250000, &ReplyLen, NULL); - if (ReplyLen <= 0) - { - InputLen = GetLastError(); - } - - CloseHandle(hPipe); - goto Returnit; - } - return 0; - } - - if (_memicmp(Context, "/CHAT/", 6) == 0) - { - HANDLE hPipe; - - hPipe = CreateFile(CHATPipeFileName, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (hPipe == (HANDLE)-1) - { - InputLen = sprintf(Reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 28\r\n\r\nChat Data is not available\r\n"); - send(sock, Reply, InputLen, 0); - } - else - { - // int Sent; - int Loops = 0; - - WriteFile(hPipe, Session, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - WriteFile(hPipe, MsgPtr, MsgLen, &InputLen, NULL); - - - ReadFile(hPipe, Session, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - ReadFile(hPipe, Reply, 100000, &ReplyLen, NULL); - if (ReplyLen <= 0) - { - InputLen = GetLastError(); - } - - CloseHandle(hPipe); - goto Returnit; - } - return 0; - } - -#endif - - NodeURL = strtok_s(NULL, "?", &Context); - - if (NodeURL == NULL) - return 0; - - if (strcmp(Method, "POST") == 0) - { - if (_stricmp(NodeURL, "/Node/freqOffset") == 0) - { - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - int port = atoi(Context); - - if (input == 0) - return 1; - - input += 4; - - if (port > 0 && port <= MaxBPQPortNo) - { - struct TNCINFO * TNC = TNCInfo[port]; - char value[6]; - - if (TNC == 0) - return 1; - - TNC->TXOffset = atoi(input); -#ifdef WIN32 - sprintf(value, "%d", TNC->TXOffset); - MySetWindowText(TNC->xIDC_TXTUNEVAL, value); - SendMessage(TNC->xIDC_TXTUNE, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) TNC->TXOffset); // min. & max. positions - -#endif - } - return 1; - } - - if (_stricmp(NodeURL, "/Node/PortAction") == 0) - { - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - int port = atoi(Context); - - if (input == 0) - return 1; - - input += 4; - - if (port > 0 && port <= MaxBPQPortNo) - { - struct TNCINFO * TNC = TNCInfo[port]; - - if (TNC == 0) - return 1; - - if (LOCAL == FALSE && COOKIE == FALSE) - return 1; - - if (strcmp(input, "Abort") == 0) - { - if (TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - } - else if (strcmp(input, "Kill") == 0) - { - TNC->DontRestart = TRUE; - KillTNC(TNC); - } - else if (strcmp(input, "KillRestart") == 0) - { - TNC->DontRestart = FALSE; - KillTNC(TNC); - RestartTNC(TNC); - - } - } - return 1; - } - - if (_stricmp(NodeURL, "/TermInput") == 0) - { - ProcessTermInput(sock, MsgPtr, MsgLen, Context); - return 0; - } - - if (_stricmp(NodeURL, "/Node/TermSignon") == 0) - { - ProcessTermSignon(conn->TNC, sock, MsgPtr, MsgLen, LOCAL); - } - - if (_stricmp(NodeURL, "/Node/Signon") == 0) - { - ProcessNodeSignon(sock, TCP, MsgPtr, Key, Reply, &Session, LOCAL); - return 0; - } - - if (_stricmp(NodeURL, "/Node/TermClose") == 0) - { - ProcessTermClose(sock, MsgPtr, MsgLen, Context, LOCAL); - return 0; - } - - if (_stricmp(NodeURL, "/Node/BeaconAction") == 0) - { - char Header[256]; - int HeaderLen; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - int Port; - char Param[100]; -#ifndef LINBPQ - int retCode, disp; - char Key[80]; - HKEY hKey; -#endif - struct PORTCONTROL * PORT; - int Slot = 0; - - - if (LOCAL == FALSE && COOKIE == FALSE) - { - // Send Not Authorized - - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
Not authorized - please sign in"); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 1; - } - - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 1; - } - - GetParam(input, "Port=", &Param[0]); - Port = atoi(&Param[0]); - PORT = GetPortTableEntryFromPortNum(Port); // Need slot not number - if (PORT) - Slot = PORT->PortSlot; - - GetParam(input, "Every=", &Param[0]); - Interval[Slot] = atoi(&Param[0]); - - GetParam(input, "Dest=", &Param[0]); - _strupr(Param); - strcpy(UIUIDEST[Slot], &Param[0]); - - GetParam(input, "Path=", &Param[0]); - _strupr(Param); - if (UIUIDigi[Slot]) - free(UIUIDigi[Slot]); - UIUIDigi[Slot] = _strdup(&Param[0]); - - GetParam(input, "File=", &Param[0]); - strcpy(FN[Slot], &Param[0]); - GetParam(input, "Text=", &Param[0]); - strcpy(Message[Slot], &Param[0]); - - MinCounter[Slot] = Interval[Slot]; - - SendFromFile[Slot] = 0; - - if (FN[Slot][0]) - SendFromFile[Slot] = 1; - - SetupUI(Slot); - -#ifdef LINBPQ - SaveUIConfig(); -#else - SaveUIConfig(); - - wsprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\UIUtil\\UIPort%d", Port); - - 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 *)&UIUIDEST[Port][0], strlen(&UIUIDEST[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, "Digis",0, REG_SZ, UIUIDigi[Port], strlen(UIUIDigi[Port])); - - RegCloseKey(hKey); - } -#endif - if (strstr(input, "Test=Test")) - SendUIBeacon(Slot); - - - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], Beacons, Port, - Interval[Slot], &UIUIDEST[Slot][0], &UIUIDigi[Slot][0], &FN[Slot][0], &Message[Slot][0], Port); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 1; - } - - if (_stricmp(NodeURL, "/Node/CfgSave") == 0) - { - // Save Config File - - SaveConfigFile(sock, MsgPtr, Key, LOCAL); - return 0; - } - - if (_stricmp(NodeURL, "/Node/LogAction") == 0) - { - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 1; - } - - - if (_stricmp(NodeURL, "/Node/ARDOPAbort") == 0) - { - int port = atoi(Context); - - if (port > 0 && port <= MaxBPQPortNo) - { - struct TNCINFO * TNC = TNCInfo[port]; - - if (TNC && TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - - - if (TNC && TNC->WebWindowProc) - ReplyLen = TNC->WebWindowProc(TNC, _REPLYBUFFER, LOCAL); - - - ReplyLen = sprintf(Reply, "", "Ok"); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - // goto SendResp; - - // HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + strlen(Tail)); - // send(sock, Header, HeaderLen, 0); - // send(sock, _REPLYBUFFER, ReplyLen, 0); - // send(sock, Tail, strlen(Tail), 0); - - return 1; - } - - } - - send(sock, _REPLYBUFFER, InputLen, 0); - return 0; - } - - if (_stricmp(NodeURL, "/") == 0 || _stricmp(NodeURL, "/Index.html") == 0) - { - // Send if present, else use default - - Bufferlen = SendMessageFile(sock, NodeURL, TRUE, allowDeflate); // return -1 if not found - - if (Bufferlen != -1) - return 0; // We've sent it - else - { - if (APRSApplConnected) - ReplyLen = sprintf(_REPLYBUFFER, Index, Mycall, Mycall); - else - ReplyLen = sprintf(_REPLYBUFFER, IndexNoAPRS, Mycall, Mycall); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 0; - } - } - - else if (_stricmp(NodeURL, "/NodeMenu.html") == 0 || _stricmp(NodeURL, "/Node/NodeMenu.html") == 0) - { - // Send if present, else use default - - char Menu[] = "/NodeMenu.html"; - - Bufferlen = SendMessageFile(sock, Menu, TRUE, allowDeflate); // return -1 if not found - - if (Bufferlen != -1) - return 0; // We've sent it - } - - else if (_memicmp(NodeURL, "/aisdata.txt", 12) == 0) - { - char * Compressed; - ReplyLen = GetAISPageInfo(_REPLYBUFFER, 1, 1); - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = _REPLYBUFFER; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: Text\r\n%s\r\n", ReplyLen, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - } - - else if (_memicmp(NodeURL, "/aprsdata.txt", 13) == 0) - { - char * Compressed; - char * ptr; - double N, S, W, E; - int aprs = 1, ais = 1, adsb = 1; - - ptr = &NodeURL[14]; - - N = atof(ptr); - ptr = strlop(ptr, '|'); - S = atof(ptr); - ptr = strlop(ptr, '|'); - W = atof(ptr); - ptr = strlop(ptr, '|'); - E = atof(ptr); - ptr = strlop(ptr, '|'); - if (ptr) - { - aprs = atoi(ptr); - ptr = strlop(ptr, '|'); - ais = atoi(ptr); - ptr = strlop(ptr, '|'); - adsb = atoi(ptr); - } - ReplyLen = GetAPRSPageInfo(_REPLYBUFFER, N, S, W, E, aprs, ais, adsb); - - if (ReplyLen < 240000) - ReplyLen += GetAISPageInfo(&_REPLYBUFFER[ReplyLen], ais, adsb); - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = _REPLYBUFFER; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: Text\r\n%s\r\n", ReplyLen, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - } - - else if (_memicmp(NodeURL, "/portstats.txt", 15) == 0) - { - char * Compressed; - char * ptr; - int port; - struct PORTCONTROL * PORT; - - ptr = &NodeURL[15]; - - port = atoi(ptr); - - PORT = GetPortTableEntryFromPortNum(port); - - ReplyLen = 0; - - if (PORT && PORT->TX) - { - // We send the last 24 hours worth of data. Buffer is cyclic so oldest byte is at StatsPointer - - int first = PORT->StatsPointer; - int firstlen = 1440 - first; - - memcpy(&_REPLYBUFFER[0], &PORT->TX[first], firstlen); - memcpy(&_REPLYBUFFER[firstlen], PORT->TX, first); - - memcpy(&_REPLYBUFFER[1440], &PORT->BUSY[first], firstlen); - memcpy(&_REPLYBUFFER[1440 + firstlen], PORT->BUSY, first); - - ReplyLen = 2880; - } - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = _REPLYBUFFER; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: Text\r\n%s\r\n", ReplyLen, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - } - - - else if (_memicmp(NodeURL, "/Icon", 5) == 0 && _memicmp(&NodeURL[10], ".png", 4) == 0) - { - // APRS internal Icon - - char * Compressed; - - ReplyLen = GetAPRSIcon(_REPLYBUFFER, NodeURL); - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = _REPLYBUFFER; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: Text\r\n%s\r\n", ReplyLen, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - - } - - else if (_memicmp(NodeURL, "/NODE/", 6)) - { - // Not Node, See if a local file - - Bufferlen = SendMessageFile(sock, NodeURL, FALSE, allowDeflate); // Send error if not found - return 0; - } - - // Node URL - - { - - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - - if (_stricmp(NodeURL, "/Node/webproc.css") == 0) - { - char WebprocCSS[] = - ".dropbtn {position: relative; border: 1px solid black;padding:1px;}\r\n" - ".dropdown {position: relative; display: inline-block;}\r\n" - ".dropdown-content {display: none; position: absolute;background-color: #ccc; " - "min-width: 160px; box-shadow: 0px 8px 16px 0px rgba(0,0,00.2); z-index: 1;}\r\n" - ".dropdown-content a {color: black; padding: 1px 1px;text-decoration:none;display:block;}" - ".dropdown-content a:hover {background-color: #dddfff;}\r\n" - ".dropdown:hover .dropdown-content {display: block;}\r\n" - ".dropdown:hover .dropbtn {background-color: #ddd;}\r\n" - "input.btn:active {background:black;color:white;}\r\n" - "submit.btn:active {background:black;color:white;}\r\n"; - ReplyLen = sprintf(_REPLYBUFFER, "%s", WebprocCSS); - } - - else if (_stricmp(NodeURL, "/Node/Killandrestart") == 0) - { - int port = atoi(Context); - - if (port > 0 && port <= MaxBPQPortNo) - { - struct TNCINFO * TNC = TNCInfo[port]; - - KillTNC(TNC); - TNC->DontRestart = FALSE; - RestartTNC(TNC); - - if (TNC && TNC->WebWindowProc) - ReplyLen = TNC->WebWindowProc(TNC, _REPLYBUFFER, LOCAL); - - } - } - - else if (_stricmp(NodeURL, "/Node/Port") == 0 || _stricmp(NodeURL, "/Node/ARDOPAbort") == 0) - { - int port = atoi(Context); - - if (port > 0 && port <= MaxBPQPortNo) - { - struct TNCINFO * TNC = TNCInfo[port]; - - if (TNC && TNC->WebWindowProc) - ReplyLen = TNC->WebWindowProc(TNC, _REPLYBUFFER, LOCAL); - } - - } - - else if (_stricmp(NodeURL, "/Node/Streams") == 0) - { - ReplyLen = StatusProc(_REPLYBUFFER); - } - - else if (_stricmp(NodeURL, "/Node/Stats.html") == 0) - { - struct tm * TM; - char UPTime[50]; - time_t szClock = STATSTIME * 60; - - TM = gmtime(&szClock); - - sprintf(UPTime, "%.2d:%.2d:%.2d", TM->tm_yday, TM->tm_hour, TM->tm_min); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", StatsHddr); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "Version", VersionString); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "Uptime (Days Hours Mins)", UPTime); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "Semaphore: Get-Rel/Clashes", Semaphore.Gets - Semaphore.Rels, Semaphore.Clashes); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "Buffers: Max/Cur/Min/Out/Wait", MAXBUFFS, QCOUNT, MINBUFFCOUNT, NOBUFFCOUNT, BUFFERWAITS); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "Known Nodes/Max Nodes", NUMBEROFNODES, MAXDESTS); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "L4 Connects Sent/Rxed ", L4CONNECTSOUT, L4CONNECTSIN); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "L4 Frames TX/RX/Resent/Reseq", L4FRAMESTX, L4FRAMESRX, L4FRAMESRETRIED, OLDFRAMES); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "L3 Frames Relayed", L3FRAMES); - - } - - else if (_stricmp(NodeURL, "/Node/RigControl.html") == 0) - { - char Test[] = - "\r\n" - "Rigcontrol\r\n" - "\r\n" - "\r\n" - "\r\n" - "
Waiting for data...
\r\n" - "\r\n"; - - - char NoRigCtl[] = - "\r\n" - "Rigcontrol\r\n" - "\r\n" - "\r\n" - "
RigControl Not Configured...
\r\n" - "\r\n"; - - if (RigWebPage) - ReplyLen = sprintf(_REPLYBUFFER, "%s", Test); - else - ReplyLen = sprintf(_REPLYBUFFER, "%s", NoRigCtl); - } - - else if (_stricmp(NodeURL, "/Node/ShowLog.html") == 0) - { - char ShowLogPage[] = - "" - "" - "Log Display" - "" - "
" - "
" -// "" - "" - "" - "
"; - - char * _REPLYBUFFER; - int ReplyLen; - char Header[256]; - int HeaderLen; - char * CfgBytes; - int CfgLen; - char inputname[250]; - FILE *fp1; - struct stat STAT; - char DummyKey[] = "DummyKey"; - time_t T; - struct tm * tm; - char Name[64] = ""; - - T = time(NULL); - tm = gmtime(&T); - - if (LOCAL == FALSE && COOKIE == FALSE) - { - // Send Not Authorized - - char _REPLYBUFFER[4096]; - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
Not authorized - please sign in"); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - return 1; - } - - if (COOKIE == FALSE) - Key = DummyKey; - - if (memcmp(Context, "date=", 5) == 0) - { - memset(tm, 0, sizeof(struct tm)); - tm->tm_year = atoi(&Context[5]) - 1900; - tm->tm_mon = atoi(&Context[10]) - 1; - tm->tm_mday = atoi(&Context[13]); - } - - - - if (strcmp(Context, "input=Back") == 0) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - return 1; - } - - if (LogDirectory[0] == 0) - { - strcpy(inputname, "logs/"); - } - else - { - strcpy(inputname,LogDirectory); - strcat(inputname,"/"); - strcat(inputname, "/logs/"); - } - - if (strstr(Context, "CMS")) - { - sprintf(Name, "CMSAccess_%04d%02d%02d.log", - tm->tm_year +1900, tm->tm_mon+1, tm->tm_mday); - } - else if (strstr(Context, "Debug")) - { - sprintf(Name, "log_%02d%02d%02d_DEBUG.txt", - tm->tm_year - 100, tm->tm_mon+1, tm->tm_mday); - } - else if (strstr(Context, "BBS")) - { - sprintf(Name, "log_%02d%02d%02d_BBS.txt", - tm->tm_year - 100, tm->tm_mon+1, tm->tm_mday); - } - else if (strstr(Context, "Chat")) - { - sprintf(Name, "log_%02d%02d%02d_CHAT.txt", - tm->tm_year - 100, tm->tm_mon+1, tm->tm_mday); - } - else if (strstr(Context, "Telnet")) - { - sprintf(Name, "Telnet_%02d%02d%02d.log", - tm->tm_year - 100, tm->tm_mon+1, tm->tm_mday); - } - - strcat(inputname, Name); - - if (stat(inputname, &STAT) == -1) - { - CfgBytes = malloc(256); - sprintf(CfgBytes, "Log %s not found", inputname); - CfgLen = strlen(CfgBytes); - } - else - { - fp1 = fopen(inputname, "rb"); - - if (fp1 == 0) - { - CfgBytes = malloc(256); - sprintf(CfgBytes, "Log %s not found", inputname); - CfgLen = strlen(CfgBytes); - } - else - { - CfgLen = STAT.st_size; - - CfgBytes = malloc(CfgLen + 1); - - CfgLen = (int)fread(CfgBytes, 1, CfgLen, fp1); - CfgBytes[CfgLen] = 0; - } - } - - _REPLYBUFFER = malloc(CfgLen + 1000); - - ReplyLen = sprintf(_REPLYBUFFER, ShowLogPage, CfgBytes); - free (CfgBytes); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, _REPLYBUFFER, ReplyLen); - sendandcheck(sock, Tail, (int)strlen(Tail)); - free (_REPLYBUFFER); - - return 1; - } - - else if (_stricmp(NodeURL, "/Node/EditCfg.html") == 0) - { - char * _REPLYBUFFER; - int ReplyLen; - char Header[256]; - int HeaderLen; - char * CfgBytes; - int CfgLen; - char inputname[250]="bpq32.cfg"; - FILE *fp1; - struct stat STAT; - char DummyKey[] = "DummyKey"; - - if (LOCAL == FALSE && COOKIE == FALSE) - { - // Send Not Authorized - - char _REPLYBUFFER[4096]; - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
Not authorized - please sign in"); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - return 1; - } - - if (COOKIE ==FALSE) - Key = DummyKey; - - if (ConfigDirectory[0] == 0) - { - strcpy(inputname, "bpq32.cfg"); - } - else - { - strcpy(inputname,ConfigDirectory); - strcat(inputname,"/"); - strcat(inputname, "bpq32.cfg"); - } - - - if (stat(inputname, &STAT) == -1) - { - CfgBytes = _strdup("Config File not found"); - } - else - { - fp1 = fopen(inputname, "rb"); - - if (fp1 == 0) - { - CfgBytes = _strdup("Config File not found"); - } - else - { - CfgLen = STAT.st_size; - - CfgBytes = malloc(CfgLen + 1); - - CfgLen = (int)fread(CfgBytes, 1, CfgLen, fp1); - CfgBytes[CfgLen] = 0; - } - } - - _REPLYBUFFER = malloc(CfgLen + 1000); - - ReplyLen = sprintf(_REPLYBUFFER, ConfigEditPage, Key, CfgBytes); - free (CfgBytes); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, _REPLYBUFFER, ReplyLen); - sendandcheck(sock, Tail, (int)strlen(Tail)); - free (_REPLYBUFFER); - - return 1; - } - - - - if (_stricmp(NodeURL, "/Node/PortBeacons") == 0) - { - char * PortChar = strtok_s(NULL, "&", &Context); - int PortNo = atoi(PortChar); - struct PORTCONTROL * PORT; - int PortSlot = 0; - - PORT = GetPortTableEntryFromPortNum(PortNo); // Need slot not number - if (PORT) - PortSlot = PORT->PortSlot; - - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], Beacons, PortNo, - Interval[PortSlot], &UIUIDEST[PortSlot][0], &UIUIDigi[PortSlot][0], &FN[PortSlot][0], &Message[PortSlot][0], PortNo); - } - - - - if (_stricmp(NodeURL, "/Node/PortStats") == 0) - { - struct _EXTPORTDATA * Port; - - char * PortChar = strtok_s(NULL, "&", &Context); - int PortNo = atoi(PortChar); - int Protocol; - int PortType; - - // char PORTTYPE; // H/W TYPE - // 0 = ASYNC, 2 = PC120, 4 = DRSI - // 6 = TOSH, 8 = QUAD, 10 = RLC100 - // 12 = RLC400 14 = INTERNAL 16 = EXTERNAL - -#define KISS 0 -#define NETROM 2 -#define HDLC 6 -#define L2 8 -#define WINMOR 10 - - - // char PROTOCOL; // PORT PROTOCOL - // 0 = KISS, 2 = NETROM, 4 = BPQKISS - //; 6 = HDLC, 8 = L2 - - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsHddr, PortNo); - - Port = (struct _EXTPORTDATA *)GetPortTableEntryFromPortNum(PortNo); - - if (Port == NULL) - { - ReplyLen = sprintf(_REPLYBUFFER, "Invalid Port"); - goto SendResp; - } - - Protocol = Port->PORTCONTROL.PROTOCOL; - PortType = Port->PORTCONTROL.PROTOCOL; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Frames Digied", Port->PORTCONTROL.L2DIGIED); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Frames Heard", Port->PORTCONTROL.L2FRAMES); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Frames Received", Port->PORTCONTROL.L2FRAMESFORUS); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Frames Sent", Port->PORTCONTROL.L2FRAMESSENT); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Timeouts", Port->PORTCONTROL.L2TIMEOUTS); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "REJ Frames Received", Port->PORTCONTROL.L2REJCOUNT); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "RX out of Seq", Port->PORTCONTROL.L2OUTOFSEQ); - // ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Resequenced", Port->PORTCONTROL.L2RESEQ); - if (Protocol == HDLC) - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "Underrun", Port->PORTCONTROL.L2URUNC); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "RX Overruns", Port->PORTCONTROL.L2ORUNC); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "RX CRC Errors", Port->PORTCONTROL.RXERRORS); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "Frames abandoned", Port->PORTCONTROL.L1DISCARD); - } - else if ((Protocol == KISS && Port->PORTCONTROL.KISSFLAGS) || Protocol == NETROM) - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "Poll Timeout", Port->PORTCONTROL.L2URUNC); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "RX CRC Errors", Port->PORTCONTROL.RXERRORS); - } - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "FRMRs Sent", Port->PORTCONTROL.L2FRMRTX); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "FRMRs Received", Port->PORTCONTROL.L2FRMRRX); - - // DB 'Link Active % ' - // DD AVSENDING - - } - - if (_stricmp(NodeURL, "/Node/Ports.html") == 0) - { - struct _EXTPORTDATA * ExtPort; - struct PORTCONTROL * Port; - - int count; - char DLL[20]; - char StatsURL[64]; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", PortsHddr); - - for (count = 1; count <= NUMBEROFPORTS; count++) - { - Port = GetPortTableEntryFromSlot(count); - ExtPort = (struct _EXTPORTDATA *)Port; - - // see if has a stats page - - if (Port->AVACTIVE) - sprintf(StatsURL, " Stats Graph", Port->PORTNUMBER); - else - StatsURL[0] = 0; - - if (Port->PORTTYPE == 0x10) - { - strcpy(DLL, ExtPort->PORT_DLL_NAME); - strlop(DLL, '.'); - } - else if (Port->PORTTYPE == 0) - strcpy(DLL, "ASYNC"); - - else if (Port->PORTTYPE == 22) - strcpy(DLL, "I2C"); - - else if (Port->PORTTYPE == 14) - strcpy(DLL, "INTERNAL"); - - else if (Port->PORTTYPE > 0 && Port->PORTTYPE < 14) - strcpy(DLL, "HDLC"); - - - if (Port->TNC && Port->TNC->WebWindowProc) // Has a Window - { - if (Port->UICAPABLE) - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithBeaconAndDriver, Port->PORTNUMBER, DLL, - Port->PORTDESCRIPTION, Port->PORTNUMBER, Port->PORTNUMBER, Port->TNC->WebWinX, Port->TNC->WebWinY, 200, 200, StatsURL); - else - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithDriver, Port->PORTNUMBER, DLL, - Port->PORTDESCRIPTION, Port->PORTNUMBER, Port->TNC->WebWinX, Port->TNC->WebWinY, 200, 200, StatsURL); - - continue; - } - - if (Port->PORTTYPE == 16 && Port->PROTOCOL == 10 && Port->UICAPABLE == 0) // EXTERNAL, Pactor/WINMO - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], SessionPortLine, Port->PORTNUMBER, DLL, - Port->PORTDESCRIPTION, Port->PORTNUMBER, StatsURL); - else - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithBeacon, Port->PORTNUMBER, Port->PORTNUMBER, - DLL, DLL, Port->PORTDESCRIPTION, Port->PORTNUMBER, StatsURL); - } - - if (RigActive) - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], RigControlLine, 64, "Rig Control", "Rig Control", 600, 350, 200, 200); - - } - - if (_stricmp(NodeURL, "/Node/Nodes.html") == 0) - { - struct DEST_LIST * Dests = DESTS; - int count, i; - char Normcall[10]; - char Alias[10]; - int Width = 5; - int x = 0, n = 0; - struct DEST_LIST * List[1000]; - char Param = 0; - - if (Context) - { - _strupr(Context); - Param = Context[0]; - } - - for (count = 0; count < MAXDESTS; count++) - { - if (Dests->DEST_CALL[0] != 0) - { - if (Param != 'T' || Dests->DEST_COUNT) - List[n++] = Dests; - - if (n > 999) - break; - } - - Dests++; - } - - if (n > 1) - { - if (Param == 'C') - qsort(List, n, sizeof(void *), CompareNode); - else - qsort(List, n, sizeof(void *), CompareAlias); - } - - Alias[6] = 0; - - if (Param == 'T') - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], NodeHddr, "with traffic"); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], ""); - } - else if (Param == 'C') - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], NodeHddr, "sorted by Call"); - else - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], NodeHddr, "sorted by Alias"); - - for (i = 0; i < n; i++) - { - int len = ConvFromAX25(List[i]->DEST_CALL, Normcall); - Normcall[len]=0; - - memcpy(Alias, List[i]->DEST_ALIAS, 6); - strlop(Alias, ' '); - - if (Param == 'T') - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - Normcall, Alias, List[i]->DEST_COUNT, List[i]->DEST_RTT /16, - (List[i]->DEST_STATE & 0x40)? 'B':' ', (List[i]->DEST_STATE & 63)); - - } - else - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], NodeLine, Normcall, Alias, Normcall); - - if (++x == Width) - { - x = 0; - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], ""); - } - } - } - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], ""); - } - - if (_stricmp(NodeURL, "/Node/NodeDetail") == 0) - { - UCHAR AXCall[8]; - struct DEST_LIST * Dest = DESTS; - struct NR_DEST_ROUTE_ENTRY * NRRoute; - struct ROUTE * Neighbour; - char Normcall[10]; - int i, len, count, Active; - char Alias[7]; - - Alias[6] = 0; - - _strupr(Context); - - ConvToAX25(Context, AXCall); - - for (count = 0; count < MAXDESTS; count++) - { - if (CompareCalls(Dest->DEST_CALL, AXCall)) - { - break; - } - Dest++; - } - - if (count == MAXDESTS) - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "

Call %s not found

", Context); - goto SendResp; - } - - memcpy(Alias, Dest->DEST_ALIAS, 6); - strlop(Alias, ' '); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], - "

Info for Node %s:%s

", Alias, Context); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "

PortDriverIDBeaconsDriver WindowStats Graph
%d %s%s
%d %s%s Beacons %s
%d%s%s %s
%d%s%s Driver Window%s
%d%s%s BeaconsDriver Window%s
%d%s%s Rig Control
%s%s
%s%s
%s%d%d
%s%d%d%d%d%d
%s%d%d
%s%d%d
%s%d%d%d%d
%s%d
CallFramesRTTBPQ?Hops
%s:%s%d%d%c%.0d
"); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
FramesRTTBPQ?Hops
%d%d%c%.0d
", - Dest->DEST_COUNT, Dest->DEST_RTT /16, - (Dest->DEST_STATE & 0x40)? 'B':' ', (Dest->DEST_STATE & 63)); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "

Neighbours

"); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], - "" - ""); - - NRRoute = &Dest->NRROUTE[0]; - - Active = Dest->DEST_ROUTE; - - for (i = 1; i < 4; i++) - { - Neighbour = NRRoute->ROUT_NEIGHBOUR; - - if (Neighbour) - { - len = ConvFromAX25(Neighbour->NEIGHBOUR_CALL, Normcall); - Normcall[len] = 0; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - (Active == i)?'>':' ',NRRoute->ROUT_QUALITY, NRRoute->ROUT_OBSCOUNT, Neighbour->NEIGHBOUR_PORT, Normcall); - } - NRRoute++; - } - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
Qual Obs Port Call
%c %d%d%d%s
"); - - goto SendResp; - - } - /* - - MOV ESI,OFFSET32 NODEROUTEHDDR - MOV ECX,11 - REP MOVSB - - LEA ESI,DEST_CALL[EBX] - CALL DECODENODENAME ; CONVERT TO ALIAS:CALL - REP MOVSB - - CMP DEST_RTT[EBX],0 - JE SHORT @f ; TIMER NOT SET - DEST PROBABLY NOT USED - - MOVSB ; ADD SPACE - CALL DORTT - - @@: - MOV AL,CR - STOSB - - MOV ECX,3 - MOV DH,DEST_ROUTE[EBX] ; CURRENT ACTIVE ROUTE - MOV DL,1 - - push ebx - - PUBLIC CMDN110 - CMDN110: - - MOV ESI,ROUT1_NEIGHBOUR[EBX] - CMP ESI,0 - JE CMDN199 - - - MOV AX,' ' - CMP DH,DL - JNE SHORT CMDN112 ; NOT CURRENT DEST - MOV AX,' >' - - CMDN112: - - STOSW - - PUSH ECX - - MOV AL,ROUT1_QUALITY[EBX] - CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS - - mov AL,' ' - stosb - - MOV AL,ROUT1_OBSCOUNT[EBX] - CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS - - mov AL,' ' - stosb - - MOV AL,NEIGHBOUR_PORT[ESI] ; GET PORT - CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS - - mov AL,' ' - stosb - - - PUSH EDI - CALL CONVFROMAX25 ; CONVERT TO CALL - POP EDI - - MOV ESI,OFFSET32 NORMCALL - REP MOVSB - - MOV AL,CR - STOSB - - ADD EBX,ROUTEVECLEN - INC DL ; ROUTE NUMBER - - POP ECX - DEC ECX - JNZ CMDN110 - - PUBLIC CMDN199 - CMDN199: - - POP EBX - - ; DISPLAY INP3 ROUTES - - MOV ECX,3 - MOV DL,4 - - PUBLIC CMDNINP3 - CMDNINP3: - - MOV ESI,INPROUT1_NEIGHBOUR[EBX] - CMP ESI,0 - JE CMDNINPEND - - MOV AX,' ' - CMP DH,DL - JNE SHORT @F ; NOT CURRENT DEST - MOV AX,' >' - - @@: - - STOSW - - PUSH ECX - - MOV AL, Hops1[EBX] - CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS - - mov AL,' ' - stosb - - MOVZX EAX, SRTT1[EBX] - - MOV EDX,0 - MOV ECX, 100 - DIV ECX - CALL CONV_5DIGITS - MOV AL,'.' - STOSB - MOV EAX, EDX - CALL PRINTNUM - MOV AL,'s' - STOSB - MOV AL,' ' - STOSB - - MOV AL,NEIGHBOUR_PORT[ESI] ; GET PORT - CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS - - mov AL,' ' - stosb - - PUSH EDI - CALL CONVFROMAX25 ; CONVERT TO CALL - POP EDI - - MOV ESI,OFFSET32 NORMCALL - REP MOVSB - - - MOV AL,CR - STOSB - - ADD EBX,INPROUTEVECLEN - INC DL ; ROUTE NUMBER - - POP ECX - LOOP CMDNINP3 - - CMDNINPEND: - - ret - - */ - - - if (_stricmp(NodeURL, "/Node/Routes.html") == 0) - { - struct ROUTE * Routes = NEIGHBOURS; - int MaxRoutes = MAXNEIGHBOURS; - int count; - char Normcall[10]; - char locked; - int NodeCount; - int Percent = 0; - int Iframes, Retries; - char Active[10]; - int Queued; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", RouteHddr); - - for (count=0; countNEIGHBOUR_CALL[0] != 0) - { - int len = ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall); - Normcall[len]=0; - - if ((Routes->NEIGHBOUR_FLAG & 1) == 1) - locked = '!'; - else - locked = ' '; - - NodeCount = COUNTNODES(Routes); - - if (Routes->NEIGHBOUR_LINK) - Queued = COUNT_AT_L2(Routes->NEIGHBOUR_LINK); - else - Queued = 0; - - Iframes = Routes->NBOUR_IFRAMES; - Retries = Routes->NBOUR_RETRIES; - - if (Routes->NEIGHBOUR_LINK && Routes->NEIGHBOUR_LINK->L2STATE >= 5) - strcpy(Active, ">"); - else - strcpy(Active, " "); - - if (Iframes) - Percent = (Retries * 100) / Iframes; - else - Percent = 0; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], RouteLine, Active, Routes->NEIGHBOUR_PORT, Normcall, locked, - Routes->NEIGHBOUR_QUAL, NodeCount, Iframes, Retries, Percent, Routes->NBOUR_MAXFRAME, Routes->NBOUR_FRACK, - Routes->NEIGHBOUR_TIME >> 8, Routes->NEIGHBOUR_TIME & 0xff, Queued, Routes->OtherendsRouteQual); - } - Routes+=1; - } - } - - if (_stricmp(NodeURL, "/Node/Links.html") == 0) - { - struct _LINKTABLE * Links = LINKS; - int MaxLinks = MAXLINKS; - int count; - char Normcall1[10]; - char Normcall2[10]; - char State[12] = "", Type[12] = "Uplink"; - int axState; - int cctType; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", LinkHddr); - - for (count=0; countLINKCALL[0] != 0) - { - int len = ConvFromAX25(Links->LINKCALL, Normcall1); - Normcall1[len] = 0; - - len = ConvFromAX25(Links->OURCALL, Normcall2); - Normcall2[len] = 0; - - axState = Links->L2STATE; - - if (axState == 2) - strcpy(State, "Connecting"); - else if (axState == 3) - strcpy(State, "FRMR"); - else if (axState == 4) - strcpy(State, "Closing"); - else if (axState == 5) - strcpy(State, "Active"); - else if (axState == 6) - strcpy(State, "REJ Sent"); - - cctType = Links->LINKTYPE; - - if (cctType == 1) - strcpy(Type, "Uplink"); - else if (cctType == 2) - strcpy(Type, "Downlink"); - else if (cctType == 3) - strcpy(Type, "Node-Node"); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], LinkLine, Normcall1, Normcall2, Links->LINKPORT->PORTNUMBER, - State, Type, 2 - Links->VER1FLAG ); - - Links+=1; - } - } - } - - if (_stricmp(NodeURL, "/Node/Users.html") == 0) - { - TRANSPORTENTRY * L4 = L4TABLE; - TRANSPORTENTRY * Partner; - int MaxLinks = MAXLINKS; - int count; - char State[12] = "", Type[12] = "Uplink"; - char LHS[50] = "", MID[10] = "", RHS[50] = ""; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", UserHddr); - - for (count=0; count < MAXCIRCUITS; count++) - { - if (L4->L4USER[0]) - { - RHS[0] = MID[0] = 0; - - if ((L4->L4CIRCUITTYPE & UPLINK) == 0) //SHORT CMDS10A ; YES - { - // IF DOWNLINK, ONLY DISPLAY IF NO CROSSLINK - - if (L4->L4CROSSLINK == 0) //jne CMDS60 ; WILL PROCESS FROM OTHER END - { - // ITS A DOWNLINK WITH NO PARTNER - MUST BE A CLOSING SESSION - // DISPLAY TO THE RIGHT FOR NOW - - strcpy(LHS, "(Closing) "); - DISPLAYCIRCUIT(L4, RHS); - goto CMDS50; - } - else - goto CMDS60; // WILL PROCESS FROM OTHER END - } - - if (L4->L4CROSSLINK == 0) - { - // Single Entry - - DISPLAYCIRCUIT(L4, LHS); - } - else - { - DISPLAYCIRCUIT(L4, LHS); - - Partner = L4->L4CROSSLINK; - - if (Partner->L4STATE == 5) - strcpy(MID, "<-->"); - else - strcpy(MID, "<~~>"); - - DISPLAYCIRCUIT(Partner, RHS); - } -CMDS50: - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], UserLine, LHS, MID, RHS); - } -CMDS60: - L4++; - } - } - /* - PUBLIC CMDUXX_1 - CMDUXX_1: - push EBX - push ESI - PUSH ECX - push EDI - - call _FINDDESTINATION - pop EDI - - jz SHORT NODE_FOUND - - push EDI ; NET/ROM not found - call CONVFROMAX25 ; CONVERT TO CALL - pop EDI - mov ESI,OFFSET32 NORMCALL - rep movsb - - jmp SHORT END_CMDUXX - - PUBLIC NODE_FOUND - NODE_FOUND: - - lea ESI,DEST_CALL[EBX] - call DECODENODENAME - - REP MOVSB - - PUBLIC END_CMDUXX - END_CMDUXX: - - POP ECX - pop ESI - pop EBX - ret - - }}} - */ - - else if (_stricmp(NodeURL, "/Node/Terminal.html") == 0) - { - if (COOKIE && Session) - { - // Already signed in as sysop - - struct UserRec * USER = Session->USER; - - struct HTTPConnectionInfo * NewSession = AllocateSession(sock, 'T'); - - if (NewSession) - { - char AXCall[10]; - ReplyLen = sprintf(_REPLYBUFFER, TermPage, Mycall, Mycall, NewSession->Key, NewSession->Key, NewSession->Key); - strcpy(NewSession->HTTPCall, USER->Callsign); - ConvToAX25(NewSession->HTTPCall, AXCall); - ChangeSessionCallsign(NewSession->Stream, AXCall); - BPQHOSTVECTOR[NewSession->Stream -1].HOSTSESSION->Secure_Session = USER->Secure; - Session->USER = USER; - NewSession->TNC = conn->TNC; - - - // if (Appl[0]) - // { - // strcat(Appl, "\r"); - // SendMsg(Session->Stream, Appl, strlen(Appl)); - // } - - } - else - { - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", BusyError); - } - } - else if (LOCAL) - { - // connected to 127.0.0.1 so sign in using node call - - struct HTTPConnectionInfo * NewSession = AllocateSession(sock, 'T'); - - if (NewSession) - { - ReplyLen = sprintf(_REPLYBUFFER, TermPage, Mycall, Mycall, NewSession->Key, NewSession->Key, NewSession->Key); - strcpy(NewSession->HTTPCall, MYNODECALL); - ChangeSessionCallsign(NewSession->Stream, MYCALL); - BPQHOSTVECTOR[NewSession->Stream -1].HOSTSESSION->Secure_Session = TRUE; - NewSession->TNC = conn->TNC; - } - } - else - ReplyLen = sprintf(_REPLYBUFFER, TermSignon, Mycall, Mycall, Context); - } - - else if (_stricmp(NodeURL, "/Node/Signon.html") == 0) - { - ReplyLen = sprintf(_REPLYBUFFER, NodeSignon, Mycall, Mycall, Context); - } - - else if (_stricmp(NodeURL, "/Node/Drivers") == 0) - { - int Bufferlen = SendMessageFile(sock, "/Drivers.htm", TRUE, allowDeflate); // return -1 if not found - - if (Bufferlen != -1) - return 0; // We've sent it - } - - else if (_stricmp(NodeURL, "/Node/OutputScreen.html") == 0) - { - struct HTTPConnectionInfo * Session = FindSession(Context); - - if (Session == NULL) - { - ReplyLen = sprintf(_REPLYBUFFER, "%s", LostSession); - } - else - { - Session->sock = sock; // socket to reply on - ReplyLen = RefreshTermWindow(TCP, Session, _REPLYBUFFER); - - if (ReplyLen == 0) // Nothing new - { - // Debugprintf("GET with no data avail - response held"); - Session->ResponseTimer = 1200; // Delay response for up to a minute - } - else - { - // Debugprintf("GET - outpur sent, timer was %d, set to zero", Session->ResponseTimer); - Session->ResponseTimer = 0; - } - - Session->KillTimer = 0; - return 0; // Refresh has sent any available output - } - } - - else if (_stricmp(NodeURL, "/Node/InputLine.html") == 0) - { - struct TNCINFO * TNC = conn->TNC; - struct TCPINFO * TCP = 0; - - if (TNC) - TCP = TNC->TCPInfo; - - if (TCP && TCP->WebTermCSS) - ReplyLen = sprintf(_REPLYBUFFER, InputLine, Context, TCP->WebTermCSS); - else - ReplyLen = sprintf(_REPLYBUFFER, InputLine, Context, ""); - - } - - else if (_stricmp(NodeURL, "/Node/PTT") == 0) - { - struct TNCINFO * TNC = conn->TNC; - int x = atoi(Context); - } - - -SendResp: - - FormatTime3(TimeString, time(NULL)); - - strcpy(&_REPLYBUFFER[ReplyLen], Tail); - ReplyLen += (int)strlen(Tail); - - - if (allowDeflate) - { - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - } - else - { - Encoding[0] = 0; - Compressed = _REPLYBUFFER; - } - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n" - "Date: %s\r\n%s\r\n", ReplyLen, TimeString, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - } - return 0; - -#ifdef WIN32xx - } -#include "StdExcept.c" -} -return 0; -#endif -} - -void ProcessHTTPMessage(void * conn) -{ - // conn is a malloc'ed copy to handle reused connections, so need to free it - - InnerProcessHTTPMessage((struct ConnectionInfo *)conn); - free(conn); - return; -} - -static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; -static char *dat[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - - -VOID FormatTime3(char * Time, time_t cTime) -{ - struct tm * TM; - TM = gmtime(&cTime); - - sprintf(Time, "%s, %02d %s %3d %02d:%02d:%02d GMT", dat[TM->tm_wday], TM->tm_mday, month[TM->tm_mon], - TM->tm_year + 1900, TM->tm_hour, TM->tm_min, TM->tm_sec); - -} - -// Sun, 06 Nov 1994 08:49:37 GMT - -int StatusProc(char * Buff) -{ - int i; - char callsign[12] = ""; - char flag[3]; - UINT Mask, MaskCopy; - int Flags; - int AppNumber; - int OneBits; - int Len = sprintf(Buff, "" - "Stream Status"); - - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - - for (i=1;i<65; i++) - { - callsign[0]=0; - - if (GetAllocationState(i)) - - strcpy(flag,"*"); - else - strcpy(flag," "); - - GetCallsign(i,callsign); - - Mask = MaskCopy = Get_APPLMASK(i); - - // if only one bit set, convert to number - - AppNumber = 0; - OneBits = 0; - - while (MaskCopy) - { - if (MaskCopy & 1) - OneBits++; - - AppNumber++; - MaskCopy = MaskCopy >> 1; - } - - Flags=GetApplFlags(i); - - if (OneBits > 1) - Len += sprintf(&Buff[Len], "" - "", - i, flag, RXCount(i), TXCount(i), MONCount(i), Mask, Flags, callsign, BPQHOSTVECTOR[i-1].PgmName); - - else - Len += sprintf(&Buff[Len], "" - "", - i, flag, RXCount(i), TXCount(i), MONCount(i), AppNumber, Flags, callsign, BPQHOSTVECTOR[i-1].PgmName); - - if ((i & 1) == 0) - Len += sprintf(&Buff[Len], ""); - - } - - Len += sprintf(&Buff[Len], "
    RX   TX   MON  App  Flg Callsign  Program    RX   TX   MON  App  Flg Callsign  Program
%d%s%d%d%d%x%x%s%s%d%s%d%d%d%d%x%s%s
"); - return Len; -} - -int ProcessNodeSignon(SOCKET sock, struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, int LOCAL) -{ - int ReplyLen = 0; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * user, * password, * Key; - char Header[256]; - int HeaderLen; - struct HTTPConnectionInfo *Sess; - - - if (input) - { - int i; - struct UserRec * USER; - - UndoTransparency(input); - - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n" - "\r\n", (int)(ReplyLen + strlen(Tail))); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - } - user = strtok_s(&input[9], "&", &Key); - password = strtok_s(NULL, "=", &Key); - password = Key; - - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if (user && _stricmp(user, USER->UserName) == 0) - { - if (strcmp(password, USER->Password) == 0 && USER->Secure) - { - // ok - - Sess = *Session = AllocateSession(sock, 'N'); - Sess->USER = USER; - - ReplyLen = SetupNodeMenu(Reply, LOCAL); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n" - "Set-Cookie: BPQSessionCookie=%s; Path = /\r\n\r\n", (int)(ReplyLen + strlen(Tail)), Sess->Key); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return ReplyLen; - } - } - } - } - - ReplyLen = sprintf(Reply, NodeSignon, Mycall, Mycall); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", PassError); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", (int)(ReplyLen + strlen(Tail))); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 0; - - - return ReplyLen; -} - -int ProcessMailAPISignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, BOOL WebMail, int LOCAL) -{ - int ReplyLen = 0; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * user, * password, * Key; - struct HTTPConnectionInfo * NewSession; - int i; - struct UserRec * USER; - - if (strchr(MsgPtr, '?')) - { - // Check Password - - user = strlop(MsgPtr, '?'); - password = strlop(user, '&'); - strlop(password, ' '); - - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if (user && _stricmp(user, USER->UserName) == 0) - { - if ((strcmp(password, USER->Password) == 0) && (USER->Secure || WebMail)) - { - // ok - - NewSession = AllocateSession(Appl[0], 'M'); - - *Session = NewSession; - - if (NewSession) - { - ReplyLen = 0; - strcpy(NewSession->Callsign, USER->Callsign); - } - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); - } - return ReplyLen; - - } - } - } - - // Pass failed attempt to BBS code so it can try a bbs user login - - // Need to put url back together - - if (user && user[0] && password && password[0]) - { - sprintf(MsgPtr, "%s?%s&%s", MsgPtr, user, password); - } - } - - NewSession = AllocateSession(Appl[0], 'M'); - - *Session = NewSession; - - if (NewSession) - ReplyLen = 0; - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); - } - - return ReplyLen; -} - - - - -int ProcessMailSignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, BOOL WebMail, int LOCAL) -{ - int ReplyLen = 0; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * user, * password, * Key; - struct HTTPConnectionInfo * NewSession; - - if (input) - { - int i; - struct UserRec * USER; - - UndoTransparency(input); - - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - return ReplyLen; - } - user = strtok_s(&input[9], "&", &Key); - password = strtok_s(NULL, "=", &Key); - password = Key; - - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if (user && _stricmp(user, USER->UserName) == 0) - { - if (strcmp(password, USER->Password) == 0 && (USER->Secure || WebMail)) - { - // ok - - NewSession = AllocateSession(Appl[0], 'M'); - - *Session = NewSession; - - if (NewSession) - { - - ReplyLen = 0; - strcpy(NewSession->Callsign, USER->Callsign); - } - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); - } - return ReplyLen; - } - } - } - } - - ReplyLen = sprintf(Reply, MailSignon, Mycall, Mycall); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", PassError); - - return ReplyLen; -} - - -int ProcessChatSignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, int LOCAL) -{ - int ReplyLen = 0; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * user, * password, * Key; - - if (input) - { - int i; - struct UserRec * USER; - - UndoTransparency(input); - - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - return ReplyLen; - } - - user = strtok_s(&input[9], "&", &Key); - password = strtok_s(NULL, "=", &Key); - password = Key; - - - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if (user && _stricmp(user, USER->UserName) == 0) - { - if (strcmp(password, USER->Password) == 0 && USER->Secure) - { - // ok - - *Session = AllocateSession(Appl[0], 'C'); - - if (Session) - { - ReplyLen = 0; - } - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); - } - return ReplyLen; - } - } - } - } - - ReplyLen = sprintf(Reply, ChatSignon, Mycall, Mycall); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", PassError); - - return ReplyLen; - -} - -#define SHA1_HASH_LEN 20 - -/* - -Copyright (C) 1998, 2009 -Paul E. Jones - -Freeware Public License (FPL) - -This software is licensed as "freeware." Permission to distribute -this software in source and binary forms, including incorporation -into other products, is hereby granted without a fee. THIS SOFTWARE -IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR SHALL NOT BE HELD -LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE, EITHER -DIRECTLY OR INDIRECTLY, INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA -OR DATA BEING RENDERED INACCURATE. -*/ - -/* sha1.h - * - * Copyright (C) 1998, 2009 - * Paul E. Jones - * All Rights Reserved - * - ***************************************************************************** - * $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $ - ***************************************************************************** - * - * Description: - * This class implements the Secure Hashing Standard as defined - * in FIPS PUB 180-1 published April 17, 1995. - * - * Many of the variable names in the SHA1Context, especially the - * single character names, were used because those were the names - * used in the publication. - * - * Please read the file sha1.c for more information. - * - */ - -#ifndef _SHA1_H_ -#define _SHA1_H_ - -/* - * This structure will hold context information for the hashing - * operation - */ -typedef struct SHA1Context -{ - unsigned Message_Digest[5]; /* Message Digest (output) */ - - unsigned Length_Low; /* Message length in bits */ - unsigned Length_High; /* Message length in bits */ - - unsigned char Message_Block[64]; /* 512-bit message blocks */ - int Message_Block_Index; /* Index into message block array */ - - int Computed; /* Is the digest computed? */ - int Corrupted; /* Is the message digest corruped? */ -} SHA1Context; - -/* - * Function Prototypes - */ -void SHA1Reset(SHA1Context *); -int SHA1Result(SHA1Context *); -void SHA1Input( SHA1Context *, const unsigned char *, unsigned); - -#endif - -BOOL SHA1PasswordHash(char * lpszPassword, char * Hash) -{ - SHA1Context sha; - int i; - - SHA1Reset(&sha); - SHA1Input(&sha, lpszPassword, strlen(lpszPassword)); - SHA1Result(&sha); - - // swap byte order if little endian - - for (i = 0; i < 5; i++) - sha.Message_Digest[i] = htonl(sha.Message_Digest[i]); - - memcpy(Hash, &sha.Message_Digest[0], 20); - - return TRUE; -} - -int BuildRigCtlPage(char * _REPLYBUFFER) -{ - int ReplyLen; - - struct RIGPORTINFO * PORT; - struct RIGINFO * RIG; - int p, i; - - char Page[] = - "\r\n" - // "\r\n" - "Rigcontrol\r\n" - "" - "

Rigcontrol

\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - ""; - char RigLine[] = - "\r\n" - " \r\n" - " \r\n" - " \r\n" - " \r\n" - " \r\n" - " \r\n" - " \r\n"; - char Tail[] = - "
RadioFreqModeSTPorts
%s%s%s/1%c%c%s
\r\n" - "\r\n"; - - ReplyLen = sprintf(_REPLYBUFFER, "%s", Page); - - for (p = 0; p < NumberofPorts; p++) - { - PORT = PORTInfo[p]; - - for (i=0; i< PORT->ConfiguredRigs; i++) - { - RIG = &PORT->Rigs[i]; - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], RigLine, RIG->WEB_Label, RIG->WEB_FREQ, RIG->WEB_MODE, RIG->WEB_SCAN, RIG->WEB_PTT, RIG->WEB_PORTS, RIG->Interlock); - } - } - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", Tail); - return ReplyLen; -} - - -void SendRigWebPage() -{ - int i, n; - struct ConnectionInfo * sockptr; - struct TNCINFO * TNC; - struct TCPINFO * TCP; - - for (i = 0; i < 33; i++) - { - TNC = TNCInfo[i]; - - if (TNC && TNC->Hardware == H_TELNET) - { - TCP = TNC->TCPInfo; - - if (TCP) - { - for (n = 0; n <= TCP->MaxSessions; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - - if (sockptr->SocketActive) - { - if (sockptr->HTTPMode && sockptr->WebSocks && strcmp(sockptr->WebURL, "RIGCTL") == 0) - { - char RigMsg[8192]; - int RigMsgLen = strlen(RigWebPage); - char* ptr; - - RigMsg[0] = 0x81; // Fin, Data - RigMsg[1] = 126; // Unmasked, Extended Len - RigMsg[2] = RigMsgLen >> 8; - RigMsg[3] = RigMsgLen & 0xff; - strcpy(&RigMsg[4], RigWebPage); - - // If secure session enable PTT button - - if (sockptr->WebSecure) - { - while (ptr = strstr(RigMsg, "hidden")) - memcpy(ptr, " ", 6); - } - - send(sockptr->socket, RigMsg, RigMsgLen + 4, 0); - } - } - } - } - } - } -} - -// Webmail web socket code - -int ProcessWebmailWebSock(char * MsgPtr, char * OutBuffer); - -void ProcessWebmailWebSockThread(void * conn) -{ - // conn is a malloc'ed copy to handle reused connections, so need to free it - - struct ConnectionInfo * sockptr = (struct ConnectionInfo *)conn; - char * URL = sockptr->WebURL; - int Loops = 0; - int Sent; - struct HTTPConnectionInfo Dummy = {0}; - int ReplyLen = 0; - int InputLen = 0; - -#ifdef LINBPQ - - char _REPLYBUFFER[250000]; - - ReplyLen = ProcessWebmailWebSock(URL, _REPLYBUFFER); - - // Send may block - - Sent = send(sockptr->socket, _REPLYBUFFER, ReplyLen, 0); - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - if (Sent > 0) // something sent - { - ReplyLen -= Sent; - memmove(_REPLYBUFFER, &_REPLYBUFFER[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sockptr->socket, _REPLYBUFFER, ReplyLen, 0); - } - -#else - // Send URL to BPQMail via Pipe. Just need a dummy session, as URL contains session key - - HANDLE hPipe; - char Reply[250000]; - - - - hPipe = CreateFile(MAILPipeFileName, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (hPipe == (HANDLE)-1) - { - free(conn); - return; - } - - WriteFile(hPipe, &Dummy, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - WriteFile(hPipe, URL, strlen(URL), &InputLen, NULL); - - ReadFile(hPipe, &Dummy, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - ReadFile(hPipe, Reply, 250000, &ReplyLen, NULL); - - if (ReplyLen <= 0) - { - InputLen = GetLastError(); - } - - CloseHandle(hPipe); - - // ?? do we need a thread to handle write which may block - - Sent = send(sockptr->socket, Reply, ReplyLen, 0); - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(Reply, &Reply[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sockptr->socket, Reply, ReplyLen, 0); - } -#endif - free(conn); - return; -} - -/* - * sha1.c - * - * Copyright (C) 1998, 2009 - * Paul E. Jones - * All Rights Reserved - * - ***************************************************************************** - * $Id: sha1.c 12 2009-06-22 19:34:25Z paulej $ - ***************************************************************************** - * - * Description: - * This file implements the Secure Hashing Standard as defined - * in FIPS PUB 180-1 published April 17, 1995. - * - * The Secure Hashing Standard, which uses the Secure Hashing - * Algorithm (SHA), produces a 160-bit message digest for a - * given data stream. In theory, it is highly improbable that - * two messages will produce the same message digest. Therefore, - * this algorithm can serve as a means of providing a "fingerprint" - * for a message. - * - * Portability Issues: - * SHA-1 is defined in terms of 32-bit "words". This code was - * written with the expectation that the processor has at least - * a 32-bit machine word size. If the machine word size is larger, - * the code should still function properly. One caveat to that - * is that the input functions taking characters and character - * arrays assume that only 8 bits of information are stored in each - * character. - * - * Caveats: - * SHA-1 is designed to work with messages less than 2^64 bits - * long. Although SHA-1 allows a message digest to be generated for - * messages of any number of bits less than 2^64, this - * implementation only works with messages with a length that is a - * multiple of the size of an 8-bit character. - * - */ - -/* - * Define the circular shift macro - */ -#define SHA1CircularShift(bits,word) \ - ((((word) << (bits)) & 0xFFFFFFFF) | \ - ((word) >> (32-(bits)))) - -/* Function prototypes */ -void SHA1ProcessMessageBlock(SHA1Context *); -void SHA1PadMessage(SHA1Context *); - -/* - * SHA1Reset - * - * Description: - * This function will initialize the SHA1Context in preparation - * for computing a new message digest. - * - * Parameters: - * context: [in/out] - * The context to reset. - * - * Returns: - * Nothing. - * - * Comments: - * - */ -void SHA1Reset(SHA1Context *context) -{ - context->Length_Low = 0; - context->Length_High = 0; - context->Message_Block_Index = 0; - - context->Message_Digest[0] = 0x67452301; - context->Message_Digest[1] = 0xEFCDAB89; - context->Message_Digest[2] = 0x98BADCFE; - context->Message_Digest[3] = 0x10325476; - context->Message_Digest[4] = 0xC3D2E1F0; - - context->Computed = 0; - context->Corrupted = 0; -} - -/* - * SHA1Result - * - * Description: - * This function will return the 160-bit message digest into the - * Message_Digest array within the SHA1Context provided - * - * Parameters: - * context: [in/out] - * The context to use to calculate the SHA-1 hash. - * - * Returns: - * 1 if successful, 0 if it failed. - * - * Comments: - * - */ -int SHA1Result(SHA1Context *context) -{ - - if (context->Corrupted) - { - return 0; - } - - if (!context->Computed) - { - SHA1PadMessage(context); - context->Computed = 1; - } - - return 1; -} - -/* - * SHA1Input - * - * Description: - * This function accepts an array of octets as the next portion of - * the message. - * - * Parameters: - * context: [in/out] - * The SHA-1 context to update - * message_array: [in] - * An array of characters representing the next portion of the - * message. - * length: [in] - * The length of the message in message_array - * - * Returns: - * Nothing. - * - * Comments: - * - */ -void SHA1Input( SHA1Context *context, - const unsigned char *message_array, - unsigned length) -{ - if (!length) - { - return; - } - - if (context->Computed || context->Corrupted) - { - context->Corrupted = 1; - return; - } - - while(length-- && !context->Corrupted) - { - context->Message_Block[context->Message_Block_Index++] = - (*message_array & 0xFF); - - context->Length_Low += 8; - /* Force it to 32 bits */ - context->Length_Low &= 0xFFFFFFFF; - if (context->Length_Low == 0) - { - context->Length_High++; - /* Force it to 32 bits */ - context->Length_High &= 0xFFFFFFFF; - if (context->Length_High == 0) - { - /* Message is too long */ - context->Corrupted = 1; - } - } - - if (context->Message_Block_Index == 64) - { - SHA1ProcessMessageBlock(context); - } - - message_array++; - } -} - -/* - * SHA1ProcessMessageBlock - * - * Description: - * This function will process the next 512 bits of the message - * stored in the Message_Block array. - * - * Parameters: - * None. - * - * Returns: - * Nothing. - * - * Comments: - * Many of the variable names in the SHAContext, especially the - * single character names, were used because those were the names - * used in the publication. - * - * - */ -void SHA1ProcessMessageBlock(SHA1Context *context) -{ - const unsigned K[] = /* Constants defined in SHA-1 */ - { - 0x5A827999, - 0x6ED9EBA1, - 0x8F1BBCDC, - 0xCA62C1D6 - }; - int t; /* Loop counter */ - unsigned temp; /* Temporary word value */ - unsigned W[80]; /* Word sequence */ - unsigned A, B, C, D, E; /* Word buffers */ - - /* - * Initialize the first 16 words in the array W - */ - for(t = 0; t < 16; t++) - { - W[t] = ((unsigned) context->Message_Block[t * 4]) << 24; - W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16; - W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8; - W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]); - } - - for(t = 16; t < 80; t++) - { - W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); - } - - A = context->Message_Digest[0]; - B = context->Message_Digest[1]; - C = context->Message_Digest[2]; - D = context->Message_Digest[3]; - E = context->Message_Digest[4]; - - for(t = 0; t < 20; t++) - { - temp = SHA1CircularShift(5,A) + - ((B & C) | ((~B) & D)) + E + W[t] + K[0]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 20; t < 40; t++) - { - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 40; t < 60; t++) - { - temp = SHA1CircularShift(5,A) + - ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 60; t < 80; t++) - { - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - context->Message_Digest[0] = - (context->Message_Digest[0] + A) & 0xFFFFFFFF; - context->Message_Digest[1] = - (context->Message_Digest[1] + B) & 0xFFFFFFFF; - context->Message_Digest[2] = - (context->Message_Digest[2] + C) & 0xFFFFFFFF; - context->Message_Digest[3] = - (context->Message_Digest[3] + D) & 0xFFFFFFFF; - context->Message_Digest[4] = - (context->Message_Digest[4] + E) & 0xFFFFFFFF; - - context->Message_Block_Index = 0; -} - -/* - * SHA1PadMessage - * - * Description: - * According to the standard, the message must be padded to an even - * 512 bits. The first padding bit must be a '1'. The last 64 - * bits represent the length of the original message. All bits in - * between should be 0. This function will pad the message - * according to those rules by filling the Message_Block array - * accordingly. It will also call SHA1ProcessMessageBlock() - * appropriately. When it returns, it can be assumed that the - * message digest has been computed. - * - * Parameters: - * context: [in/out] - * The context to pad - * - * Returns: - * Nothing. - * - * Comments: - * - */ -void SHA1PadMessage(SHA1Context *context) -{ - /* - * Check to see if the current message block is too small to hold - * the initial padding bits and length. If so, we will pad the - * block, process it, and then continue padding into a second - * block. - */ - if (context->Message_Block_Index > 55) - { - context->Message_Block[context->Message_Block_Index++] = 0x80; - while(context->Message_Block_Index < 64) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } - - SHA1ProcessMessageBlock(context); - - while(context->Message_Block_Index < 56) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } - } - else - { - context->Message_Block[context->Message_Block_Index++] = 0x80; - while(context->Message_Block_Index < 56) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } - } - - /* - * Store the message length as the last 8 octets - */ - context->Message_Block[56] = (context->Length_High >> 24) & 0xFF; - context->Message_Block[57] = (context->Length_High >> 16) & 0xFF; - context->Message_Block[58] = (context->Length_High >> 8) & 0xFF; - context->Message_Block[59] = (context->Length_High) & 0xFF; - context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF; - context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF; - context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF; - context->Message_Block[63] = (context->Length_Low) & 0xFF; - - SHA1ProcessMessageBlock(context); -} - - diff --git a/HTTPcode.c b/HTTPcode.c index 54a0614..f3f0d22 100644 --- a/HTTPcode.c +++ b/HTTPcode.c @@ -17,7 +17,6 @@ You should have received a copy of the GNU General Public License along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses */ - //#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define _CRT_SECURE_NO_DEPRECATE @@ -71,6 +70,8 @@ BOOL SHA1PasswordHash(char * String, char * Hash); char * byte_base64_encode(char *str, int len); int APIProcessHTTPMessage(char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE); int RHPProcessHTTPMessage(struct ConnectionInfo * conn, char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE); +unsigned char * Compressit(unsigned char * In, int Len, int * OutLen); +int doinflate(unsigned char * source, unsigned char * dest, int Len, int destlen, int * outLen); extern struct ROUTE * NEIGHBOURS; extern int ROUTE_LEN; @@ -143,7 +144,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
" "
" @@ -2412,7 +2413,10 @@ doHeader: if (Session == 0) Session = &Dummy; - Session->TNC = LOCAL; // TNC is only used on Web Terminal Sessions so can reuse as LOCAL flag + if (LOCAL) + Session->TNC = (struct TNCINFO *)(uintptr_t)1; // TNC is only used on Web Terminal Sessions so can reuse as LOCAL flag + else + Session->TNC = 0; WriteFile(hPipe, Session, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); WriteFile(hPipe, MsgPtr, MsgLen, &InputLen, NULL); @@ -3796,7 +3800,7 @@ doHeader: int MaxRoutes = MAXNEIGHBOURS; int count; char Normcall[10]; - char locked; + char locked[4] = " "; int NodeCount; int Percent = 0; int Iframes, Retries; @@ -3812,10 +3816,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); @@ -4322,7 +4330,7 @@ int ProcessMailAPISignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char { int ReplyLen = 0; char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * user, * password, * Key; + char * user, * password; struct HTTPConnectionInfo * NewSession; int i; struct UserRec * USER; diff --git a/IPCode.c b/IPCode.c index 17dd412..f340d4b 100644 --- a/IPCode.c +++ b/IPCode.c @@ -5413,11 +5413,8 @@ VOID ProcessSNMPMessage(PIPMSG IPptr) int Len; PUDPMSG UDPptr = (PUDPMSG)&IPptr->Data; UCHAR * Msg; - int Type; - int Length, ComLen; - int IntVal; UCHAR Reply[256]; - int PDULen, SendLen; + int SendLen; int Offset = 0; Len = ntohs(IPptr->IPLENGTH); diff --git a/KAMPactor.c b/KAMPactor.c index 749d561..318c6e0 100644 --- a/KAMPactor.c +++ b/KAMPactor.c @@ -567,15 +567,15 @@ void * KAMExtInit(EXTPORTDATA * PortEntry) return ExtProc; } TNC->Port = port; + TNC->PortRecord = PortEntry; - TNC->Hardware = H_KAM; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_KAM; if (TNC->BusyWait == 0) TNC->BusyWait = 10; PortEntry->MAXHOSTMODESESSIONS = 11; // Default - TNC->PortRecord = PortEntry; if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); diff --git a/KISSHF.c b/KISSHF.c index 0c066ff..ec2d29a 100644 --- a/KISSHF.c +++ b/KISSHF.c @@ -809,10 +809,10 @@ VOID * KISSHFExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; - TNC->Hardware = H_KISSHF; + TNC->PortRecord = PortEntry; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_KISSHF; TNC->ARDOPBuffer = malloc(8192); - TNC->PortRecord = PortEntry; if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); 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 81870a8..99ac4b3 100644 --- a/L4Code.c +++ b/L4Code.c @@ -67,12 +67,18 @@ VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, UCHAR * ApplCall); void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode); void SendVARANetromMsg(struct TNCINFO * TNC, PL3MESSAGEBUFFER MSG); +unsigned char * Compressit(unsigned char * In, int Len, int * OutLen); +int doinflate(unsigned char * source, unsigned char * dest, int Len, int destlen, int * outLen); static UINT APPLMASK; extern BOOL LogL4Connects; extern BOOL LogAllConnects; +extern int L4Compress; +extern int L4CompMaxframe; +extern int L4CompPaclen; + // L4 Flags Values #define DISCPENDING 8 // SEND DISC WHEN ALL DATA ACK'ED @@ -341,6 +347,17 @@ VOID SENDL4MESSAGE(TRANSPORTENTRY * L4, struct DATAMESSAGE * Msg) L3MSG->L4FLAGS = L4INFO | L4->NAKBITS; + if (Msg->PID == 0xF1) // Compressed Message + { + 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 @@ -470,6 +487,9 @@ VOID SENDL4CONNECT(TRANSPORTENTRY * Session) MSG->LENGTH = (int)(&MSG->L4DATA[17] - (UCHAR *)MSG); + if (L4Compress) + MSG->L4DATA[16] |= 0x40; // Set Compression Supported + if (Session->SPYFLAG) { MSG->L4DATA[17] = 'Z'; // ADD SPY ON BBS FLAG @@ -500,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 @@ -593,8 +660,151 @@ VOID L4BG() if (L4->L4CIRCUITTYPE & SESSION) { - SENDL4MESSAGE(L4, Msg); - ReleaseBuffer(Msg); + // Now support compressing NetRom Sessions. + // We collect as much data as possible before compressing and re-packetizing + + if (L4->AllowCompress) + { + 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 == 0) + { + // 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 + + L4->SentAfterCompression += complen; + SENDL4MESSAGE(L4, Msg); + ReleaseBuffer(Msg); + + free(L4->toCompress); + L4->toCompressLen = 0; + L4->toCompress = 0; + free(Compressed); + continue; + } + + 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; + + ReleaseBuffer(Msg); + } + + L4->toCompress[L4->toCompressLen] = 0; + + Compressed = Compressit(L4->toCompress, L4->toCompressLen, &complen); +// Debugprintf("%d %d %d%%", L4->toCompressLen, complen, ((L4->toCompressLen - complen) * 100) / L4->toCompressLen); + + // Send compressed + + // 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) + { + 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); + + sendChunk(L4, Compressed, complen, savePort); + + CompressPtr += Len; + bytesleft -= Len; + } + + } + 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); + } continue; } @@ -703,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)); } @@ -900,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 } @@ -978,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; } @@ -1250,6 +1489,7 @@ VOID SENDL4DISC(TRANSPORTENTRY * Session) MSG->LENGTH = (int)(&MSG->L4DATA[0] - (UCHAR *)MSG); C_Q_ADD(&DEST->DEST_Q, (UINT *)MSG); + } @@ -1458,6 +1698,9 @@ VOID SendConACK(struct _LINKTABLE * LINK, TRANSPORTENTRY * L4, L3MESSAGEBUFFER * if (BPQNODE) { L3MSG->L4DATA[1] = L3LIVES; // Our TTL + if (L4->AllowCompress) + L3MSG->L4DATA[1] |= 0x80; + L3MSG->LENGTH++; } @@ -1559,6 +1802,25 @@ VOID SendConNAK(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) C_Q_ADD(&LINK->TX_Q, L3MSG); } +VOID SendL4RESET(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) +{ + // Paula's extension + + L3MSG->L4FLAGS = L4RESET; + + L3SWAPADDRESSES(L3MSG); + L3MSG->L3TTL = L3LIVES; + + L3MSG->LENGTH = (int)(&L3MSG->L4DATA[0] - (UCHAR *)L3MSG); + C_Q_ADD(&LINK->TX_Q, L3MSG); +} + + + + + + + VOID SETUPNEWCIRCUIT(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, char * BPQPARAMS, int ApplMask, int * BPQNODE) { @@ -1573,8 +1835,9 @@ VOID SETUPNEWCIRCUIT(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, L4->CIRCUITID = NEXTID; NEXTID++; - if (NEXTID == 0) - NEXTID++; // kEEP nON-ZERO + + if (NEXTID == 0) + NEXTID++; // kEEP nON-ZERO L4->SESSIONT1 = L4T1; @@ -1597,10 +1860,18 @@ VOID SETUPNEWCIRCUIT(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, // GET BPQ EXTENDED CONNECT PARAMS IF PRESENT - if (L3MSG->LENGTH == MSGHDDRLEN + 38 || L3MSG->LENGTH == MSGHDDRLEN + 39) + if (L3MSG->LENGTH == MSGHDDRLEN + 38 || L3MSG->LENGTH == MSGHDDRLEN + 39) { *BPQNODE = 1; + memcpy(BPQPARAMS, &L3MSG->L4DATA[15],L3MSG->LENGTH - (MSGHDDRLEN + 36)); + + // 40 bit of 2nd byte is Compress Flag + + if (BPQPARAMS[1] & 0x40 && L4Compress) + L4->AllowCompress = 1; + + BPQPARAMS[1] &= 0xf; // Only bottom bit is significant in Timeeout field } L4->L4CIRCUITTYPE = SESSION | UPLINK; @@ -1658,7 +1929,7 @@ TryAgain: { SHORT T1; - DEST->DEST_STATE |= 0x40; // SET BPQ _NODE BIT + DEST->DEST_STATE |= 0x40; // SET BPQ NODE BIT memcpy((char *)&T1, BPQPARAMS, 2); if (T1 > 300) @@ -1694,7 +1965,7 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, { // INTERNODE LINK - TRANSPORTENTRY * L4; + TRANSPORTENTRY * L4 = 0; struct DEST_LIST * DEST; int Opcode; char Nodename[20]; @@ -1741,22 +2012,48 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, CONNECTREQUEST(LINK, L3MSG, ApplMask, ApplCall); return; } - + // OTHERS NEED A SESSION - L4 = &L4TABLE[L3MSG->L4INDEX]; - - if (L4->CIRCUITID!= L3MSG->L4ID) + if (Opcode == L4RESET) { + // Paula's extension - other end dosn't know about session so disconnect + + // A reset has our far index and id, not our index and id so have to search table for L4 entry + + int n = MAXCIRCUITS; + L4 = L4TABLE; + + while (n--) + { + if (L4->L4USER[0] && L4->FARID == L3MSG->L4ID && L4->FARINDEX == L3MSG->L4INDEX) + { + // Check L3 source call to be sure (should that be L4 source call?? + + L3MSG->L3SRCE[6] &= 0xfe; // mask end of call + + if (memcmp(L3MSG->L3SRCE, L4->L4TARGET.DEST->DEST_CALL, 7) == 0) + { + CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT) + } + ReleaseBuffer(L3MSG); + return; + } + L4++; + } + ReleaseBuffer(L3MSG); return; } - if ((L4->L4CIRCUITTYPE & SESSION) == 0) - { - // Not an L4 Session - must be an old connection + if (L3MSG->L4INDEX < MAXCIRCUITS) + L4 = &L4TABLE[L3MSG->L4INDEX]; - ReleaseBuffer(L3MSG); + // If wrong ID or not an L4 session we must have restarted or cleared session + + if (L4 == 0 || L4->CIRCUITID != L3MSG->L4ID || (L4->L4CIRCUITTYPE & SESSION) == 0) + { + SendL4RESET(LINK, L3MSG); // Paula's extension return; } @@ -1767,13 +2064,19 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, case L4CACK: // CONNECT ACK - + DEST = L4->L4TARGET.DEST; - + // EXTRACT EXTENDED PARAMS IF PRESENT if (L3MSG->LENGTH > MSGHDDRLEN + 22) // Standard Msg { + if (L3MSG->L4DATA[1] & 0x80) // Compress Flag + { + L4->AllowCompress = 1; + L3MSG->L4DATA[1] &= 0x7f; + } + DEST->DEST_STATE &= 0x80; DEST->DEST_STATE |= (L3MSG->L4DATA[1] - L3MSG->L3TTL) + 0x41; // Hops to dest + x40 } @@ -1840,13 +2143,13 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, // DISCONNECT REQUEST - L3MSG->L4INDEX = L4->FARINDEX; - L3MSG->L4ID = L4->FARID; - - L3MSG->L4FLAGS = L4DACK; + L3MSG->L4INDEX = L4->FARINDEX; + L3MSG->L4ID = L4->FARID; - L3SWAPADDRESSES(L3MSG); // EXCHANGE SOURCE AND DEST - L3MSG->L3TTL = L3LIVES; + L3MSG->L4FLAGS = L4DACK; + + L3SWAPADDRESSES(L3MSG); // EXCHANGE SOURCE AND DEST + L3MSG->L3TTL = L3LIVES; TNC = LINK->LINKPORT->TNC; @@ -1855,11 +2158,11 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, else C_Q_ADD(&LINK->TX_Q, L3MSG); - CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT) - return; - + CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT) + return; + case L4DACK: - + CLEARSESSIONENTRY(L4); ReleaseBuffer(L3MSG); return; @@ -1874,6 +2177,19 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, return; } + // Randomly drop packets + + /* + Debugprintf("L4 Test Received packet %d ", L3MSG->L4TXNO); + + if ((rand() % 7) > 5) + { + Debugprintf("L4 Test Drop packet %d ", L3MSG->L4TXNO); + ReleaseBuffer(L3MSG); + return; + } + */ + ACKFRAMES(L3MSG, L4, L3MSG->L4RXNO); // If DISCPENDING or STATE IS 4, THEN SESSION IS CLOSING - IGNORE ANY I FRAMES @@ -1898,36 +2214,35 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, // FRAME IS A REPEAT Call[ConvFromAX25(L3MSG->L3SRCE, Call)] = 0; - Debugprintf("Discarding repeated frame seq %d from %s", L3MSG->L4TXNO, Call); + Debugprintf("L4 Discarding repeated frame seq %d from %s", L3MSG->L4TXNO, Call); L4->L4ACKREQ = 1; ReleaseBuffer(L3MSG); return; } - + if (FramesMissing > 0) { // EXPECTED FRAME HAS BEEN MISSED - ASK FOR IT AGAIN, // AND KEEP THIS FRAME UNTIL MISSING ONE ARRIVES L4->NAKBITS |= L4NAK; // SET NAK REQUIRED - SENDL4IACK(L4); // SEND DATA ACK COMMAND TO ACK OUTSTANDING FRAMES - + // SEE IF WE ALREADY HAVE A COPY OF THIS ONE -/* + Saved = L4->L4RESEQ_Q; Call[ConvFromAX25(L3MSG->L3SRCE, Call)] = 0; - Debugprintf("saving seq %d from %s", L3MSG->L4TXNO, Call); + Debugprintf("L4 Out Of Seq saving seq %d from %s", L3MSG->L4TXNO, Call); while (Saved) { if (Saved->L4TXNO == L3MSG->L4TXNO) { // ALREADY HAVE A COPY - DISCARD IT - - Debugprintf("Already have seq %d - discarding", L3MSG->L4TXNO); + + Debugprintf("L4 Already have seq %d - discarding", L3MSG->L4TXNO); ReleaseBuffer(L3MSG); return; } @@ -1937,7 +2252,6 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, C_Q_ADD(&L4->L4RESEQ_Q, L3MSG); // ADD TO CHAIN return; -*/ } // Frame is OK @@ -1953,7 +2267,7 @@ L4INFO_OK: L4->NAKBITS &= ~L4NAK; // CLEAR MESSAGE LOST STATE L4->RXSEQNO++; - + // REMOVE HEADERS, AND QUEUE INFO L3MSG->LENGTH -= 20; // L3/L4 Header @@ -1966,15 +2280,122 @@ L4INFO_OK: L3MSG->L3PID = 0xF0; // Normal Data PID - memmove(L3MSG->L3SRCE, L3MSG->L4DATA, L3MSG->LENGTH - (4 + sizeof(void *))); + // if compressed, expand - REFRESHROUTE(L4); + if ((L3MSG->L4FLAGS & L4COMP) == 0) + { + // 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; + int sendLen; + char * sendptr; + int savePort = L3MSG->Port; + + // May be more thsn one packet + + Len = L3MSG->LENGTH - MSGHDDRLEN - 1; + + 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; @@ -1991,13 +2412,13 @@ L4INFO_OK: *Prev = Saved->Next; // CHAIN NEXT IN CHAIN TO PREVIOUS OLDFRAMES++; // COUNT FOR STATS - + L3MSG = Saved; - Debugprintf("Processing Saved Message %d Address %x", L4->RXSEQNO, L3MSG); + Debugprintf("L4 Processing Saved Message %d Address %x", L4->RXSEQNO, L3MSG); goto L4INFO_OK; } - Debugprintf("Message %d %x still on Reseq Queue", Saved->L4TXNO, Saved); + Debugprintf("L4 Message %d %x still on Reseq Queue", Saved->L4TXNO, Saved); Prev = &Saved; Saved = Saved->Next; @@ -2010,7 +2431,9 @@ L4INFO_OK: ACKFRAMES(L3MSG, L4, L3MSG->L4RXNO); REFRESHROUTE(L4); - // Drop Through + ReleaseBuffer(L3MSG); + return; + } // Unrecognised - Ignore @@ -2061,15 +2484,18 @@ VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR) if (L4->RTT_TIMER) { // FRAME BEING TIMED HAS BEEN ACKED - UPDATE DEST RTT TIMER - + DEST = L4->L4TARGET.DEST; - + RTT = GetTickCount() - L4->RTT_TIMER; - if (DEST->DEST_RTT == 0) - DEST->DEST_RTT = RTT; - else - DEST->DEST_RTT = ((DEST->DEST_RTT * 9) + RTT) /10; // 90% Old + New + 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 + } } } @@ -2091,7 +2517,7 @@ VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR) if ((L4->FLAGS & DISCPENDING) && L4->L4TX_Q == 0) { // All Acked and DISC Pending, so send it - + SENDL4DISC(L4); return; } @@ -2100,13 +2526,13 @@ VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR) // SEE IF CHOKE SET L4->FLAGS &= ~L4BUSY; - + if (L3MSG->L4FLAGS & L4BUSY) { L4->FLAGS |= L3MSG->L4FLAGS & L4BUSY; // Get Busy flag from message if ((L3MSG->L4FLAGS & L4NAK) == 0) - return; // Dont send while biust unless NAC received + return; // Dont send while busy unless NAK received } if (L3MSG->L4FLAGS & L4NAK) @@ -2114,10 +2540,10 @@ VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR) // RETRANSMIT REQUESTED MESSAGE - WILL BE FIRST ON HOLD QUEUE Msg = L4->L4HOLD_Q; - + if (Msg == 0) return; - + Copy = GetBuff(); if (Copy == 0) @@ -2134,17 +2560,6 @@ VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR) - - - - - - - - - - - VOID SENDL4IACK(TRANSPORTENTRY * Session) { // SEND INFO ACK @@ -2167,7 +2582,8 @@ VOID SENDL4IACK(TRANSPORTENTRY * Session) MSG->L4TXNO = 0; - + + MSG->L4RXNO = Session->RXSEQNO; Session->L4LASTACKED = Session->RXSEQNO; // SAVE LAST NUMBER ACKED @@ -2175,7 +2591,10 @@ VOID SENDL4IACK(TRANSPORTENTRY * Session) MSG->LENGTH = MSGHDDRLEN + 22; + // Debugprintf("Sending L4 IACK %d %x", MSG->L4RXNO, MSG->L4FLAGS); + C_Q_ADD(&DEST->DEST_Q, (UINT *)MSG); + } diff --git a/LinBPQ-skigdebian.c b/LinBPQ-skigdebian.c deleted file mode 100644 index 60f670e..0000000 --- a/LinBPQ-skigdebian.c +++ /dev/null @@ -1,2154 +0,0 @@ -/* -Copyright 2001-2018 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 -*/ - -// Control Routine for LinBPQ - -#define _CRT_SECURE_NO_DEPRECATE - -#include "cheaders.h" -#include "bpqmail.h" -#ifdef WIN32 -#include -//#include "C:\Program Files (x86)\GnuWin32\include\iconv.h" -#else -#include -#include -#ifndef MACBPQ -#ifndef FREEBSD -#include -#endif -#endif -#endif - -#include "time.h" - -#define Connect(stream) SessionControl(stream,1,0) -#define Disconnect(stream) SessionControl(stream,2,0) -#define ReturntoNode(stream) SessionControl(stream,3,0) -#define ConnectUsingAppl(stream, appl) SessionControl(stream, 0, appl) - -BOOL APIENTRY Rig_Init(); - - - -#define GetSemaphore(Semaphore,ID) _GetSemaphore(Semaphore, ID, __FILE__, __LINE__) - -void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line); -void FreeSemaphore(struct SEM * Semaphore); -VOID CopyConfigFile(char * ConfigName); -VOID SendMailForThread(VOID * Param); -VOID GetUIConfig(); -Dll BOOL APIENTRY Init_IP(); -VOID OpenReportingSockets(); -VOID SetupNTSAliases(char * FN); -int DeleteRedundantMessages(); -BOOL InitializeTNCEmulator(); -VOID FindLostBuffers(); -VOID IPClose(); -DllExport BOOL APIENTRY Rig_Close(); -Dll BOOL APIENTRY Poll_IP(); -BOOL Rig_Poll(); -BOOL Rig_Poll(); -VOID CheckWL2KReportTimer(); -VOID TNCTimer(); -VOID SendLocation(); -int ChatPollStreams(); -void ChatTrytoSend(); -VOID BBSSlowTimer(); -int GetHTMLForms(); -char * AddUser(char * Call, char * password, BOOL BBSFlag); -VOID SaveChatConfigFile(char * ConfigName); -VOID SaveMH(); -int upnpClose(); -void SaveAIS(); -void initAIS(); -void DRATSPoll(); -void RHPPoll(); - -VOID GetPGConfig(); -void SendBBSDataToPktMap(); - -extern uint64_t timeLoadedMS; - -BOOL IncludesMail = FALSE; -BOOL IncludesChat = FALSE; - -BOOL RunMail = FALSE; -BOOL RunChat = FALSE; -BOOL needAIS= FALSE; -BOOL needADSB = FALSE; - -int CloseOnError = 0; - -VOID Poll_AGW(); -BOOL AGWAPIInit(); -int AGWAPITerminate(); - -BOOL AGWActive = FALSE; - -extern int AGWPort; - -BOOL RigActive = FALSE; - -extern ULONG ChatApplMask; -extern char Verstring[]; - -extern char SignoffMsg[]; -extern char AbortedMsg[]; -extern char InfoBoxText[]; // Text to display in Config Info Popup - -extern int LastVer[4]; // In case we need to do somthing the first time a version is run - -extern HWND MainWnd; -extern char BaseDir[]; -extern char BaseDirRaw[]; -extern char MailDir[]; -extern char WPDatabasePath[]; -extern char RlineVer[50]; - -extern BOOL LogBBS; -extern BOOL LogCHAT; -extern BOOL LogTCP; -extern BOOL ForwardToMe; - -extern int LatestMsg; -extern char BBSName[]; -extern char SYSOPCall[]; -extern char BBSSID[]; -extern char NewUserPrompt[]; - -extern int NumberofStreams; -extern int MaxStreams; -extern ULONG BBSApplMask; -extern int BBSApplNum; -extern int ChatApplNum; -extern int MaxChatStreams; - -extern int NUMBEROFTNCPORTS; - -extern int EnableUI; - -extern BOOL AUTOSAVEMH; - -extern FILE * LogHandle[4]; - -#define MaxSockets 64 - -extern ConnectionInfo Connections[MaxSockets+1]; - -time_t LastTrafficTime; -extern int MaintTime; - -#define LOG_BBS 0 -#define LOG_CHAT 1 -#define LOG_TCP 2 -#define LOG_DEBUG_X 3 - -int _MYTIMEZONE = 0; - -// flags equates - -#define F_Excluded 0x0001 -#define F_LOC 0x0002 -#define F_Expert 0x0004 -#define F_SYSOP 0x0008 -#define F_BBS 0x0010 -#define F_PAG 0x0020 -#define F_GST 0x0040 -#define F_MOD 0x0080 -#define F_PRV 0x0100 -#define F_UNP 0x0200 -#define F_NEW 0x0400 -#define F_PMS 0x0800 -#define F_EMAIL 0x1000 -#define F_HOLDMAIL 0x2000 -#define F_POLLRMS 0x4000 -#define F_SYSOP_IN_LM 0x8000 -#define F_Temp_B2_BBS 0x00010000 - -/* #define F_PWD 0x1000 */ - - -extern UCHAR BPQDirectory[260]; -extern UCHAR LogDirectory[260]; -extern UCHAR ConfigDirectory[260]; - -// overrides from params -UCHAR LogDir[260] = ""; -UCHAR ConfigDir[260] = ""; -UCHAR DataDir[260] = ""; - - -BOOL GetConfig(char * ConfigName); -VOID DecryptPass(char * Encrypt, unsigned char * Pass, unsigned int len); -int EncryptPass(char * Pass, char * Encrypt); -int APIENTRY FindFreeStream(); -int PollStreams(); -int APIENTRY SetAppl(int stream, int flags, int mask); -int APIENTRY SessionState(int stream, int * state, int * change); -int APIENTRY SessionControl(int stream, int command, int Mask); - -BOOL ChatInit(); -VOID CloseChat(); -VOID CloseTNCEmulator(); - -static config_t cfg; -static config_setting_t * group; - -BOOL MonBBS = TRUE; -BOOL MonCHAT = TRUE; -BOOL MonTCP = TRUE; - -BOOL LogBBS = TRUE; -BOOL LogCHAT = TRUE; -BOOL LogTCP = TRUE; - -extern BOOL LogAPRSIS; - -BOOL UIEnabled[33]; -BOOL UINull[33]; -char * UIDigi[33]; - -extern struct UserInfo ** UserRecPtr; -extern int NumberofUsers; - -extern struct UserInfo * BBSChain; // Chain of users that are BBSes - -extern struct MsgInfo ** MsgHddrPtr; -extern int NumberofMessages; - -extern int FirstMessageIndextoForward; // Lowest Message wirh a forward bit set - limits search - -extern char UserDatabaseName[MAX_PATH]; -extern char UserDatabasePath[MAX_PATH]; - -extern char MsgDatabasePath[MAX_PATH]; -extern char MsgDatabaseName[MAX_PATH]; - -extern char BIDDatabasePath[MAX_PATH]; -extern char BIDDatabaseName[MAX_PATH]; - -extern char WPDatabasePath[MAX_PATH]; -extern char WPDatabaseName[MAX_PATH]; - -extern char BadWordsPath[MAX_PATH]; -extern char BadWordsName[MAX_PATH]; - -extern char NTSAliasesPath[MAX_PATH]; -extern char NTSAliasesName[MAX_PATH]; - -extern char BaseDir[MAX_PATH]; -extern char BaseDirRaw[MAX_PATH]; // As set in registry - may contain %NAME% -extern char ProperBaseDir[MAX_PATH]; // BPQ Directory/BPQMailChat - -extern char MailDir[MAX_PATH]; - -extern time_t MaintClock; // Time to run housekeeping - -#ifdef WIN32 -BOOL KEEPGOING = 30; // 5 secs to shut down -#else -BOOL KEEPGOING = 50; // 5 secs to shut down -#endif -BOOL Restarting = FALSE; -BOOL CLOSING = FALSE; - -int ProgramErrors; -int Slowtimer = 0; - -#define REPORTINTERVAL 15 * 549; // Magic Ticks Per Minute for PC's nominal 100 ms timer -int ReportTimer = 0; - -// Console Terminal Support - -struct ConTermS -{ - int BPQStream; - BOOL Active; - int Incoming; - - char kbbuf[INPUTLEN]; - int kbptr; - - char * KbdStack[MAXSTACK]; - int StackIndex; - - BOOL CONNECTED; - int SlowTimer; -}; - -struct ConTermS ConTerm = {0, 0}; - - -VOID CheckProgramErrors() -{ - if (Restarting) - exit(0); // Make sure can't loop in restarting - - ProgramErrors++; - - if (ProgramErrors > 25) - { - Restarting = TRUE; - - Logprintf(LOG_DEBUG_X, NULL, '!', "Too Many Program Errors - Closing"); - -/* - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - GetModuleFileName(NULL, ProgName, 256); - - Debugprintf("Attempting to Restart %s", ProgName); - - CreateProcess(ProgName, "MailChat.exe WAIT", NULL, NULL, FALSE, 0, NULL, NULL, &SInfo, &PInfo); -*/ - exit(0); - } -} - -#ifdef WIN32 - -BOOL CtrlHandler(DWORD fdwCtrlType) -{ - switch( fdwCtrlType ) - { - // Handle the CTRL-C signal. - case CTRL_C_EVENT: - printf( "Ctrl-C event\n\n" ); - CLOSING = TRUE; - Beep( 750, 300 ); - return( TRUE ); - - // CTRL-CLOSE: confirm that the user wants to exit. - case CTRL_CLOSE_EVENT: - - CLOSING = TRUE; - printf( "Ctrl-Close event\n\n" ); - Sleep(20000); - Beep( 750, 300 ); - return( TRUE ); - - // Pass other signals to the next handler. - case CTRL_BREAK_EVENT: - Beep( 900, 200 ); - printf( "Ctrl-Break event\n\n" ); - CLOSING = TRUE; - Beep( 750, 300 ); - return FALSE; - - case CTRL_LOGOFF_EVENT: - Beep( 1000, 200 ); - printf( "Ctrl-Logoff event\n\n" ); - return FALSE; - - case CTRL_SHUTDOWN_EVENT: - Beep( 750, 500 ); - printf( "Ctrl-Shutdown event\n\n" ); - CLOSING = TRUE; - Beep( 750, 300 ); - return FALSE; - - default: - return FALSE; - } -} - -#else - -#include -#include - -// Linux Signal Handlers - -static void segvhandler(int sig) -{ - void *array[10]; - size_t size; - char msg[] = "SIGSEGV Received\n"; - - write(STDERR_FILENO, msg, strlen(msg)); - - // get void*'s for all entries on the stack - size = backtrace(array, 10); - - // print out all the frames to stderr - - backtrace_symbols_fd(array, size, STDERR_FILENO); - - exit(1); -} - -static void abrthandler(int sig) -{ - void *array[10]; - size_t size; - char msg[] = "SIGABRT Received\n"; - - write(STDERR_FILENO, msg, strlen(msg)); - - // get void*'s for all entries on the stack - - size = backtrace(array, 10); - backtrace_symbols_fd(array, size, STDERR_FILENO); - - exit(1); -} - -static void sigterm_handler(int sig) -{ - syslog(LOG_INFO, "terminating on SIGTERM\n"); - CLOSING = TRUE; -} - -static void sigint_handler(int sig) -{ - printf("terminating on SIGINT\n"); - CLOSING = TRUE; -} - - -static void sigusr1_handler(int sig) -{ - signal(SIGUSR1, sigusr1_handler); -} - -#endif - - -#ifndef WIN32 - -BOOL CopyFile(char * In, char * Out, BOOL Failifexists) -{ - FILE * Handle; - DWORD FileSize; - char * Buffer; - struct stat STAT; - - if (stat(In, &STAT) == -1) - return FALSE; - - FileSize = STAT.st_size; - - Handle = fopen(In, "rb"); - - if (Handle == NULL) - return FALSE; - - Buffer = malloc(FileSize+1); - - FileSize = fread(Buffer, 1, STAT.st_size, Handle); - - fclose(Handle); - - if (FileSize != STAT.st_size) - { - free(Buffer); - return FALSE; - } - - Handle = fopen(Out, "wb"); - - if (Handle == NULL) - { - free(Buffer); - return FALSE; - } - - FileSize = fwrite(Buffer, 1, STAT.st_size, Handle); - - fclose(Handle); - free(Buffer); - - return TRUE; -} -#endif - -int RefreshMainWindow() -{ - return 0; -} - -int LastSemGets = 0; - -extern int SemHeldByAPI; - -VOID MonitorThread(void * x) -{ - // Thread to detect stuck semaphore - - do - { - if ((Semaphore.Gets == LastSemGets) && Semaphore.Flag) - { - // It is stuck - try to release - - Debugprintf ("Semaphore locked - Process ID = %d, Held By %d from %s Line %d", - Semaphore.SemProcessID, SemHeldByAPI, Semaphore.File, Semaphore.Line); - - - Semaphore.Flag = 0; - } - - LastSemGets = Semaphore.Gets; - - Sleep(30000); -// Debugprintf("Monitor Thread Still going %d %d %d %x %d", LastSemGets, Semaphore.Gets, Semaphore.Flag, Semaphore.SemThreadID, SemHeldByAPI); - - } - while (TRUE); -} - - - - -VOID TIMERINTERRUPT(); - -BOOL Start(); -VOID INITIALISEPORTS(); -Dll BOOL APIENTRY Init_APRS(); -VOID APRSClose(); -Dll VOID APIENTRY Poll_APRS(); -VOID HTTPTimer(); - - -#define CKernel -#include "Versions.h" - -extern struct SEM Semaphore; - -int SemHeldByAPI = 0; -BOOL IGateEnabled = TRUE; -BOOL APRSActive = FALSE; -BOOL ReconfigFlag = FALSE; -BOOL APRSReconfigFlag = FALSE; -BOOL RigReconfigFlag = FALSE; - -BOOL IPActive = FALSE; -extern BOOL IPRequired; - -extern struct WL2KInfo * WL2KReports; - -int InitDone; -char pgm[256] = "LINBPQ"; - -char SESSIONHDDR[80] = ""; -int SESSHDDRLEN = 0; - - -// Next 3 should be uninitialised so they are local to each process - -UCHAR MCOM; -UCHAR MUIONLY; -UCHAR MTX; -uint64_t MMASK; - - -UCHAR AuthorisedProgram; // Local Variable. Set if Program is on secure list - -int SAVEPORT = 0; - -VOID SetApplPorts(); - -char VersionString[50] = Verstring; -char VersionStringWithBuild[50]=Verstring; -int Ver[4] = {Vers}; -char TextVerstring[50] = Verstring; - -extern UCHAR PWLen; -extern char PWTEXT[]; -extern int ISPort; - -extern char ChatConfigName[250]; - -BOOL EventsEnabled = 0; - -UCHAR * GetBPQDirectory() -{ - return BPQDirectory; -} -UCHAR * GetLogDirectory() -{ - return LogDirectory; -} -extern int POP3Timer; - -// Console Terminal Stuff - -#ifndef WIN32 - - - -#define _getch getchar - -/** - Linux (POSIX) implementation of _kbhit(). - Morgan McGuire, morgan@cs.brown.edu - */ - -#include -#include -#include - -int _kbhit() { - static const int STDIN = 0; - static int initialized = 0; - - if (! initialized) { - // Use termios to turn off line buffering - struct termios term; - tcgetattr(STDIN, &term); - term.c_lflag &= ~ICANON; - - tcsetattr(STDIN, TCSANOW, &term); - setbuf(stdin, NULL); - initialized = 1; - } - - int bytesWaiting; - ioctl(STDIN, FIONREAD, &bytesWaiting); - return bytesWaiting; -} - -#endif - -void ConTermInput(char * Msg) -{ - int i; - - if (ConTerm.BPQStream == 0) - { - ConTerm.BPQStream = FindFreeStream(); - - if (ConTerm.BPQStream == 255) - { - ConTerm.BPQStream = 0; - printf("No Free Streams\n"); - return; - } - } - - if (!ConTerm.CONNECTED) - SessionControl(ConTerm.BPQStream, 1, 0); - - ConTerm.StackIndex = 0; - - // Stack it - - if (ConTerm.KbdStack[19]) - free(ConTerm.KbdStack[19]); - - for (i = 18; i >= 0; i--) - { - ConTerm.KbdStack[i+1] = ConTerm.KbdStack[i]; - } - - ConTerm.KbdStack[0] = _strdup(ConTerm.kbbuf); - - ConTerm.kbbuf[ConTerm.kbptr]=13; - - SendMsg(ConTerm.BPQStream, ConTerm.kbbuf, ConTerm.kbptr+1); -} - -void ConTermPoll() -{ - int port, sesstype, paclen, maxframe, l4window, len; - int state, change, InputLen, count; - char callsign[11] = ""; - char Msg[300]; - - // Get current Session State. Any state changed is ACK'ed - // automatically. See BPQHOST functions 4 and 5. - - SessionState(ConTerm.BPQStream, &state, &change); - - if (change == 1) - { - if (state == 1) - { - // Connected - - ConTerm.CONNECTED = TRUE; - ConTerm.SlowTimer = 0; - } - else - { - ConTerm.CONNECTED = FALSE; - printf("*** Disconnected\n"); - } - } - - GetMsg(ConTerm.BPQStream, Msg, &InputLen, &count); - - if (InputLen) - { - char * ptr = Msg; - char * ptr2 = ptr; - Msg[InputLen] = 0; - - while (ptr) - { - ptr2 = strlop(ptr, 13); - - // Replace CR with CRLF - - printf("%s", ptr); - - if (ptr2) - printf("\r\n"); - - ptr = ptr2; - } - } - - if (_kbhit()) - { - unsigned char c = _getch(); - - if (c == 0xe0) - { - // Cursor control - - c = _getch(); - - if (c == 75) // cursor left - c = 8; - } - -#ifdef WIN32 - printf("%c", c); -#endif - if (c == 8) - { - if (ConTerm.kbptr) - ConTerm.kbptr--; - printf(" \b"); // Already echoed bs - clear typed char from screen - return; - } - - if (c == 13 || c == 10) - { - ConTermInput(ConTerm.kbbuf); - ConTerm.kbptr = 0; - return; - } - - ConTerm.kbbuf[ConTerm.kbptr++] = c; - fflush(NULL); - - } - - return; - -} - -#include - -static struct option long_options[] = -{ - {"logdir", required_argument, 0 , 'l'}, - {"configdir", required_argument, 0 , 'c'}, - {"datadir", required_argument, 0 , 'd'}, - {"help", no_argument, 0 , 'h'}, - { NULL , no_argument , NULL , no_argument } -}; - -char HelpScreen[] = - "Usage:\n" - "Optional Paramters\n" - "-l path or --logdir path Path for log files\n" - "-c path or --configdir path Path to Config file bpq32.cfg\n" - "-d path or --datadir path Path to Data Files\n" - "-v Show version and exit\n"; - -int Redirected = 0; - -static void segvhandler(int sig); -static void abrthandler(int sig); - - -int main(int argc, char * argv[]) -{ - int i; - struct UserInfo * user = NULL; - ConnectionInfo * conn; - struct stat STAT; - PEXTPORTDATA PORTVEC; - -#ifdef WIN32 - - WSADATA WsaData; // receives data from WSAStartup - HWND hWnd = GetForegroundWindow(); - - WSAStartup(MAKEWORD(2, 0), &WsaData); - SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); - - // disable the [x] button. - - if (hWnd != NULL) - { - HMENU hMenu = GetSystemMenu(hWnd, 0); - if (hMenu != NULL) - { - DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND); - DrawMenuBar(hWnd); - } - } - -#else - - signal(SIGSEGV, segvhandler); - signal(SIGABRT, abrthandler); - - setlinebuf(stdout); - struct sigaction act; - openlog("LINBPQ", LOG_PID, LOG_DAEMON); -#ifndef MACBPQ -#ifndef FREEBSD - prctl(PR_SET_DUMPABLE, 1); // Enable Core Dumps even with setcap -#endif -#endif - - // Disable Console Terminal if stdout redirected - -// printf("STDOUT %d\n",isatty(STDOUT_FILENO)); -// printf("STDIN %d\n",isatty(STDIN_FILENO)); - - if (!isatty(STDOUT_FILENO) || !isatty(STDIN_FILENO)) - Redirected = 1; - - timeLoadedMS = GetTickCount(); - -#endif - - printf("G8BPQ AX25 Packet Switch System Version %s %s\n", TextVerstring, Datestring); - printf("%s\n", VerCopyright); - - - // look for optarg format parameters - - { - int val; - UCHAR * ptr1; - UCHAR * ptr2; - int c; - - while (1) - { - int option_index = 0; - - c = getopt_long(argc, argv, "l:c:d:hv", long_options, &option_index); - - // Check for end of operation or error - - if (c == -1) - break; - - // Handle options - switch (c) - { - case 'h': - - printf("%s", HelpScreen); - exit (0); - - case 'l': - strcpy(LogDir, optarg); - printf("cc %s\n", LogDir); - break; - - case 'c': - strcpy(ConfigDir, optarg); - break; - - case 'd': - strcpy(DataDir, optarg); - break; - - - case '?': - /* getopt_long already printed an error message. */ - break; - - case 'v': - return 0; - } - } - } - - sprintf(RlineVer, "LinBPQ%d.%d.%d", Ver[0], Ver[1], Ver[2]); - - - Debugprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - -#ifndef MACBPQ - _MYTIMEZONE = _timezone; -#endif - - if (_MYTIMEZONE < -86400 || _MYTIMEZONE > 86400) - _MYTIMEZONE = 0; - -#ifdef WIN32 - GetCurrentDirectory(256, BPQDirectory); -#else - getcwd(BPQDirectory, 256); -#endif - - strcpy(ConfigDirectory, BPQDirectory); - strcpy(LogDirectory, BPQDirectory); - - Consoleprintf("Current Directory is %s", BPQDirectory); - - if (LogDir[0]) - { - strcpy(LogDirectory, LogDir); - } - if (DataDir[0]) - { - strcpy(BPQDirectory, DataDir); - Consoleprintf("Working Directory is %s", BPQDirectory); - } - if (ConfigDir[0]) - { - strcpy(ConfigDirectory, ConfigDir); - Consoleprintf("Config Directory is %s", ConfigDirectory); - } - - for (i = optind; i < argc; i++) - { - if (_memicmp(argv[i], "logdir=", 7) == 0) - { - strcpy(LogDirectory, &argv[i][7]); - Consoleprintf("Log Directory is %s\n", LogDirectory); - break; - } - } - - Consoleprintf("Log Directory is %s", LogDirectory); - - // Make sure logs directory exists - - sprintf(LogDir, "%s/logs", LogDirectory); - -#ifdef WIN32 - CreateDirectory(LogDir, NULL); -#else - printf("Making Directory %s\n", LogDir); - i = mkdir(LogDir, S_IRWXU | S_IRWXG | S_IRWXO); - if (i == -1 && errno != EEXIST) - { - perror("Couldn't create log directory\n"); - return 0; - } - chmod(LogDir, S_IRWXU | S_IRWXG | S_IRWXO); -#endif - - if (!ProcessConfig()) - { - WritetoConsoleLocal("Configuration File Error\n"); - return (0); - } - - SESSHDDRLEN = sprintf(SESSIONHDDR, "G8BPQ Network System %s for Linux (", TextVerstring); - -#ifdef MACBPQ - SESSHDDRLEN = sprintf(SESSIONHDDR, "G8BPQ Network System %s for MAC (", TextVerstring); -#endif -#ifdef FREEBSD - SESSHDDRLEN = sprintf(SESSIONHDDR, "G8BPQ Network System %s for FreeBSD (", TextVerstring); -#endif - - - GetSemaphore(&Semaphore, 0); - - if (Start() != 0) - { - FreeSemaphore(&Semaphore); - return (0); - } - - for (i=0;PWTEXT[i] > 0x20;i++); //Scan for cr or null - - PWLen=i; - - SetApplPorts(); - - GetUIConfig(); - - INITIALISEPORTS(); - - if (IPRequired) IPActive = Init_IP(); - - APRSActive = Init_APRS(); - - if (ISPort == 0) - IGateEnabled = 0; - - if (needAIS) - initAIS(); - - RigActive = Rig_Init(); - - FreeSemaphore(&Semaphore); - - OpenReportingSockets(); - - initUTF8(); - - InitDone = TRUE; - - Debugprintf("Monitor Thread ID %x", _beginthread(MonitorThread, 0, 0)); - - -#ifdef WIN32 -#else - openlog("LINBPQ", LOG_PID, LOG_DAEMON); - - memset (&act, '\0', sizeof(act)); - - act.sa_handler = &sigint_handler; - if (sigaction(SIGINT, &act, NULL) < 0) - perror ("SIGINT"); - - act.sa_handler = &sigterm_handler; - if (sigaction(SIGTERM, &act, NULL) < 0) - perror ("sigaction"); - - act.sa_handler = SIG_IGN; - if (sigaction(SIGHUP, &act, NULL) < 0) - perror ("SIGHUP"); - - if (sigaction(SIGPIPE, &act, NULL) < 0) - perror ("SIGPIPE"); - -#endif - - for (i = optind; i < argc; i++) - { - if (_stricmp(argv[i], "chat") == 0) - IncludesChat = TRUE; - } - - if (IncludesChat) - { - RunChat = TRUE; - - printf("Starting Chat\n"); - - sprintf (ChatConfigName, "%s/chatconfig.cfg", BPQDirectory); - printf("Config File is %s\n", ChatConfigName); - - if (stat(ChatConfigName, &STAT) == -1) - { - printf("Chat Config File not found - creating a default config\n"); - ChatApplNum = 2; - MaxChatStreams = 10; - SaveChatConfigFile(ChatConfigName); - } - - if (GetChatConfig(ChatConfigName) == EXIT_FAILURE) - { - printf("Chat Config File seems corrupt - check before continuing\n"); - return -1; - } - - if (ChatApplNum) - { - if (ChatInit() == 0) - { - printf("Chat Init Failed\n"); - RunChat = 0; - } - else - { - printf("Chat Started\n"); - } - } - else - { - printf("Chat APPLNUM not defined\n"); - RunChat = 0; - } - CopyConfigFile(ChatConfigName); - } - - // Start Mail if requested by command line or config - - for (i = optind; i < argc; i++) - { - if (_stricmp(argv[i], "mail") == 0) - IncludesMail = TRUE; - } - - - if (IncludesMail) - { - RunMail = TRUE; - - printf("Starting Mail\n"); - - sprintf (ConfigName, "%s/linmail.cfg", BPQDirectory); - printf("Config File is %s\n", ConfigName); - - if (stat(ConfigName, &STAT) == -1) - { - printf("Config File not found - creating a default config\n"); - strcpy(BBSName, MYNODECALL); - strlop(BBSName, '-'); - strlop(BBSName, ' '); - BBSApplNum = 1; - MaxStreams = 10; - SaveConfig(ConfigName); - } - - if (GetConfig(ConfigName) == EXIT_FAILURE) - { - printf("BBS Config File seems corrupt - check before continuing\n"); - return -1; - } - - printf("Config Processed\n"); - - BBSApplMask = 1<<(BBSApplNum-1); - - // See if we need to warn of possible problem with BaseDir moved by installer - - sprintf(BaseDir, "%s", BPQDirectory); - - - // Set up file and directory names - - strcpy(UserDatabasePath, BaseDir); - strcat(UserDatabasePath, "/"); - strcat(UserDatabasePath, UserDatabaseName); - - strcpy(MsgDatabasePath, BaseDir); - strcat(MsgDatabasePath, "/"); - strcat(MsgDatabasePath, MsgDatabaseName); - - strcpy(BIDDatabasePath, BaseDir); - strcat(BIDDatabasePath, "/"); - strcat(BIDDatabasePath, BIDDatabaseName); - - strcpy(WPDatabasePath, BaseDir); - strcat(WPDatabasePath, "/"); - strcat(WPDatabasePath, WPDatabaseName); - - strcpy(BadWordsPath, BaseDir); - strcat(BadWordsPath, "/"); - strcat(BadWordsPath, BadWordsName); - - strcpy(NTSAliasesPath, BaseDir); - strcat(NTSAliasesPath, "/"); - strcat(NTSAliasesPath, NTSAliasesName); - - strcpy(MailDir, BaseDir); - strcat(MailDir, "/"); - strcat(MailDir, "Mail"); - -#ifdef WIN32 - CreateDirectory(MailDir, NULL); // Just in case -#else - mkdir(MailDir, S_IRWXU | S_IRWXG | S_IRWXO); - chmod(MailDir, S_IRWXU | S_IRWXG | S_IRWXO); -#endif - - // Make backup copies of Databases - - // CopyConfigFile(ConfigName); - - CopyBIDDatabase(); - CopyMessageDatabase(); - CopyUserDatabase(); - CopyWPDatabase(); - - SetupMyHA(); - SetupFwdAliases(); - SetupNTSAliases(NTSAliasesPath); - - GetWPDatabase(); - - GetMessageDatabase(); - GetUserDatabase(); - GetBIDDatabase(); - GetBadWordFile(); - GetHTMLForms(); - GetPGConfig(); - - // Make sure there is a user record for the BBS, with BBS bit set. - - user = LookupCall(BBSName); - - if (user == NULL) - { - user = AllocateUserRecord(BBSName); - user->Temp = zalloc(sizeof (struct TempUserInfo)); - } - - if ((user->flags & F_BBS) == 0) - { - // Not Defined as a BBS - - if(SetupNewBBS(user)) - user->flags |= F_BBS; - } - - // if forwarding AMPR mail make sure User/BBS AMPR exists - - if (SendAMPRDirect) - { - BOOL NeedSave = FALSE; - - user = LookupCall("AMPR"); - - if (user == NULL) - { - user = AllocateUserRecord("AMPR"); - user->Temp = zalloc(sizeof (struct TempUserInfo)); - NeedSave = TRUE; - } - - if ((user->flags & F_BBS) == 0) - { - // Not Defined as a BBS - - if (SetupNewBBS(user)) - user->flags |= F_BBS; - NeedSave = TRUE; - } - - if (NeedSave) - SaveUserDatabase(); - } - - - // Make sure SYSOPCALL is set - - if (SYSOPCall[0] == 0) - strcpy(SYSOPCall, BBSName); - - // See if just want to add user (mainly for setup scripts) - - if (argc == 5 && _stricmp(argv[1], "--adduser") == 0) - { - BOOL isBBS = FALSE; - char * response; - - if (_stricmp(argv[4], "TRUE") == 0) - isBBS = TRUE; - - printf("Adding User %s\r\n", argv[2]); - response = AddUser(argv[2], argv[3], isBBS); - printf("%s", response); - exit(0); - } - // Allocate Streams - - strcpy(pgm, "BBS"); - - for (i=0; i < MaxStreams; i++) - { - conn = &Connections[i]; - conn->BPQStream = FindFreeStream(); - - if (conn->BPQStream == 255) break; - - NumberofStreams++; - - // BPQSetHandle(conn->BPQStream, hWnd); - - SetAppl(conn->BPQStream, (i == 0 && EnableUI) ? 0x82 : 2, BBSApplMask); - Disconnect(conn->BPQStream); - } - - strcpy(pgm, "LINBPQ"); - - InitialiseTCP(); - InitialiseNNTP(); - - SetupListenSet(); // Master set of listening sockets - - if (EnableUI || MailForInterval) - SetupUIInterface(); - - if (MailForInterval) - _beginthread(SendMailForThread, 0, 0); - - - // Calulate time to run Housekeeping - { - struct tm *tm; - time_t now; - - now = time(NULL); - - tm = gmtime(&now); - - tm->tm_hour = MaintTime / 100; - tm->tm_min = MaintTime % 100; - tm->tm_sec = 0; - - MaintClock = mktime(tm) - (time_t)_MYTIMEZONE; - - while (MaintClock < now) - MaintClock += MaintInterval * 3600; - - Debugprintf("Maint Clock %lld NOW %lld Time to HouseKeeping %lld", (long long)MaintClock, (long long)now, (long long)(MaintClock - now)); - - if (LastHouseKeepingTime) - { - if ((now - LastHouseKeepingTime) > MaintInterval * 3600) - { - DoHouseKeeping(FALSE); - } - } - for (i = optind; i < argc; i++) - - { - if (_stricmp(argv[i], "tidymail") == 0) - DeleteRedundantMessages(); - - if (_stricmp(argv[i], "nohomebbs") == 0) - DontNeedHomeBBS = TRUE; - } - - printf("Mail Started\n"); - Logprintf(LOG_BBS, NULL, '!', "Mail Starting"); - - APIClock = 0; - - SendBBSDataToPktMap(); - - } - } - - if (NUMBEROFTNCPORTS) - InitializeTNCEmulator(); - - AGWActive = AGWAPIInit(); - - if (Redirected == 0) - ConTerm.BPQStream = FindFreeStream(); - - -#ifndef WIN32 - - for (i = 1; i < argc; i++) - { - if (_stricmp(argv[i], "daemon") == 0) - { - - // Convert to daemon - - pid_t pid, sid; - - /* Fork off the parent process */ - pid = fork(); - - if (pid < 0) - exit(EXIT_FAILURE); - - if (pid > 0) - exit(EXIT_SUCCESS); - - /* Change the file mode mask */ - - umask(0); - - /* Create a new SID for the child process */ - - sid = setsid(); - - if (sid < 0) - exit(EXIT_FAILURE); - - /* Change the current working directory */ - - if ((chdir("/")) < 0) - exit(EXIT_FAILURE); - - /* Close out the standard file descriptors */ - - printf("Entering daemon mode\n"); - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - break; - } - } -#endif - - while (KEEPGOING) - { - Sleep(100); - GetSemaphore(&Semaphore, 2); - - if (QCOUNT < 10) - { - if (CLOSING == FALSE) - FindLostBuffers(); - CLOSING = TRUE; - } - - if (CLOSING) - { - if (RunChat) - { - CloseChat(); - RunChat = FALSE; - } - - if (RunMail) - { - int BPQStream, n; - - RunMail = FALSE; - - for (n = 0; n < NumberofStreams; n++) - { - BPQStream = Connections[n].BPQStream; - - if (BPQStream) - { - SetAppl(BPQStream, 0, 0); - Disconnect(BPQStream); - DeallocateStream(BPQStream); - } - } - -// SaveUserDatabase(); - SaveMessageDatabase(); - SaveBIDDatabase(); - SaveConfig(ConfigName); - } - - KEEPGOING--; // Give time for links to close - setbuf(stdout, NULL); - printf("Closing... %d \r", KEEPGOING); - } - - - if (RigReconfigFlag) - { - RigReconfigFlag = FALSE; - Rig_Close(); - Sleep(2000); // Allow CATPTT threads to close - RigActive = Rig_Init(); - - Consoleprintf("Rigcontrol Reconfiguration Complete"); - } - - if (APRSReconfigFlag) - { - APRSReconfigFlag = FALSE; - APRSClose(); - APRSActive = Init_APRS(); - - Consoleprintf("APRS Reconfiguration Complete"); - } - - if (ReconfigFlag) - { - int i; - BPQVECSTRUC * HOSTVEC; - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - - ReconfigFlag = FALSE; - -// SetupBPQDirectory(); - - WritetoConsoleLocal("Reconfiguring ...\n\n"); - OutputDebugString("BPQ32 Reconfiguring ...\n"); - - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { -// SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); -// SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); -// CloseDriverWindow(PORTVEC->PORTCONTROL.PORTNUMBER); - PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); // Close External Ports - } - } - PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL); - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - IPClose(); - APRSClose(); - Rig_Close(); - CloseTNCEmulator(); - - if (AGWActive) - AGWAPITerminate(); - - WL2KReports = NULL; - -// Sleep(2000); - - Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - Consoleprintf(VerCopyright); - - Start(); - - INITIALISEPORTS(); - - SetApplPorts(); - - GetUIConfig(); - - FreeConfig(); - - for (i=1; i<68; i++) // Include Telnet, APRS, IP Vec - { - HOSTVEC=&BPQHOSTVECTOR[i-1]; - - HOSTVEC->HOSTTRACEQ=0; - - if (HOSTVEC->HOSTSESSION !=0) - { - // Had a connection - - HOSTVEC->HOSTSESSION=0; - HOSTVEC->HOSTFLAGS |=3; // Disconnected - -// PostMessage(HOSTVEC->HOSTHANDLE, BPQMsg, i, 4); - } - } - - OpenReportingSockets(); - - WritetoConsoleLocal("\n\nReconfiguration Complete\n"); - - if (IPRequired) IPActive = Init_IP(); - - APRSActive = Init_APRS(); - - if (ISPort == 0) - IGateEnabled = 0; - - RigActive = Rig_Init(); - - if (NUMBEROFTNCPORTS) - { - FreeSemaphore(&Semaphore); - InitializeTNCEmulator(); - GetSemaphore(&Semaphore, 2); - } - - FreeSemaphore(&Semaphore); - AGWActive = AGWAPIInit(); - GetSemaphore(&Semaphore, 2); - - OutputDebugString("BPQ32 Reconfiguration Complete\n"); - } - - if (IPActive) Poll_IP(); - if (RigActive) Rig_Poll(); - if (APRSActive) Poll_APRS(); - CheckWL2KReportTimer(); - - TIMERINTERRUPT(); - - FreeSemaphore(&Semaphore); - - if (Redirected == 0) - ConTermPoll(); - - if (NUMBEROFTNCPORTS) - TNCTimer(); - - if (AGWActive) - Poll_AGW(); - - DRATSPoll(); - RHPPoll(); - - HTTPTimer(); - - if (ReportTimer) - { - ReportTimer--; - - if (ReportTimer == 0) - { - ReportTimer = REPORTINTERVAL; - SendLocation(); - } - } - - Slowtimer++; - - if (RunChat) - { - ChatPollStreams(); - ChatTrytoSend(); - - if (Slowtimer > 100) // 10 secs - { - ChatTimer(); - } - } - - if (RunMail) - { - PollStreams(); - - if ((Slowtimer % 20) == 0) - FWDTimerProc(); - - if (Slowtimer > 100) // 10 secs - { - time_t NOW = time(NULL); - struct tm * tm; - - TCPTimer(); - BBSSlowTimer(); - - if (MaintClock < NOW) - { - while (MaintClock < NOW) // in case large time step - MaintClock += MaintInterval * 3600; - - Debugprintf("|Enter HouseKeeping"); - DoHouseKeeping(FALSE); - } - - if (APIClock < NOW) - { - SendBBSDataToPktMap(); - APIClock = NOW + 7200; // Every 2 hours - } - - - tm = gmtime(&NOW); - - if (tm->tm_wday == 0) // Sunday - { - if (GenerateTrafficReport && (LastTrafficTime + 86400) < NOW) - { - CreateBBSTrafficReport(); - LastTrafficTime = NOW; - } - } - } - TCPFastTimer(); - TrytoSend(); - } - - if (Slowtimer > 100) - Slowtimer = 0; - } - - printf("Closing Ports\n"); - - CloseTNCEmulator(); - - if (AGWActive) - AGWAPITerminate(); - - if (needAIS) - SaveAIS(); - - // Close Ports - - PORTVEC=(PEXTPORTDATA)PORTTABLE; - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { - PORTVEC->PORT_EXT_ADDR(5, PORTVEC->PORTCONTROL.PORTNUMBER, NULL); - } - } - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - if (AUTOSAVE) - SaveNodes(); - - if (AUTOSAVEMH) - SaveMH(); - - if (IPActive) - IPClose(); - - if (RunMail) - FreeWebMailMallocs(); - - upnpClose(); - - // Close any open logs - - for (i = 0; i < 4; i++) - { - if (LogHandle[i]) - fclose(LogHandle[i]); - } - - return 0; -} - -int APIENTRY WritetoConsole(char * buff) -{ - return WritetoConsoleLocal(buff); -} - -int WritetoConsoleLocal(char * buff) -{ - return printf("%s", buff); -} - -#ifdef WIN32 -void * VCOMExtInit(struct PORTCONTROL * PortEntry); -void * V4ExtInit(EXTPORTDATA * PortEntry); -#endif -//UINT SoundModemExtInit(EXTPORTDATA * PortEntry); -//UINT BaycomExtInit(EXTPORTDATA * PortEntry); - -void * AEAExtInit(struct PORTCONTROL * PortEntry); -void * MPSKExtInit(EXTPORTDATA * PortEntry); -void * HALExtInit(struct PORTCONTROL * PortEntry); - -void * AGWExtInit(struct PORTCONTROL * PortEntry); -void * KAMExtInit(struct PORTCONTROL * PortEntry); -void * WinmorExtInit(EXTPORTDATA * PortEntry); -void * SCSExtInit(struct PORTCONTROL * PortEntry); -void * TrackerExtInit(EXTPORTDATA * PortEntry); -void * TrackerMExtInit(EXTPORTDATA * PortEntry); - -void * TelnetExtInit(EXTPORTDATA * PortEntry); -void * UZ7HOExtInit(EXTPORTDATA * PortEntry); -void * FLDigiExtInit(EXTPORTDATA * PortEntry); -void * ETHERExtInit(struct PORTCONTROL * PortEntry); -void * AXIPExtInit(struct PORTCONTROL * PortEntry); -void * ARDOPExtInit(EXTPORTDATA * PortEntry); -void * VARAExtInit(EXTPORTDATA * PortEntry); -void * SerialExtInit(EXTPORTDATA * PortEntry); -void * WinRPRExtInit(EXTPORTDATA * PortEntry); -void * HSMODEMExtInit(EXTPORTDATA * PortEntry); -void * FreeDataExtInit(EXTPORTDATA * PortEntry); -void * KISSHFExtInit(EXTPORTDATA * PortEntry); - -void * InitializeExtDriver(PEXTPORTDATA PORTVEC) -{ - // Only works with built in drivers - - UCHAR Value[20]; - - strcpy(Value,PORTVEC->PORT_DLL_NAME); - - _strupr(Value); - -#ifndef FREEBSD -#ifndef MACBPQ - if (strstr(Value, "BPQETHER")) - return ETHERExtInit; -#endif -#endif - if (strstr(Value, "BPQAXIP")) - return AXIPExtInit; - - if (strstr(Value, "BPQTOAGW")) - return AGWExtInit; - - if (strstr(Value, "AEAPACTOR")) - return AEAExtInit; - - if (strstr(Value, "HALDRIVER")) - return HALExtInit; - -#ifdef WIN32 - - if (strstr(Value, "BPQVKISS")) - return VCOMExtInit; - - if (strstr(Value, "V4")) - return V4ExtInit; - -#endif -/* - if (strstr(Value, "SOUNDMODEM")) - return (UINT) SoundModemExtInit; - - if (strstr(Value, "BAYCOM")) - return (UINT) BaycomExtInit; -*/ - if (strstr(Value, "MULTIPSK")) - return MPSKExtInit; - - if (strstr(Value, "KAMPACTOR")) - return KAMExtInit; - - if (strstr(Value, "WINMOR")) - return WinmorExtInit; - - if (strstr(Value, "SCSPACTOR")) - return SCSExtInit; - - if (strstr(Value, "SCSTRACKER")) - return TrackerExtInit; - - if (strstr(Value, "TRKMULTI")) - return TrackerMExtInit; - - if (strstr(Value, "UZ7HO")) - return UZ7HOExtInit; - - if (strstr(Value, "FLDIGI")) - return FLDigiExtInit; - - if (strstr(Value, "TELNET")) - return TelnetExtInit; - - if (strstr(Value, "ARDOP")) - return ARDOPExtInit; - - if (strstr(Value, "VARA")) - return VARAExtInit; - - if (strstr(Value, "KISSHF")) - return KISSHFExtInit; - - if (strstr(Value, "SERIAL")) - return SerialExtInit; - - if (strstr(Value, "WINRPR")) - return WinRPRExtInit; - - if (strstr(Value, "HSMODEM")) - return HSMODEMExtInit; - - if (strstr(Value, "FREEDATA")) - return FreeDataExtInit; - - return(0); -} - -int APIENTRY Restart() -{ - CLOSING = TRUE; - return TRUE; -} - -int APIENTRY Reboot() -{ - // Run sudo shutdown -r -f -#ifdef WIN32 - STARTUPINFO SInfo; - PROCESS_INFORMATION PInfo; - char Cmd[] = "shutdown -r -f"; - - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - return CreateProcess(NULL, Cmd, NULL, NULL, FALSE,0 ,NULL ,NULL, &SInfo, &PInfo); - return 0; -#else - - char * arg_list[] = {NULL, NULL, NULL, NULL, NULL}; - pid_t child_pid; - char * Context; - signal(SIGCHLD, SIG_IGN); // Silently (and portably) reap children. - - arg_list[0] = "sudo"; - arg_list[1] = "shutdown"; - arg_list[2] = "now"; - arg_list[3] = "-r"; - - // Fork and Exec shutdown - - // Duplicate this process. - - child_pid = fork(); - - if (child_pid == -1) - { - printf ("Reboot 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 shutdown\n"); - exit(0); // Kill the new process - } - return TRUE; -#endif - -} - -int APIENTRY Reconfig() -{ - if (!ProcessConfig()) - { - return (0); - } - SaveNodes(); - WritetoConsoleLocal("Nodes Saved\n"); - ReconfigFlag=TRUE; - WritetoConsoleLocal("Reconfig requested ... Waiting for Timer Poll\n"); - return 1; -} - -int APRSWriteLog(char * msg); - -VOID MonitorAPRSIS(char * Msg, size_t MsgLen, BOOL TX) -{ - char Line[300]; - char Copy[300]; - int Len; - struct tm * TM; - time_t NOW; - - if (LogAPRSIS == 0) - return; - - if (MsgLen > 250) - return; - - // Mustn't change Msg - - memcpy(Copy, Msg, MsgLen); - Copy[MsgLen] = 0; - - NOW = time(NULL); - TM = gmtime(&NOW); - - Len = sprintf_s(Line, 299, "%02d:%02d:%02d%c %s", TM->tm_hour, TM->tm_min, TM->tm_sec, (TX)? 'T': 'R', Copy); - - APRSWriteLog(Line); - -} - -struct TNCINFO * TNC; - -#ifndef WIN32 - -#include -#include - -#ifndef MACBPQ -#ifdef __MACH__ - -#include - -#define CLOCK_REALTIME 0 -#define CLOCK_MONOTONIC 0 - - - -int clock_gettime(int clk_id, struct timespec *t){ - mach_timebase_info_data_t timebase; - mach_timebase_info(&timebase); - uint64_t time; - time = mach_absolute_time(); - double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom); - double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9); - t->tv_sec = seconds; - t->tv_nsec = nseconds; - return 0; -} -#endif -#endif - - -uint64_t GetTickCount() -{ - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000); -} - - - -void SetWindowText(HWND hWnd, char * lpString) -{ - return; -}; - -BOOL SetDlgItemText(HWND hWnd, int item, char * lpString) -{ - return 0; -}; - -#endif - -int GetListeningPortsPID(int Port) -{ -#ifdef WIN32 - - MIB_TCPTABLE_OWNER_PID * TcpTable = NULL; - PMIB_TCPROW_OWNER_PID Row; - int dwSize = 0; - unsigned int n; - - // Get PID of process for this TCP Port - - // Get Length of table - - GetExtendedTcpTable(TcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0); - - TcpTable = malloc(dwSize); - GetExtendedTcpTable(TcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0); - - for (n = 0; n < TcpTable->dwNumEntries; n++) - { - Row = &TcpTable->table[n]; - - if (Row->dwLocalPort == Port && Row->dwState == MIB_TCP_STATE_LISTEN) - { - return Row->dwOwningPid; - break; - } - } -#endif - return 0; // Not found -} - - - -VOID Check_Timer() -{ -} - -VOID POSTDATAAVAIL(){}; - -COLORREF Colours[256] = {0, - RGB(0,0,0), RGB(0,0,128), RGB(0,0,192), RGB(0,0,255), // 1 - 4 - RGB(0,64,0), RGB(0,64,128), RGB(0,64,192), RGB(0,64,255), // 5 - 8 - RGB(0,128,0), RGB(0,128,128), RGB(0,128,192), RGB(0,128,255), // 9 - 12 - RGB(0,192,0), RGB(0,192,128), RGB(0,192,192), RGB(0,192,255), // 13 - 16 - RGB(0,255,0), RGB(0,255,128), RGB(0,255,192), RGB(0,255,255), // 17 - 20 - - RGB(6425,0,0), RGB(64,0,128), RGB(64,0,192), RGB(0,0,255), // 21 - RGB(64,64,0), RGB(64,64,128), RGB(64,64,192), RGB(64,64,255), - RGB(64,128,0), RGB(64,128,128), RGB(64,128,192), RGB(64,128,255), - RGB(64,192,0), RGB(64,192,128), RGB(64,192,192), RGB(64,192,255), - RGB(64,255,0), RGB(64,255,128), RGB(64,255,192), RGB(64,255,255), - - RGB(128,0,0), RGB(128,0,128), RGB(128,0,192), RGB(128,0,255), // 41 - RGB(128,64,0), RGB(128,64,128), RGB(128,64,192), RGB(128,64,255), - RGB(128,128,0), RGB(128,128,128), RGB(128,128,192), RGB(128,128,255), - RGB(128,192,0), RGB(128,192,128), RGB(128,192,192), RGB(128,192,255), - RGB(128,255,0), RGB(128,255,128), RGB(128,255,192), RGB(128,255,255), - - RGB(192,0,0), RGB(192,0,128), RGB(192,0,192), RGB(192,0,255), // 61 - RGB(192,64,0), RGB(192,64,128), RGB(192,64,192), RGB(192,64,255), - RGB(192,128,0), RGB(192,128,128), RGB(192,128,192), RGB(192,128,255), - RGB(192,192,0), RGB(192,192,128), RGB(192,192,192), RGB(192,192,255), - RGB(192,255,0), RGB(192,255,128), RGB(192,255,192), RGB(192,255,255), - - RGB(255,0,0), RGB(255,0,128), RGB(255,0,192), RGB(255,0,255), // 81 - RGB(255,64,0), RGB(255,64,128), RGB(255,64,192), RGB(255,64,255), - RGB(255,128,0), RGB(255,128,128), RGB(255,128,192), RGB(255,128,255), - RGB(255,192,0), RGB(255,192,128), RGB(255,192,192), RGB(255,192,255), - RGB(255,255,0), RGB(255,255,128), RGB(255,255,192), RGB(255,255,255) -}; - - -//VOID SendRPBeacon(struct TNCINFO * TNC) -//{ -//} - -int PollStreams() -{ - int state,change; - ConnectionInfo * conn; - int n; - struct UserInfo * user = NULL; - char ConnectedMsg[] = "*** CONNECTED "; - - for (n = 0; n < NumberofStreams; n++) - { - conn = &Connections[n]; - - DoReceivedData(conn->BPQStream); - DoBBSMonitorData(conn->BPQStream); - - SessionState(conn->BPQStream, &state, &change); - - if (change == 1) - { - if (state == 1) // Connected - { - GetSemaphore(&ConSemaphore, 0); - Connected(conn->BPQStream); - FreeSemaphore(&ConSemaphore); - } - else - { - GetSemaphore(&ConSemaphore, 0); - Disconnected(conn->BPQStream); - FreeSemaphore(&ConSemaphore); - } - } - } - - return 0; -} - - -VOID CloseConsole(int Stream) -{ -} - -#ifndef WIN32 - -int V4ProcessReceivedData(struct TNCINFO * TNC) -{ - return 0; -} -#endif - -#ifdef FREEBSD - -char * gcvt(double _Val, int _NumOfDigits, char * _DstBuf) -{ - sprintf(_DstBuf, "%f", _Val); - return _DstBuf; -} - -#endif - - - - - diff --git a/MULTIPSK.c b/MULTIPSK.c index 6f2a9ac..3fb81c1 100644 --- a/MULTIPSK.c +++ b/MULTIPSK.c @@ -710,7 +710,7 @@ void * MPSKExtInit(EXTPORTDATA * PortEntry) ptr=strchr(TNC->NodeCall, ' '); if (ptr) *(ptr) = 0; // Null Terminate - TNC->Hardware = H_MPSK; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_MPSK; MPSKChannel[port] = PortEntry->PORTCONTROL.CHANNELNUM-65; diff --git a/Moncode.c b/Moncode.c index c725d0f..1de165b 100644 --- a/Moncode.c +++ b/Moncode.c @@ -728,6 +728,10 @@ char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen) return Output + sprintf((char *)Output, " "); + case L4RESET: + + return Output + sprintf((char *)Output, " "); + case L4INFO: { char Infofield[257]; @@ -746,6 +750,9 @@ char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen) if (Flags & L4MORE) *(Output++) = 'M'; + if (Flags & L4COMP) + *(Output++) = 'C'; + MsgLen = MsgLen - (19 + sizeof(void *)); if (MsgLen < 0 || MsgLen > 257) diff --git a/RHP-skigdebian.c b/RHP-skigdebian.c deleted file mode 100644 index 611e8c7..0000000 --- a/RHP-skigdebian.c +++ /dev/null @@ -1,641 +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 -*/ - -/* - - Paula (G8PZT)'s Remote Host Protocol interface. - For now only sufficient support for WhatsPac - - -*/ -#define _CRT_SECURE_NO_DEPRECATE - -#include "cheaders.h" -#include "bpq32.h" - -int FindFreeStreamNoSem(); -DllExport int APIENTRY DeallocateStream(int stream); -int SendMsgNoSem(int stream, char * msg, int len); - -static void GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value, int Len); -static int GetJSONInt(char * _REPLYBUFFER, char * Name); - -// Generally Can have multiple RHP connections and each can have multiple RHF Sessions - -struct RHPSessionInfo -{ - SOCKET Socket; // Websocks Socket - int BPQStream; - int Handle; // RHP session ID - int Seq; - char Local[12]; - char Remote[12]; - BOOL Connecting; // Set while waiting for connection to complete - BOOL Listening; - BOOL Connected; -}; - -struct RHPConnectionInfo -{ - SOCKET socket; - struct RHPSessionInfo ** RHPSessions; - int NumberofRHPSessions; -}; - - -struct RHPConnectionInfo ** RHPSockets = NULL; -int NumberofRHPConnections = 0; - -struct RHPSessionInfo ** RHPSessions; -int NumberofRHPSessions; - -char ErrCodes[18][24] = -{"Ok", "Unspecified", "Bad or missing type", "Invalid handle", "No memory", "Bad or missing mode", - - "Invalid local address", - "Invalid remote address" , - "Bad or missing family" , - "Duplicate socket" , - "No such port" , - "Invalid protocol" , - "Bad parameter" , - "No buffers" , - "Unauthorised" , - "No Route" , - "Operation not supported"}; - - - - -extern char pgm[256]; - -SOCKET agwsock; - -extern int SemHeldByAPI; - -char szBuff[80]; - -int WhatsPacConfigured = 1; - - -int RHPPaclen = 236; - - -int processRHCPOpen(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer); -int processRHCPSend(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer); -int processRHCPClose(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer); - - - -void SendWebSockMessage(SOCKET socket, char * Msg, int Len) -{ - int Loops = 0; - int Sent; - int TxLen; - char * OutBuffer = Msg; - - // WebSock Encode. Buffer has 10 bytes on front for header but header len depends on Msg len - - - if (Len < 126) - { - // Two Byte Header - - OutBuffer[8] = 0x81; // Fin, Data - OutBuffer[9] = Len; - - TxLen = Len + 2; - OutBuffer = &Msg[8]; - } - else if (Len < 65536) - { - OutBuffer[6] = 0x81; // Fin, Data - OutBuffer[7] = 126; // Unmasked, Extended Len 16 - OutBuffer[8] = Len >> 8; - OutBuffer[9] = Len & 0xff; - TxLen = Len + 4; - OutBuffer = &Msg[6]; - } - else - { - OutBuffer[0] = 0x81; // Fin, Data - OutBuffer[1] = 127; // Unmasked, Extended Len 64 bits - // Len is 32 bits, so pad with zeros - OutBuffer[2] = 0; - OutBuffer[3] = 0; - OutBuffer[4] = 0; - OutBuffer[5] = 0; - OutBuffer[6] = (Len >> 24) & 0xff; - OutBuffer[7] = (Len >> 16) & 0xff; - OutBuffer[8] = (Len >> 8) & 0xff; - OutBuffer[9] = Len & 0xff; - - TxLen = Len + + 10; - OutBuffer = &Msg[0]; - } - - // Send may block - - Sent = send(socket, OutBuffer, TxLen, 0); - - while (Sent != TxLen && Loops++ < 3000) // 100 secs max - { - if (Sent > 0) // something sent - { - TxLen -= Sent; - memmove(OutBuffer, &OutBuffer[Sent], TxLen); - } - - Sleep(30); - Sent = send(socket, OutBuffer, TxLen, 0); - if (Sent == -1) - break; - } - - free(Msg); - return; -} - - - - -int RHPProcessHTTPMessage(struct ConnectionInfo * conn, char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE) -{ - // RHP messages can be sent over Websocks or normal http but I think WhatsPac only uses WebSocks - return 0; -} - - -void ProcessRHPWebSock(SOCKET socket, char * Msg, int MsgLen) -{ - int Loops = 0; - int InputLen = 0; - int Len; - - char Value[16]; - char * OutBuffer = malloc(250000); - - struct RHPConnectionInfo * RHPSocket = NULL; - int n; - - Msg[MsgLen] = 0; - - // Find Connection Record. If none, create one - - for (n = 0; n < NumberofRHPConnections; n++) - { - if (RHPSockets[n]->socket == socket) - { - RHPSocket = RHPSockets[n]; - break; - } - } - - if (RHPSocket == 0) - { - NumberofRHPConnections; - RHPSockets = realloc(RHPSockets, sizeof(void *) * (NumberofRHPConnections + 1)); - RHPSocket = RHPSockets[NumberofRHPConnections] = zalloc(sizeof (struct RHPConnectionInfo)); - NumberofRHPConnections++; - RHPSocket->socket = socket; - } - - -// {"type":"open","id":5,"pfam":"ax25","mode":"stream","port":"1","local":"G8BPQ","remote":"G8BPQ-2","flags":128} -// {"type": "openReply", "id": 82, "handle": 1, "errCode": 0, "errText": "Ok"} -// {"seqno": 0, "type": "status", "handle": 1, "flags": 0} -// ("seqno": 1, "type": "close", "handle": 1} -// {"id":40,"type":"close","handle":1} - -// {"seqno": 0, "type": "status", "handle": 1, "flags": 2}.~. -// {"seqno": 1, "type": "recv", "handle": 1, "data": "Welcome to G8BPQ's Test Switch in Nottingham \rType ? for list of available commands.\r"}. - - GetJSONValue(Msg, "\"type\":", Value, 15); - - if (_stricmp(Value, "open") == 0) - { - Len = processRHCPOpen(RHPSocket, Msg, &OutBuffer[10]); // Space at front for WebSock Header - if (Len) - SendWebSockMessage(RHPSocket->socket, OutBuffer, Len); - return; - } - - if (_stricmp(Value, "send") == 0) - { - Len = processRHCPSend(RHPSocket, Msg, &OutBuffer[10]); // Space at front for WebSock Header - SendWebSockMessage(RHPSocket->socket, OutBuffer, Len); - return; - } - - if (_stricmp(Value, "close") == 0) - { - Len = processRHCPClose(RHPSocket, Msg, &OutBuffer[10]); // Space at front for WebSock Header - SendWebSockMessage(RHPSocket->socket, OutBuffer, Len); - return; - } - Debugprintf(Msg); -} - -void ProcessRHPWebSockClosed(SOCKET socket) -{ - // Close any connections on this scoket and delete socket entry - - struct RHPConnectionInfo * RHPSocket = NULL; - int n; - - // Find Connection Record. CLear any Sessions - - for (n = 0; n < NumberofRHPConnections; n++) - { - if (RHPSockets[n]->socket == socket) - { - RHPSocket = RHPSockets[n]; - - break; - } - } -} - - - -int processRHCPOpen(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer) -{ - //{"type":"open","id":5,"pfam":"ax25","mode":"stream","port":"1","local":"G8BPQ","remote":"G8BPQ-2","flags":128} - - struct RHPSessionInfo * RHPSession = 0; - - char * Value = malloc(strlen(Msg)); // Will always be long enough - int ID; - - char pfam[16]; - char Mode[16]; - int Port; - char Local[16]; - char Remote[16]; - int flags; - int Handle = 1; - int Stream; - unsigned char AXCall[10]; - int Len; - int n; - - // ID seems to be used for control commands like open. SeqNo for data within a session (i Think! - - ID = GetJSONInt(Msg, "\"id\":"); - GetJSONValue(Msg, "\"pfam\":", pfam, 15); - GetJSONValue(Msg, "\"mode\":", Mode, 15); - Port = GetJSONInt(Msg, "\"port\":"); - GetJSONValue(Msg, "\"local\":", Local, 15); - GetJSONValue(Msg, "\"remote\":", Remote, 15); - flags = GetJSONInt(Msg, "\"flags\":"); - - if (_stricmp(pfam, "ax25") != 0) - return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0); - - if (_stricmp(Mode, "stream") == 0) - { - { - // Allocate a RHP Session - - // See if there is an old one we can reuse - - for (n = 0; n < NumberofRHPSessions; n++) - { - if (RHPSessions[n]->BPQStream == 0) - { - RHPSession = RHPSessions[n]; - Handle = n + 1; - Stream = RHPSessions[n]->BPQStream; - - break; - } - } - - if (RHPSession == 0) - { - RHPSessions = realloc(RHPSessions, sizeof(void *) * (NumberofRHPSessions + 1)); - RHPSession = RHPSessions[NumberofRHPSessions] = zalloc(sizeof (struct RHPSessionInfo)); - NumberofRHPSessions++; - - Handle = NumberofRHPSessions; - } - - strcpy(pgm, "RHP"); - Stream = FindFreeStreamNoSem(); - strcpy(pgm, "bpq32.exe"); - - if (Stream == 255) - return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0); - - RHPSession->BPQStream = Stream; - RHPSession->Handle = Handle; - RHPSession->Connecting = TRUE; - RHPSession->Socket = RHPSocket->socket; - - strcpy(RHPSession->Local, Local); - strcpy(RHPSession->Remote, Remote); - - Connect(Stream); - - ConvToAX25(Local, AXCall); - ChangeSessionCallsign(Stream, AXCall); - - return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 0, \"errText\": \"Ok\"}", ID, Handle); - } - } - return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0); -} - -int processRHCPSend(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer) -{ - // {"type":"send","handle":1,"data":";;;;;;\r","id":70} - - struct RHPSessionInfo * RHPSession; - - int ID; - char * Data; - char * ptr; - int c; - int Len; - - int Handle = 1; - - Data = malloc(strlen(Msg)); - - ID = GetJSONInt(Msg, "\"id\":"); - Handle = GetJSONInt(Msg, "\"handle\":"); - GetJSONValue(Msg, "\"data\":", Data, strlen(Msg) - 1); - - if (Handle < 1 || Handle > NumberofRHPSessions) - { - free(Data); - return sprintf(ReplyBuffer, "{\"type\": \"sendReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errtext\": \"Invalid handle\"}", ID, Handle); - } - - RHPSession = RHPSessions[Handle - 1]; - - // Look for \ escapes - - ptr = Data; - - while (ptr = strchr(ptr, '\\')) - { - c = ptr[1]; - - switch (c) - { - case 'r': - - *ptr = 13; - break; - - case '\\': - - *ptr = '\\'; - break; - - case '"': - - *ptr = '"'; - break; - } - memmove(ptr + 1, ptr + 2, strlen(ptr + 1)); - ptr++; - } - - Debugprintf(Data); - - Len = strlen(Data); - ptr = Data; - - - while (Len > RHPPaclen) - { - SendMsgNoSem(RHPSession->BPQStream, ptr, RHPPaclen); - Len -= RHPPaclen; - ptr += RHPPaclen; - } - - SendMsgNoSem(RHPSession->BPQStream, ptr, Len); - - free(Data); - return sprintf(ReplyBuffer, "{\"type\": \"sendReply\", \"id\": %d, \"handle\": %d, \"errCode\": 0, \"errText\": \"Ok\", \"status\": %d}", ID, Handle, 2); -} - - -int processRHCPClose(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer) -{ - - // {"id":70,"type":"close","handle":1} - - - struct RHPSessionInfo * RHPSession; - - int ID; - int Handle = 1; - - char * OutBuffer = malloc(256); - - ID = GetJSONInt(Msg, "\"id\":"); - Handle = GetJSONInt(Msg, "\"handle\":"); - - if (Handle < 1 || Handle > NumberofRHPSessions) - return sprintf(ReplyBuffer, "{\"id\": %d, \"type\": \"closeReply\", \"handle\": %d, \"errcode\": 12, \"errtext\": \"Invalid handle\"}", ID, Handle); - - - RHPSession = RHPSessions[Handle - 1]; - Disconnect(RHPSession->BPQStream); - RHPSession->Connected = 0; - RHPSession->Connecting = 0; - - DeallocateStream(RHPSession->BPQStream); - RHPSession->BPQStream = 0; - - return sprintf(ReplyBuffer, "{\"id\": %d, \"type\": \"closeReply\", \"handle\": %d, \"errcode\": 0, \"errtext\": \"Ok\"}", ID, Handle); -} - - - -void RHPPoll() -{ - int Stream; - int n; - int state, change; - int Len; - char * RHPMsg; - unsigned char Buffer[1024]; // Space to escape control chars - int pktlen, count; - - struct RHPSessionInfo * RHPSession; - - for (n = 0; n < NumberofRHPSessions; n++) - { - RHPSession = RHPSessions[n]; - Stream = RHPSession->BPQStream; - - // See if connected state has changed - - SessionState(Stream, &state, &change); - - if (change == 1) - { - if (state == 1) - { - // Connected - - RHPSession->Seq = 0; - RHPSession->Connecting = FALSE; - RHPSession->Connected = TRUE; - - RHPMsg = malloc(256); - Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"status\", \"handle\": %d, \"flags\": 2}", RHPSession->Seq++, RHPSession->Handle); - SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); - - // Send RHP CTEXT - - RHPMsg = malloc(256); - Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"recv\", \"handle\": %d, \"data\": \"Connected to RHP Server\\r\"}", RHPSession->Seq++, RHPSession->Handle); - SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); - } - else - { - // Disconnected. Send Close to client - - RHPMsg = malloc(256); - Len = sprintf(&RHPMsg[10], "{\"type\": \"close\", \"seqno\": %d, \"handle\": %d}", RHPSession->Seq++, RHPSession->Handle); - SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); - - RHPSession->Connected = 0; - RHPSession->Connecting = 0; - - DeallocateStream(RHPSession->BPQStream); - RHPSession->BPQStream = 0; - } - } - do - { - GetMsg(Stream, Buffer, &pktlen, &count); - - if (pktlen > 0) - { - char * ptr = Buffer; - char c; - - Buffer[pktlen] = 0; - - // Message is JSON so Convert CR to \r, \ to \\ " to \" - - while (c = *(ptr)) - { - switch (c) - { - case 13: - - memmove(ptr + 2, ptr + 1, strlen(ptr)); - *(ptr++) = '\\'; - *(ptr++) = 'r'; - break; - - case '"': - - memmove(ptr + 2, ptr + 1, strlen(ptr)); - *(ptr++) = '\\'; - *(ptr++) = '"'; - break; - - case '\\': - - memmove(ptr + 2, ptr + 1, strlen(ptr)); - *(ptr++) = '\\'; - *(ptr++) = '\\'; - break; - } - ptr++; - } - - - RHPMsg = malloc(1024); - - Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"recv\", \"handle\": %d, \"data\": \"%s\"}", RHPSession->Seq++, RHPSession->Handle, Buffer); - SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); - - } - - } - while (count > 0); - - } -} - - - -static void GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value, int Len) -{ - char * ptr1, * ptr2; - - Value[0] = 0; - - ptr1 = strstr(_REPLYBUFFER, Name); - - if (ptr1 == 0) - return; - - ptr1 += (strlen(Name) + 1); - -// "data":"{\"t\":\"c\",\"n\":\"John\",\"c\":\"G8BPQ\",\"lm\":1737912636,\"le\":1737883907,\"led\":1737758451,\"v\":0.33,\"cc\":[{\"cid\":1,\"lp\":1737917257201,\"le\":1737913735726,\"led\":1737905249785},{\"cid\":0,\"lp\":1737324074107,\"le\":1737323831510,\"led\":1737322973662},{\"cid\":5,\"lp\":1737992107419,\"le\":1737931466510,\"led\":1737770056244}]}\r","id":28} - - // There may be escaped " in data stream - - ptr2 = strchr(ptr1, '"'); - - while (*(ptr2 - 1) == '\\') - { - ptr2 = strchr(ptr2 + 2, '"'); - } - - - if (ptr2) - { - size_t ValLen = ptr2 - ptr1; - if (ValLen > Len) - ValLen = Len; - - memcpy(Value, ptr1, ValLen); - Value[ValLen] = 0; - } - - return; -} - - -static int GetJSONInt(char * _REPLYBUFFER, char * Name) -{ - char * ptr1; - - ptr1 = strstr(_REPLYBUFFER, Name); - - if (ptr1 == 0) - return 0; - - ptr1 += (strlen(Name)); - - return atoi(ptr1); -} - - diff --git a/RHP.c b/RHP.c index b7002be..18b933d 100644 --- a/RHP.c +++ b/RHP.c @@ -1,711 +1,756 @@ -/* -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 -*/ - -/* - - Paula (G8PZT)'s Remote Host Protocol interface. - For now only sufficient support for WhatsPac - - -*/ -#define _CRT_SECURE_NO_DEPRECATE - -#include "cheaders.h" -#include "bpq32.h" - -int FindFreeStreamNoSem(); -DllExport int APIENTRY DeallocateStream(int stream); -int SendMsgNoSem(int stream, char * msg, int len); - -static void GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value, int Len); -static int GetJSONInt(char * _REPLYBUFFER, char * Name); - -// Generally Can have multiple RHP connections and each can have multiple RHF Sessions - -struct RHPSessionInfo -{ - SOCKET Socket; // Websocks Socket - int BPQStream; - int Handle; // RHP session ID - int Seq; - char Local[12]; - char Remote[12]; - BOOL Connecting; // Set while waiting for connection to complete - BOOL Listening; - BOOL Connected; -}; - -struct RHPConnectionInfo -{ - SOCKET socket; - struct RHPSessionInfo ** RHPSessions; - int NumberofRHPSessions; -}; - -// Struct passed by beginhread - -struct RHPParamBlock -{ - unsigned char * Msg; - int Len; - SOCKET Socket; -}; - - - -//struct RHPConnectionInfo ** RHPSockets = NULL; -//int NumberofRHPConnections = 0; - -struct RHPSessionInfo ** RHPSessions; -int NumberofRHPSessions; - -char ErrCodes[18][24] = -{"Ok", "Unspecified", "Bad or missing type", "Invalid handle", "No memory", "Bad or missing mode", - - "Invalid local address", - "Invalid remote address" , - "Bad or missing family" , - "Duplicate socket" , - "No such port" , - "Invalid protocol" , - "Bad parameter" , - "No buffers" , - "Unauthorised" , - "No Route" , - "Operation not supported"}; - - - - -extern char pgm[256]; - -SOCKET agwsock; - -extern int SemHeldByAPI; - -char szBuff[80]; - -int WhatsPacConfigured = 1; - - -int RHPPaclen = 236; - - -int processRHCPOpen(SOCKET Socket, char * Msg, char * ReplyBuffer); -int processRHCPSend(SOCKET Socket, char * Msg, char * ReplyBuffer); -int processRHCPClose(SOCKET Socket, char * Msg, char * ReplyBuffer); - - - -void SendWebSockMessage(SOCKET socket, char * Msg, int Len) -{ - int Loops = 0; - int Sent; - int TxLen; - char * OutBuffer = Msg; - - // WebSock Encode. Buffer has 10 bytes on front for header but header len depends on Msg len - - - if (Len < 126) - { - // Two Byte Header - - OutBuffer[8] = 0x81; // Fin, Data - OutBuffer[9] = Len; - - TxLen = Len + 2; - OutBuffer = &Msg[8]; - } - else if (Len < 65536) - { - OutBuffer[6] = 0x81; // Fin, Data - OutBuffer[7] = 126; // Unmasked, Extended Len 16 - OutBuffer[8] = Len >> 8; - OutBuffer[9] = Len & 0xff; - TxLen = Len + 4; - OutBuffer = &Msg[6]; - } - else - { - OutBuffer[0] = 0x81; // Fin, Data - OutBuffer[1] = 127; // Unmasked, Extended Len 64 bits - // Len is 32 bits, so pad with zeros - OutBuffer[2] = 0; - OutBuffer[3] = 0; - OutBuffer[4] = 0; - OutBuffer[5] = 0; - OutBuffer[6] = (Len >> 24) & 0xff; - OutBuffer[7] = (Len >> 16) & 0xff; - OutBuffer[8] = (Len >> 8) & 0xff; - OutBuffer[9] = Len & 0xff; - - TxLen = Len + + 10; - OutBuffer = &Msg[0]; - } - - // Send may block - - Sent = send(socket, OutBuffer, TxLen, 0); - - while (Sent != TxLen && Loops++ < 3000) // 100 secs max - { - if (Sent > 0) // something sent - { - TxLen -= Sent; - memmove(OutBuffer, &OutBuffer[Sent], TxLen); - } - - Sleep(30); - Sent = send(socket, OutBuffer, TxLen, 0); - if (Sent == -1) - break; - } - - free(Msg); - return; -} - -void ProcessRHPWebSock(SOCKET Socket, char * Msg, int MsgLen); - -void RHPThread(void * Params) -{ - // Params and data buffer are malloced blocks so free when done with it - - struct RHPParamBlock * Block = (struct RHPParamBlock *)Params; - - ProcessRHPWebSock(Block->Socket, Block->Msg, Block->Len); - - free(Block->Msg); - free(Params); -} - -int RHPProcessHTTPMessage(void * conn, char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE) -{ - // RHP messages can be sent over Websocks or normal http but I think WhatsPac only uses WebSocks - return 0; -} - -void ProcessRHPWebSock(SOCKET Socket, char * Msg, int MsgLen) -{ - int Loops = 0; - int InputLen = 0; - int Len; - - char Value[16]; - char * OutBuffer = malloc(250000); - -// struct RHPConnectionInfo * RHPSocket = NULL; -// int n; - - Msg[MsgLen] = 0; - - // Find Connection Record. If none, create one - - // I dont think I need connection records - -/* - for (n = 0; n < NumberofRHPConnections; n++) - { - if (RHPSockets[n]->socket == socket) - { - RHPSocket = RHPSockets[n]; - break; - } - } - - if (RHPSocket == 0) - { - // See if there is an old one we can reuse - - for (n = 0; n < NumberofRHPConnections; n++) - { - if (RHPSockets[n]-Socket == -1) - { - RHPSocket = RHPSockets[n]; - RHP - - break; - } - } - - if (RHPSocket == 0) - - NumberofRHPConnections; - RHPSockets = realloc(RHPSockets, sizeof(void *) * (NumberofRHPConnections + 1)); - RHPSocket = RHPSockets[NumberofRHPConnections] = zalloc(sizeof (struct RHPConnectionInfo)); - NumberofRHPConnections++; - RHPSocket->socket = socket; - } -*/ - -// {"type":"open","id":5,"pfam":"ax25","mode":"stream","port":"1","local":"G8BPQ","remote":"G8BPQ-2","flags":128} -// {"type": "openReply", "id": 82, "handle": 1, "errCode": 0, "errText": "Ok"} -// {"seqno": 0, "type": "status", "handle": 1, "flags": 0} -// ("seqno": 1, "type": "close", "handle": 1} -// {"id":40,"type":"close","handle":1} - -// {"seqno": 0, "type": "status", "handle": 1, "flags": 2}.~. -// {"seqno": 1, "type": "recv", "handle": 1, "data": "Welcome to G8BPQ's Test Switch in Nottingham \rType ? for list of available commands.\r"}. - - GetJSONValue(Msg, "\"type\":", Value, 15); - - if (_stricmp(Value, "open") == 0) - { - Len = processRHCPOpen(Socket, Msg, &OutBuffer[10]); // Space at front for WebSock Header - if (Len) - SendWebSockMessage(Socket, OutBuffer, Len); - return; - } - - if (_stricmp(Value, "send") == 0) - { - Len = processRHCPSend(Socket, Msg, &OutBuffer[10]); // Space at front for WebSock Header - SendWebSockMessage(Socket, OutBuffer, Len); - return; - } - - if (_stricmp(Value, "close") == 0) - { - Len = processRHCPClose(Socket, Msg, &OutBuffer[10]); // Space at front for WebSock Header - SendWebSockMessage(Socket, OutBuffer, Len); - return; - } - Debugprintf(Msg); -} - -void ProcessRHPWebSockClosed(SOCKET socket) -{ - // Close any connections on this scoket and delete socket entry - - struct RHPSessionInfo * RHPSession = 0; - int n; - - // Find and close any Sessions - - for (n = 0; n < NumberofRHPSessions; n++) - { - if (RHPSessions[n]->Socket == socket) - { - RHPSession = RHPSessions[n]; - - if (RHPSession->BPQStream) - { - Disconnect(RHPSession->BPQStream); - DeallocateStream(RHPSession->BPQStream); - - RHPSession->BPQStream = 0; - - } - - RHPSession->Connecting = 0; - - // We can't send a close to RHP endpont as socket has gone - - RHPSession->Connected = 0; - } - } -} - - - - -int processRHCPOpen(SOCKET Socket, char * Msg, char * ReplyBuffer) -{ - //{"type":"open","id":5,"pfam":"ax25","mode":"stream","port":"1","local":"G8BPQ","remote":"G8BPQ-2","flags":128} - - struct RHPSessionInfo * RHPSession = 0; - - char * Value = malloc(strlen(Msg)); // Will always be long enough - int ID; - - char pfam[16]; - char Mode[16]; - int Port; - char Local[16]; - char Remote[16]; - int flags; - int Handle = 1; - int Stream; - unsigned char AXCall[10]; - int Len; - int n; - - // ID seems to be used for control commands like open. SeqNo for data within a session (i Think! - - ID = GetJSONInt(Msg, "\"id\":"); - GetJSONValue(Msg, "\"pfam\":", pfam, 15); - GetJSONValue(Msg, "\"mode\":", Mode, 15); - Port = GetJSONInt(Msg, "\"port\":"); - GetJSONValue(Msg, "\"local\":", Local, 15); - GetJSONValue(Msg, "\"remote\":", Remote, 15); - flags = GetJSONInt(Msg, "\"flags\":"); - - if (_stricmp(pfam, "ax25") != 0) - return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0); - - if (_stricmp(Mode, "stream") == 0) - { - { - // Allocate a RHP Session - - // See if there is an old one we can reuse - - for (n = 0; n < NumberofRHPSessions; n++) - { - if (RHPSessions[n]->BPQStream == 0) - { - RHPSession = RHPSessions[n]; - Handle = n + 1; - Stream = RHPSessions[n]->BPQStream; - - break; - } - } - - if (RHPSession == 0) - { - RHPSessions = realloc(RHPSessions, sizeof(void *) * (NumberofRHPSessions + 1)); - RHPSession = RHPSessions[NumberofRHPSessions] = zalloc(sizeof (struct RHPSessionInfo)); - NumberofRHPSessions++; - - Handle = NumberofRHPSessions; - } - - strcpy(pgm, "RHP"); - Stream = FindFreeStreamNoSem(); - strcpy(pgm, "bpq32.exe"); - - if (Stream == 255) - return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0); - - RHPSession->BPQStream = Stream; - RHPSession->Handle = Handle; - RHPSession->Connecting = TRUE; - RHPSession->Socket = Socket; - - strcpy(RHPSession->Local, Local); - strcpy(RHPSession->Remote, Remote); - - Connect(Stream); - - ConvToAX25(Local, AXCall); - ChangeSessionCallsign(Stream, AXCall); - - return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 0, \"errText\": \"Ok\"}", ID, Handle); - } - } - return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0); -} - -int processRHCPSend(SOCKET Socket, char * Msg, char * ReplyBuffer) -{ - // {"type":"send","handle":1,"data":";;;;;;\r","id":70} - - struct RHPSessionInfo * RHPSession; - - int ID; - char * Data; - char * ptr; - int c; - int Len; - - int Handle = 1; - - Data = malloc(strlen(Msg)); - - ID = GetJSONInt(Msg, "\"id\":"); - Handle = GetJSONInt(Msg, "\"handle\":"); - GetJSONValue(Msg, "\"data\":", Data, strlen(Msg) - 1); - - if (Handle < 1 || Handle > NumberofRHPSessions) - { - free(Data); - return sprintf(ReplyBuffer, "{\"type\": \"sendReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errtext\": \"Invalid handle\"}", ID, Handle); - } - - RHPSession = RHPSessions[Handle - 1]; - - // Look for \ escapes - - ptr = Data; - - while (ptr = strchr(ptr, '\\')) - { - c = ptr[1]; - - switch (c) - { - case 'r': - - *ptr = 13; - break; - - case '\\': - - *ptr = '\\'; - break; - - case '"': - - *ptr = '"'; - break; - } - memmove(ptr + 1, ptr + 2, strlen(ptr + 1)); - ptr++; - } - - Debugprintf(Data); - - Len = strlen(Data); - ptr = Data; - - - while (Len > RHPPaclen) - { - SendMsgNoSem(RHPSession->BPQStream, ptr, RHPPaclen); - Len -= RHPPaclen; - ptr += RHPPaclen; - } - - SendMsgNoSem(RHPSession->BPQStream, ptr, Len); - - free(Data); - return sprintf(ReplyBuffer, "{\"type\": \"sendReply\", \"id\": %d, \"handle\": %d, \"errCode\": 0, \"errText\": \"Ok\", \"status\": %d}", ID, Handle, 2); -} - - -int processRHCPClose(SOCKET Socket, char * Msg, char * ReplyBuffer) -{ - - // {"id":70,"type":"close","handle":1} - - - struct RHPSessionInfo * RHPSession; - - int ID; - int Handle = 1; - - char * OutBuffer = malloc(256); - - ID = GetJSONInt(Msg, "\"id\":"); - Handle = GetJSONInt(Msg, "\"handle\":"); - - if (Handle < 1 || Handle > NumberofRHPSessions) - return sprintf(ReplyBuffer, "{\"id\": %d, \"type\": \"closeReply\", \"handle\": %d, \"errcode\": 12, \"errtext\": \"Invalid handle\"}", ID, Handle); - - - RHPSession = RHPSessions[Handle - 1]; - Disconnect(RHPSession->BPQStream); - RHPSession->Connected = 0; - RHPSession->Connecting = 0; - - DeallocateStream(RHPSession->BPQStream); - RHPSession->BPQStream = 0; - - return sprintf(ReplyBuffer, "{\"id\": %d, \"type\": \"closeReply\", \"handle\": %d, \"errcode\": 0, \"errtext\": \"Ok\"}", ID, Handle); -} - -char toHex[] = "0123456789abcdef"; - -void RHPPoll() -{ - int Stream; - int n; - int state, change; - int Len; - char * RHPMsg; - unsigned char Buffer[2048]; // Space to escape control chars - int pktlen, count; - - struct RHPSessionInfo * RHPSession; - - for (n = 0; n < NumberofRHPSessions; n++) - { - RHPSession = RHPSessions[n]; - Stream = RHPSession->BPQStream; - - // See if connected state has changed - - SessionState(Stream, &state, &change); - - if (change == 1) - { - if (state == 1) - { - // Connected - - RHPSession->Seq = 0; - RHPSession->Connecting = FALSE; - RHPSession->Connected = TRUE; - - RHPMsg = malloc(256); - Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"status\", \"handle\": %d, \"flags\": 2}", RHPSession->Seq++, RHPSession->Handle); - SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); - - // Send RHP CTEXT - - RHPMsg = malloc(256); - Sleep(10); // otherwise WhatsPac doesn't display connected - Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"recv\", \"handle\": %d, \"data\": \"Connected to RHP Server\\r\"}", RHPSession->Seq++, RHPSession->Handle); - SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); - } - else - { - // Disconnected. Send Close to client - - RHPMsg = malloc(256); - Len = sprintf(&RHPMsg[10], "{\"type\": \"close\", \"seqno\": %d, \"handle\": %d}", RHPSession->Seq++, RHPSession->Handle); - SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); - - RHPSession->Connected = 0; - RHPSession->Connecting = 0; - - DeallocateStream(RHPSession->BPQStream); - RHPSession->BPQStream = 0; - } - } - do - { - GetMsg(Stream, Buffer, &pktlen, &count); - - if (pktlen > 0) - { - char * ptr = Buffer; - unsigned char c; - - Buffer[pktlen] = 0; - - // Message is JSON so Convert CR to \r, \ to \\ " to \" - - // Looks like I need to escape everything not between 0x20 and 0x7f eg \U00c3 - - - while (c = *(ptr)) - { - switch (c) - { - case 13: - - memmove(ptr + 2, ptr + 1, strlen(ptr) + 1); - *(ptr++) = '\\'; - *(ptr++) = 'r'; - break; - - case '"': - - memmove(ptr + 2, ptr + 1, strlen(ptr) + 1); - *(ptr++) = '\\'; - *(ptr++) = '"'; - break; - - case '\\': - - memmove(ptr + 2, ptr + 1, strlen(ptr) + 1); - *(ptr++) = '\\'; - *(ptr++) = '\\'; - break; - - default: - - if (c > 127) - { - memmove(ptr + 6, ptr + 1, strlen(ptr) + 1); - *(ptr++) = '\\'; - *(ptr++) = 'u'; - *(ptr++) = '0'; - *(ptr++) = '0'; - *(ptr++) = toHex[c >> 4]; - *(ptr++) = toHex[c & 15]; - break; - } - else - ptr++; - } - } - - RHPMsg = malloc(2048); - - Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"recv\", \"handle\": %d, \"data\": \"%s\"}", RHPSession->Seq++, RHPSession->Handle, Buffer); - SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); - - } - - } - while (count > 0); - - } -} - - - -static void GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value, int Len) -{ - char * ptr1, * ptr2; - - Value[0] = 0; - - ptr1 = strstr(_REPLYBUFFER, Name); - - if (ptr1 == 0) - return; - - ptr1 += (strlen(Name) + 1); - -// "data":"{\"t\":\"c\",\"n\":\"John\",\"c\":\"G8BPQ\",\"lm\":1737912636,\"le\":1737883907,\"led\":1737758451,\"v\":0.33,\"cc\":[{\"cid\":1,\"lp\":1737917257201,\"le\":1737913735726,\"led\":1737905249785},{\"cid\":0,\"lp\":1737324074107,\"le\":1737323831510,\"led\":1737322973662},{\"cid\":5,\"lp\":1737992107419,\"le\":1737931466510,\"led\":1737770056244}]}\r","id":28} - - // There may be escaped " in data stream - - ptr2 = strchr(ptr1, '"'); - - while (*(ptr2 - 1) == '\\') - { - ptr2 = strchr(ptr2 + 2, '"'); - } - - - if (ptr2) - { - size_t ValLen = ptr2 - ptr1; - if (ValLen > Len) - ValLen = Len; - - memcpy(Value, ptr1, ValLen); - Value[ValLen] = 0; - } - - return; -} - - -static int GetJSONInt(char * _REPLYBUFFER, char * Name) -{ - char * ptr1; - - ptr1 = strstr(_REPLYBUFFER, Name); - - if (ptr1 == 0) - return 0; - - ptr1 += (strlen(Name)); - - return atoi(ptr1); -} - - +/* +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 +*/ + +/* + + Paula (G8PZT)'s Remote Host Protocol interface. + For now only sufficient support for WhatsPac + + +*/ +#define _CRT_SECURE_NO_DEPRECATE + +#include "cheaders.h" +#include "bpq32.h" +#include "telnetserver.h" + +int FindFreeStreamNoSem(); +DllExport int APIENTRY DeallocateStream(int stream); +int SendMsgNoSem(int stream, char * msg, int len); + +static void GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value, int Len); +static int GetJSONInt(char * _REPLYBUFFER, char * Name); + +// Generally Can have multiple RHP connections and each can have multiple RHF Sessions + +struct RHPSessionInfo +{ + struct ConnectionInfo * sockptr; + SOCKET Socket; // Websocks Socket + int BPQStream; + int Handle; // RHP session ID + int Seq; + char Local[12]; + char Remote[12]; + BOOL Connecting; // Set while waiting for connection to complete + BOOL Listening; + BOOL Connected; + int Busy; +}; + +struct RHPConnectionInfo +{ + SOCKET socket; + struct RHPSessionInfo ** RHPSessions; + int NumberofRHPSessions; +}; + +// Struct passed by beginhread + +struct RHPParamBlock +{ + unsigned char * Msg; + int Len; + SOCKET Socket; + struct ConnectionInfo * sockptr; +}; + + + +//struct RHPConnectionInfo ** RHPSockets = NULL; +//int NumberofRHPConnections = 0; + +struct RHPSessionInfo ** RHPSessions; +int NumberofRHPSessions; + +char ErrCodes[18][24] = +{ + "Ok", + "Unspecified", + "Bad or missing type", + "Invalid handle", + "No memory", + "Bad or missing mode", + "Invalid local address", + "Invalid remote address" , + "Bad or missing family" , + "Duplicate socket" , + "No such port" , + "Invalid protocol" , + "Bad parameter" , + "No buffers" , + "Unauthorised" , + "No Route" , + "Operation not supported"}; + + + + +extern char pgm[256]; + +SOCKET agwsock; + +extern int SemHeldByAPI; + +char szBuff[80]; + +int WhatsPacConfigured = 1; + + +int RHPPaclen = 236; + + +int processRHCPOpen(struct ConnectionInfo * sockptr, SOCKET Socket, char * Msg, char * ReplyBuffer); +int processRHCPSend(SOCKET Socket, char * Msg, char * ReplyBuffer); +int processRHCPClose(SOCKET Socket, char * Msg, char * ReplyBuffer); +int processRHCPStatus(SOCKET Socket, char * Msg, char * ReplyBuffer); + + + +void SendWebSockMessage(SOCKET socket, char * Msg, int Len) +{ + int Loops = 0; + int Sent; + int TxLen; + char * OutBuffer = Msg; + + // WebSock Encode. Buffer has 10 bytes on front for header but header len depends on Msg len + + if (Len < 126) + { + // Two Byte Header + + OutBuffer[8] = 0x81; // Fin, Data + OutBuffer[9] = Len; + + TxLen = Len + 2; + OutBuffer = &Msg[8]; + } + else if (Len < 65536) + { + OutBuffer[6] = 0x81; // Fin, Data + OutBuffer[7] = 126; // Unmasked, Extended Len 16 + OutBuffer[8] = Len >> 8; + OutBuffer[9] = Len & 0xff; + TxLen = Len + 4; + OutBuffer = &Msg[6]; + } + else + { + OutBuffer[0] = 0x81; // Fin, Data + OutBuffer[1] = 127; // Unmasked, Extended Len 64 bits + // Len is 32 bits, so pad with zeros + OutBuffer[2] = 0; + OutBuffer[3] = 0; + OutBuffer[4] = 0; + OutBuffer[5] = 0; + OutBuffer[6] = (Len >> 24) & 0xff; + OutBuffer[7] = (Len >> 16) & 0xff; + OutBuffer[8] = (Len >> 8) & 0xff; + OutBuffer[9] = Len & 0xff; + + TxLen = Len + + 10; + OutBuffer = &Msg[0]; + } + + // Send may block + + Sent = send(socket, OutBuffer, TxLen, 0); + + while (Sent != TxLen && Loops++ < 3000) // 100 secs max + { + if (Sent > 0) // something sent + { + TxLen -= Sent; + memmove(OutBuffer, &OutBuffer[Sent], TxLen); + } + + Sleep(30); + Sent = send(socket, OutBuffer, TxLen, 0); + if (Sent == -1) + break; + } + + free(Msg); + return; +} + +void ProcessRHPWebSock(struct ConnectionInfo * sockptr, SOCKET Socket, char * Msg, int MsgLen); + +void RHPThread(void * Params) +{ + // Params and data buffer are malloced blocks so free when done with it + + struct RHPParamBlock * Block = (struct RHPParamBlock *)Params; + + ProcessRHPWebSock(Block->sockptr, Block->Socket, Block->Msg, Block->Len); + + free(Block->Msg); + free(Params); +} + +int RHPProcessHTTPMessage(void * conn, char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE) +{ + // RHP messages can be sent over Websocks or normal http but I think WhatsPac only uses WebSocks + return 0; +} + +void ProcessRHPWebSock(struct ConnectionInfo * sockptr, SOCKET Socket, char * Msg, int MsgLen) +{ + int Loops = 0; + int InputLen = 0; + int Len; + + char Value[16]; + char * OutBuffer = malloc(250000); + +// struct RHPConnectionInfo * RHPSocket = NULL; +// int n; + + Msg[MsgLen] = 0; + + // Find Connection Record. If none, create one + + // I dont think I need connection records + +/* + for (n = 0; n < NumberofRHPConnections; n++) + { + if (RHPSockets[n]->socket == socket) + { + RHPSocket = RHPSockets[n]; + break; + } + } + + if (RHPSocket == 0) + { + // See if there is an old one we can reuse + + for (n = 0; n < NumberofRHPConnections; n++) + { + if (RHPSockets[n]-Socket == -1) + { + RHPSocket = RHPSockets[n]; + RHP + + break; + } + } + + if (RHPSocket == 0) + + NumberofRHPConnections; + RHPSockets = realloc(RHPSockets, sizeof(void *) * (NumberofRHPConnections + 1)); + RHPSocket = RHPSockets[NumberofRHPConnections] = zalloc(sizeof (struct RHPConnectionInfo)); + NumberofRHPConnections++; + RHPSocket->socket = socket; + } +*/ + +// {"type":"open","id":5,"pfam":"ax25","mode":"stream","port":"1","local":"G8BPQ","remote":"G8BPQ-2","flags":128} +// {"type": "openReply", "id": 82, "handle": 1, "errCode": 0, "errText": "Ok"} +// {"seqno": 0, "type": "status", "handle": 1, "flags": 0} +// ("seqno": 1, "type": "close", "handle": 1} +// {"id":40,"type":"close","handle":1} + +// {"seqno": 0, "type": "status", "handle": 1, "flags": 2}.~. +// {"seqno": 1, "type": "recv", "handle": 1, "data": "Welcome to G8BPQ's Test Switch in Nottingham \rType ? for list of available commands.\r"}. + +// {"type": "status", "handle": 0}. XRouter will reply with {"type": "statusReply", "handle": 0, "errcode": 12, "errtext": "invalid handle"}. It +// {type: 'keepalive'} if there has been no other activity for nearly 3 minutes. Replies with {"type": "keepaliveReply"} + + GetJSONValue(Msg, "\"type\":", Value, 15); + + if (_stricmp(Value, "open") == 0) + { + Len = processRHCPOpen(sockptr, Socket, Msg, &OutBuffer[10]); // Space at front for WebSock Header + if (Len) + SendWebSockMessage(Socket, OutBuffer, Len); + return; + } + + if (_stricmp(Value, "send") == 0) + { + Len = processRHCPSend(Socket, Msg, &OutBuffer[10]); // Space at front for WebSock Header + SendWebSockMessage(Socket, OutBuffer, Len); + return; + } + + if (_stricmp(Value, "close") == 0) + { + Len = processRHCPClose(Socket, Msg, &OutBuffer[10]); // Space at front for WebSock Header + SendWebSockMessage(Socket, OutBuffer, Len); + return; + } + + if (_stricmp(Value, "status") == 0) + { + Len = processRHCPStatus(Socket, Msg, &OutBuffer[10]); // Space at front for WebSock Header + SendWebSockMessage(Socket, OutBuffer, Len); + return; + } + + if (_stricmp(Value, "keepalive") == 0) + { + Len = sprintf(&OutBuffer[10], "{\"type\": \"keepaliveReply\"}"); // Space at front for WebSock Header + SendWebSockMessage(Socket, OutBuffer, Len); + return; + } + + Debugprintf("Unrecognised RHP Message - %s", Msg); +} + +void ProcessRHPWebSockClosed(SOCKET socket) +{ + // Close any connections on this scoket and delete socket entry + + struct RHPSessionInfo * RHPSession = 0; + int n; + + // Find and close any Sessions + + for (n = 0; n < NumberofRHPSessions; n++) + { + if (RHPSessions[n]->Socket == socket) + { + RHPSession = RHPSessions[n]; + + if (RHPSession->BPQStream) + { + Disconnect(RHPSession->BPQStream); + DeallocateStream(RHPSession->BPQStream); + + RHPSession->BPQStream = 0; + + } + + RHPSession->Connecting = 0; + + // We can't send a close to RHP endpont as socket has gone + + RHPSession->Connected = 0; + } + } +} + + + + +int processRHCPOpen(struct ConnectionInfo * sockptr, SOCKET Socket, char * Msg, char * ReplyBuffer) +{ + //{"type":"open","id":5,"pfam":"ax25","mode":"stream","port":"1","local":"G8BPQ","remote":"G8BPQ-2","flags":128} + + struct RHPSessionInfo * RHPSession = 0; + + char * Value = malloc(strlen(Msg)); // Will always be long enough + int ID; + + char pfam[16]; + char Mode[16]; + int Port; + char Local[16]; + char Remote[16]; + int flags; + int Handle = 1; + int Stream; + unsigned char AXCall[10]; + + int n; + + // ID seems to be used for control commands like open. SeqNo for data within a session (i Think! + + ID = GetJSONInt(Msg, "\"id\":"); + GetJSONValue(Msg, "\"pfam\":", pfam, 15); + GetJSONValue(Msg, "\"mode\":", Mode, 15); + Port = GetJSONInt(Msg, "\"port\":"); + GetJSONValue(Msg, "\"local\":", Local, 15); + GetJSONValue(Msg, "\"remote\":", Remote, 15); + flags = GetJSONInt(Msg, "\"flags\":"); + + if (_stricmp(pfam, "ax25") != 0) + return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0); + + if (_stricmp(Mode, "stream") == 0) + { + { + // Allocate a RHP Session + + // See if there is an old one we can reuse + + for (n = 0; n < NumberofRHPSessions; n++) + { + if (RHPSessions[n]->BPQStream == 0) + { + RHPSession = RHPSessions[n]; + Handle = n + 1; + Stream = RHPSessions[n]->BPQStream; + + break; + } + } + + if (RHPSession == 0) + { + RHPSessions = realloc(RHPSessions, sizeof(void *) * (NumberofRHPSessions + 1)); + RHPSession = RHPSessions[NumberofRHPSessions] = zalloc(sizeof (struct RHPSessionInfo)); + NumberofRHPSessions++; + + Handle = NumberofRHPSessions; + } + + strcpy(pgm, "RHP"); + Stream = FindFreeStream(); + strcpy(pgm, "bpq32.exe"); + + if (Stream == 255) + return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0); + + RHPSession->BPQStream = Stream; + RHPSession->Handle = Handle; + RHPSession->Connecting = TRUE; + RHPSession->Socket = Socket; + RHPSession->sockptr = sockptr; + + strcpy(RHPSession->Local, Local); + strcpy(RHPSession->Remote, Remote); + + Connect(Stream); + + ConvToAX25(Local, AXCall); + ChangeSessionCallsign(Stream, AXCall); + + return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 0, \"errText\": \"Ok\"}", ID, Handle); + } + } + return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0); +} + +int processRHCPSend(SOCKET Socket, char * Msg, char * ReplyBuffer) +{ + // {"type":"send","handle":1,"data":";;;;;;\r","id":70} + + struct RHPSessionInfo * RHPSession; + + int ID; + char * Data; + char * ptr; + int c; + int Len; + + int Handle = 1; + + Data = malloc(strlen(Msg)); + + ID = GetJSONInt(Msg, "\"id\":"); + Handle = GetJSONInt(Msg, "\"handle\":"); + GetJSONValue(Msg, "\"data\":", Data, strlen(Msg) - 1); + + if (Handle < 1 || Handle > NumberofRHPSessions) + { + free(Data); + return sprintf(ReplyBuffer, "{\"type\": \"sendReply\", \"id\": %d, \"handle\": %d, \"errCode\": 3, \"errtext\": \"Invalid handle\"}", ID, Handle); + } + + RHPSession = RHPSessions[Handle - 1]; + + // Look for \ escapes + + ptr = Data; + + while (ptr = strchr(ptr, '\\')) + { + c = ptr[1]; + + switch (c) + { + case 'r': + + *ptr = 13; + break; + + case '\\': + + *ptr = '\\'; + break; + + case '"': + + *ptr = '"'; + break; + } + memmove(ptr + 1, ptr + 2, strlen(ptr + 1)); + ptr++; + } + + Len = strlen(Data); + ptr = Data; + + while (Len > RHPPaclen) + { + SendMsg(RHPSession->BPQStream, ptr, RHPPaclen); + Len -= RHPPaclen; + ptr += RHPPaclen; + } + + SendMsg(RHPSession->BPQStream, ptr, Len); + + free(Data); + return sprintf(ReplyBuffer, "{\"type\": \"sendReply\", \"id\": %d, \"handle\": %d, \"errCode\": 0, \"errText\": \"Ok\", \"status\": %d}", ID, Handle, 2); +} + + +int processRHCPClose(SOCKET Socket, char * Msg, char * ReplyBuffer) +{ + + // {"id":70,"type":"close","handle":1} + + + struct RHPSessionInfo * RHPSession; + + int ID; + int Handle = 1; + + char * OutBuffer = malloc(256); + + ID = GetJSONInt(Msg, "\"id\":"); + Handle = GetJSONInt(Msg, "\"handle\":"); + + if (Handle < 1 || Handle > NumberofRHPSessions) + return sprintf(ReplyBuffer, "{\"id\": %d, \"type\": \"closeReply\", \"handle\": %d, \"errcode\": 3, \"errtext\": \"Invalid handle\"}", ID, Handle); + + + RHPSession = RHPSessions[Handle - 1]; + Disconnect(RHPSession->BPQStream); + RHPSession->Connected = 0; + RHPSession->Connecting = 0; + + DeallocateStream(RHPSession->BPQStream); + RHPSession->BPQStream = 0; + + return sprintf(ReplyBuffer, "{\"id\": %d, \"type\": \"closeReply\", \"handle\": %d, \"errcode\": 0, \"errtext\": \"Ok\"}", ID, Handle); +} + +int processRHCPStatus(SOCKET Socket, char * Msg, char * ReplyBuffer) +{ + // {"type": "status", "handle": 0}. XRouter will reply with {"type": "statusReply", "handle": 0, "errcode": 3, "errtext": "invalid handle"}. It + + struct RHPSessionInfo * RHPSession; + int Handle = 0; + + Handle = GetJSONInt(Msg, "\"handle\":"); + + if (Handle < 1 || Handle > NumberofRHPSessions) + return sprintf(ReplyBuffer, "{\"type\": \"statusReply\", \"handle\": %d, \"errcode\": 3, \"errtext\": \"Invalid handle\"}", Handle); + + RHPSession = RHPSessions[Handle - 1]; + + return sprintf(ReplyBuffer, "{\"type\": \"status\", \"handle\": %d, \"flags\": 2}", RHPSession->Handle); + +} + +char toHex[] = "0123456789abcdef"; + +void RHPPoll() +{ + int Stream; + int n; + int state, change; + int Len; + char * RHPMsg; + unsigned char Buffer[2048]; // Space to escape control chars + int pktlen, count; + + struct RHPSessionInfo * RHPSession; + + for (n = 0; n < NumberofRHPSessions; n++) + { + RHPSession = RHPSessions[n]; + Stream = RHPSession->BPQStream; + + // See if connected state has changed + + SessionState(Stream, &state, &change); + + if (change == 1) + { + if (state == 1) + { + // Connected + + RHPSession->Seq = 0; + RHPSession->Connecting = FALSE; + RHPSession->Connected = TRUE; + + RHPMsg = malloc(256); + Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"status\", \"handle\": %d, \"flags\": 2}", RHPSession->Seq++, RHPSession->Handle); + SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); + + // Send RHP CTEXT + + RHPMsg = malloc(256); + Sleep(10); // otherwise WhatsPac doesn't display connected + Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"recv\", \"handle\": %d, \"data\": \"Connected to RHP Server\\r\"}", RHPSession->Seq++, RHPSession->Handle); + SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); + } + else + { + // Disconnected. Send Close to client + + RHPMsg = malloc(256); + Len = sprintf(&RHPMsg[10], "{\"type\": \"close\", \"seqno\": %d, \"handle\": %d}", RHPSession->Seq++, RHPSession->Handle); + SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); + + RHPSession->Connected = 0; + RHPSession->Connecting = 0; + + DeallocateStream(RHPSession->BPQStream); + RHPSession->BPQStream = 0; + } + } + do + { + GetMsg(Stream, Buffer, &pktlen, &count); + + if (pktlen > 0) + { + char * ptr = Buffer; + unsigned char c; + + Buffer[pktlen] = 0; + + RHPSession->sockptr->LastSendTime = time(NULL); + + + // Message is JSON so Convert CR to \r, \ to \\ " to \" + + // Looks like I need to escape everything not between 0x20 and 0x7f eg \U00c3 + + + while (c = *(ptr)) + { + switch (c) + { + case 13: + + memmove(ptr + 2, ptr + 1, strlen(ptr) + 1); + *(ptr++) = '\\'; + *(ptr++) = 'r'; + break; + + case '"': + + memmove(ptr + 2, ptr + 1, strlen(ptr) + 1); + *(ptr++) = '\\'; + *(ptr++) = '"'; + break; + + case '\\': + + memmove(ptr + 2, ptr + 1, strlen(ptr) + 1); + *(ptr++) = '\\'; + *(ptr++) = '\\'; + break; + + default: + + if (c > 127) + { + memmove(ptr + 6, ptr + 1, strlen(ptr) + 1); + *(ptr++) = '\\'; + *(ptr++) = 'u'; + *(ptr++) = '0'; + *(ptr++) = '0'; + *(ptr++) = toHex[c >> 4]; + *(ptr++) = toHex[c & 15]; + break; + } + else + ptr++; + } + } + + RHPMsg = malloc(2048); + + Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"recv\", \"handle\": %d, \"data\": \"%s\"}", RHPSession->Seq++, RHPSession->Handle, Buffer); + SendWebSockMessage(RHPSession->Socket, RHPMsg, Len); + + } + + } + while (count > 0); + } +} + + + +static void GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value, int Len) +{ + char * ptr1, * ptr2; + + Value[0] = 0; + + ptr1 = strstr(_REPLYBUFFER, Name); + + if (ptr1 == 0) + return; + + ptr1 += (strlen(Name) + 1); + +// "data":"{\"t\":\"c\",\"n\":\"John\",\"c\":\"G8BPQ\",\"lm\":1737912636,\"le\":1737883907,\"led\":1737758451,\"v\":0.33,\"cc\":[{\"cid\":1,\"lp\":1737917257201,\"le\":1737913735726,\"led\":1737905249785},{\"cid\":0,\"lp\":1737324074107,\"le\":1737323831510,\"led\":1737322973662},{\"cid\":5,\"lp\":1737992107419,\"le\":1737931466510,\"led\":1737770056244}]}\r","id":28} + + // There may be escaped " in data stream + + ptr2 = strchr(ptr1, '"'); + + while (*(ptr2 - 1) == '\\') + { + ptr2 = strchr(ptr2 + 2, '"'); + } + + + if (ptr2) + { + size_t ValLen = ptr2 - ptr1; + if (ValLen > Len) + ValLen = Len; + + memcpy(Value, ptr1, ValLen); + Value[ValLen] = 0; + } + + return; +} + + +static int GetJSONInt(char * _REPLYBUFFER, char * Name) +{ + char * ptr1; + + ptr1 = strstr(_REPLYBUFFER, Name); + + if (ptr1 == 0) + return 0; + + ptr1 += (strlen(Name)); + + return atoi(ptr1); +} + + diff --git a/SCSPactor.c b/SCSPactor.c index bca138a..5a6de7a 100644 --- a/SCSPactor.c +++ b/SCSPactor.c @@ -854,7 +854,8 @@ void * SCSExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; - TNC->Hardware = H_SCS; + TNC->PortRecord = PortEntry; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_SCS; OpenLogFile(TNC->Port); CloseLogFile(TNC->Port); @@ -885,8 +886,6 @@ void * SCSExtInit(EXTPORTDATA * PortEntry) PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream PortEntry->SCANCAPABILITIES = CONLOCK; // Scan Control 3 stage/conlock - TNC->PortRecord = PortEntry; - if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; diff --git a/SCSTrackeMulti.c b/SCSTrackeMulti.c index 590a61a..110a4e3 100644 --- a/SCSTrackeMulti.c +++ b/SCSTrackeMulti.c @@ -376,7 +376,8 @@ void * TrackerMExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; - TNC->Hardware = H_TRKM; + TNC->PortRecord = PortEntry; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_TRKM; // Set up DED addresses for streams @@ -392,8 +393,6 @@ void * TrackerMExtInit(EXTPORTDATA * PortEntry) PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream PortEntry->SCANCAPABILITIES = NONE; // Scan Control 3 stage/conlock - TNC->PortRecord = PortEntry; - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); else diff --git a/SCSTracker.c b/SCSTracker.c index 5cc106f..41d26a9 100644 --- a/SCSTracker.c +++ b/SCSTracker.c @@ -666,7 +666,8 @@ void * TrackerExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; - TNC->Hardware = H_TRK; + TNC->PortRecord = PortEntry; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_TRK; // Set up DED addresses for streams @@ -682,8 +683,6 @@ void * TrackerExtInit(EXTPORTDATA * PortEntry) PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream PortEntry->SCANCAPABILITIES = NONE; // Scan Control 3 stage/conlock - TNC->PortRecord = PortEntry; - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); else diff --git a/SerialPort.c b/SerialPort.c index 3cda40e..2df4ed6 100644 --- a/SerialPort.c +++ b/SerialPort.c @@ -770,9 +770,9 @@ VOID * SerialExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; - TNC->Hardware = H_SERIAL; - TNC->PortRecord = PortEntry; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_SERIAL; + if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); diff --git a/TelnetV6-skigdebian.c b/TelnetV6-skigdebian.c deleted file mode 100644 index 8074a4a..0000000 --- a/TelnetV6-skigdebian.c +++ /dev/null @@ -1,7157 +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 -*/ - -// -// Telnet Driver for BPQ Switch -// -// Uses BPQ EXTERNAL interface -// - -//#define WIN32_LEAN_AND_MEAN - -#define _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include -#include "time.h" - -#include "kernelresource.h" - -#define IDM_DISCONNECT 2000 -#define IDM_LOGGING 2100 - -#include "cheaders.h" -#include "tncinfo.h" - -#ifdef WIN32 -#include -#include "WS2tcpip.h" -#else -//#define TIOCOUTQ 0x5411 -#define SIOCOUTQ TIOCOUTQ /* output queue size (not sent + not acked) */ -#endif - -#include "adif.h" -#include "telnetserver.h" - -#define MAX_PENDING_CONNECTS 4 - -extern UCHAR LogDirectory[]; - - -static char ClassName[]="TELNETSERVER"; -static char WindowTitle[] = "Telnet Server"; -static int RigControlRow = 190; - -UCHAR * APIENTRY GetLogDirectory(); -static BOOL OpenSockets(struct TNCINFO * TNC); -static BOOL OpenSockets6(struct TNCINFO * TNC); -void ProcessHTTPMessage(void * conn); -static VOID SetupListenSet(struct TNCINFO * TNC); -int WritetoConsoleLocal(char * buff); -BOOL TelSendPacket(int Stream, struct STREAMINFO * STREAM, PMSGWITHLEN buffptr, struct ADIF * ADIF); -int GetCMSHash(char * Challenge, char * Password); -int IsUTF8(unsigned char *cpt, int len); -int Convert437toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF); -int Convert1251toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF); -int Convert1252toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF); -VOID initUTF8(); -int TrytoGuessCode(unsigned char * Char, int Len); -DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot); -extern BPQVECSTRUC * TELNETMONVECPTR; -BOOL SendWL2KSessionRecord(ADIF * ADIF, int BytesSent, int BytesReceived); -int DataSocket_ReadSync(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, int Stream); -VOID SendWL2KRegisterHybrid(struct TNCINFO * TNC); -int IntSetTraceOptionsEx(uint64_t mask, int mtxparam, int mcomparam, int monUIOnly); -int DataSocket_ReadDRATS(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, int Stream); -void processDRATSFrame(unsigned char * Message, int Len, struct ConnectionInfo * sockptr); -void DRATSConnectionLost(struct ConnectionInfo * sockptr); -int BuildRigCtlPage(char * _REPLYBUFFER); -void ProcessWebmailWebSockThread(void * conn); -void ProcessRHPWebSock(SOCKET Socket, char * msg, int Len); -void ProcessRHPWebSockClosed(SOCKET socket); -int ProcessSNMPPayload(UCHAR * Msg, int Len, UCHAR * Reply, int * OffPtr); -int RHPProcessHTTPMessage(struct ConnectionInfo * conn, char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE); - - -#ifndef LINBPQ -extern HKEY REGTREE; -extern HMENU hMainFrameMenu; -extern HMENU hBaseMenu; -extern HMENU hWndMenu; -extern HFONT hFont; -extern HBRUSH bgBrush; - -extern HWND ClientWnd, FrameWnd; - -extern HANDLE hInstance; -static RECT Rect; - -LRESULT CALLBACK TelWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - -#endif - -extern int REALTIMETICKS; - -#define MaxSockets 26 - -struct UserRec RelayUser; -struct UserRec SyncUser = {"","Sync"};; -struct UserRec CMSUser; -struct UserRec HostUser = {"","Host"}; -struct UserRec TriModeUser; - -static char AttemptsMsg[] = "Too many attempts - Disconnected\r\n"; -static char disMsg[] = "Disconnected by SYSOP\r\n"; - -static char BlankCall[]=" "; - -BOOL LogEnabled = FALSE; -BOOL CMSLogEnabled = TRUE; -extern BOOL IncludesMail; - -extern int HTTPPort; - -static HMENU hMenu, hPopMenu, hPopMenu2, hPopMenu3; // handle of menu - -static int ProcessLine(char * buf, int Port); -VOID __cdecl Debugprintf(const char * format, ...); - - -int DisplaySessions(struct TNCINFO * TNC); -int DoStateChange(int Stream); -int Connected(int Stream); -int Disconnected(int Stream); -//int DeleteConnection(con); -static int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port); -static int Socket_Data(struct TNCINFO * TNC, SOCKET SocketId,int error, int eventcode); -static int DataSocket_Read(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, struct STREAMINFO * STREAM); -int DataSocket_ReadFBB(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, int Stream); -int DataSocket_ReadRelay(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, struct STREAMINFO * STREAM); -int DataSocket_ReadHTTP(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, int Stream); -int DataSocket_Write(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET TCPSock); -int DataSocket_Disconnect(struct TNCINFO * TNC, struct ConnectionInfo * sockptr); -BOOL ProcessTelnetCommand(struct ConnectionInfo * sockptr, byte * Msg, int * Len); -int ShowConnections(struct TNCINFO * TNC); -int Terminate(); -int SendtoSocket(SOCKET TCPSock,char * Msg); -int WriteLog(char * msg); -VOID WriteCMSLog(char * msg); -byte * EncodeCall(byte * Call); -VOID SendtoNode(struct TNCINFO * TNC, int Stream, char * Msg, int MsgLen); -DllExport int APIENTRY GetNumberofPorts(); - -BOOL CheckCMS(struct TNCINFO * TNC); -int TCPConnect(struct TNCINFO * TNC, struct TCPINFO * TCP, struct STREAMINFO * STREAM, char * Host, int Port, BOOL FBB); -int CMSConnect(struct TNCINFO * TNC, struct TCPINFO * TCP, struct STREAMINFO * STREAM, int Stream); -int Telnet_Connected(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, int Error); -BOOL ProcessConfig(); -VOID FreeConfig(); -VOID SaveCMSHostInfo(int port, struct TCPINFO * TCP, int CMSNo); -VOID GetCMSCachedInfo(struct TNCINFO * TNC); -BOOL CMSCheck(struct TNCINFO * TNC, struct TCPINFO * TCP); -VOID Tel_Format_Addr(struct ConnectionInfo * sockptr, char * dst); -VOID ProcessTrimodeCommand(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, char * MsgPtr); -VOID ProcessTrimodeResponse(struct TNCINFO * TNC, struct STREAMINFO * STREAM, unsigned char * MsgPtr, int Msglen); -VOID ProcessTriModeDataMessage(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, struct STREAMINFO * STREAM); - - -static int LogAge = 13; - - - -#ifdef WIN32 - -int DeleteLogFile(char * Log); - -void DeleteTelnetLogFiles() -{ - DeleteLogFile("/logs/Telnet*.log"); - DeleteLogFile("/logs/CMSAccess_*.log"); - DeleteLogFile("/logs/ConnectLog_*.log"); -} - -int DeleteLogFile(char * Log) -{ - - - 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, Log); - - // Find the first file in the directory. - - hFind = FindFirstFile(szDir, &ffd); - - if (INVALID_HANDLE_VALUE == hFind) - return dwError; - - // List all the files in the directory with some info about them. - - 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 TelFilter(const struct dirent * dir) -{ - return (memcmp(dir->d_name, "CMSAccess", 9) == 0 - || memcmp(dir->d_name, "Telnet", 6) == 0 - || memcmp(dir->d_name, "ConnectLog", 6) == 0) - && strstr(dir->d_name, ".log"); -} - -int DeleteTelnetLogFiles() -{ - struct dirent **namelist; - int n; - struct stat STAT; - time_t now = time(NULL); - int Age = 0, res; - char FN[256]; - - n = scandir("logs", &namelist, TelFilter, 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 - - - -void BuffertoNode(struct ConnectionInfo * sockptr, char * MsgPtr, int InputLen) -{ - // Queue to Node. Data may arrive it large quatities, possibly exceeding node buffer capacity - - if (sockptr->FromHostBuffPutptr + InputLen > sockptr->FromHostBufferSize) - { - if (InputLen > 10000) - sockptr->FromHostBufferSize += InputLen; - else - sockptr->FromHostBufferSize += 10000; - - sockptr->FromHostBuffer = realloc(sockptr->FromHostBuffer, sockptr->FromHostBufferSize); - } - - memcpy(&sockptr->FromHostBuffer[sockptr->FromHostBuffPutptr], MsgPtr, InputLen); - - sockptr->FromHostBuffPutptr += InputLen; - sockptr->InputLen = 0; - - return; - } - -BOOL SendAndCheck(struct ConnectionInfo * sockptr, unsigned char * MsgPtr, int len, int flags) -{ - int err; - int sent = send(sockptr->socket, MsgPtr, len, flags); - - if (sent == len) - return TRUE; // OK - - err = WSAGetLastError(); - - Debugprintf("TCP Send Failed - Sent %d should be %d err %d - requeue data", sent, len, err); - - if (err == 10035 || err == 115 || err == 36) //EWOULDBLOCK - { - // Save unsent data - - if (sent == -1) // -1 means none sent - sent = 0; - - sockptr->ResendBuffer = malloc(len - sent); - sockptr->ResendLen = len - sent; - - memmove(sockptr->ResendBuffer, MsgPtr + sent, len - sent); - } - return FALSE; -} - -VOID SendPortsForMonitor(SOCKET sock, int Secure) -{ - UCHAR PortInfo[3000] = {0xff, 0xff}; - UCHAR * ptr = &PortInfo[2]; - char ID[31] = ""; - struct PORTCONTROL * PORT; - int i, n, p; - - // Sends the ID of each Port to TermTCP - - p = GetNumberofPorts(); - - if (IncludesMail && Secure) - p++; - - ptr += sprintf(ptr, "%d|", p); - - if (IncludesMail && Secure) - { - p--; - ptr += sprintf(ptr,"0 Mail Monitor|"); - } - - for (n=1; n <= p; n++) - { - PORT = GetPortTableEntryFromSlot(n); - - memcpy(ID, PORT->PORTDESCRIPTION, 30); - - for (i = 29; i; i--) - { - if (ID[i] != ' ') - break; - - ID[i] = 0; - } - - ptr += sprintf(ptr,"%d %s|", PORT->PORTNUMBER, ID); - } - - - send(sock, PortInfo, (int)(ptr - PortInfo), 0); -} - -int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr; - UCHAR * ptr1; - - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int len=510; - char errbuf[256]; - char * param; - char * value; - char *User, *Pwd, *UserCall, *Secure, * Appl; - int End = (int)strlen(buf) -1; - struct TNCINFO * TNC; - struct TCPINFO * TCP; - - strcpy(errbuf,buf); // save in case of error - - if (buf[End] == 10) - buf[End]=0; // remove newline - - if(buf[0] =='#') return (TRUE); // comment - - if(buf[0] ==';') return (TRUE); // comment - - ptr=strchr(buf,'='); - - if (!ptr) - ptr=strchr(buf,' '); - - if (!ptr) - return 0; - - if (TNCInfo[Port] == NULL) - { - TNC = TNCInfo[Port] = zalloc(sizeof(struct TNCINFO)); - TCP = TNC->TCPInfo = zalloc(sizeof (struct TCPINFO)); // Telnet Server Specific Data - - TCP->MaxSessions = 10; // Default Values - TNC->Hardware = H_TELNET; - TCP->IPV4 = TRUE; - TCP->SecureTelnet = 1; - strcpy(TCP->CMSServer, "cms.winlink.org"); - } - - TNC = TNCInfo[Port]; - TCP = TNC->TCPInfo; - - param=buf; - *(ptr)=0; - value=ptr+1; - - if (_stricmp(param, "IPV4") == 0) - TCP->IPV4 = atoi(value); - - else if (_stricmp(param, "IPV6") == 0) - TCP->IPV6 = atoi(value); - - else if (_stricmp(param, "CMS") == 0) - TCP->CMS = atoi(value); - - else if (_stricmp(param, "CMSPASS") == 0) - { - char Temp[80]; - - if (strlen(value) > 79) - value[79] = 0; - - strcpy(Temp, value); - strlop(Temp, 32); - strlop(Temp, 13); - strcpy(TCP->SecureCMSPassword, Temp); - - } - - else if (_stricmp(param, "CMSCALL") == 0) - { - if (strlen(value) > 9) - value[9] = 0; - strcpy(TCP->GatewayCall, value); - strlop(TCP->GatewayCall, 13); - _strupr(TCP->GatewayCall); - } - - else if (_stricmp(param, "CMSLOC") == 0) - { - if (strlen(value) > 9) - value[9] = 0; - strcpy(TCP->GatewayLoc, value); - strlop(TCP->GatewayLoc, 13); - _strupr(TCP->GatewayLoc); - } - - else if (_stricmp(param,"ReportHybrid") == 0) - TCP->ReportHybrid = atoi(value); - - else if (_stricmp(param, "HybridServiceCode") == 0) - { - TCP->HybridServiceCode = _strdup(value); - strlop(TCP->HybridServiceCode, 13); - strlop(TCP->HybridServiceCode, ';'); - _strupr(TCP->HybridServiceCode); - } - - else if (_stricmp(param, "HybridFrequencies") == 0) - { - TCP->HybridFrequencies = _strdup(value); - strlop(TCP->HybridFrequencies, 13); - strlop(TCP->HybridFrequencies, ' '); - _strupr(TCP->HybridFrequencies); - } - - else if (_stricmp(param, "HybridCoLocatedRMS") == 0) - { - TCP->HybridCoLocatedRMS = _strdup(value); - strlop(TCP->HybridCoLocatedRMS, 13); - strlop(TCP->HybridCoLocatedRMS, ' '); - _strupr(TCP->HybridCoLocatedRMS); - } - - else if (_stricmp(param,"LOGGING") == 0) - LogEnabled = atoi(value); - - else if (_stricmp(param,"CMSLOGGING") == 0) - CMSLogEnabled = atoi(value); - - else if (_stricmp(param,"DisconnectOnClose") == 0) - TCP->DisconnectOnClose = atoi(value); - - else if (_stricmp(param,"ReportRelayTraffic") == 0) - TCP->ReportRelayTraffic = atoi(value); - - else if (_stricmp(param,"SecureTelnet") == 0) - TCP->SecureTelnet = atoi(value); - - else if (_stricmp(param,"CloseOnDisconnect") == 0) - TCP->DisconnectOnClose = atoi(value); - - else if (_stricmp(param,"TCPPORT") == 0) - TCP->TCPPort = atoi(value); - - else if (_stricmp(param,"DRATSPORT") == 0) - TCP->DRATSPort = atoi(value); - - else if (_stricmp(param,"TRIMODEPORT") == 0) - TCP->TriModePort = atoi(value); - - else if (_stricmp(param,"HTTPPORT") == 0) - HTTPPort = TCP->HTTPPort = atoi(value); - - else if (_stricmp(param,"APIPORT") == 0) - TCP->APIPort = atoi(value); - - else if (_stricmp(param,"SYNCPORT") == 0) - TCP->SyncPort = atoi(value); - - else if (_stricmp(param,"SNMPPORT") == 0) - TCP->SNMPPort = atoi(value); - - else if ((_stricmp(param,"CMDPORT") == 0) || (_stricmp(param,"LINUXPORT") == 0)) - { - int n = 0; - char * context; - char * ptr = strtok_s(value, ", ", &context); - - while (ptr && n < 33) - { - TCP->CMDPort[n++] = atoi(ptr); - ptr = strtok_s(NULL, ", ", &context); - } - } - - else if (_stricmp(param,"CMSSERVER") == 0) - { - int n = 0; - char * context; - char * ptr = strtok_s(value, ", \r", &context); - - strcpy(TCP->CMSServer, ptr); - } - - else if (_stricmp(param,"RELAYHOST") == 0) - { - int n = 0; - char * context; - char * ptr = strtok_s(value, ", \r", &context); - - strcpy(TCP->RELAYHOST, ptr); - } - - - else if (_stricmp(param,"FALLBACKTORELAY") == 0) - { - int n = 0; - char * context; - char * ptr = strtok_s(value, ", \r", &context); - - TCP->FallbacktoRelay = atoi(value); - } - - else if (_stricmp(param,"FBBPORT") == 0) - { - int n = 0; - char * context; - char * ptr = strtok_s(value, ", ", &context); - - while (ptr && n < 99) - { - TCP->FBBPort[n++] = atoi(ptr); - ptr = strtok_s(NULL, ", ", &context); - } - } - - else if (_stricmp(param,"RELAYPORT") == 0) - TCP->RelayPort = atoi(value); - - else if (_stricmp(param,"RELAYAPPL") == 0) - { - if (TCP->RelayPort == 0) - TCP->RelayPort = 8772; - strcpy(TCP->RelayAPPL, value); - strcat(TCP->RelayAPPL, "\r"); - } - - else if (_stricmp(param,"SYNCAPPL") == 0) - { - if (TCP->SyncPort == 0) - TCP->SyncPort = 8780; - strcpy(TCP->SyncAPPL, value); - strcat(TCP->SyncAPPL, "\r"); - } - - // if (strcmp(param,"LOGINRESPONSE") == 0) cfgLOGINRESPONSE = value; - // if (strcmp(param,"PASSWORDRESPONSE") == 0) cfgPASSWORDRESPONSE = value; - - else if (_stricmp(param,"LOGINPROMPT") == 0) - { - ptr1 = strchr(value, 13); - if (ptr1) *ptr1 = 0; - strcpy(TCP->LoginMsg,value); - } - - else if (_stricmp(param,"PASSWORDPROMPT") == 0) - { - ptr1 = strchr(value, 13); - if (ptr1) *ptr1 = 0; - strcpy(TCP->PasswordMsg, value); - } - - else if (_stricmp(param,"HOSTPROMPT") == 0) - strcpy(TCP->cfgHOSTPROMPT, value); - - else if (_stricmp(param,"LOCALECHO") == 0) - strcpy(TCP->cfgLOCALECHO, value); - - else if (_stricmp(param,"MAXSESSIONS") == 0) - { - TCP->MaxSessions = atoi(value); - if (TCP->MaxSessions > MaxSockets ) TCP->MaxSessions = MaxSockets; - } - - else if (_stricmp(param,"CTEXT") == 0 ) - { - int len = (int)strlen (value); - - if (value[len -1] == ' ') - value[len -1] = 0; - - strcpy(TCP->cfgCTEXT, value); - - // Replace \n Signon string with cr lf - - ptr = &TCP->cfgCTEXT[0]; - -scanCTEXT: - - ptr = strstr(ptr, "\\n"); - - if (ptr) - { - *(ptr++)=13; // put in cr - *(ptr++)=10; // put in lf - - goto scanCTEXT; - } - } - - else if (_stricmp(param,"LOCALNET") == 0) - { - uint32_t Network, Mask; - uint32_t IPMask; - char * Netptr, * MaskPtr, *Context; - struct LOCALNET * LocalNet; - int Bits = 24; - - Netptr = strtok_s(value, " /;", &Context); - - if (Netptr) - { - Network = inet_addr(Netptr); - MaskPtr = strtok_s(NULL, " /;", &Context); - - if (MaskPtr) - { - Bits = atoi(MaskPtr); - - if (Bits > 32) - Bits = 32; - } - - if (Bits == 0) - IPMask = 0; - else - IPMask = (0xFFFFFFFF) << (32 - Bits); - - Mask = htonl(IPMask); // Needs to be Network order - - LocalNet = (struct LOCALNET *)zalloc(sizeof(struct LOCALNET)); - - LocalNet->Network = Network; - LocalNet->Mask = Mask; - LocalNet->Next = TNC->TCPInfo->LocalNets; - - TNC->TCPInfo->LocalNets = LocalNet; - - } - } - - - - - else if (_stricmp(param,"USER") == 0) - { - struct UserRec * USER; - char Param[8][256]; - char * ptr1, * ptr2; - int n = 0; - - // USER=user,password,call,appl,SYSOP - - memset(Param, 0, 2048); - strlop(value, 13); - strlop(value, ';'); - - ptr1 = value; - - while (ptr1 && *ptr1 && n < 8) - { - ptr2 = strchr(ptr1, ','); - if (ptr2) *ptr2++ = 0; - - strcpy(&Param[n][0], ptr1); - strlop(Param[n++], ' '); - ptr1 = ptr2; - while(ptr1 && *ptr1 && *ptr1 == ' ') - ptr1++; - } - - - User = &Param[0][0]; - - if (_stricmp(User, "ANON") == 0) - { - strcpy(&Param[2][0], "ANON"); - strcpy(&Param[4][0], ""); // Dont allow SYSOP if ANON - } - - Pwd = &Param[1][0]; - UserCall = &Param[2][0]; - Appl = &Param[3][0]; - Secure = &Param[4][0]; - - if (User[0] == 0 || Pwd[0] == 0 || UserCall[0] == 0) // invalid record - return 0; - - _strupr(UserCall); - - if (TCP->NumberofUsers == 0) - TCP->UserRecPtr = zalloc(sizeof(void *)); - else - TCP->UserRecPtr = realloc(TCP->UserRecPtr, (TCP->NumberofUsers+1) * sizeof(void *)); - - USER = zalloc(sizeof(struct UserRec)); - - TCP->UserRecPtr[TCP->NumberofUsers] = USER; - - USER->Callsign = _strdup(UserCall); - USER->Password = _strdup(Pwd); - USER->UserName = _strdup(User); - USER->Appl = zalloc(32); - USER->Secure = FALSE; - - if (_stricmp(Secure, "SYSOP") == 0) - USER->Secure = TRUE; - - if (Appl[0] && strcmp(Appl, "\"\"") != 0) - { - strcpy(USER->Appl, _strupr(Appl)); - strcat(USER->Appl, "\r\n"); - } - TCP->NumberofUsers += 1; - } - else if (_memicmp(errbuf, "WL2KREPORT", 10) == 0) - TNC->WL2K = DecodeWL2KReportLine(errbuf); - else if (_stricmp(param,"WebTermCSS") == 0) - { - TCP->WebTermCSS = _strdup(value); - } - else - return FALSE; - - return TRUE; -} - -static int MaxStreams = 26; - -void CheckRX(struct TNCINFO * TNC); -VOID TelnetPoll(int Port); -VOID ProcessTermModeResponse(struct TNCINFO * TNC); -VOID DoTNCReinit(struct TNCINFO * TNC); -VOID DoTermModeTimeout(struct TNCINFO * TNC); - -VOID DoMonitor(struct TNCINFO * TNC, UCHAR * Msg, int Len); - - -static VOID WritetoTrace(int Stream, char * Msg, int Len, struct ADIF * ADIF, char Dirn) -{ - int index = 0; - UCHAR * ptr1 = Msg, * ptr2; - UCHAR Line[1000]; - int LineLen, i; - char logmsg[200]; - - Msg[Len] = 0; - -lineloop: - - if (Len > 0) - { - // copy text to file a line at a time - - ptr2 = memchr(ptr1, 13 , Len); - - if (ptr2) - { - ptr2++; - LineLen = (int)(ptr2 - ptr1); - Len -= LineLen; - - if (LineLen > 900) - goto Skip; - - memcpy(Line, ptr1, LineLen); - memcpy(&Line[LineLen - 1], "", 4); - LineLen += 3; - - if ((*ptr2) == 10) - { - memcpy(&Line[LineLen], "", 4); - LineLen += 4; - ptr2++; - Len --; - } - - Line[LineLen] = 0; - - // If line contains any data above 7f, assume binary and dont display - - for (i = 0; i < LineLen; i++) - { - if (Line[i] > 127 || Line[i] < 32) - goto Skip; - } - - if (strlen(Line) < 100) - { - sprintf(logmsg,"%d %s\r\n", Stream, Line); - WriteCMSLog(logmsg); - UpdateADIFRecord(ADIF, Line, Dirn); - } - -Skip: - ptr1 = ptr2; - goto lineloop; - } - - // No CR - - for (i = 0; i < Len; i++) - { - if (ptr1[i] > 127) - break; - } - - if (i == Len) // No binary data - { - if (strlen(ptr1) < 100) - { - sprintf(logmsg,"%d %s\r\n", Stream, ptr1); - WriteCMSLog(logmsg); - UpdateADIFRecord(ADIF, ptr1, Dirn); - } - } - } -} - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - int txlen = 0, n; - PMSGWITHLEN buffptr; - struct TNCINFO * TNC = TNCInfo[port]; - struct TCPINFO * TCP; - - int Stream; - struct ConnectionInfo * sockptr; - struct STREAMINFO * STREAM; - - if (TNC == NULL) - return 0; // Not configured - - switch (fn) - { - case 7: - - // 100 mS Timer. Now needed, as Poll can be called more frequently in some circuymstances - - while (TNC->PortRecord->UI_Q) // Release anything accidentally put on UI_Q - { - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - ReleaseBuffer(buffptr); - } - - TCP = TNC->TCPInfo; - - if (TCP->CMS) - { - TCP->CheckCMSTimer++; - - if (TCP->CMSOK) - { - if (TCP->CheckCMSTimer > 600 * 15) - CheckCMS(TNC); - } - else - { - if (TCP->CheckCMSTimer > 600 * 2) - CheckCMS(TNC); - } - } - - // We now use persistent HTTP sessions, so need to close after a reasonable time - - for (n = 0; n <= TCP->MaxSessions; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - - if (sockptr->SocketActive) - { - if (sockptr->HTTPMode) - { - if (sockptr->WebSocks == 0) - { - if (sockptr->LastSendTime && (REALTIMETICKS - sockptr->LastSendTime) > 1500) // ~ 2.5 mins - { - closesocket(sockptr->socket); - sockptr->SocketActive = FALSE; - ShowConnections(TNC); - } - } - } - else - { - // Time out Login - - if (sockptr->LoginState < 2 && (time(NULL) - sockptr->ConnectTime) > 30) - { - closesocket(sockptr->socket); - sockptr->SocketActive = FALSE; - ShowConnections(TNC); - } - } - } - } - - - - return 0; - - case 1: // poll - - for (Stream = 0; Stream <= MaxStreams; Stream++) - { - TRANSPORTENTRY * SESS; - struct ConnectionInfo * sockptr = TNC->Streams[Stream].ConnectionInfo; - - if (sockptr && sockptr->UserPointer == &CMSUser) // Connected to CMS - { - SESS = TNC->PortRecord->ATTACHEDSESSIONS[sockptr->Number]; - - if (SESS) - { - n = SESS->L4KILLTIMER; - if (n < (SESS->L4LIMIT - 120)) - { - SESS->L4KILLTIMER = SESS->L4LIMIT - 120; - SESS = SESS->L4CROSSLINK; - if (SESS) - SESS->L4KILLTIMER = SESS->L4LIMIT - 120; - } - } - } - - STREAM = &TNC->Streams[Stream]; - - if (STREAM->NeedDisc) - { - STREAM->NeedDisc--; - - if (STREAM->NeedDisc == 0) - { - // Send the DISCONNECT - - STREAM->ReportDISC = TRUE; - } - } - - if (STREAM->ReportDISC) - { - STREAM->ReportDISC = FALSE; - buff->PORT = Stream; - - return -1; - } - } - - TelnetPoll(port); - - for (Stream = 0; Stream <= MaxStreams; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->PACTORtoBPQ_Q !=0) - { - int datalen; - - buffptr = Q_REM(&STREAM->PACTORtoBPQ_Q); - - datalen = (int)buffptr->Len; - - buff->PORT = Stream; - buff->PID = 0xf0; - memcpy(&buff->L2DATA, &buffptr->Data[0], datalen); // Data goes to + 7, but we have an extra byte - datalen += sizeof(void *) + 4; - - PutLengthinBuffer(buff, datalen); - - ReleaseBuffer(buffptr); - return (1); - } - } - - return 0; - - case 2: // send - - buffptr = GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - // Find TNC Record - - Stream = buff->PORT; - STREAM = &TNC->Streams[Stream]; - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - - buffptr->Len = txlen; - memcpy(&buffptr->Data, &buff->L2DATA, txlen); - - C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr); - STREAM->FramesQueued++; - - return (0); - - - case 3: // CHECK IF OK TO SEND. Also used to check if TNC is responding - - Stream = (int)(size_t)buff; - - STREAM = &TNC->Streams[Stream]; - - if (STREAM->FramesQueued > 40) - return (257); // Busy - - return 256; // OK - -#define SD_BOTH 0x02 - - case 4: // reinit - { - struct _EXTPORTDATA * PortRecord; - -#ifndef LINBPQ - HWND SavehDlg, SaveCMS, SaveMonitor; - HMENU SaveMenu1, SaveMenu2, SaveMenu3; -#endif - int n, i; - - if (!ProcessConfig()) - { - Consoleprintf("Failed to reread config file - leaving config unchanged"); - break; - } - - FreeConfig(); - - for (n = 1; n <= TNC->TCPInfo->CurrentSockets; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - sockptr->SocketActive = FALSE; - closesocket(sockptr->socket); - } - - TCP = TNC->TCPInfo; - - shutdown(TCP->TCPSock, SD_BOTH); - shutdown(TCP->sock6, SD_BOTH); - - n = 0; - while (TCP->FBBsock[n]) - shutdown(TCP->FBBsock[n++], SD_BOTH); - - shutdown(TCP->Relaysock, SD_BOTH); - shutdown(TCP->HTTPsock, SD_BOTH); - shutdown(TCP->HTTPsock6, SD_BOTH); - - - n = 0; - while (TCP->FBBsock6[n]) - shutdown(TCP->FBBsock[n++], SD_BOTH); - - shutdown(TCP->Relaysock6, SD_BOTH); - Sleep(500); - - closesocket(TCP->TCPSock); - closesocket(TCP->sock6); - - n = 0; - while (TCP->FBBsock[n]) - closesocket(TCP->FBBsock[n++]); - - n = 0; - while (TCP->FBBsock6[n]) - closesocket(TCP->FBBsock6[n++]); - - closesocket(TCP->Relaysock); - closesocket(TCP->Relaysock6); - closesocket(TCP->HTTPsock); - closesocket(TCP->HTTPsock6); - - // Save info from old TNC record - - n = TNC->Port; - PortRecord = TNC->PortRecord; -#ifndef LINBPQ - SavehDlg = TNC->hDlg; - SaveCMS = TCP->hCMSWnd; - SaveMonitor = TNC->hMonitor; - SaveMenu1 = TCP->hActionMenu; - SaveMenu2 = TCP->hDisMenu; - SaveMenu3 = TCP->hLogMenu; -#endif - // Free old TCP Session Stucts - - for (i = 0; i <= TNC->TCPInfo->MaxSessions; i++) - { - free(TNC->Streams[i].ConnectionInfo); - } - - ReadConfigFile(TNC->Port, ProcessLine); - - TNC = TNCInfo[n]; - TNC->Port = n; - TNC->Hardware = H_TELNET; - TNC->RIG = &TNC->DummyRig; // Not using Rig control, so use Dummy - - // Get Menu Handles - - TCP = TNC->TCPInfo; -#ifndef LINBPQ - TNC->hDlg = SavehDlg; - TCP->hCMSWnd = SaveCMS; - TNC->hMonitor = SaveMonitor; - TCP->hActionMenu = SaveMenu1; - TCP->hDisMenu = SaveMenu2; - TCP->hLogMenu = SaveMenu3; - - CheckMenuItem(TCP->hActionMenu, 3, MF_BYPOSITION | TNC->TCPInfo->CMS<<3); - CheckMenuItem(TCP->hLogMenu, 0, MF_BYPOSITION | LogEnabled<<3); - CheckMenuItem(TCP->hLogMenu, 1, MF_BYPOSITION | CMSLogEnabled<<3); -#endif - // Malloc TCP Session Stucts - - for (i = 0; i <= TNC->TCPInfo->MaxSessions; i++) - { - TNC->Streams[i].ConnectionInfo = zalloc(sizeof(struct ConnectionInfo)); - TCP->CurrentSockets = i; //Record max used to save searching all entries -#ifndef LINBPQ - if (i > 0) - ModifyMenu(TCP->hDisMenu,i - 1 ,MF_BYPOSITION | MF_STRING,IDM_DISCONNECT + 1, "."); -#endif - } - - TNC->PortRecord = PortRecord; - - Sleep(500); - OpenSockets(TNC); - OpenSockets6(TNC); - SetupListenSet(TNC); - CheckCMS(TNC); - ShowConnections(TNC); - } - - break; - - case 5: // Close - - TCP = TNC->TCPInfo; - - for (n = 1; n <= TCP->CurrentSockets; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - closesocket(sockptr->socket); - } - - shutdown(TCP->TCPSock, SD_BOTH); - - n = 0; - while (TCP->FBBsock[n]) - shutdown(TCP->FBBsock[n++], SD_BOTH); - - shutdown(TCP->Relaysock, SD_BOTH); - shutdown(TCP->HTTPsock, SD_BOTH); - shutdown(TCP->HTTPsock6, SD_BOTH); - - shutdown(TCP->sock6, SD_BOTH); - - n = 0; - while (TCP->FBBsock6[n]) - shutdown(TCP->FBBsock6[n++], SD_BOTH); - - shutdown(TCP->Relaysock6, SD_BOTH); - - Sleep(500); - closesocket(TCP->TCPSock); - - n = 0; - while (TCP->FBBsock[n]) - closesocket(TCP->FBBsock[n++]); - - closesocket(TCP->Relaysock); - - closesocket(TCP->sock6); - - n = 0; - while (TCP->FBBsock6[n]) - closesocket(TCP->FBBsock6[n++]); - - closesocket(TCP->Relaysock6); - closesocket(TCP->HTTPsock); - closesocket(TCP->HTTPsock6); - - return (0); - - case 6: // Scan Control - - return 0; // None Yet - - } - return 0; - -} - - - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len; - char msg[256]; - struct ConnectionInfo * sockptr; - int i,n; - - char CMSStatus[80] = ""; - - if (TNC->TCPInfo->CMS) - { - if (TNC->TCPInfo->CMSOK) - strcpy(CMSStatus, "CMS Ok"); - else - strcpy(CMSStatus, "No CMS"); - } - - Len = sprintf(Buff, "" - "Telnet StatusTelnet Status         %s", CMSStatus); - - Len += sprintf(&Buff[Len], ""); - - - Len += sprintf(&Buff[Len], ""); - - for (n = 1; n <= TNC->TCPInfo->CurrentSockets; n++) - { - sockptr=TNC->Streams[n].ConnectionInfo; - - if (!sockptr->SocketActive) - { - strcpy(msg,""); - } - else - { - if (sockptr->UserPointer == 0) - { - if (sockptr->HTTPMode) - { - char Addr[100]; - Tel_Format_Addr(sockptr, Addr); - if (sockptr->WebSocks) - sprintf(msg,"", Addr); - else - sprintf(msg,"", Addr); - } - else if (sockptr->DRATSMode) - { - char Addr[100]; - Tel_Format_Addr(sockptr, Addr); - sprintf(msg,"", Addr); - } - else - strcpy(msg,""); - } - else - { - i=sprintf(msg,"", - sockptr->UserPointer->UserName, sockptr->Callsign, - sockptr->FromHostBuffPutptr - sockptr->FromHostBuffGetptr); - } - } - Len += sprintf(&Buff[Len], "%s", msg); - } - - Len += sprintf(&Buff[Len], "
UserCallsignQueue
Idle  
Websock<%s  
HTTP<%s  
DRATS<%s  
Logging in  
%s%s%d
"); - return Len; -} - - - -void * TelnetExtInit(EXTPORTDATA * PortEntry) -{ - char msg[500]; - struct TNCINFO * TNC; - struct TCPINFO * TCP; - int port; - char * ptr; - int i; - HWND x=0; - -/* - UCHAR NC[257]; - WCHAR WC[1024]; - - int WLen, NLen; - - UINT UTF[256] = {0}; - UINT UTFL[256]; - - int n, u; - - for (n = 0; n < 256; n++) - NC[n] =n ; - - n = MultiByteToWideChar(437, 0, NC, 256, &WC[0], 1024); - - for (n = 0; n < 256; n++) - UTFL[n] = WideCharToMultiByte(CP_UTF8, 0, &WC[n], 1, &UTF[n], 1024 , NULL, NULL); - - // write UTF8 data as source - - { - HANDLE Handle; - int i, n, Len; - char Line [256]; - - - Handle = CreateFile("c:\\UTF8437Data.c", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - n = wsprintf (Line, "unsigned int CP437toUTF8Data[128] = {\r\n"); - - WriteFile(Handle, Line ,n , &n, NULL); - - if (Handle != INVALID_HANDLE_VALUE) - { - for (i = 128; i < 256; i += 4) - { - n = wsprintf (Line, " %d, %d, %d, %d, \r\n", - UTF[i], UTF[i+1], UTF[i+2], UTF[i+3]); - WriteFile(Handle, Line ,n , &n, NULL); - - } - - WriteFile(Handle, "};\r\n", 4, &n, NULL); - } - n = wsprintf (Line, "unsigned int CP437toUTF8DataLen[128] = {\r\n"); - - WriteFile(Handle, Line ,n , &n, NULL); - - if (Handle != INVALID_HANDLE_VALUE) - { - for (i = 128; i < 256;i += 4) - { - n = wsprintf (Line, " %d, %d, %d, %d, \r\n", - UTFL[i], UTFL[i+1], UTFL[i+2], UTFL[i+3]); - WriteFile(Handle, Line ,n , &n, NULL); - - } - - WriteFile(Handle, "};\r\n", 4, &n, NULL); - - SetEndOfFile(Handle); - - CloseHandle(Handle); - } - } -*/ - - DeleteTelnetLogFiles(); - - initUTF8(); - - sprintf(msg,"Telnet Server "); - WritetoConsoleLocal(msg); - - port=PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - - TNC = TNCInfo[port]; - - if (TNC == NULL) - { - // Not defined in Config file - - WritetoConsoleLocal("\n"); - return ExtProc; - } - - TCP = TNC->TCPInfo; - - TNC->Port = port; - - TNC->Hardware = H_TELNET; - - PortEntry->MAXHOSTMODESESSIONS = TNC->TCPInfo->MaxSessions + 1; // Default - - TNC->PortRecord = PortEntry; - - if (PortEntry->PORTCONTROL.PORTCALL[0] != 0) - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - - PortEntry->PORTCONTROL.PROTOCOL = 10; // WINMOR/Pactor - PortEntry->PORTCONTROL.PORTQUALITY = 0; - PortEntry->SCANCAPABILITIES = NONE; // No Scan Control - PortEntry->PERMITGATEWAY = TRUE; - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - TELNETMONVECPTR->HOSTAPPLFLAGS = 0x80; // Requext Monitoring - - if (TCP->LoginMsg[0] == 0) - strcpy(TCP->LoginMsg, "user:"); - if (TCP->PasswordMsg[0] == 0) - strcpy(TCP->PasswordMsg, "password:"); - if (TCP->cfgCTEXT[0] == 0) - { - char Call[10]; - memcpy(Call, MYNODECALL, 10); - strlop(Call, ' '); - - sprintf(TCP->cfgCTEXT, "Connected to %s's Telnet Server\r\n\r\n", Call); - } - - PortEntry->PORTCONTROL.TNC = TNC; - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 260; - TNC->WebWinY = 325; - -#ifndef LINBPQ - - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, TelWndProc, 400, 300, NULL); - - TCP->hCMSWnd = CreateWindowEx(0, "STATIC", "CMS OK ", WS_CHILD | WS_VISIBLE, - 240,0,60,16, TNC->hDlg, NULL, hInstance, NULL); - - SendMessage(TCP->hCMSWnd, WM_SETFONT, (WPARAM)hFont, 0); - - x = CreateWindowEx(0, "STATIC", " User Callsign Queue", WS_CHILD | WS_VISIBLE, - 0,0,240,16, TNC->hDlg, NULL, hInstance, NULL); - - SendMessage(x, WM_SETFONT, (WPARAM)hFont, 0); - - - TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | WS_VSCROLL, - 0,20,400,2800, TNC->hDlg, NULL, hInstance, NULL); - - SendMessage(TNC->hMonitor, WM_SETFONT, (WPARAM)hFont, 0); - - hPopMenu = CreatePopupMenu(); - hPopMenu2 = CreatePopupMenu(); - hPopMenu3 = CreatePopupMenu(); - - AppendMenu(hPopMenu, MF_STRING + MF_POPUP, (UINT)hPopMenu2,"Logging Options"); - AppendMenu(hPopMenu, MF_STRING + MF_POPUP, (UINT)hPopMenu3,"Disconnect User"); - AppendMenu(hPopMenu, MF_STRING, TELNET_RECONFIG, "ReRead Config"); - AppendMenu(hPopMenu, MF_STRING, CMSENABLED, "CMS Access Enabled"); - AppendMenu(hPopMenu, MF_STRING, USECACHEDCMS, "Using Cached CMS Addresses"); - - AppendMenu(hPopMenu2, MF_STRING, IDM_LOGGING, "Log incoming connections"); - AppendMenu(hPopMenu2, MF_STRING, IDM_CMS_LOGGING, "Log CMS Connections"); - - AppendMenu(hPopMenu3, MF_STRING, IDM_DISCONNECT, "1"); - - TCP->hActionMenu = hPopMenu; - - CheckMenuItem(TCP->hActionMenu, 3, MF_BYPOSITION | TCP->CMS<<3); - - TCP->hLogMenu = hPopMenu2; - TCP->hDisMenu = hPopMenu3; - - CheckMenuItem(TCP->hLogMenu, 0, MF_BYPOSITION | LogEnabled<<3); - CheckMenuItem(TCP->hLogMenu, 1, MF_BYPOSITION | CMSLogEnabled<<3); - -// ModifyMenu(hMenu, 1, MF_BYPOSITION | MF_OWNERDRAW | MF_STRING, 10000, 0); - -#endif - - // Malloc TCP Session Stucts - - for (i = 0; i <= TNC->TCPInfo->MaxSessions; i++) - { - TNC->Streams[i].ConnectionInfo = zalloc(sizeof(struct ConnectionInfo)); - TNC->Streams[i].ConnectionInfo->Number = i; - TCP->CurrentSockets = i; //Record max used to save searching all entries - - sprintf(msg,"%d", i); - -#ifndef LINBPQ - if (i > 1) - AppendMenu(TCP->hDisMenu, MF_STRING, IDM_DISCONNECT ,msg); -#endif - } - - OpenSockets(TNC); - OpenSockets6(TNC); - SetupListenSet(TNC); - TNC->RIG = &TNC->DummyRig; // Not using Rig control, so use Dummy - - if (TCP->CMS) - CheckCMS(TNC); - - WritetoConsoleLocal("\n"); - - ShowConnections(TNC); - - if (TCP->ReportHybrid) - SendWL2KRegisterHybrid(TNC); - - - return ExtProc; -} - -SOCKET OpenUDPSocket(struct TNCINFO * TNC) -{ - u_long param = 1; - struct sockaddr_in sinx; - int err, ret; - struct TCPINFO * TCP = TNC->TCPInfo; - char Msg[80]; - - TCP->SNMPsock = socket(AF_INET,SOCK_DGRAM,0); - - if (TCP->SNMPsock == INVALID_SOCKET) - { - WritetoConsoleLocal("Failed to create SNMP UDP socket"); - return 0; - } - - ioctl (TCP->SNMPsock, FIONBIO, ¶m); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - - sinx.sin_port = htons(TCP->SNMPPort); - - ret = bind(TCP->SNMPsock, (struct sockaddr *) &sinx, sizeof(sinx)); - - if (ret != 0) - { - // Bind Failed - - err = WSAGetLastError(); - sprintf(Msg, "Bind Failed for SNMP UDP socket %d - error code = %d", TCP->SNMPPort, err); - WritetoConsoleLocal(Msg); - return 0; - } - - return TCP->SNMPsock; -} - - - -SOCKET OpenSocket4(struct TNCINFO * xTNC, int port) -{ - struct sockaddr_in local_sin; /* Local socket - internet style */ - struct sockaddr_in * psin; - SOCKET sock = 0; - u_long param=1; - - char szBuff[80]; - - psin=&local_sin; - psin->sin_family = AF_INET; - psin->sin_addr.s_addr = INADDR_ANY; - - if (port) - { - sock = socket(AF_INET, SOCK_STREAM, 0); - - if (sock == INVALID_SOCKET) - { - sprintf(szBuff, "socket() failed error %d\n", WSAGetLastError()); - WritetoConsoleLocal(szBuff); - return 0; - } - - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (char *)¶m,4); - - - psin->sin_port = htons(port); // Convert to network ordering - - if (bind( sock, (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) - { - sprintf(szBuff, "bind(sock) failed port %d Error %d\n", port, WSAGetLastError()); - WritetoConsoleLocal(szBuff); - closesocket( sock ); - return FALSE; - } - - if (listen( sock, MAX_PENDING_CONNECTS ) < 0) - { - sprintf(szBuff, "listen(sock) failed port %d Error %d\n", port, WSAGetLastError()); - WritetoConsoleLocal(szBuff); - return FALSE; - } - ioctl(sock, FIONBIO, ¶m); - } - - return sock; -} - -BOOL OpenSockets(struct TNCINFO * TNC) -{ - struct sockaddr_in local_sin; /* Local socket - internet style */ - struct sockaddr_in * psin; - u_long param=1; - struct TCPINFO * TCP = TNC->TCPInfo; - int n; - - if (!TCP->IPV4) - return TRUE; - - psin=&local_sin; - psin->sin_family = AF_INET; - psin->sin_addr.s_addr = INADDR_ANY; - - if (TCP->TCPPort) - TCP->TCPSock = OpenSocket4(TNC, TCP->TCPPort); - - n = 0; - - while (TCP->FBBPort[n]) - { - TCP->FBBsock[n] = OpenSocket4(TNC, TCP->FBBPort[n]); - n++; - } - - if (TCP->RelayPort) - TCP->Relaysock = OpenSocket4(TNC, TCP->RelayPort); - - if (TCP->TriModePort) - { - TCP->TriModeSock = OpenSocket4(TNC, TCP->TriModePort); - TCP->TriModeDataSock = OpenSocket4(TNC, TCP->TriModePort + 1); - } - - if (TCP->HTTPPort) - TCP->HTTPsock = OpenSocket4(TNC, TCP->HTTPPort); - - if (TCP->APIPort) - TCP->APIsock = OpenSocket4(TNC, TCP->APIPort); - - if (TCP->SyncPort) - TCP->Syncsock = OpenSocket4(TNC, TCP->SyncPort); - - if (TCP->DRATSPort) - TCP->DRATSsock = OpenSocket4(TNC, TCP->DRATSPort); - - if (TCP->SNMPPort) - TCP->SNMPsock = OpenUDPSocket(TNC); - - CMSUser.UserName = _strdup("CMS"); - - TriModeUser.Secure = TRUE; - TriModeUser.UserName = _strdup("TRIMODE"); - TriModeUser.Callsign = zalloc(10); - - return TRUE; -} - -SOCKET OpenSocket6(struct TNCINFO * TNC, int port) -{ - - struct sockaddr_in6 local_sin; /* Local socket - internet style */ - struct sockaddr_in6 * psin; - SOCKET sock; - char szBuff[80]; - u_long param=1; - - memset(&local_sin, 0, sizeof(local_sin)); - - psin=&local_sin; - psin->sin6_family = AF_INET6; - psin->sin6_addr = in6addr_any; - psin->sin6_flowinfo = 0; - psin->sin6_scope_id = 0; - - sock = socket(AF_INET6, SOCK_STREAM, 0); - -#ifndef WIN32 - - if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, ¶m, sizeof(param)) < 0) - { - perror("setting option IPV6_V6ONLY"); - } - -#endif - - if (sock == INVALID_SOCKET) - { - sprintf(szBuff, "IPV6 socket() failed error %d\n", WSAGetLastError()); - WritetoConsoleLocal(szBuff); - return FALSE; - } - - psin->sin6_port = htons(port); // Convert to network ordering - - if (bind(sock, (struct sockaddr FAR *)psin, sizeof(local_sin)) == SOCKET_ERROR) - { - sprintf(szBuff, "IPV6 bind(sock) failed Port %d Error %d\n", port, WSAGetLastError()); - WritetoConsoleLocal(szBuff); - closesocket( sock ); - - return FALSE; - } - - if (listen( sock, MAX_PENDING_CONNECTS ) < 0) - { - sprintf(szBuff, "IPV6 listen(sock) failed Error %d\n", WSAGetLastError()); - WritetoConsoleLocal(szBuff); - - return FALSE; - } - - ioctl(sock, FIONBIO, ¶m); - return sock; -} - - -BOOL OpenSockets6(struct TNCINFO * TNC) -{ - struct sockaddr_in6 local_sin; /* Local socket - internet style */ - - struct sockaddr_in6 * psin; - struct TCPINFO * TCP = TNC->TCPInfo; - int n; - u_long param=1; - - if (!TCP->IPV6) - return TRUE; - - memset(&local_sin, 0, sizeof(local_sin)); - - psin=&local_sin; - psin->sin6_family = AF_INET6; - psin->sin6_addr = in6addr_any; - psin->sin6_flowinfo = 0; - psin->sin6_scope_id = 0; - - - if (TCP->TCPPort) - TCP->sock6 = OpenSocket6(TNC, TCP->TCPPort); - - n = 0; - - while (TCP->FBBPort[n]) - { - TCP->FBBsock6[n] = OpenSocket6(TNC, TCP->FBBPort[n]); - n++; - } - - if (TCP->RelayPort) - TCP->Relaysock6 = OpenSocket6(TNC, TCP->RelayPort); - - if (TCP->HTTPPort) - TCP->HTTPsock6 = OpenSocket6(TNC, TCP->HTTPPort); - - if (TCP->APIPort) - TCP->APIsock6 = OpenSocket6(TNC, TCP->APIPort); - - if (TCP->SyncPort) - TCP->Syncsock6 = OpenSocket6(TNC, TCP->SyncPort); - - if (TCP->DRATSPort) - TCP->DRATSsock6 = OpenSocket6(TNC, TCP->DRATSPort); - - - CMSUser.UserName = _strdup("CMS"); - - return TRUE; -} - -static VOID SetupListenSet(struct TNCINFO * TNC) -{ - // Set up master set of fd's for checking for incoming calls - - struct TCPINFO * TCP = TNC->TCPInfo; - SOCKET maxsock = 0; - int n; - fd_set * readfd = &TCP->ListenSet; - SOCKET sock; - - FD_ZERO(readfd); - - n = 0; - while (n < 100) - { - sock = TCP->FBBsock[n++]; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - } - - sock = TCP->TCPSock; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->Relaysock; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->HTTPsock; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->APIsock; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->Syncsock; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->DRATSsock; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->TriModeSock; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->TriModeDataSock; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - n = 0; - while (n < 100) - { - sock = TCP->FBBsock6[n++]; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - } - - sock = TCP->sock6; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->Relaysock6; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->HTTPsock6; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->APIsock6; - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - - sock = TCP->DRATSsock6; - - if (sock) - { - FD_SET(sock, readfd); - if (sock > maxsock) - maxsock = sock; - } - TCP->maxsock = maxsock; -} - - -VOID TelnetPoll(int Port) -{ - struct TNCINFO * TNC = TNCInfo[Port]; - UCHAR * Poll = TNC->TXBuffer; - struct TCPINFO * TCP = TNC->TCPInfo; - struct STREAMINFO * STREAM; - int Msglen; - int Stream; - - // we now poll for incoming connections - - struct timeval timeout; - int retval; - int n; - struct ConnectionInfo * sockptr; - SOCKET sock; - int Active = 0; - SOCKET maxsock; - - fd_set readfd, writefd, exceptfd; - timeout.tv_sec = 0; - timeout.tv_usec = 0; // poll - - if (TCP->maxsock == 0) - goto nosocks; - - memcpy(&readfd, &TCP->ListenSet, sizeof(fd_set)); - - retval = select((int)(TCP->maxsock) + 1, &readfd, NULL, NULL, &timeout); - - if (retval == -1) - { - retval = WSAGetLastError(); - perror("listen select"); - } - - if (retval) - { - n = 0; - while (TCP->FBBsock[n]) - { - sock = TCP->FBBsock[n]; - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->FBBPort[n]); - - n++; - } - - sock = TCP->TCPSock; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->TCPPort); - } - - sock = TCP->TriModeSock; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->TriModePort); - } - sock = TCP->TriModeDataSock; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->TriModePort + 1); - } - - sock = TCP->Relaysock; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->RelayPort); - } - - sock = TCP->HTTPsock; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->HTTPPort); - } - - sock = TCP->DRATSsock; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->DRATSPort); - } - - sock = TCP->Syncsock; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->SyncPort); - } - - - - n = 0; - - while (TCP->FBBsock6[n]) - { - sock = TCP->FBBsock6[n]; - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->FBBPort[n]); - n++; - } - - sock = TCP->sock6; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->TCPPort); - } - - sock = TCP->Relaysock6; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->RelayPort); - } - - sock = TCP->HTTPsock6; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->HTTPPort); - } - - sock = TCP->DRATSsock6; - if (sock) - { - if (FD_ISSET(sock, &readfd)) - Socket_Accept(TNC, sock, TCP->DRATSPort); - } - } - - // look for data on any active sockets - - maxsock = 0; - - FD_ZERO(&readfd); - FD_ZERO(&writefd); - FD_ZERO(&exceptfd); - - for (n = 0; n <= TCP->MaxSessions; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - - // Should we use write event after a blocked write ???? - - if (sockptr->SocketActive) - { -// if (sockptr->socket == 0) -// { -// Debugprintf("Active Session but zero socket"); -// DataSocket_Disconnect(TNC, sockptr); -// return; -// } - - if (TNC->Streams[n].Connecting) - { - // look for complete or failed - - FD_SET(sockptr->socket, &writefd); - FD_SET(sockptr->socket, &exceptfd); - } - else - { - FD_SET(sockptr->socket, &readfd); - FD_SET(sockptr->socket, &exceptfd); - } - Active++; - if (sockptr->socket > maxsock) - maxsock = sockptr->socket; - - if (sockptr->TriModeDataSock) - { - FD_SET(sockptr->TriModeDataSock, &readfd); - FD_SET(sockptr->TriModeDataSock, &exceptfd); - - if (sockptr->TriModeDataSock > maxsock) - maxsock = sockptr->TriModeDataSock; - } - } - } - - if (Active) - { - retval = select((int)maxsock + 1, &readfd, &writefd, &exceptfd, &timeout); - - if (retval == -1) - { - perror("data select"); - Debugprintf("Telnet Select Error %d Active %d", WSAGetLastError(), Active); - - for (n = 0; n <= TCP->MaxSessions; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - if (sockptr->SocketActive) - Debugprintf("Active Session %d socket %d", n, sockptr->socket); - } - } - else - { - if (retval) - { - // see who has data - - for (n = 0; n <= TCP->MaxSessions; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - - if (sockptr->SocketActive) - { - sock = sockptr->socket; - - if (sockptr->TriModeDataSock) - { - if (FD_ISSET(sockptr->TriModeDataSock, &readfd)) - { - ProcessTriModeDataMessage(TNC, sockptr, sockptr->TriModeDataSock, &TNC->Streams[n]); - } - } - - if (FD_ISSET(sock, &readfd)) - { - if (sockptr->RelayMode) - DataSocket_ReadRelay(TNC, sockptr, sock, &TNC->Streams[n]); - else if (sockptr->HTTPMode) - DataSocket_ReadHTTP(TNC, sockptr, sock, n); - else if (sockptr->SyncMode) - DataSocket_ReadSync(TNC, sockptr, sock, n); - else if (sockptr->FBBMode) - DataSocket_ReadFBB(TNC, sockptr, sock, n); - else if (sockptr->DRATSMode) - DataSocket_ReadDRATS(TNC, sockptr, sock, n); - else - DataSocket_Read(TNC, sockptr, sock, &TNC->Streams[n]); - } - - if (FD_ISSET(sock, &exceptfd)) - { - Debugprintf("exceptfd set"); - Telnet_Connected(TNC, sockptr, sock, 1); - } - - if (FD_ISSET(sock, &writefd)) - Telnet_Connected(TNC, sockptr, sock, 0); - - } - } - } - } - } - - -nosocks: - - // Try SNMP - - if (TCP->SNMPsock) - { - struct sockaddr_in rxaddr; - char rxbuff[500]; - int addrlen = sizeof(struct sockaddr_in); - int Offset = 0; - - int len = recvfrom(TCP->SNMPsock, rxbuff, 500, 0,(struct sockaddr *)&rxaddr, &addrlen); - - if (len > 0) - { - UCHAR Reply[256]; - int SendLen; - - SendLen = ProcessSNMPPayload(rxbuff, len, Reply, &Offset); - - if (SendLen == 0) - return; - - sendto(TCP->SNMPsock, &Reply[Offset], SendLen, 0, (struct sockaddr *)&rxaddr, addrlen); - return; - } - } - while (TELNETMONVECPTR->HOSTTRACEQ) - { - int len; - time_t stamp; - BOOL MonitorNODES = FALSE; - MESSAGE * monbuff; - UCHAR * monchars; - - unsigned char buffer[1024] = "\xff\x1b\xb"; - - monbuff = Q_REM((void **)&TELNETMONVECPTR->HOSTTRACEQ); - monchars = (UCHAR *)monbuff; - - stamp = monbuff->Timestamp; - - if (monbuff->PORT & 0x80) // TX - buffer[2] = 91; - else - buffer[2] = 17; - - for (Stream = 0; Stream <= TCP->MaxSessions; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream]) - { - struct ConnectionInfo * sockptr = STREAM->ConnectionInfo; - - if (sockptr->BPQTermMode) - { - if (sizeof(void *) > 4) - monchars += 4; - - if (!sockptr->MonitorNODES && monchars[21] == 3 && monchars[22] == 0xcf && monchars[23] == 0xff) - { - len = 0; - } - else - { - unsigned long long SaveMMASK = MMASK; - BOOL SaveMTX = MTX; - BOOL SaveMCOM = MCOM; - BOOL SaveMUI = MUIONLY; - - IntSetTraceOptionsEx(sockptr->MMASK, sockptr->MTX, sockptr->MCOM, sockptr->MUIOnly); - len = IntDecodeFrame((MESSAGE *)monbuff, &buffer[3], stamp, sockptr->MMASK, FALSE, FALSE); - IntSetTraceOptionsEx(SaveMMASK, SaveMTX, SaveMCOM, SaveMUI); - - if (len) - { - len += 3; - buffer[len++] = 0xfe; - send(STREAM->ConnectionInfo->socket, buffer, len, 0); - } - } - } - } - } - - ReleaseBuffer(monbuff); - } - - for (Stream = 0; Stream <= TCP->MaxSessions; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] && STREAM->Attached == 0) - { - // New Attach - - int calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, TNC->Streams[Stream].MyCall); - TNC->Streams[Stream].MyCall[calllen] = 0; - - STREAM->Attached = TRUE; - STREAM->FramesQueued= 0; - STREAM->NoCMSFallback = 0; - - continue; - } - - if (STREAM->Attached) - { - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] == 0 && STREAM->Attached) - { - // Node has disconnected - clear any connection - - struct ConnectionInfo * sockptr = TNC->Streams[Stream].ConnectionInfo; - SOCKET sock = sockptr->socket; - char Msg[80]; - PMSGWITHLEN buffptr; - - STREAM->Attached = FALSE; - STREAM->Connected = FALSE; - STREAM->NoCMSFallback = FALSE; - - sockptr->FromHostBuffPutptr = sockptr->FromHostBuffGetptr = 0; // clear any queued data - - while(TNC->Streams[Stream].BPQtoPACTOR_Q) - { - buffptr = (PMSGWITHLEN)Q_REM(&TNC->Streams[Stream].BPQtoPACTOR_Q); - if (TelSendPacket(Stream, &TNC->Streams[Stream], buffptr, sockptr->ADIF) == FALSE) - { - // Send failed, and has saved packet - // free saved and discard any more on queue - - free(sockptr->ResendBuffer); - sockptr->ResendBuffer = NULL; - sockptr->ResendLen = 0; - - while(TNC->Streams[Stream].BPQtoPACTOR_Q) - { - buffptr=Q_REM(&TNC->Streams[Stream].BPQtoPACTOR_Q); - ReleaseBuffer(buffptr); - } - break; - } - } - - while(TNC->Streams[Stream].PACTORtoBPQ_Q) - { - buffptr=Q_REM(&TNC->Streams[Stream].PACTORtoBPQ_Q); - ReleaseBuffer(buffptr); - } - - if (LogEnabled) - { - char logmsg[120]; - sprintf(logmsg,"%d Disconnected. Bytes Sent = %d Bytes Received %d\n", - sockptr->Number, STREAM->bytesTXed, STREAM->bytesRXed); - - WriteLog (logmsg); - } - - if (!sockptr->FBBMode) - { - sprintf(Msg,"*** Disconnected from Stream %d\r\n",Stream); - send(sock, Msg, (int)strlen(Msg),0); - } - - if (sockptr->UserPointer == &TriModeUser) - { - // Always Disconnect - - send(sockptr->socket, "DISCONNECTED\r\n", 14, 0); - return; - } - - if (sockptr->UserPointer == &CMSUser) - { - if (CMSLogEnabled) - { - char logmsg[120]; - sprintf(logmsg,"%d Disconnected. Bytes Sent = %d Bytes Received %d Time %d Seconds\r\n", - sockptr->Number, STREAM->bytesTXed, STREAM->bytesRXed, (int)(time(NULL) - sockptr->ConnectTime)); - - WriteCMSLog (logmsg); - } - - // Don't report if Internet down unless ReportRelayTraffic set) - - if (sockptr->RelaySession == FALSE || TCP->ReportRelayTraffic) - SendWL2KSessionRecord(sockptr->ADIF, STREAM->bytesTXed, STREAM->bytesRXed); - - WriteADIFRecord(sockptr->ADIF); - - if (sockptr->ADIF) - free(sockptr->ADIF); - - sockptr->ADIF = NULL; - - // Always Disconnect CMS Socket - - DataSocket_Disconnect(TNC, sockptr); - return; - } - - if (sockptr->RelayMode) - { - // Always Disconnect Relay Socket - - Sleep(100); - DataSocket_Disconnect(TNC, sockptr); - return; - } - - if (sockptr->Signon[0] || sockptr->ClientSession) // Outward Connect - { - Sleep(1000); - DataSocket_Disconnect(TNC, sockptr); - return; - } - - - if (TCP->DisconnectOnClose) - { - Sleep(1000); - DataSocket_Disconnect(TNC, sockptr); - } - else - { - char DisfromNodeMsg[] = "Disconnected from Node - Telnet Session kept\r\n"; - send(sockptr->socket, DisfromNodeMsg, (int)strlen(DisfromNodeMsg),0); - } - } - } - } - - for (Stream = 0; Stream <= TCP->MaxSessions; Stream++) - { - struct ConnectionInfo * sockptr = TNC->Streams[Stream].ConnectionInfo; - STREAM = &TNC->Streams[Stream]; - - if (sockptr->SocketActive && sockptr->Keepalive && L4LIMIT) - { -#ifdef WIN32 - if ((REALTIMETICKS - sockptr->LastSendTime) > (L4LIMIT - 60) * 9) // PC Ticks are about 10% slow -#else - if ((REALTIMETICKS - sockptr->LastSendTime) > (L4LIMIT - 60) * 10) -#endif - { - // Send Keepalive - - sockptr->LastSendTime = REALTIMETICKS; - BuffertoNode(sockptr, "Keepalive\r", 10); - } - } - - if (sockptr->ResendBuffer) - { - // Data saved after EWOULDBLOCK returned to send - - UCHAR * ptr = sockptr->ResendBuffer; - sockptr->ResendBuffer = NULL; - - SendAndCheck(sockptr, ptr, sockptr->ResendLen, 0); - free(ptr); - - continue; - } - - while (STREAM->BPQtoPACTOR_Q) - { - int datalen; - PMSGWITHLEN buffptr; - UCHAR * MsgPtr; - - // Make sure there is space. Linux TCP buffer is quite small - // Windows doesn't support SIOCOUTQ - -#ifndef WIN32 - int value = 0, error; - - error = ioctl(sockptr->socket, SIOCOUTQ, &value); - - if (value > 1500) - break; -#endif - buffptr = (PMSGWITHLEN)Q_REM(&TNC->Streams[Stream].BPQtoPACTOR_Q); - STREAM->FramesQueued--; - datalen = (int)(buffptr->Len); - MsgPtr = &buffptr->Data[0]; - - if (STREAM->ConnectionInfo->TriMode) - { - ProcessTrimodeResponse(TNC, STREAM, MsgPtr, datalen); - ReleaseBuffer(buffptr); - return; - } - - - if (TNC->Streams[Stream].Connected) - { - if (sockptr->SyncMode) - { - // Suppress Conected and SID - Relay doesn't understand them - - if (strstr(buffptr->Data, "Connected to") || memcmp(buffptr->Data, "[BPQ-", 5) == 0) - { - ReleaseBuffer(buffptr); - return; - } - } - - if (TelSendPacket(Stream, STREAM, buffptr, sockptr->ADIF) == FALSE) - { - // Send failed, and has requeued packet - // Dont send any more - - break; - } - } - else // Not Connected - { - // Command. Do some sanity checking and look for things to process locally - - datalen--; // Exclude CR - MsgPtr[datalen] = 0; // Null Terminate - - if (_stricmp(MsgPtr, "NoFallback") == 0) - { - TNC->Streams[Stream].NoCMSFallback = TRUE; - buffptr->Len = sprintf(&buffptr->Data[0], "Ok\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - return; - } - - if (_memicmp(MsgPtr, "D", 1) == 0) - { - TNC->Streams[Stream].ReportDISC = TRUE; // Tell Node - ReleaseBuffer(buffptr); - return; - } - - if ((_memicmp(MsgPtr, "C", 1) == 0) && MsgPtr[1] == ' ' && datalen > 2) // Connect - { - char Host[100] = ""; - char P2[100] = ""; - char P3[100] = ""; - char P4[100] = ""; - char P5[100] = ""; - char P6[100] = ""; - char P7[100] = ""; - unsigned int Port = 0; - int n; - - n = sscanf(&MsgPtr[2], "%s %s %s %s %s %s %s", - &Host[0], &P2[0], &P3[0], &P4[0], &P5[0], &P6[0], &P7[0]); - - sockptr->Signon[0] = 0; // Not outgoing; - sockptr->Keepalive = FALSE; // No Keepalives - sockptr->NoCallsign = FALSE; - sockptr->UTF8 = 0; // Not UTF8 - - if (_stricmp(Host, "HOST") == 0) - { - Port = atoi(P2); - - if (Port > MaxBPQPortNo || TCP->CMDPort[Port] == 0) - { - buffptr->Len = sprintf(&buffptr->Data[0], "Error - Invalid HOST Port\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - STREAM->NeedDisc = 10; - return; - } - - STREAM->Connecting = TRUE; - sockptr->CMSSession = FALSE; - sockptr->FBBMode = FALSE; - - if (P3[0] == 'K' || P4[0] == 'K' || P5[0] == 'K' || P6[0] == 'K') - { - sockptr->Keepalive = TRUE; - sockptr->LastSendTime = REALTIMETICKS; - } - - if (P3[0] == 'S' || P4[0] == 'S' || P5[0] == 'S' || P6[0] == 'S') - { - // Set Say flag on partner session - - struct _TRANSPORTENTRY * Sess = TNC->PortRecord->ATTACHEDSESSIONS[sockptr->Number]->L4CROSSLINK; - if (Sess) - Sess->STAYFLAG = 1; - } - - if (_stricmp(P3, "NOCALL") == 0 || _stricmp(P4, "NOCALL") == 0 || _stricmp(P5, "NOCALL") == 0 || _stricmp(P6, "NOCALL") == 0) - sockptr->NoCallsign = TRUE; - - if (_stricmp(P3, "TRANS") == 0 || _stricmp(P4, "TRANS") == 0 || _stricmp(P5, "TRANS") == 0 || _stricmp(P6, "TRANS") == 0) - { - sockptr->FBBMode = TRUE; - sockptr->NeedLF = TRUE; - } - - TCPConnect(TNC, TCP, STREAM, "127.0.0.1", TCP->CMDPort[Port], sockptr->FBBMode); - ReleaseBuffer(buffptr); - return; - } - - if (_stricmp(Host, "RELAY") == 0) - { - if (P2[0] == 0) - { - strcpy(P2, TCP->RELAYHOST); - strcpy(P3, "8772"); - } - - if (P2[0]) - { - STREAM->Connecting = TRUE; - STREAM->ConnectionInfo->CMSSession = TRUE; - STREAM->ConnectionInfo->RelaySession = TRUE; - TCPConnect(TNC, TCP, STREAM, P2, atoi(P3), TRUE); - ReleaseBuffer(buffptr); - return; - } - } - - if (_stricmp(Host, "SYNC") == 0) - { - if (P2[0] == 0) - { - strcpy(P2, TCP->RELAYHOST); - strcpy(P3, "8780"); - } - - if (P2[0]) - { - sockptr->CMSSession = FALSE; - STREAM->Connecting = TRUE; - STREAM->ConnectionInfo->SyncMode = TRUE; - TCPConnect(TNC, TCP, STREAM, P2, atoi(P3), TRUE); - ReleaseBuffer(buffptr); - return; - } - } - - - if (_stricmp(Host, "CMS") == 0) - { - if (TCP->CMS == 0 || !TCP->CMSOK) - { - if (TCP->RELAYHOST[0] && TCP->FallbacktoRelay && STREAM->NoCMSFallback == 0) - { - STREAM->Connecting = TRUE; - STREAM->ConnectionInfo->CMSSession = TRUE; - STREAM->ConnectionInfo->RelaySession = TRUE; - TCPConnect(TNC, TCP, STREAM, TCP->RELAYHOST, 8772, TRUE); - ReleaseBuffer(buffptr); - return; - } - - buffptr->Len = sprintf(&buffptr->Data[0], "Error - CMS Not Available\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - STREAM->NeedDisc = 10; - CheckCMS(TNC); - - return; - } - - STREAM->Connecting = TRUE; - STREAM->ConnectionInfo->CMSSession = TRUE; - STREAM->ConnectionInfo->RelaySession = FALSE; - CMSConnect(TNC, TCP, STREAM, Stream); - ReleaseBuffer(buffptr); - - return; - } - - // Outward Connect. - - // Only Allow user specified host if Secure Session - - if (TCP->SecureTelnet) - { - struct _TRANSPORTENTRY * Sess = TNC->PortRecord->ATTACHEDSESSIONS[sockptr->Number]; - -// if (Sess && Sess->L4CROSSLINK) -// Sess = Sess->L4CROSSLINK; - - if (Sess && !Sess->Secure_Session) - { - buffptr->Len = sprintf(&buffptr->Data[0], "Error - Telnet Outward Connect needs SYSOP Status\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - STREAM->NeedDisc = 10; - return; - } - } - - Port = atoi(P2); - - if (Port) - { - int useFBBMode = TRUE; - - STREAM->Connecting = TRUE; - STREAM->ConnectionInfo->CMSSession = FALSE; - STREAM->ConnectionInfo->RelaySession = FALSE; - - if (_stricmp(P3, "TELNET") == 0) - { -// // FBB with CRLF - - STREAM->ConnectionInfo->NeedLF = TRUE; - } - else if (_stricmp(P3, "REALTELNET") == 0) - { -// // Telnet Mode with CRLF - - useFBBMode = FALSE; - STREAM->ConnectionInfo->NeedLF = TRUE; - } - else - STREAM->ConnectionInfo->NeedLF = FALSE; - - - STREAM->ConnectionInfo->FBBMode = TRUE; - - if (_stricmp(P3, "NOCALL") == 0 || _stricmp(P4, "NOCALL") == 0 || _stricmp(P5, "NOCALL") == 0 || _stricmp(P6, "NOCALL") == 0) - { - STREAM->ConnectionInfo->NoCallsign = TRUE; - } - else - { - if (_stricmp(P3, "NEEDLF") == 0 || STREAM->ConnectionInfo->NeedLF) - { - // Send LF after each param - - if (P6[0]) - sprintf(STREAM->ConnectionInfo->Signon, "%s\r\n%s\r\n%s\r\n", P4, P5, P6); - else - if (P5[0]) - sprintf(STREAM->ConnectionInfo->Signon, "%s\r\n%s\r\n", P4, P5); - else - if (P4[0]) - sprintf(STREAM->ConnectionInfo->Signon, "%s\r\n", P4); - } - else - { - if (P5[0]) - sprintf(STREAM->ConnectionInfo->Signon, "%s\r%s\r%s\r", P3, P4, P5); - else - if (P4[0]) - sprintf(STREAM->ConnectionInfo->Signon, "%s\r%s\r", P3, P4); - else - if (P3[0]) - sprintf(STREAM->ConnectionInfo->Signon, "%s\r", P3); - } - } - - TCPConnect(TNC, TCP, STREAM, Host, Port, useFBBMode); - ReleaseBuffer(buffptr); - return; - } - } - - buffptr->Len = sprintf(&buffptr->Data[0], "Error - Invalid Command\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - STREAM->NeedDisc = 10; - return; - } - } - - Msglen = sockptr->FromHostBuffPutptr - sockptr->FromHostBuffGetptr; - - if (Msglen) - { - int Paclen = 0; - int Queued = 0; - TRANSPORTENTRY * Sess1 = TNC->PortRecord->ATTACHEDSESSIONS[Stream]; - TRANSPORTENTRY * Sess2 = NULL; - - if (Sess1) - Sess2 = Sess1->L4CROSSLINK; - - // Can't use TXCount - it is Semaphored= - - Queued = C_Q_COUNT(&TNC->Streams[Stream].PACTORtoBPQ_Q); - Queued += C_Q_COUNT((UINT *)&TNC->PortRecord->PORTCONTROL.PORTRX_Q); - - if (Sess2) - Queued += CountFramesQueuedOnSession(Sess2); - - if (Sess1) - Queued += CountFramesQueuedOnSession(Sess1); - - if (Queued > 15) - continue; - - if (Sess1) - Paclen = Sess1->SESSPACLEN; - - if (Paclen == 0) - Paclen = 256; - - ShowConnections(TNC); - - if (Msglen > Paclen) - Msglen = Paclen; - - if (Sess1) Sess1->L4KILLTIMER = 0; - if (Sess2) Sess2->L4KILLTIMER = 0; - - SendtoNode(TNC, Stream, &sockptr->FromHostBuffer[sockptr->FromHostBuffGetptr], Msglen); - sockptr->FromHostBuffGetptr += Msglen; - sockptr->LastSendTime = REALTIMETICKS; - } - } -} - -#ifndef LINBPQ - -LRESULT CALLBACK TelWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - struct ConnectionInfo * sockptr; - SOCKET sock; - int i, n; - struct TNCINFO * TNC; - struct TCPINFO * TCP; - struct _EXTPORTDATA * PortRecord; - HWND SavehDlg, SaveCMS, SaveMonitor; - HMENU SaveMenu1, SaveMenu2, SaveMenu3; - MINMAXINFO * mmi; - - LPMEASUREITEMSTRUCT lpmis; // pointer to item of data - LPDRAWITEMSTRUCT lpdis; // pointer to item drawing data - -// struct ConnectionInfo * ConnectionInfo; - - for (i=1; i <= MAXBPQPORTS; i++) - { - TNC = TNCInfo[i]; - if (TNC == NULL) - continue; - - if (TNC->hDlg == hWnd) - break; - } - - if (TNC == NULL) - return DefMDIChildProc(hWnd, message, wParam, lParam); - - switch (message) - { -// case WM_SIZING: - case WM_SIZE: - { - RECT rcClient; - int ClientHeight, ClientWidth; - - GetClientRect(TNC->hDlg, &rcClient); - - ClientHeight = rcClient.bottom; - ClientWidth = rcClient.right; - - MoveWindow(TNC->hMonitor, 0,20 ,ClientWidth-4, ClientHeight-25, TRUE); - break; - } - - case WM_GETMINMAXINFO: - - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = 400; - mmi->ptMaxSize.y = 500; - mmi->ptMaxTrackSize.x = 400; - mmi->ptMaxTrackSize.y = 500; - break; - - - case WM_MDIACTIVATE: - { - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)hPopMenu, "Actions"); - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - // call DrawMenuBar after the menu items are set - DrawMenuBar(FrameWnd); - - return TRUE; //DefMDIChildProc(hWnd, message, wParam, lParam); - - } - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - case SC_RESTORE: - - TNC->Minimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case SC_MINIMIZE: - - TNC->Minimized = TRUE; - return DefMDIChildProc(hWnd, message, wParam, lParam); - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_COMMAND: - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - // Parse the menu selections: - - if (wmId > IDM_DISCONNECT && wmId < IDM_DISCONNECT+MaxSockets+1) - { - // disconnect user - - sockptr = TNC->Streams[wmId-IDM_DISCONNECT].ConnectionInfo; - - if (sockptr->SocketActive) - { - sock=sockptr->socket; - - send(sock,disMsg, (int)strlen(disMsg),0); - - Sleep (1000); - - shutdown(sock,2); - - DataSocket_Disconnect(TNC, sockptr); - - TNC->Streams[wmId-IDM_DISCONNECT].ReportDISC = TRUE; //Tell Node - - return 0; - } - } - - switch (wmId) - { - case CMSENABLED: - - // Toggle CMS Enabled Flag - - TCP = TNC->TCPInfo; - - TCP->CMS = !TCP->CMS; - CheckMenuItem(TCP->hActionMenu, 3, MF_BYPOSITION | TCP->CMS<<3); - - if (TCP->CMS) - CheckCMS(TNC); - else - { - TCP->CMSOK = FALSE; - SetWindowText(TCP->hCMSWnd, "CMS Off"); - } - break; - - case IDM_LOGGING: - - // Toggle Logging Flag - - LogEnabled = !LogEnabled; - CheckMenuItem(TNC->TCPInfo->hLogMenu, 0, MF_BYPOSITION | LogEnabled<<3); - - break; - - case IDM_CMS_LOGGING: - - // Toggle Logging Flag - - LogEnabled = !LogEnabled; - CheckMenuItem(TNC->TCPInfo->hLogMenu, 1, MF_BYPOSITION | CMSLogEnabled<<3); - - break; - - case TELNET_RECONFIG: - - if (!ProcessConfig()) - { - Consoleprintf("Failed to reread config file - leaving config unchanged"); - break; - } - - FreeConfig(); - - for (n = 1; n <= TNC->TCPInfo->CurrentSockets; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - sockptr->SocketActive = FALSE; - closesocket(sockptr->socket); - } - - TCP = TNC->TCPInfo; - - shutdown(TCP->TCPSock, SD_BOTH); - shutdown(TCP->sock6, SD_BOTH); - - n = 0; - while (TCP->FBBsock[n]) - shutdown(TCP->FBBsock[n++], SD_BOTH); - - shutdown(TCP->Relaysock, SD_BOTH); - shutdown(TCP->HTTPsock, SD_BOTH); - shutdown(TCP->HTTPsock6, SD_BOTH); - - - n = 0; - while (TCP->FBBsock6[n]) - shutdown(TCP->FBBsock[n++], SD_BOTH); - - shutdown(TCP->Relaysock6, SD_BOTH); - - Sleep(500); - - closesocket(TCP->TCPSock); - closesocket(TCP->sock6); - - n = 0; - while (TCP->FBBsock[n]) - closesocket(TCP->FBBsock[n++]); - - n = 0; - while (TCP->FBBsock6[n]) - closesocket(TCP->FBBsock6[n++]); - - closesocket(TCP->Relaysock); - closesocket(TCP->Relaysock6); - closesocket(TCP->HTTPsock); - closesocket(TCP->HTTPsock6); - - // Save info from old TNC record - - n = TNC->Port; - PortRecord = TNC->PortRecord; - SavehDlg = TNC->hDlg; - SaveCMS = TCP->hCMSWnd; - SaveMonitor = TNC->hMonitor; - SaveMenu1 = TCP->hActionMenu; - SaveMenu2 = TCP->hDisMenu; - SaveMenu3 = TCP->hLogMenu; - - // Free old TCP Session Stucts - - for (i = 0; i <= TNC->TCPInfo->MaxSessions; i++) - { - free(TNC->Streams[i].ConnectionInfo); - } - - ReadConfigFile(TNC->Port, ProcessLine); - - TNC = TNCInfo[n]; - TNC->Port = n; - TNC->Hardware = H_TELNET; - TNC->hDlg = SavehDlg; - TNC->RIG = &TNC->DummyRig; // Not using Rig control, so use Dummy - - // Get Menu Handles - - TCP = TNC->TCPInfo; - - TCP->hCMSWnd = SaveCMS; - TNC->hMonitor = SaveMonitor; - TCP->hActionMenu = SaveMenu1; - TCP->hDisMenu = SaveMenu2; - TCP->hLogMenu = SaveMenu3; - - CheckMenuItem(TCP->hActionMenu, 3, MF_BYPOSITION | TNC->TCPInfo->CMS<<3); - CheckMenuItem(TCP->hLogMenu, 0, MF_BYPOSITION | LogEnabled<<3); - CheckMenuItem(TCP->hLogMenu, 1, MF_BYPOSITION | CMSLogEnabled<<3); - - // Malloc TCP Session Stucts - - for (i = 0; i <= TNC->TCPInfo->MaxSessions; i++) - { - TNC->Streams[i].ConnectionInfo = zalloc(sizeof(struct ConnectionInfo)); - TNC->Streams[i].ConnectionInfo->Number = i; - - TCP->CurrentSockets = i; //Record max used to save searching all entries - - if (i > 0) - ModifyMenu(TCP->hDisMenu,i - 1 ,MF_BYPOSITION | MF_STRING,IDM_DISCONNECT + 1, "."); - } - - TNC->PortRecord = PortRecord; - - Sleep(500); - OpenSockets(TNC); - OpenSockets6(TNC); - SetupListenSet(TNC); - CheckCMS(TNC); - ShowConnections(TNC); - - break; - default: - return DefMDIChildProc(hWnd, message, wParam, lParam); - } - break; - - // case WM_SIZE: - -// if (wParam == SIZE_MINIMIZED) -// return (0); - - case WM_CTLCOLORDLG: - - return (LONG)bgBrush; - - - case WM_CTLCOLORSTATIC: - { - HDC hdcStatic = (HDC)wParam; - - if (TNC->TCPInfo->hCMSWnd == (HWND)lParam) - { - if (TNC->TCPInfo->CMSOK) - SetTextColor(hdcStatic, RGB(0, 128, 0)); - else - SetTextColor(hdcStatic, RGB(255, 0, 0)); - } - - SetBkMode(hdcStatic, TRANSPARENT); - return (LONG)bgBrush; - } - case WM_MEASUREITEM: - - // Retrieve pointers to the menu item's - // MEASUREITEMSTRUCT structure and MYITEM structure. - - lpmis = (LPMEASUREITEMSTRUCT) lParam; - lpmis->itemWidth = 300; - - return TRUE; - - case WM_DRAWITEM: - - // Get pointers to the menu item's DRAWITEMSTRUCT - // structure and MYITEM structure. - - lpdis = (LPDRAWITEMSTRUCT) lParam; - - // If the user has selected the item, use the selected - // text and background colors to display the item. - - SetTextColor(lpdis->hDC, RGB(0, 128, 0)); - - if (TNC->TCPInfo->CMS) - { - if (TNC->TCPInfo->CMSOK) - TextOut(lpdis->hDC, 340, lpdis->rcItem.top + 2, "CMS OK", 6); - else - { - SetTextColor(lpdis->hDC, RGB(255, 0, 0)); - TextOut(lpdis->hDC, 340, lpdis->rcItem.top + 2, "NO CMS", 6); - } - } - else - TextOut(lpdis->hDC, 340, lpdis->rcItem.top + 2, " ", 13); - - return TRUE; - - case WM_DESTROY: - - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - -} -#endif - -int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port) -{ - int n, addrlen = sizeof(struct sockaddr_in6); - struct sockaddr_in6 sin6; - - struct ConnectionInfo * sockptr; - SOCKET sock; - char Negotiate[6]={IAC,WILL,suppressgoahead,IAC,WILL,echo}; -// char Negotiate[3]={IAC,WILL,echo}; - struct TCPINFO * TCP = TNC->TCPInfo; - HMENU hDisMenu = TCP->hDisMenu; - u_long param=1; - - // if for TriModeData Session, use the TriMode Control connection entry - - if (SocketId == TCP->TriModeDataSock) - { - sockptr = TNC->TCPInfo->TriModeControlSession; - sock = accept(SocketId, (struct sockaddr *)&sockptr->sin, &addrlen); - sockptr->TriModeDataSock = sock; - ioctl(sock, FIONBIO, ¶m); - - return 0; - } - -// Find a free Session - - for (n = 1; n <= TCP->MaxSessions; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - - if (sockptr->SocketActive == FALSE) - { - sock = accept(SocketId, (struct sockaddr *)&sockptr->sin, &addrlen); - - if (sock == INVALID_SOCKET) - { - Debugprintf("BPQ32 Telnet accept() failed Error %d", WSAGetLastError()); - return FALSE; - } - - // Log, including port - - if (LogEnabled) - { - char Addr[256]; - char logmsg[512]; - - Tel_Format_Addr(sockptr, Addr); - - sprintf(logmsg,"%d %s Incoming Connect on Port %d\n", sockptr->Number, Addr, Port); - WriteLog (logmsg); - } - - - -// Debugprintf("BPQ32 Telnet accept() Sock %d", sock); - - ioctl(sock, FIONBIO, ¶m); - - sockptr->socket = sock; - sockptr->SocketActive = TRUE; - sockptr->InputLen = 0; - sockptr->Number = n; - sockptr->LoginState = 0; - sockptr->UserPointer = 0; - sockptr->DoEcho = FALSE; - sockptr->BPQTermMode = FALSE; - sockptr->ConnectTime = time(NULL); - sockptr->Keepalive = FALSE; - sockptr->UTF8 = 0; - - TNC->Streams[n].bytesRXed = TNC->Streams[n].bytesTXed = 0; - TNC->Streams[n].FramesQueued = 0; - - sockptr->HTTPMode = FALSE; - sockptr->APIMode = FALSE; - sockptr->SyncMode = FALSE; - sockptr->DRATSMode = FALSE; - sockptr->FBBMode = FALSE; - sockptr->RelayMode = FALSE; - sockptr->ClientSession = FALSE; - sockptr->NeedLF = FALSE; - sockptr->TNC = TNC; - sockptr->WebSocks = 0; - - if (sockptr->ADIF == NULL) - sockptr->ADIF = malloc(sizeof(struct ADIF)); - - memset(sockptr->ADIF, 0, sizeof(struct ADIF)); - - if (SocketId == TCP->HTTPsock || SocketId == TCP->HTTPsock6) - sockptr->HTTPMode = TRUE; - - if (SocketId == TCP->APIsock || SocketId == TCP->APIsock6) - { - sockptr->HTTPMode = TRUE; // API is a type of HTTP socket - sockptr->APIMode = TRUE; - } - else if (SocketId == TCP->Syncsock || SocketId == TCP->Syncsock6) - sockptr->SyncMode = TRUE; - else if (SocketId == TCP->DRATSsock || SocketId == TCP->DRATSsock6) - sockptr->DRATSMode = TRUE; - - else if (SocketId == TCP->Relaysock || SocketId == TCP->Relaysock6) - { - sockptr->RelayMode = TRUE; - sockptr->FBBMode = TRUE; - } - else if (SocketId == TCP->TriModeSock) - { - sockptr->TriMode = TRUE; - sockptr->FBBMode = TRUE; - TNC->TCPInfo->TriModeControlSession = sockptr; - sockptr->TriModeConnected = FALSE; - sockptr->TriModeDataSock = 0; - } - else if (SocketId != TCP->TCPSock && SocketId != TCP->sock6) // We can have several listening FBB mode sockets - sockptr->FBBMode = TRUE; -#ifndef LINBPQ - ModifyMenu(hDisMenu, n - 1, MF_BYPOSITION | MF_STRING, IDM_DISCONNECT + n, "."); - DrawMenuBar(TNC->hDlg); -#endif - ShowConnections(TNC); - - if (sockptr->HTTPMode) - return 0; - - if (sockptr->DRATSMode) - { - send(sock, "100 Authentication not required\n", 33, 0); - sockptr->LoginState = 2; - return 0; - } - - if (sockptr->SyncMode) - { - char MyCall[16] = ""; - char Hello[32]; - int Len; - memcpy(MyCall, MYNODECALL, 10); - strlop(MyCall, ' '); - strlop(MyCall, '-'); - - Len = sprintf(Hello, "POSYNCHELLO %s\r", MyCall); - - send(sock, Hello, Len, 0); - return 0; - } - else - if (sockptr->RelayMode) - { - send(sock,"\r\rCallsign :\r", 13,0); - } - else - if (sockptr->TriMode) - { - // Trimode emulator Control Connection. - - sockptr->UserPointer = &TriModeUser; - - - send(sock,"CMD\r\n", 5,0); - sockptr->LoginState = 5; - } - else - if (sockptr->FBBMode == FALSE) - { - send(sock, Negotiate, 6, 0); - send(sock, TCP->LoginMsg, (int)strlen(TCP->LoginMsg), 0); - } - - if (sockptr->FromHostBuffer == 0) - { - sockptr->FromHostBuffer = malloc(10000); - sockptr->FromHostBufferSize = 10000; - } - - sockptr->FromHostBuffPutptr = sockptr->FromHostBuffGetptr = 0; - - return 0; - } - } - - // No free sessions. Must accept() then close - - sock = accept(SocketId, (struct sockaddr *)&sin6, &addrlen); - - send(sock,"No Free Sessions\r\n", 18,0); - Debugprintf("No Free Telnet Sessions"); - - Sleep (1000); - closesocket(sock); - - return 0; -} - -/* -int Socket_Data(struct TNCINFO * TNC, int sock, int error, int eventcode) -{ - int n; - struct ConnectionInfo * sockptr; - struct TCPINFO * TCP = TNC->TCPInfo; - HMENU hDisMenu = TCP->hDisMenu; - - // Find Connection Record - - for (n = 0; n <= TCP->CurrentSockets; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - - if (sockptr->socket == sock && sockptr->SocketActive) - { -#ifndef LINBPQ - switch (eventcode) - { - case FD_READ: - - if (sockptr->RelayMode) - return DataSocket_ReadRelay(TNC, sockptr, sock, &TNC->Streams[n]); - - if (sockptr->HTTPMode) - return DataSocket_ReadHTTP(TNC, sockptr, sock, n); - - if (sockptr->FBBMode) - return DataSocket_ReadFBB(TNC, sockptr, sock, n); - else - return DataSocket_Read(TNC, sockptr, sock, &TNC->Streams[n]); - - case FD_WRITE: - - return 0; - - case FD_OOB: - - return 0; - - case FD_ACCEPT: - - return 0; - - case FD_CONNECT: - - return 0; - - case FD_CLOSE: - - TNC->Streams[n].ReportDISC = TRUE; //Tell Node - DataSocket_Disconnect(TNC, sockptr); - return 0; - } - return 0; -#endif - } - - } - - return 0; -} - -*/ -#define PACLEN 100 - -VOID SendtoNode(struct TNCINFO * TNC, int Stream, char * Msg, int MsgLen) -{ - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == NULL) - return; // No buffers, so ignore - - if (TNC->Streams[Stream].Connected == 0) - { - // Connection Closed - Get Another - - struct ConnectionInfo * sockptr = TNC->Streams[Stream].ConnectionInfo; - - if (ProcessIncommingConnect(TNC, sockptr->Callsign, sockptr->Number, FALSE) == FALSE) - { - DataSocket_Disconnect(TNC, sockptr); //' Tidy up - return; - } - - if (sockptr->UserPointer) - TNC->PortRecord->ATTACHEDSESSIONS[sockptr->Number]->Secure_Session = sockptr->UserPointer->Secure; - } - - buffptr->Len= MsgLen; // Length - - memcpy(&buffptr->Data, Msg, MsgLen); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); -} - -int InnerProcessData(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, struct STREAMINFO * STREAM, int len); - - -int DataSocket_Read(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, struct STREAMINFO * STREAM) -{ - int len=0, maxlen; - char NLMsg[3]={13,10,0}; - byte * IACptr; - BOOL wait; - - struct TCPINFO * TCP = TNC->TCPInfo; - int SendIndex = 0; - byte * TelCommand; - int beforeIAC = 0; - int rest = 0; - - ioctl(sock,FIONREAD,&len); - - maxlen = InputBufferLen - sockptr->InputLen; - - if (len > maxlen) len=maxlen; - - len = recv(sock, &sockptr->InputBuffer[sockptr->InputLen], len, 0); - - if (len == SOCKET_ERROR || len ==0) - { - // Failed or closed - clear connection - - TNC->Streams[sockptr->Number].ReportDISC = TRUE; //Tell Node - DataSocket_Disconnect(TNC, sockptr); - return 0; - } - - // If message contains Telnet Commands we should process the data in the buffer first - // and not echo the commands! - - - IACptr = memchr(sockptr->InputBuffer, IAC, sockptr->InputLen + len); - - if (IACptr) - { - beforeIAC = IACptr - sockptr->InputBuffer; - rest = (sockptr->InputLen + len) - beforeIAC; - - if (beforeIAC) - { - TelCommand = malloc(rest); - memcpy(TelCommand, IACptr, rest); - InnerProcessData(TNC, sockptr, sock, STREAM, beforeIAC); - - // There may still be data in buffer, but it may be less than before - // Put IAC and following into buffer - - memcpy(&sockptr->InputBuffer[sockptr->InputLen], TelCommand, rest); - len -= sockptr->InputLen; - free(TelCommand); - } - } - -IACLoop: - - IACptr = memchr(sockptr->InputBuffer, IAC, sockptr->InputLen + len); - - if (IACptr) - { - // There still may be data in the buffer. - - wait = ProcessTelnetCommand(sockptr, IACptr, &rest); - - if (wait) - { - // Need more. - - sockptr->InputLen += len; - return 0; // wait for more chars - } - - // If ProcessTelnet Command returns FALSE, then it has removed the IAC and its - // params from the buffer. There may still be more to process. - - if (rest == 0) - return 0; // Nothing Left - - memmove(&sockptr->InputBuffer[sockptr->InputLen], IACptr + len - rest, rest); - len = rest; - - goto IACLoop; // There may be more - } - - return InnerProcessData(TNC, sockptr, sock, STREAM, len); -} - - -int InnerProcessData(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, struct STREAMINFO * STREAM, int len) -{ - int InputLen, MsgLen, i, n,charsAfter; - char NLMsg[3]={13,10,0}; - byte * CRPtr; - byte * LFPtr; - byte * BSptr; - byte * MsgPtr; - char logmsg[1000]; - struct UserRec * USER; - struct TCPINFO * TCP = TNC->TCPInfo; - int SendIndex = 0; - - // echo data just read - - if (sockptr->DoEcho && sockptr->LoginState != 1) // Password - send(sockptr->socket,&sockptr->InputBuffer[sockptr->InputLen], len, 0); - - sockptr->InputLen += len; - - // look for backspaces in data just read - - BSptr = memchr(&sockptr->InputBuffer[0], 8, sockptr->InputLen); - - if (BSptr == NULL) - BSptr = memchr(&sockptr->InputBuffer[0], 127, sockptr->InputLen); - - if (BSptr != 0) - { - // single char or BS as last is most likely, and worth treating as a special case - - int n; - - charsAfter = sockptr->InputLen - (int)((BSptr-&sockptr->InputBuffer[0])) - 1; - - if (charsAfter == 0) - { - sockptr->InputLen--; - if (sockptr->InputLen > 0) - sockptr->InputLen--; //Remove last char - - goto noBS; - } - // more than single char. Copy stuff after bs over char before - - memmove(BSptr-1, BSptr+1, charsAfter); - - n = sockptr->InputLen; - - sockptr->InputLen -= 2; // drop bs and char before - - // see if more bs chars -BSCheck: - BSptr = memchr(&sockptr->InputBuffer[0], 8, sockptr->InputLen); - - if (BSptr == NULL) - BSptr = memchr(&sockptr->InputBuffer[0], 127, sockptr->InputLen); - - if (BSptr == NULL) - goto noBS; - - charsAfter = sockptr->InputLen - (int)((BSptr-&sockptr->InputBuffer[0])) - 1; - - if (charsAfter == 0) - { - sockptr->InputLen--; // Remove BS - if (sockptr->InputLen > 0) - sockptr->InputLen--; //Remove last char if not at start - goto noBS; - } - - memmove(BSptr-1, BSptr+1, charsAfter); - sockptr->InputLen--; // Remove BS - if (sockptr->InputLen > 0) sockptr->InputLen--; //Remove last char if not at start - - goto BSCheck; // may be more bs chars - } - -noBS: - - // Extract lines from input stream - - MsgPtr = &sockptr->InputBuffer[0]; - InputLen = sockptr->InputLen; - -MsgLoop: - - // if in Client Mode, accept CR, CR Null, CR LF or LF, and replace with CR - // Also send immediately to client - dont wait for complete lines - - if (sockptr->ClientSession) - { - int n = InputLen; - char * ptr = MsgPtr; - char * Start = MsgPtr; - char c; - int len = 0; - char NodeLine[300]; - char * optr = NodeLine; - - while (n--) - { - c = *(ptr++); - - if (c == 0) - // Ignore Nulls - continue; - - len++; - *(optr++) = c; - - if (c == 13) - { - // See if next is lf or null - - if (n) - { - // Some Left - - if ((*ptr) == 0 || *(ptr) == 10) - { - // skip next - - n--; - ptr++; - } - } - } - else if (c == 10) - { - *(optr - 1) = 13; - } - else - { - // Normal Char - - if (len >= PACLEN) - { - BuffertoNode(sockptr, NodeLine, len); - optr = NodeLine; - len = 0; - } - } - } - - // All scanned - send anything outstanding - - if (len) - BuffertoNode(sockptr, NodeLine, len); - - sockptr->InputLen = 0; - ShowConnections(TNC);; - - return 0; - } - - - // Server Mode - - CRPtr=memchr(MsgPtr, 13, InputLen); - - if (CRPtr) - { - // Convert CR Null to CR LF - - LFPtr=memchr(MsgPtr, 0, InputLen); - - if (LFPtr && *(LFPtr - 1) == 13) // Convert CR NULL to CR LF - { - *LFPtr = 10; // Replace NULL with LF - send(sockptr->socket, LFPtr, 1, 0); // And echo it - } - } - - // could just have LF?? - - LFPtr=memchr(MsgPtr, 10, InputLen); - - if (LFPtr == 0) - if (CRPtr) - { - LFPtr = ++CRPtr; - InputLen++; - } - if (LFPtr == 0) - { - // Check Paclen - - if (InputLen > PACLEN) - { - if (sockptr->LoginState != 2) // Normal Data - { - // Long message received when waiting for user or password - just ignore - - sockptr->InputLen=0; - - return 0; - } - - // Send to Node - - // Line could be up to 500 chars if coming from a program rather than an interative user - // Limit send to node to 255 - - while (InputLen > 255) - { - SendtoNode(TNC, sockptr->Number, MsgPtr, 255); - sockptr->InputLen -= 255; - InputLen -= 255; - - memmove(MsgPtr,MsgPtr+255,InputLen); - } - - SendtoNode(TNC, sockptr->Number, MsgPtr, InputLen); - - sockptr->InputLen = 0; - - } // PACLEN - - return 0; // No CR - } - - // Got a LF - - // Process data up to the cr - - MsgLen = (int)(LFPtr-MsgPtr); // Include the CR but not LF - - switch (sockptr->LoginState) - { - - case 2: - - // Normal Data State - - STREAM->bytesRXed += MsgLen; - SendIndex = 0; - - // Line could be up to 500 chars if coming from a program rather than an interative user - // Limit send to node to 255. Should really use PACLEN instead of 255.... - - while (MsgLen > 255) - { - SendtoNode(TNC, sockptr->Number, MsgPtr + SendIndex, 255); - SendIndex += 255; - MsgLen -= 255; - } - - SendtoNode(TNC, sockptr->Number, MsgPtr + SendIndex, MsgLen); - - MsgLen += SendIndex; - - // If anything left, copy down buffer, and go back - - InputLen=InputLen-MsgLen-1; - - sockptr->InputLen=InputLen; - - if (InputLen > 0) - { - memmove(MsgPtr,LFPtr+1,InputLen); - - goto MsgLoop; - } - - return 0; - - case 0: - - // Check Username - // - - *(LFPtr-1)=0; // remove cr - - // send(sock, NLMsg, 2, 0); - - if (LogEnabled) - { - char Addr[256]; - - Tel_Format_Addr(sockptr, Addr); - - if (strlen(MsgPtr) > 64) - { - MsgPtr[64] = 0; - Debugprintf("Telnet Bad User Name %s", MsgPtr); - } - - sprintf(logmsg,"%d %s User=%s\n", sockptr->Number, Addr, MsgPtr); - WriteLog (logmsg); - } - - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if (USER == NULL) - continue; - - if (_stricmp(USER->UserName, "ANON") == 0) - { - // Anon Login - Callsign is supplied as user - - sockptr->UserPointer = USER; //' Save pointer for checking password - strcpy(sockptr->Callsign, _strupr(MsgPtr)); //' for *** linked - } - else if (strcmp(MsgPtr,USER->UserName) == 0) - { - sockptr->UserPointer = USER; //' Save pointer for checking password - strcpy(sockptr->Callsign, USER->Callsign); //' for *** linked - } - else - continue; - - send(sock, TCP->PasswordMsg, (int)strlen(TCP->PasswordMsg),0); - - sockptr->Retries = 0; - - sockptr->LoginState = 1; - sockptr->InputLen = 0; - - n=sockptr->Number; -#ifndef LINBPQ - ModifyMenu(TCP->hDisMenu, n - 1, MF_BYPOSITION | MF_STRING, IDM_DISCONNECT + n, MsgPtr); -#endif - ShowConnections(TNC);; - return 0; - } - - // Not found - - - if (sockptr->Retries++ == 4) - { - send(sock,AttemptsMsg,sizeof(AttemptsMsg),0); - Sleep (1000); - DataSocket_Disconnect(TNC, sockptr); //' Tidy up - } - else - { - send(sock, TCP->LoginMsg, (int)strlen(TCP->LoginMsg), 0); - sockptr->InputLen=0; - } - - return 0; - - case 1: - - *(LFPtr-1)=0; // remove cr - - send(sock, NLMsg, 2, 0); // Need to echo NL, as password is not echoed - - if (LogEnabled) - { - char Addr[256]; - - Tel_Format_Addr(sockptr, Addr); - - if (strlen(MsgPtr) > 64) - { - MsgPtr[64] = 0; - Debugprintf("Telnet Bad Password %s", MsgPtr); - } - - - sprintf(logmsg,"%d %s Password=%s\n", sockptr->Number, Addr, MsgPtr); - WriteLog (logmsg); - } - - if (strcmp(MsgPtr, sockptr->UserPointer->Password) == 0) { - char * ct = TCP->cfgCTEXT; - char * Appl; - int ctlen = (int)strlen(ct); - - if (ProcessIncommingConnect(TNC, sockptr->Callsign, sockptr->Number, FALSE) == FALSE) - { - DataSocket_Disconnect(TNC, sockptr); //' Tidy up - return 0; - } - - TNC->PortRecord->ATTACHEDSESSIONS[sockptr->Number]->Secure_Session = sockptr->UserPointer->Secure; - - sockptr->LoginState = 2; - sockptr->InputLen = 0; - - if (ctlen > 0) send(sock, ct, ctlen, 0); - - STREAM->bytesTXed = ctlen; - - if (LogEnabled) - { - char Addr[100]; - - Tel_Format_Addr(sockptr, Addr); - sprintf(logmsg,"%d %s Call Accepted Callsign=%s\n", sockptr->Number, Addr, sockptr->Callsign); - WriteLog (logmsg); - } - - Appl = sockptr->UserPointer->Appl; - - if (Appl[0]) - SendtoNode(TNC, sockptr->Number, Appl, (int)strlen(Appl)); - - ShowConnections(TNC); - - return 0; - } - - // Bad Password - - if (sockptr->Retries++ == 4) - { - send(sock,AttemptsMsg, (int)strlen(AttemptsMsg),0); - Sleep (1000); - DataSocket_Disconnect (TNC, sockptr); //' Tidy up - } - else - { - send(sock, TCP->PasswordMsg, (int)strlen(TCP->PasswordMsg), 0); - sockptr->InputLen=0; - } - - return 0; - - default: - - return 0; - - } - - return 0; -} - -int DataSocket_ReadRelay(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, struct STREAMINFO * STREAM) -{ - int len=0, maxlen, InputLen, MsgLen, n; - char NLMsg[3]={13,10,0}; - byte * LFPtr; - byte * MsgPtr; - char logmsg[256]; - char RelayMsg[] = "No CMS connection available - using local BPQMail\r"; - struct TCPINFO * TCP = TNC->TCPInfo; - - ioctl(sock,FIONREAD,&len); - - maxlen = InputBufferLen - sockptr->InputLen; - - if (len > maxlen) len=maxlen; - - len = recv(sock, &sockptr->InputBuffer[sockptr->InputLen], len, 0); - - - if (len == SOCKET_ERROR || len ==0) - { - // Failed or closed - clear connection - - TNC->Streams[sockptr->Number].ReportDISC = TRUE; //Tell Node - DataSocket_Disconnect(TNC, sockptr); - return 0; - } - - sockptr->InputLen+=len; - - // Extract lines from input stream - - MsgPtr = &sockptr->InputBuffer[0]; - InputLen = sockptr->InputLen; - - STREAM->bytesRXed += InputLen; - - if (sockptr->LoginState == 2) - { - // Data. FBB is binary - - // Send to Node - - // Queue to Node. Data may arrive it large quatities, possibly exceeding node buffer capacity - - STREAM->bytesRXed += InputLen; - - if (sockptr->FromHostBuffPutptr + InputLen > sockptr->FromHostBufferSize) - { - if (InputLen > 10000) - sockptr->FromHostBufferSize += InputLen; - else - sockptr->FromHostBufferSize += 10000; - - sockptr->FromHostBuffer = realloc(sockptr->FromHostBuffer, sockptr->FromHostBufferSize); - } - - memcpy(&sockptr->FromHostBuffer[sockptr->FromHostBuffPutptr], MsgPtr, InputLen); - - sockptr->FromHostBuffPutptr += InputLen; - sockptr->InputLen = 0; - - return 0; - } -/* - if (InputLen > 256) - { - SendtoNode(TNC, sockptr->Number, MsgPtr, 256); - sockptr->InputLen -= 256; - - InputLen -= 256; - - memmove(MsgPtr,MsgPtr+256,InputLen); - - goto MsgLoop; - } - - SendtoNode(TNC, sockptr->Number, MsgPtr, InputLen); - sockptr->InputLen = 0; - - return 0; - } -*/ - if (InputLen > 256) - { - // Long message received when waiting for user or password - just ignore - - sockptr->InputLen=0; - - return 0; - } - - LFPtr=memchr(MsgPtr, 13, InputLen); - - if (LFPtr == 0) - return 0; // Waitr for more - - // Got a CR - - // Process data up to the cr - - MsgLen = (int)(LFPtr-MsgPtr); - - switch (sockptr->LoginState) - { - - case 0: - - // Check Username - // - - *(LFPtr)=0; // remove cr - - if (*MsgPtr == '.') - MsgPtr++; - - if (strlen(MsgPtr) == 0) - { - DataSocket_Disconnect(TNC, sockptr); // Silently disconnect - should only be used for automatic systems - return 0; - } - - if (LogEnabled) - { - unsigned char work[4]; - memcpy(work, &sockptr->sin.sin_addr.s_addr, 4); - sprintf(logmsg,"%d %d.%d.%d.%d User=%s\n", - sockptr->Number, - work[0], work[1], work[2], work[3], - MsgPtr); - - WriteLog (logmsg); - } - - strcpy(sockptr->Callsign, _strupr(MsgPtr)); - - // Save callsign for *** linked - - send(sock, "Password :\r", 11,0); - - sockptr->Retries = 0; - sockptr->LoginState = 1; - sockptr->InputLen = 0; - - n=sockptr->Number; -#ifndef LINBPQ - ModifyMenu(TCP->hDisMenu, n - 1, MF_BYPOSITION | MF_STRING, IDM_DISCONNECT + n, MsgPtr); -#endif - ShowConnections(TNC);; - - return 0; - - - case 1: - - *(LFPtr)=0; // remove cr - - if (strlen(MsgPtr) == 0) - { - DataSocket_Disconnect(TNC, sockptr); // Silently disconnect - should only be used for automatic systems - return 0; - } - - if (LogEnabled) - { - unsigned char work[4]; - memcpy(work, &sockptr->sin.sin_addr.s_addr, 4); - sprintf(logmsg,"%d %d.%d.%d.%d Password=%s\n", - sockptr->Number, - work[0], work[1], work[2], work[3], - MsgPtr); - - WriteLog (logmsg); - } - - if (strchr(MsgPtr, '$')) - { - // Special format Password for PAT Gateway Mode - - char * Port = strlop(MsgPtr, '$'); - char * Call; - int PortNo; - char ConMsg[80]; - - if (Port) - { - Call = strlop(Port, '$'); - - if (Call) - { - struct PORTCONTROL * PORT; - - PortNo = atoi(Port); - PORT = GetPortTableEntryFromPortNum(PortNo); - - if (PORT == NULL || PORT->PROTOCOL < 10) - sprintf(ConMsg, "C %s %s", Port, Call); - else - sprintf(ConMsg, "ATT %s %s", Port, Call); - - } - - if (ProcessIncommingConnect(TNC, sockptr->Callsign, sockptr->Number, FALSE) == 0) - { - DataSocket_Disconnect(TNC, sockptr); //' Tidy up - return 0; - } - - sockptr->LoginState = 2; - - sockptr->InputLen = 0; - - if (LogEnabled) - { - unsigned char work[4]; - memcpy(work, &sockptr->sin.sin_addr.s_addr, 4); - sprintf(logmsg,"%d %d.%d.%d.%d Gateway Connect Call=%s Command=%s\n", - sockptr->Number, - work[0], work[1], work[2], work[3], - sockptr->Callsign,ConMsg); - - WriteLog (logmsg); - } - - // Send Command to Node - - strcat(ConMsg, "\r"); - SendtoNode(TNC, sockptr->Number, ConMsg, (int)strlen(ConMsg)); - } - - return 0; - } - - sockptr->UserPointer = &RelayUser; - - if (ProcessIncommingConnectEx(TNC, sockptr->Callsign, sockptr->Number, FALSE, TRUE) == 0) - { - DataSocket_Disconnect(TNC, sockptr); //' Tidy up - return 0; - } - - if (TCP->FallbacktoRelay) - send(sock, RelayMsg, (int)strlen(RelayMsg), 0); - - sockptr->LoginState = 2; - - sockptr->InputLen = 0; - - if (LogEnabled) - { - unsigned char work[4]; - memcpy(work, &sockptr->sin.sin_addr.s_addr, 4); - sprintf(logmsg,"%d %d.%d.%d.%d Call Accepted Callsign =%s\n", - sockptr->Number, - work[0], work[1], work[2], work[3], - sockptr->Callsign); - - WriteLog (logmsg); - } - - ShowConnections(TNC); - - sockptr->InputLen = 0; - - // Connect to the BBS - - SendtoNode(TNC, sockptr->Number, TCP->RelayAPPL, (int)strlen(TCP->RelayAPPL)); - - ShowConnections(TNC);; - - return 0; - - default: - - return 0; - - } - - return 0; -} -#define ZEXPORT WINAPI - -#include "zlib.h" - -int DataSocket_ReadSync(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, int Stream) -{ - int len=0, maxlen, InputLen; - byte * MsgPtr; - struct TCPINFO * TCP = TNC->TCPInfo; - struct STREAMINFO * STREAM = &TNC->Streams[Stream]; - TRANSPORTENTRY * Sess1 = TNC->PortRecord->ATTACHEDSESSIONS[Stream]; - TRANSPORTENTRY * Sess2 = NULL; - - ioctl(sock,FIONREAD,&len); - - maxlen = InputBufferLen - sockptr->InputLen; - - if (len > maxlen) len = maxlen; - - len = recv(sock, &sockptr->InputBuffer[sockptr->InputLen], len, 0); - - if (len == SOCKET_ERROR || len == 0) - { - // Failed or closed - clear connection - - TNC->Streams[sockptr->Number].ReportDISC = TRUE; //Tell Node - DataSocket_Disconnect(TNC, sockptr); - return 0; - } - - sockptr->InputLen+=len; - MsgPtr = &sockptr->InputBuffer[0]; - InputLen = sockptr->InputLen; - MsgPtr[InputLen] = 0; - - STREAM->bytesRXed += InputLen; - - if (sockptr->LoginState == 0) // Initial connection - { - // First Message should be POSYNCLOGON CALL - - // Extract the callsign - - char * call = strlop(MsgPtr, ' '); - - if (call == NULL || strcmp(MsgPtr, "POSYNCLOGON") !=0) - { - DataSocket_Disconnect(TNC, sockptr); //' Tidy up - return 0; - } - - strcpy(sockptr->Callsign, call); - - call --; - *(call) = ' '; - - sockptr->UserPointer = &SyncUser; - - SendtoNode(TNC, sockptr->Number, TCP->SyncAPPL, (int)strlen(TCP->SyncAPPL)); - BuffertoNode(sockptr, MsgPtr, InputLen); - STREAM->RelaySyncStream = 1; - sockptr->LoginState = 2; - - ShowConnections(TNC); - return 0; - } - - // Queue to Node. Data may arrive in large quantities, possibly exceeding node buffer capacity - - BuffertoNode(sockptr, MsgPtr, InputLen); - sockptr->InputLen = 0; - - return 0; -} - - - -int DataSocket_ReadFBB(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, int Stream) -{ - int len=0, maxlen, InputLen, MsgLen, i, n; - char NLMsg[3]={13,10,0}; - byte * CRPtr; - byte * MsgPtr; - char logmsg[1000]; - struct UserRec * USER; - struct TCPINFO * TCP = TNC->TCPInfo; - struct STREAMINFO * STREAM = &TNC->Streams[Stream]; - TRANSPORTENTRY * Sess1 = TNC->PortRecord->ATTACHEDSESSIONS[Stream]; - TRANSPORTENTRY * Sess2 = NULL; - - ioctl(sock,FIONREAD,&len); - - maxlen = InputBufferLen - sockptr->InputLen; - - if (len > maxlen) len = maxlen; - - len = recv(sock, &sockptr->InputBuffer[sockptr->InputLen], len, 0); - - if (len == SOCKET_ERROR || len == 0) - { - // Failed or closed - clear connection - - TNC->Streams[sockptr->Number].ReportDISC = TRUE; //Tell Node - DataSocket_Disconnect(TNC, sockptr); - return 0; - } - - sockptr->InputLen+=len; - - // Extract lines from input stream - - MsgPtr = &sockptr->InputBuffer[0]; - InputLen = sockptr->InputLen; - MsgPtr[InputLen] = 0; - - if (sockptr->LoginState == 0) - { - // Look for FLMSG Header - - if (InputLen > 10 && memcmp(MsgPtr, "... start\n", 10) == 0) - { - MsgPtr[9] = 13; // Convert to CR - sockptr->LoginState = 2; // Set Logged in - - SendtoNode(TNC, Stream, "..FLMSG\r", 8); // Dummy command to command handler - - } - } - -MsgLoop: - - if (sockptr->LoginState == 2) - { - // Data. FBB is binary - - int Paclen = 0; - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream]) - Paclen = TNC->PortRecord->ATTACHEDSESSIONS[Stream]->SESSPACLEN; - -// if (Paclen == 0) - Paclen = 256; - - if (sockptr->BPQTermMode) - { - if (memcmp(MsgPtr, "\\\\\\\\", 4) == 0) - { - // Monitor Control - - int P8 = 0; - - int n = sscanf(&MsgPtr[4], "%llx %x %x %x %x %x %x %x", - &sockptr->MMASK, &sockptr->MTX, &sockptr->MCOM, &sockptr->MonitorNODES, - &sockptr->MonitorColour, &sockptr->MUIOnly, &sockptr->UTF8, &P8); - - if (n == 5) - sockptr->MUIOnly = sockptr->UTF8 = 0; - - if (n == 6) - sockptr->UTF8 = 0; - - if (P8 == 1) - SendPortsForMonitor(sock, sockptr->UserPointer->Secure); - sockptr->InputLen = 0; - return 0; - } - } - - if (sockptr->UserPointer == &CMSUser) - { - WritetoTrace(Stream, MsgPtr, InputLen, sockptr->ADIF, 'R'); - } - - if (InputLen == 8 && memcmp(MsgPtr, ";;;;;;\r\n", 8) == 0) - { - // CMS Keepalive - - sockptr->InputLen = 0; - return 0; - } - - // Queue to Node. Data may arrive it large quantities, possibly exceeding node buffer capacity - - STREAM->bytesRXed += InputLen; - BuffertoNode(sockptr, MsgPtr, InputLen); - sockptr->InputLen = 0; - - return 0; - } - - if (InputLen > 256) - { - // Long message received when waiting for user or password - just ignore - - sockptr->InputLen=0; - - return 0; - } - - if (MsgPtr[0] == 10) // LF - { - // Remove the LF - - InputLen--; - sockptr->InputLen--; - - memmove(MsgPtr, MsgPtr+1, InputLen); - } - - CRPtr = memchr(MsgPtr, 13, InputLen); - - if (CRPtr == 0) - return 0; // Waitr for more - - // Got a CR - - // Process data up to the cr - - MsgLen = (int)(CRPtr - MsgPtr); - - if (MsgLen == 0) // Just CR - { - MsgPtr++; // Skip it - InputLen--; - sockptr->InputLen--; - goto MsgLoop; - } - - - switch (sockptr->LoginState) - { - case 5: - - // Trimode Emulator Command - - *CRPtr = 0; - - ProcessTrimodeCommand(TNC, sockptr, MsgPtr); - - MsgLen++; - - InputLen -= MsgLen; - - memmove(MsgPtr, MsgPtr+MsgLen, InputLen); - sockptr->InputLen = InputLen ; - MsgPtr[InputLen] = 0; - - - goto MsgLoop; - - case 3: - - // CMS Signon - - strlop(MsgPtr, 13); - - sprintf(logmsg,"%d %s\r\n", Stream, MsgPtr); - WriteCMSLog (logmsg); - - if (strstr(MsgPtr, "Callsign :")) - { - char Msg[80]; - int Len; - - if (sockptr->LogonSent) - { - sockptr->InputLen=0; - return TRUE; - } - - sockptr->LogonSent = TRUE; - - if (TCP->SecureCMSPassword[0] && sockptr->RelaySession == 0) - Len = sprintf(Msg, "%s %s\r", TNC->Streams[sockptr->Number].MyCall, TCP->GatewayCall); - else - Len = sprintf(Msg, "%s\r", TNC->Streams[sockptr->Number].MyCall); - - if (sockptr->ADIF == NULL) - { - sockptr->ADIF = malloc(sizeof(struct ADIF)); - memset(sockptr->ADIF, 0, sizeof(struct ADIF)); - } - - strcpy(sockptr->ADIF->CMSCall, TCP->GatewayCall); - - send(sock, Msg, Len, 0); - sprintf(logmsg,"%d %s\n", Stream, Msg); - WriteCMSLog (logmsg); - - sockptr->InputLen=0; - - return TRUE; - } - if (memcmp(MsgPtr, ";SQ: ", 5) == 0) - { - // Secure CMS challenge - - char Msg[80]; - int Len; - int Response = GetCMSHash(&MsgPtr[5], TCP->SecureCMSPassword); - char RespString[12]; - long long Freq = 0; - int Mode = 0; - ADIF * ADIF = sockptr->ADIF; - - strcat(MsgPtr,""); - UpdateADIFRecord(ADIF, MsgPtr, 'R'); - - if (Sess1) - { - Sess2 = Sess1->L4CROSSLINK; - - if (Sess2) - { - // if Session has report info, use it - - if (Sess2->Mode) - { - ADIF->Freq = Freq = Sess2->Frequency; - ADIF->Mode = Mode = Sess2->Mode; - } - else - { - // See if L2 session - if so, get info from WL2K report line - - if (Sess2->L4CIRCUITTYPE & L2LINK) - { - LINKTABLE * LINK = Sess2->L4TARGET.LINK; - PORTCONTROLX * PORT = LINK->LINKPORT; - - ADIF->Freq = Freq = PORT->WL2KInfo.Freq; - ADIF->Mode = Mode = PORT->WL2KInfo.mode; - } - else - { - if (Sess2->RMSCall[0]) - { - ADIF->Freq = Freq = Sess2->Frequency; - ADIF->Mode = Mode = Sess2->Mode; - } - } - } - } - } - - sprintf(RespString, "%010d", Response); - - Len = sprintf(Msg, ";SR: %s %lld %d\r", &RespString[2], Freq, Mode); - - send(sock, Msg, Len,0); - sprintf(logmsg,"%d %s\n", Stream, Msg); - WriteCMSLog (logmsg); - - strcat(Msg,""); - UpdateADIFRecord(ADIF, Msg, 'S'); - - sockptr->InputLen=0; - sockptr->LoginState = 2; // Data - sockptr->LogonSent = FALSE; - - return TRUE; - } - - if (strstr(MsgPtr, "Password :")) - { - // Send "CMSTelnet" + gateway callsign + frequency + emission type if info is available - - TRANSPORTENTRY * Sess1 = TNC->PortRecord->ATTACHEDSESSIONS[Stream]; - TRANSPORTENTRY * Sess2 = NULL; - char Passline[80] = "CMSTELNET\r"; - int len = 10; - ADIF * ADIF = sockptr->ADIF; - - - if (Sess1) - { - Sess2 = Sess1->L4CROSSLINK; - - if (Sess2) - { - // if Session has report info, use it - - if (Sess2->Mode) - { - ADIF->Freq = Sess2->Frequency; - ADIF->Mode = Sess2->Mode; - } - else - { - // See if L2 session - if so, get info from WL2K report line - - if (Sess2->L4CIRCUITTYPE & L2LINK) - { - LINKTABLE * LINK = Sess2->L4TARGET.LINK; - PORTCONTROLX * PORT = LINK->LINKPORT; - - if (PORT->WL2KInfo.Freq) - { - len = sprintf(Passline, "CMSTELNET %s %lld %d\r", PORT->WL2KInfo.RMSCall, PORT->WL2KInfo.Freq, PORT->WL2KInfo.mode); - ADIF->Freq = PORT->WL2KInfo.Freq; - ADIF->Mode = PORT->WL2KInfo.mode; - } - } - else - { - if (Sess2->RMSCall[0]) - { - len = sprintf(Passline, "CMSTELNET %s %lld %d\r", Sess2->RMSCall, Sess2->Frequency, Sess2->Mode); - ADIF->Mode = Sess2->Frequency; - ADIF->Mode = Sess2->Mode; - } - } - } - } - } - send(sock, Passline, len, 0); - sockptr->LoginState = 2; // Data - sockptr->InputLen=0; - sockptr->LogonSent = FALSE; - - if (CMSLogEnabled) - { - char logmsg[120]; - sprintf(logmsg,"%d %s\r\n", sockptr->Number, Passline); - WriteCMSLog (logmsg); - } - - return TRUE; - } - - return TRUE; - - case 0: - - // Check Username - // - - *(CRPtr)=0; // remove cr - - if (LogEnabled) - { - char Addr[256]; - Tel_Format_Addr(sockptr, Addr); - - if (strlen(MsgPtr) > 64) - { - MsgPtr[64] = 0; - Debugprintf("Telnet Bad User Name %s", MsgPtr); - } - - sprintf(logmsg,"%d %s User=%s\n", sockptr->Number, Addr, MsgPtr); - WriteLog (logmsg); - } - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if (USER == NULL) - continue; - - if (_stricmp(USER->UserName, "ANON") == 0) - { - // Anon Login - Callsign is supplied as user - - sockptr->UserPointer = USER; //' Save pointer for checking password - strcpy(sockptr->Callsign, _strupr(MsgPtr)); //' for *** linked - } - else if (strcmp(MsgPtr,USER->UserName) == 0) - { - sockptr->UserPointer = USER; //' Save pointer for checking password - strcpy(sockptr->Callsign, USER->Callsign); //' for *** linked - - } - else - continue; - - sockptr->Retries = 0; - - sockptr->LoginState = 1; - sockptr->InputLen = 0; - - n=sockptr->Number; - -#ifndef LINBPQ - ModifyMenu(TCP->hDisMenu, n - 1, MF_BYPOSITION | MF_STRING, IDM_DISCONNECT + n, MsgPtr); -#endif - - ShowConnections(TNC);; - - InputLen=InputLen-(MsgLen+1); - - sockptr->InputLen=InputLen; - - if (InputLen > 0) - { - memmove(MsgPtr, CRPtr+1, InputLen); - goto MsgLoop; - } - - return 0; - } - - // User Not found - - if (sockptr->Retries++ == 4) - { - send(sock,AttemptsMsg,sizeof(AttemptsMsg),0); - Sleep (1000); - DataSocket_Disconnect(TNC, sockptr); //' Tidy up - } - else - { - send(sock, TCP->LoginMsg, (int)strlen(TCP->LoginMsg), 0); - sockptr->InputLen=0; - - } - - return 0; - - case 1: - - *(CRPtr)=0; // remove cr - - if (LogEnabled) - { - char Addr[256]; - Tel_Format_Addr(sockptr, Addr); - - if (strlen(MsgPtr) > 64) - { - MsgPtr[64] = 0; - Debugprintf("Telnet Bad Password %s", MsgPtr); - } - - sprintf(logmsg,"%d %s Password=%s\n", sockptr->Number, Addr, MsgPtr); - WriteLog (logmsg); - } - if (strcmp(MsgPtr, sockptr->UserPointer->Password) == 0) - { - char * Appl; - - if (ProcessIncommingConnect(TNC, sockptr->Callsign, sockptr->Number, FALSE) == FALSE) - { - DataSocket_Disconnect(TNC, sockptr); //' Tidy up - return 0; - } - - TNC->PortRecord->ATTACHEDSESSIONS[sockptr->Number]->Secure_Session = sockptr->UserPointer->Secure; - - sockptr->LoginState = 2; - - sockptr->InputLen = 0; - - if (LogEnabled) - { - char Addr[100]; - Tel_Format_Addr(sockptr, Addr); - sprintf(logmsg,"%d %s Call Accepted. Callsign=%s\n", - sockptr->Number, Addr,sockptr->Callsign); - - WriteLog (logmsg); - } - - ShowConnections(TNC);; - InputLen=InputLen-(MsgLen+1); - - sockptr->InputLen=InputLen; - - // What is left is the Command to connect to the BBS - - if (InputLen > 1) - { - if (*(CRPtr+1) == 10) - { - CRPtr++; - InputLen--; - } - - memmove(MsgPtr, CRPtr+1, InputLen); - - if (_memicmp(MsgPtr, "BPQTermTCP", 10) == 0) - { - send(sock, "Connected to TelnetServer\r", 26, 0); - sockptr->BPQTermMode = TRUE; - sockptr->MMASK = 0; // Make sure defaults to off - sockptr->InputLen -= 11; - - if (sockptr->InputLen) - { - // Monitor control info may arrive in same packet - - int P8 = 0; - - memmove(MsgPtr, &MsgPtr[11], InputLen); - if (memcmp(MsgPtr, "\\\\\\\\", 4) == 0) - { - // Monitor Control - - int n = sscanf(&MsgPtr[4], "%llx %x %x %x %x %x %x %x", - &sockptr->MMASK, &sockptr->MTX, &sockptr->MCOM, &sockptr->MonitorNODES, - &sockptr->MonitorColour, &sockptr->MUIOnly, &sockptr->UTF8, &P8); - - if (n == 5) - sockptr->MUIOnly = sockptr->UTF8 = 0; - - if (n == 6) - sockptr->UTF8 = 0; - - if (P8 == 1) - SendPortsForMonitor(sock, sockptr->UserPointer->Secure); - - - sockptr->InputLen = 0; - } - } - } - else - { - MsgPtr[InputLen] = 13; - SendtoNode(TNC, sockptr->Number, MsgPtr, InputLen+1); - } - sockptr->InputLen = 0; - } - - Appl = sockptr->UserPointer->Appl; - - if (Appl[0]) - SendtoNode(TNC, sockptr->Number, Appl, (int)strlen(Appl)); - - return 0; - } - // Bad Password - - if (sockptr->Retries++ == 4) - { - send(sock,AttemptsMsg, (int)strlen(AttemptsMsg),0); - Sleep (1000); - DataSocket_Disconnect(TNC, sockptr); //' Tidy up - } - else - { - send(sock, TCP->PasswordMsg, (int)strlen(TCP->PasswordMsg), 0); - sockptr->InputLen=0; - } - - return 0; - - default: - - return 0; - } - return 0; -} - -extern char * RigWebPage; - -int DataSocket_ReadHTTP(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, int Stream) -{ - int w =1, x= 1, len=0, y = 2, maxlen, InputLen, ret; - char NLMsg[3]={13,10,0}; - UCHAR * MsgPtr; - UCHAR * CRLFCRLF; - UCHAR * LenPtr; - int BodyLen, ContentLen; - struct ConnectionInfo * sockcopy; - - ret = ioctl(sock,FIONREAD,&w); - - maxlen = InputBufferLen - sockptr->InputLen; - - if (w > maxlen) w = maxlen; - - len = recv(sock, &sockptr->InputBuffer[sockptr->InputLen], w, 0); - - if (len == SOCKET_ERROR || len == 0) - { - // Failed or closed - clear connection - - // if Websock connection till app - - if (sockptr->WebSocks) - { - if (memcmp(sockptr->WebURL, "rhp", 3) == 0) - { - ProcessRHPWebSockClosed(sockptr->socket); - return 0; - } - } - else - { - TNC->Streams[sockptr->Number].ReportDISC = TRUE; //Tell Node - DataSocket_Disconnect(TNC, sockptr); - return 0; - } - } - - MsgPtr = &sockptr->InputBuffer[0]; - sockptr->InputLen += len; - InputLen = sockptr->InputLen; - - MsgPtr[InputLen] = 0; - - if (sockptr->WebSocks) - { - // Websocks message - - int i, j; - int Fin, Opcode, Len, Mask; - char MaskingKey[4]; - char * ptr; - char * Payload; - - /* - +-+-+-+-+-------+-+-------------+-------------------------------+ - |F|R|R|R| opcode|M| Payload len | Extended payload length | - |I|S|S|S| (4) |A| (7) | (16/64) | - |N|V|V|V| |S| | (if payload len==126/127) | - | |1|2|3| |K| | | - +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + - | Extended payload length continued, if payload len == 127 | - + - - - - - - - - - - - - - - - +-------------------------------+ - | |Masking-key, if MASK set to 1 | - +-------------------------------+-------------------------------+ - | Masking-key (continued) | Payload Data | - +-------------------------------- - - - - - - - - - - - - - - - + - : Payload Data continued ... : - - Octet i of the transformed data ("transformed-octet-i") is the XOR of - octet i of the original data ("original-octet-i") with octet at index - i modulo 4 of the masking key ("masking-key-octet-j"): - - j = i MOD 4 - transformed-octet-i = original-octet-i XOR masking-key-octet-j -*/ - Fin = MsgPtr[0] >> 7; - Opcode = MsgPtr[0] & 15; - Mask = MsgPtr[1] >> 7; - Len = MsgPtr[1] & 127; - - if (Len == 126) // Two Byte Len - { - Len = (MsgPtr[2] << 8) + MsgPtr[3]; - memcpy(MaskingKey, &MsgPtr[4], 4); - ptr = &MsgPtr[8]; - } - else - { - memcpy(MaskingKey, &MsgPtr[2], 4); - ptr = &MsgPtr[6]; - } - - Payload = ptr; - - for (i = 0; i < Len; i++) - { - j = i & 3; - - *ptr = *ptr ^ MaskingKey[j]; - ptr++; - } - - if (Opcode == 8) - { - Debugprintf("WebSock Close"); - } - else if (Opcode == 1) - { - if (strcmp(sockptr->WebURL, "RIGCTL") == 0) - { - // PTT Message - - char RigCMD[64]; - - sprintf(RigCMD, "%s PTT", Payload); - Rig_Command( (TRANSPORTENTRY *) -1, RigCMD); - } - else if (memcmp(sockptr->WebURL, "WMRefresh", 9) == 0) - { - sockcopy = malloc(sizeof(struct ConnectionInfo)); - sockptr->TNC = TNC; - sockptr->LastSendTime = REALTIMETICKS; - - memcpy(sockcopy, sockptr, sizeof(struct ConnectionInfo)); - - _beginthread(ProcessWebmailWebSockThread, 2048000, (VOID *)sockcopy); // Needs big stack - return 0; - } - else if (memcmp(sockptr->WebURL, "rhp", 3) == 0) - { - sockcopy = malloc(sizeof(struct ConnectionInfo)); - sockptr->TNC = TNC; - sockptr->LastSendTime = REALTIMETICKS; - - memcpy(sockcopy, sockptr, sizeof(struct ConnectionInfo)); - - ProcessRHPWebSock(sockptr->socket, Payload, Len); - sockptr->InputLen = 0; - return 0; - } - } - else - Debugprintf("WebSock Opcode %d Msg %s", Opcode, &MsgPtr[6]); - - sockptr->InputLen = 0; - return 0; - } - - // Make sure request is complete - should end crlfcrlf, and if a post have the required input message - - - CRLFCRLF = strstr(MsgPtr, "\r\n\r\n"); - - if (CRLFCRLF == 0) - return 0; - - LenPtr = strstr(MsgPtr, "Content-Length:"); - - if (LenPtr) - { - ContentLen = atoi(LenPtr + 15); - BodyLen = InputLen - (int)((CRLFCRLF + 4 - MsgPtr)); - - if (BodyLen < ContentLen) - return 0; - } - - sockcopy = malloc(sizeof(struct ConnectionInfo)); - sockptr->TNC = TNC; - sockptr->LastSendTime = REALTIMETICKS; - - memcpy(sockcopy, sockptr, sizeof(struct ConnectionInfo)); - - if(strstr(MsgPtr, "Upgrade: websocket")) - { - int LOCAL = 0, COOKIE = 0; - char * HostPtr; - char * ptr; - - sockptr->WebSocks = 1; - ShowConnections(TNC); - - memcpy(sockptr->WebURL, &MsgPtr[5], 31); - strlop(sockptr->WebURL, ' '); - if (RigWebPage) - RigWebPage[0] = 0; - - HostPtr = strstr(MsgPtr, "Host: "); - - if (HostPtr) - { - uint32_t Host; - char Hostname[32]= ""; - struct LOCALNET * LocalNet = sockptr->TNC->TCPInfo->LocalNets; - - HostPtr += 6; - memcpy(Hostname, HostPtr, 31); - strlop(Hostname, ':'); - Host = inet_addr(Hostname); - - if (strcmp(Hostname, "127.0.0.1") == 0) - LOCAL = TRUE; - else - { - if (sockptr->sin.sin_family != AF_INET6) - { - while(LocalNet) - { - uint32_t MaskedHost = sockptr->sin.sin_addr.s_addr & LocalNet->Mask; - if (MaskedHost == LocalNet->Network) - { - LOCAL = 1; - break; - } - LocalNet = LocalNet->Next; - } - } - - ptr = strstr(MsgPtr, "BPQSessionCookie=N"); - - if (ptr) - COOKIE = TRUE; - } - sockptr->WebSecure = LOCAL | COOKIE; - } - } - - - _beginthread(ProcessHTTPMessage, 2048000, (VOID *)sockcopy); // Needs big stack - - sockptr->InputLen = 0; - return 0; -} - -int DataSocket_ReadDRATS(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, int Stream) -{ - int len=0, maxlen; - - ioctl(sock,FIONREAD,&len); - - maxlen = InputBufferLen - sockptr->InputLen; - - if (len > maxlen) len = maxlen; - - len = recv(sock, &sockptr->InputBuffer[sockptr->InputLen], len, 0); - - if (len == SOCKET_ERROR || len == 0) - { - // Failed or closed - clear connection - - DRATSConnectionLost(sockptr); - DataSocket_Disconnect(TNC, sockptr); - return 0; - } - - // Make sure request is complete - should end [EOB] - - processDRATSFrame(&sockptr->InputBuffer[sockptr->InputLen], len, sockptr); - return 0; -} - - -int DataSocket_Disconnect(struct TNCINFO * TNC, struct ConnectionInfo * sockptr) -{ - int n; - - if (sockptr->SocketActive) - { - if (sockptr->socket) - closesocket(sockptr->socket); - - n = sockptr->Number; -#ifndef LINBPQ - ModifyMenu(TNC->TCPInfo->hDisMenu, n - 1, MF_BYPOSITION | MF_STRING, IDM_DISCONNECT + n, "."); -#endif - sockptr->SocketActive = FALSE; - ShowConnections(TNC);; - } - return 0; -} - -int ShowConnections(struct TNCINFO * TNC) -{ -#ifndef LINBPQ - char msg[80]; - struct ConnectionInfo * sockptr; - int i,n; - - SendMessage(TNC->hMonitor,LB_RESETCONTENT,0,0); - - for (n = 1; n <= TNC->TCPInfo->CurrentSockets; n++) - { - sockptr=TNC->Streams[n].ConnectionInfo; - - if (!sockptr->SocketActive) - { - strcpy(msg,"Idle"); - } - else - { - if (sockptr->UserPointer == 0) - { - if (sockptr->HTTPMode) - { - char Addr[100]; - Tel_Format_Addr(sockptr, Addr); - - if (sockptr->WebSocks) - sprintf(msg, "Websock From %s", Addr); - else - sprintf(msg, "HTTP From %s", Addr); - } - else if (sockptr->DRATSMode) - { - char Addr[100]; - Tel_Format_Addr(sockptr, Addr); - sprintf(msg, "DRATS From %s", Addr); - } - else - strcpy(msg,"Logging in"); - } - else - { - i=sprintf(msg,"%-10s %-10s %2d", - sockptr->UserPointer->UserName, sockptr->Callsign, sockptr->FromHostBuffPutptr - sockptr->FromHostBuffGetptr); - } - } - SendMessage(TNC->hMonitor, LB_ADDSTRING ,0, (LPARAM)msg); - } -#endif - return 0; -} -byte * EncodeCall(byte * Call) -{ - static char axcall[10]; - - ConvToAX25(Call, axcall); - return &axcall[0]; -} -BOOL ProcessTelnetCommand(struct ConnectionInfo * sockptr, byte * Msg, int * Len) -{ - int cmd, TelOption; - int used; - char WillSupGA[3]={IAC,WILL,suppressgoahead}; - char WillEcho[3]={IAC,WILL,echo}; - char Wont[3]={IAC,WONT,echo}; - char Dont[3]={IAC,DONT,echo}; - - // Note Msg points to the IAC, which may not be at the start of the receive buffer - // Len is number of bytes left in buffer including the IAC - - if (*Len < 2) return TRUE; //' Wait for more - - cmd = Msg[1]; - - if (cmd == DOx || cmd == DONT || cmd == WILL || cmd == WONT) - if (*Len < 3) return TRUE; //' wait for option - - TelOption = Msg[2]; - - switch (cmd) - { - case DOx: - - switch (TelOption) - { - case echo: - sockptr->DoEcho = TRUE; - send(sockptr->socket,WillEcho,3,0); - break; - - case suppressgoahead: - - send(sockptr->socket,WillSupGA,3,0); - break; - - default: - - Wont[2] = TelOption; - send(sockptr->socket,Wont,3,0); - } - - used=3; - - break; - - case DONT: - - // Debug.Print "DONT"; TelOption - - switch (TelOption) - { - case echo: - sockptr->DoEcho = FALSE; - break; - } - - Wont[2] = TelOption; - send(sockptr->socket,Wont,3,0); - - used=3; - - break; - - case WILL: - - // Debug.Print "WILL"; TelOption - -// if (TelOption == echo) sockptr->DoEcho = TRUE; - - Dont[2] = TelOption; - send(sockptr->socket, Dont, 3, 0); - - used=3; - - break; - - case WONT: - -// Debug.Print "WONT"; TelOption - - used=3; - - break; - - default: - - used=2; - - } - - // remove the processed command from the buffer - - *Len -= used; - - return FALSE; -} - - -int WriteLog(char * msg) -{ - FILE *file; - char timebuf[128]; - time_t ltime; - - UCHAR Value[MAX_PATH]; - time_t T; - struct tm * tm; - - T = time(NULL); - tm = gmtime(&T); - - if (LogDirectory[0] == 0) - { - strcpy(Value, "logs/Telnet_"); - } - else - { - strcpy(Value, LogDirectory); - strcat(Value, "/"); - strcat(Value, "logs/Telnet_"); - } - - sprintf(Value, "%s%02d%02d%02d.log", Value, - tm->tm_year - 100, tm->tm_mon+1, tm->tm_mday); - - if ((file = fopen(Value, "a")) == NULL) - return FALSE; - - time(<ime); - -#ifdef LINBPQ - { - struct tm * tmp = localtime(<ime); - strftime( timebuf, 128, - "%d/%m/%Y %H:%M:%S ", tmp ); - } -#else - { - struct tm * today; - - today = localtime(<ime); - strftime(timebuf, 128, "%d/%m/%Y %H:%M:%S ", today); - } -#endif - fputs(timebuf, file); - fputs(msg, file); - fclose(file); - return 0; -} - -char LastCMSLog[256]; - -VOID WriteCMSLog(char * msg) -{ - UCHAR Value[MAX_PATH]; - time_t T; - struct tm * tm; - FILE * Handle; - char LogMsg[256]; - int MsgLen; - - if (CMSLogEnabled == FALSE) - return; - - T = time(NULL); - tm = gmtime(&T); - - if (LogDirectory[0] == 0) - { - strcpy(Value, "logs/CMSAccess"); - } - else - { - strcpy(Value, LogDirectory); - strcat(Value, "/"); - strcat(Value, "logs/CMSAccess"); - } - - sprintf(Value, "%s_%04d%02d%02d.log", Value, - tm->tm_year +1900, tm->tm_mon+1, tm->tm_mday); - - Handle = fopen(Value, "ab"); - - if (Handle == NULL) - return; - - MsgLen = sprintf(LogMsg, "%02d:%02d:%02d %s", tm->tm_hour, tm->tm_min, tm->tm_sec, msg); - - fwrite(LogMsg , 1, MsgLen, Handle); - - fclose(Handle); - -#ifndef WIN32 - - if (strcmp(Value, LastCMSLog)) - { - UCHAR SYMLINK[MAX_PATH]; - - sprintf(SYMLINK,"%s/CMSAccessLatest.log", BPQDirectory); - unlink(SYMLINK); - strcpy(LastCMSLog, Value); - symlink(Value, SYMLINK); - } - -#endif - - return; -} - - - - - - -int Telnet_Connected(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, int Error) -{ - struct TCPINFO * TCP = TNC->TCPInfo; - PMSGWITHLEN buffptr; - int Stream = sockptr->Number; - char Signon[80]; - int errlen = 4; - - buffptr = (PMSGWITHLEN)GetBuff(); - if (buffptr == 0) return 0; // No buffers, so ignore - -#ifndef WIN32 - -// SO_ERROR codes - -//#define ETIMEDOUT 110 /* Connection timed out */ -//#define ECONNREFUSED 111 /* Connection refused */ -//#define EHOSTDOWN 112 /* Host is down */ -//#define EHOSTUNREACH 113 /* No route to host */ -//#define EALREADY 114 /* Operation already in progress */ -//#define EINPROGRESS 115 /* Operation now in progress */ - - if (Error == 0) - getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&Error, &errlen); - -// Debugprintf("Except Event Error after opts = %d", Error); -#endif - - if (Error) - { - if (sockptr->CMSSession && sockptr->RelaySession == 0) - { - // Try Next - - TCP->CMSFailed[sockptr->CMSIndex] = TRUE; - - if (CMSConnect(TNC, TNC->TCPInfo, &TNC->Streams[Stream], Stream)) - return 0; - - // Connect failure - if no more servers to check look for FALLBACKTORELAY - - return 0; - } - else - { - int err = 0; - int errlen = 4; - - getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); - - buffptr->Len = sprintf(&buffptr->Data[0], "*** Failed to Connect\r"); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - closesocket(sock); - TNC->Streams[Stream].Connecting = FALSE; - sockptr->SocketActive = FALSE; - ShowConnections(TNC); - TNC->Streams[Stream].NeedDisc = 10; - return 0; - } - } - - sockptr->LogonSent = FALSE; - - if (sockptr->CMSSession) - { - sockptr->LoginState = 3; // Password State - - sockptr->UserPointer = &CMSUser; - strcpy(sockptr->Callsign, TNC->Streams[Stream].MyCall); - - sockptr->DoEcho = FALSE; - sockptr->FBBMode = TRUE; - sockptr->RelayMode = FALSE; - sockptr->ClientSession = FALSE; - sockptr->SyncMode = FALSE; - - if (TCP->CMS) - SaveCMSHostInfo(TNC->Port, TNC->TCPInfo, sockptr->CMSIndex); - - if (CMSLogEnabled) - { - char logmsg[120]; - - if (sockptr->RelaySession) - sprintf(logmsg,"%d %s Connected to RELAY\r\n", sockptr->Number, TNC->Streams[Stream].MyCall); - else - sprintf(logmsg,"%d %s Connected to CMS\r\n", sockptr->Number, TNC->Streams[Stream].MyCall); - - WriteCMSLog (logmsg); - } - - if (sockptr->RelaySession) - buffptr->Len = sprintf(&buffptr->Data[0], "*** %s Connected to RELAY\r", TNC->Streams[Stream].MyCall); - else - buffptr->Len = sprintf(&buffptr->Data[0], "*** %s Connected to CMS\r", TNC->Streams[Stream].MyCall); - } - else - { - sockptr->LoginState = 2; // Data State - sockptr->UserPointer = &HostUser; - strcpy(sockptr->Callsign, TNC->Streams[Stream].MyCall); - sockptr->DoEcho = FALSE; - sockptr->ClientSession = TRUE; - - if (sockptr->SyncMode) - { - char Addr[256]; - Tel_Format_Addr(sockptr, Addr); - - buffptr->Len = sprintf(&buffptr->Data[0], "*** Connected to SYNC %s:%d\r", Addr, htons(sockptr->sin.sin_port)); - send(sockptr->socket, sockptr->Signon, (int)strlen(sockptr->Signon), 0); - } - else - { - if (sockptr->Signon[0]) - { - buffptr->Len = sprintf(&buffptr->Data[0], "*** Connected to Server\r"); - send(sockptr->socket, sockptr->Signon, (int)strlen(sockptr->Signon), 0); - } - else - { - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4CROSSLINK->APPL[0]) - buffptr->Len = sprintf(&buffptr->Data[0], "*** Connected to %s\r", - TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4CROSSLINK->APPL); - else - buffptr->Len = sprintf(&buffptr->Data[0], "*** Connected to APPL\r"); - - if (sockptr->NoCallsign == FALSE) - send(sockptr->socket, Signon, sprintf(Signon, "%s\r\n", TNC->Streams[Stream].MyCall), 0); - } - } - } - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - sockptr->SocketActive = TRUE; - sockptr->InputLen = 0; -// sockptr->Number = Stream; - sockptr->RelayMode = FALSE; - sockptr->ConnectTime = time(NULL); - TNC->Streams[Stream].Connecting = FALSE; - TNC->Streams[Stream].Connected = TRUE; - - if (sockptr->ADIF == NULL) - sockptr->ADIF = malloc(sizeof(struct ADIF)); - - memset(sockptr->ADIF, 0, sizeof(struct ADIF)); - - strcpy(sockptr->ADIF->Call, TNC->Streams[Stream].MyCall); - - ShowConnections(TNC); - - if (sockptr->FromHostBuffer == 0) - { - sockptr->FromHostBuffer = malloc(10000); - sockptr->FromHostBufferSize = 10000; - } - - sockptr->FromHostBuffPutptr = sockptr->FromHostBuffGetptr = 0; - - TNC->Streams[Stream].bytesRXed = TNC->Streams[Stream].bytesTXed = 0; - - return 0; -} - -VOID ReportError(struct STREAMINFO * STREAM, char * Msg) -{ - PMSGWITHLEN buffptr; - - buffptr = (PMSGWITHLEN)GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(&buffptr->Data[0], "Error - %s\r", Msg); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); -} - -VOID Report(struct STREAMINFO * STREAM, char * Msg) -{ - PMSGWITHLEN buffptr; - - buffptr = (PMSGWITHLEN)GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(&buffptr->Data[0], "%s\r", Msg); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); -} - -void CheckCMSThread(void * TNC); - -BOOL CheckCMS(struct TNCINFO * TNC) -{ - if (TNC->TCPInfo->CMS) - { - TNC->TCPInfo->CheckCMSTimer = 0; - _beginthread(CheckCMSThread, 0, (void *)TNC); - } - return 0; -} - -void CheckCMSThread(void * TNCPtr) -{ - // Resolve Name and check connectivity to each address - - struct TNCINFO * TNC = (struct TNCINFO *)TNCPtr; - struct TCPINFO * TCP = TNC->TCPInfo; -// struct hostent * HostEnt; - struct in_addr addr; - struct hostent *remoteHost; - char **pAlias; int i = 0; - BOOL INETOK = FALSE; - struct addrinfo hints, *res = 0, *saveres; - int n; - unsigned long cms; - - TCP->UseCachedCMSAddrs = FALSE; - - // if TCP->CMSServer is an ip address use it - - cms = inet_addr(TCP->CMSServer); - - if (cms != INADDR_NONE) - { - Debugprintf("Using %s for CMS Server", TCP->CMSServer); - TCP->CMSAddr[0].s_addr = cms; - TCP->CMSFailed[0] = FALSE; - TCP->CMSName[0] = _strdup(TCP->CMSServer); // Save Host Name - TCP->NumberofCMSAddrs = 1; - goto CheckServers; - } - - // First make sure we have a functioning DNS - - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_INET6; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_DGRAM; - - n = getaddrinfo("a.root-servers.net", NULL, &hints, &res); - - if (n == 0) - goto rootok; - - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_DGRAM; - n = getaddrinfo("b.root-servers.net", NULL, &hints, &res); - - if (n == 0) - goto rootok; - - Debugprintf("Resolve root nameserver failed"); - - // Most likely is a local Internet Outage, but we could have Internet, but no name servers - // Either way, switch to using cached CMS addresses. CMS Validation will check connectivity - - TCP->UseCachedCMSAddrs = TRUE; - goto CheckServers; - -rootok: - - freeaddrinfo(res); - - INETOK = TRUE; // We have connectivity - - res = 0; - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_DGRAM; - n = getaddrinfo(TCP->CMSServer, NULL, &hints, &res); - - if (n || !res || res->ai_next == 0) // Resolve Failed, or Returned only one Host - { - // Switch to Cached Servers - - if (res) - { - // If Host is amazonaws, allow it - - remoteHost = gethostbyaddr((char *) &res->ai_addr->sa_data[2], 4, AF_INET); - - if (remoteHost && strstr(_strlwr(remoteHost->h_name), "amazonaws")) - goto resok; - - Debugprintf("Resolve CMS returned only one host"); - freeaddrinfo(res); - } - else - Debugprintf("Resolve CMS Failed"); - - TCP->UseCachedCMSAddrs = TRUE; - - goto CheckServers; - } - -resok: - - saveres = res; - - while (res) - { - memcpy(&addr.s_addr, &res->ai_addr->sa_data[2], 4); - TCP->CMSAddr[i] = addr; - TCP->CMSFailed[i] = FALSE; - i++; - res = res->ai_next; - } - - freeaddrinfo(saveres); - - TCP->NumberofCMSAddrs = i; - - i = 0; - - while (i < TCP->NumberofCMSAddrs) - { - if (TCP->CMSName[i]) - free(TCP->CMSName[i]); - - remoteHost = gethostbyaddr((char *) &TCP->CMSAddr[i], 4, AF_INET); - - if (remoteHost == NULL) - { - int dwError = WSAGetLastError(); - - TCP->CMSName[i] = NULL; - - if (dwError != 0) - { - if (dwError == HOST_NOT_FOUND) - Debugprintf("CMS - Host not found"); - else if (dwError == NO_DATA) - Debugprintf("CMS No data record found"); - else - Debugprintf("CMS Gethost failed %d", dwError); - } - } - else - { - Debugprintf("CMS #%d %s Official name : %s",i, inet_ntoa(TCP->CMSAddr[i]), remoteHost->h_name); - - TCP->CMSName[i] = _strdup(remoteHost->h_name); // Save Host Name - - for (pAlias = remoteHost->h_aliases; *pAlias != 0; pAlias++) - { - Debugprintf("\tAlternate name #%d: %s\n", i, *pAlias); - } - } - i++; - } - - TCP->NumberofCMSAddrs = i; - -CheckServers: -#ifndef LINBPQ - CheckMenuItem(TNC->TCPInfo->hActionMenu, 4, MF_BYPOSITION | TCP->UseCachedCMSAddrs<<3); -#endif - if (TCP->UseCachedCMSAddrs) - { - // Get Cached Servers from CMSInfo.txt - - GetCMSCachedInfo(TNC); - } - - if (TCP->NumberofCMSAddrs == 0) - { - TCP->CMSOK = FALSE; -#ifndef LINBPQ - SetWindowText(TCP->hCMSWnd, "NO CMS"); -#endif - return; - } - - // if we don't know we have Internet connectivity, make sure we can connect to at least one of them - - TCP->CMSOK = INETOK | CMSCheck(TNC, TCP); // If we know we have Inet, dont check connectivity - -#ifndef LINBPQ - if (TCP->CMSOK) - MySetWindowText(TCP->hCMSWnd, "CMS OK"); - else - MySetWindowText(TCP->hCMSWnd, "NO CMS"); -#endif - return; -} - -#define MAX_KEY_LENGTH 255 -#define MAX_VALUE_NAME 255 -#define MAX_VALUE_DATA 255 - - - -VOID GetCMSCachedInfo(struct TNCINFO * TNC) -{ - struct TCPINFO * TCP = TNC->TCPInfo; - ULONG IPAD; - char inname[256]; - - FILE *in; - char Buffer[2048]; - char *buf = Buffer; - char *ptr1, *ptr2, *context; - int i = 0; - - if (LogDirectory[0] == 0) - { - strcpy(inname, "logs/CMSInfo.txt"); - } - else - { - strcpy(inname, LogDirectory); - strcat(inname, "/"); - strcat(inname, "logs/CMSInfo.txt"); - } - - TCP->NumberofCMSAddrs = 0; - - in = fopen(inname, "r"); - - if (!(in)) return; - - while(fgets(buf, 128, in)) - { - ptr1 = strtok_s(buf, ", ", &context); - ptr2 = strtok_s(NULL, ", ", &context); // Skip Time - ptr2 = strtok_s(NULL, ", ", &context); - - if (ptr1[0] < 32 || ptr1[0] > 127 || ptr2 == NULL) - continue; - - IPAD = inet_addr(ptr2); - - memcpy(&TCP->CMSAddr[i], &IPAD, 4); - - TCP->CMSFailed[i] = FALSE; - - if (TCP->CMSName[i]) - free(TCP->CMSName[i]); - - TCP->CMSName[i] = _strdup(ptr1); // Save Host Name - i++; - - if (i >= MaxCMS) - break; - } - - fclose(in); - - TCP->NumberofCMSAddrs = i; - - return; -} - -BOOL CMSCheck(struct TNCINFO * TNC, struct TCPINFO * TCP) -{ - // Make sure at least one CMS can be connected to - - u_long param=1; - BOOL bcopt=TRUE; - SOCKET sock; - struct sockaddr_in sinx; - struct sockaddr_in destaddr; - int addrlen=sizeof(sinx); - int n = 0; - - destaddr.sin_family = AF_INET; - destaddr.sin_port = htons(8772); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - for (n = 0; n < TCP->NumberofCMSAddrs; n++) - { - sock = socket(AF_INET, SOCK_STREAM, 0); - - if (sock == INVALID_SOCKET) - return FALSE; - - memcpy(&destaddr.sin_addr.s_addr, &TCP->CMSAddr[n], 4); - - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); - - if (bind(sock, (struct sockaddr *) &sinx, addrlen) != 0 ) - return FALSE; - - if (connect(sock,(struct sockaddr *) &destaddr, sizeof(destaddr)) == 0) - { - closesocket(sock); - return TRUE; - } - - // Failed - try next - - if (TCP->CMSName[n]) - Debugprintf("Check CMS Failed for %s", TCP->CMSName[n]); - closesocket(sock); - } - return FALSE; -} - - - -int CMSConnect(struct TNCINFO * TNC, struct TCPINFO * TCP, struct STREAMINFO * STREAM, int Stream) -{ - int err; - u_long param=1; - BOOL bcopt=TRUE; - struct ConnectionInfo * sockptr; - SOCKET sock; - struct sockaddr_in sinx; - struct sockaddr_in destaddr; - int addrlen=sizeof(sinx); - int n; - char Msg[80]; - - sockptr = STREAM->ConnectionInfo; - - sock = sockptr->socket = socket(AF_INET, SOCK_STREAM, 0); - - if (sock == INVALID_SOCKET) - { - ReportError(STREAM, "Create Socket Failed"); - return FALSE; - } - - if (sockptr->ADIF == NULL) - sockptr->ADIF = malloc(sizeof(struct ADIF)); - - memset(sockptr->ADIF, 0, sizeof(struct ADIF)); - - sockptr->SocketActive = TRUE; - sockptr->InputLen = 0; - sockptr->LoginState = 2; - sockptr->UserPointer = 0; - sockptr->DoEcho = FALSE; - sockptr->BPQTermMode = FALSE; - - sockptr->FBBMode = TRUE; // Raw Data - sockptr->NeedLF = FALSE; - - if (sockptr->ADIF == NULL) - sockptr->ADIF = malloc(sizeof(struct ADIF)); - - memset(sockptr->ADIF, 0, sizeof(struct ADIF)); - - destaddr.sin_family = AF_INET; - destaddr.sin_port = htons(8772); - - // See if current CMS is down - - n = 0; - - while (TCP->CMSFailed[TCP->NextCMSAddr]) - { - TCP->NextCMSAddr++; - if (TCP->NextCMSAddr >= TCP->NumberofCMSAddrs) TCP->NextCMSAddr = 0; - n++; - - if (n == TCP->NumberofCMSAddrs) - { - TCP->CMSOK = FALSE; -#ifndef LINBPQ - DrawMenuBar(TNC->hDlg); -#endif - ReportError(STREAM, "All CMS Servers are inaccessible"); - closesocket(sock); - - if (TCP->RELAYHOST[0] && TCP->FallbacktoRelay && STREAM->NoCMSFallback == 0) - { - STREAM->Connecting = TRUE; - STREAM->ConnectionInfo->CMSSession = TRUE; - STREAM->ConnectionInfo->RelaySession = TRUE; - return TCPConnect(TNC, TCP, STREAM, TCP->RELAYHOST, 8772, TRUE); - } - - STREAM->NeedDisc = 10; - TNC->Streams[Stream].Connecting = FALSE; - sockptr->SocketActive = FALSE; - ShowConnections(TNC); - return FALSE; - } - } - - sockptr->CMSIndex = TCP->NextCMSAddr; - - sprintf(Msg, "Trying %s", TCP->CMSName[TCP->NextCMSAddr]); - - memcpy(&destaddr.sin_addr.s_addr, &TCP->CMSAddr[TCP->NextCMSAddr++], 4); - - if (TCP->NextCMSAddr >= TCP->NumberofCMSAddrs) - TCP->NextCMSAddr = 0; - - ioctl(sockptr->socket, FIONBIO, ¶m); - - setsockopt (sockptr->socket, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - if (bind(sockptr->socket, (struct sockaddr *) &sinx, addrlen) != 0 ) - { - ReportError(STREAM, "Bind Failed"); - return FALSE; - } - -#ifndef LINBPQ - ModifyMenu(TCP->hDisMenu, Stream - 1, MF_BYPOSITION | MF_STRING, IDM_DISCONNECT + Stream, "CMS"); -#endif - - Report(STREAM, Msg); - - if (connect(sockptr->socket,(struct sockaddr *) &destaddr, sizeof(destaddr)) == 0) - { - // - // Connected successful - // - - ReportError(STREAM, "*** Connected"); - return TRUE; - } - else - { - err=WSAGetLastError(); - - if (err == 10035 || err == 115 || err == 36 || err == 150) //EWOULDBLOCK - { - // Connect in Progress - - sockptr->UserPointer = &CMSUser; - return TRUE; - } - else - { - // Connect failed - - closesocket(sockptr->socket); - - if (sockptr->CMSSession && sockptr->RelaySession == 0) - { - // Try Next - - TCP->CMSFailed[sockptr->CMSIndex] = TRUE; - Debugprintf("Connect Failed %d, trying next", err); - CMSConnect(TNC, TNC->TCPInfo, &TNC->Streams[Stream], Stream); - return 0; - } - - ReportError(STREAM, "Connect Failed"); - CheckCMS(TNC); - - STREAM->Connecting = FALSE; - sockptr->SocketActive = FALSE; - ShowConnections(TNC); - STREAM->NeedDisc = 10; - - return FALSE; - } - } - return FALSE; - -} - -VOID SaveCMSHostInfo(int port, struct TCPINFO * TCP, int CMSNo) -{ - char Info[256]; - char inname[256]; - char outname[256]; - - unsigned char work[4]; - FILE *in, *out; - char Buffer[2048]; - char *buf = Buffer; - - if (TCP->CMS == 0) - return; - - if (CMSNo > 9 || CMSNo < 0 || TCP->CMSName[CMSNo] == 0) - { - Debugprintf("SaveCMSHostInfo invalid CMS Number %d", CMSNo); - return; - } - - if (LogDirectory[0] == 0) - { - strcpy(inname, "logs/CMSInfo.txt"); - } - else - { - strcpy(inname, LogDirectory); - strcat(inname, "/"); - strcat(inname, "logs/CMSInfo.txt"); - } - - if (LogDirectory[0] == 0) - { - strcpy(outname, "logs/CMSInfo.tmp"); - } - else - { - strcpy(outname, LogDirectory); - strcat(outname, "/"); - strcat(outname, "logs/CMSInfo.tmp"); - } - - memcpy(work, &TCP->CMSAddr[CMSNo].s_addr, 4); - - sprintf(Info,"%s %d %d.%d.%d.%d\n", TCP->CMSName[CMSNo], (int)time(NULL), - work[0], work[1], work[2], work[3]); - - - in = fopen(inname, "r"); - - if (!(in)) - { - in = fopen(inname, "w"); - - if (!(in)) - { - perror("Failed to create CMSInfo.txt"); - Debugprintf("Failed to create CMSInfo.txt"); - return; - } - fclose(in); - in = fopen(inname, "r"); - } - - if (!(in)) return; - - out = fopen(outname, "w"); - - if (!(out)) return; - - while(fgets(buf, 128, in)) - { - char addr[256]; - time_t t; - char ip[256]; - int n; - - if (sizeof(time_t) == 4) - n = sscanf(buf,"%s %d %s", addr, (int *)&t, ip); - else - n = sscanf(buf, "%s %lld %s", addr, &t, ip); - - if (n == 3) - { - time_t age = time(NULL) - t; - - // if not current server and not too old, copy across - - if (addr[0] > 31 && addr[0] < 127) - if ((age < 86400 * 30) && strcmp(addr, TCP->CMSName[CMSNo]) != 0) - fputs(buf, out); - } - } - - fputs(Info, out); - - fclose(in); - fclose(out); - - remove(inname); - rename(outname, inname); - - return; -} - -int TCPConnect(struct TNCINFO * TNC, struct TCPINFO * TCP, struct STREAMINFO * STREAM, char * Host, int Port, BOOL FBB) -{ - int err; - u_long param=1; - BOOL bcopt=TRUE; - struct ConnectionInfo * sockptr; - SOCKET sock; - struct sockaddr_in sinx; - struct sockaddr_in destaddr; - int addrlen=sizeof(sinx); - int i; - - sockptr = STREAM->ConnectionInfo; - - sock = sockptr->socket = socket(AF_INET, SOCK_STREAM, 0); - - if (sock == INVALID_SOCKET) - { - ReportError(STREAM, "Create Socket Failed"); - return FALSE; - } - - sockptr->SocketActive = TRUE; - sockptr->InputLen = 0; - sockptr->LoginState = 2; - sockptr->UserPointer = 0; - sockptr->DoEcho = FALSE; - - sockptr->FBBMode = FBB; // Raw Data - - if (sockptr->ADIF == NULL) - sockptr->ADIF = malloc(sizeof(struct ADIF)); - - memset(sockptr->ADIF, 0, sizeof(struct ADIF)); - - - // Resolve Name if needed - - sockptr->sin.sin_family = AF_INET; - sockptr->sin.sin_port = htons(Port); - - sockptr->sin.sin_addr.s_addr = inet_addr(Host); - - if (sockptr->sin.sin_addr.s_addr == INADDR_NONE) - { - struct hostent * HostEnt; - - // Resolve name to address - - HostEnt = gethostbyname(Host); - - if (!HostEnt) - { - ReportError(STREAM, "Resolve HostName Failed"); - return FALSE; // Resolve failed - } - i = 0; - while (HostEnt->h_addr_list[i] != 0) - { - struct in_addr addr; - addr.s_addr = *(u_long *) HostEnt->h_addr_list[i++]; - } - memcpy(&sockptr->sin.sin_addr.s_addr, HostEnt->h_addr, 4); - } - - ioctl (sockptr->socket, FIONBIO, ¶m); - - setsockopt (sockptr->socket, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - if (bind(sockptr->socket, (struct sockaddr *) &sinx, addrlen) != 0 ) - { - ReportError(STREAM, "Bind Failed"); - return FALSE; - } - - if (LogEnabled) - { - char logmsg[512]; - - sprintf(logmsg,"%d Outward Connect to %s Port %d\n", sockptr->Number, Host, Port); - WriteLog (logmsg); - } - - - if (connect(sockptr->socket,(struct sockaddr *) &sockptr->sin, sizeof(destaddr)) == 0) - { - // - // Connected successful - // - - ReportError(STREAM, "*** Connected"); - - // Get Send Buffer Size - - return TRUE; - } - else - { - err=WSAGetLastError(); - - if (err == 10035 || err == 115 || err == 36) //EWOULDBLOCK - { - // Connect in Progress - - sockptr->UserPointer = &HostUser; - return TRUE; - } - else - { - // Connect failed - - closesocket(sockptr->socket); - ReportError(STREAM, "Connect Failed"); - STREAM->Connecting = FALSE; - sockptr->SocketActive = FALSE; - ShowConnections(TNC); - STREAM->NeedDisc = 10; - - return FALSE; - } - } - - return FALSE; - -} - - -VOID Tel_Format_Addr(struct ConnectionInfo * sockptr, char * dst) -{ - unsigned char * src; - char zeros[12] = ""; - char * ptr; - struct - { - int base, len; - } best, cur; - unsigned int words[8]; - int i; - - if (sockptr->sin.sin_family != AF_INET6) - { - unsigned char work[4]; - memcpy(work, &sockptr->sin.sin_addr.s_addr, 4); - sprintf(dst,"%d.%d.%d.%d", work[0], work[1], work[2], work[3]); - return; - } - - src = (unsigned char *)&sockptr->sin6.sin6_addr; - - // See if Encapsulated IPV4 addr - - if (src[12] != 0) - { - if (memcmp(src, zeros, 12) == 0) // 12 zeros, followed by non-zero - { - sprintf(dst,"::%d.%d.%d.%d", src[12], src[13], src[14], src[15]); - return; - } - } - - // Convert 16 bytes to 8 words - - for (i = 0; i < 16; i += 2) - words[i / 2] = (src[i] << 8) | src[i + 1]; - - // Look for longest run of zeros - - best.base = -1; - cur.base = -1; - - for (i = 0; i < 8; i++) - { - if (words[i] == 0) - { - if (cur.base == -1) - cur.base = i, cur.len = 1; // New run, save start - else - cur.len++; // Continuation - increment length - } - else - { - // End of a run of zeros - - if (cur.base != -1) - { - // See if this run is longer - - if (best.base == -1 || cur.len > best.len) - best = cur; - - cur.base = -1; // Start again - } - } - } - - if (cur.base != -1) - { - if (best.base == -1 || cur.len > best.len) - best = cur; - } - - if (best.base != -1 && best.len < 2) - best.base = -1; - - ptr = dst; - - for (i = 0; i < 8; i++) - { - /* Are we inside the best run of 0x00's? */ - - if (best.base != -1 && i >= best.base && i < (best.base + best.len)) - { - // Just output one : for whole string of zeros - - *ptr++ = ':'; - i = best.base + best.len - 1; // skip rest of zeros - continue; - } - - /* Are we following an initial run of 0x00s or any real hex? */ - - if (i != 0) - *ptr++ = ':'; - - ptr += sprintf (ptr, "%x", words[i]); - - // Was it a trailing run of 0x00's? - } - - if (best.base != -1 && (best.base + best.len) == 8) - *ptr++ = ':'; - - *ptr++ = '\0'; -} - -BOOL TelSendPacket(int Stream, struct STREAMINFO * STREAM, PMSGWITHLEN buffptr, struct ADIF * ADIF) -{ - int datalen; - UCHAR * MsgPtr; - SOCKET sock; - struct ConnectionInfo * sockptr = STREAM->ConnectionInfo; - - datalen = (int)buffptr->Len; - MsgPtr = &buffptr->Data[0]; - - STREAM->bytesTXed += datalen; - - sock = sockptr->socket; - - if (sockptr->UserPointer == &CMSUser) - { - WritetoTrace(Stream, MsgPtr, datalen, ADIF, 'S'); - } - - if (sockptr->UTF8) - { - // Convert any non-utf8 chars - - if (IsUTF8(MsgPtr, datalen) == FALSE) - { - unsigned char UTF[1024]; - int u, code; - - // Try to guess encoding - - code = TrytoGuessCode(MsgPtr, datalen); - - if (code == 437) - u = Convert437toUTF8(MsgPtr, datalen, UTF); - else if (code == 1251) - u = Convert1251toUTF8(MsgPtr, datalen, UTF); - else - u = Convert1252toUTF8(MsgPtr, datalen, UTF); - - SendAndCheck(sockptr, UTF, u, 0); - ReleaseBuffer(buffptr); - return TRUE; - } - } - - if (sockptr->FBBMode && sockptr->NeedLF == FALSE) - { -/* - // if Outward Connect to FBB, Replace ff with ffff - - if (0) // if we use this need to fix retry - { - char * ptr2, * ptr = &MsgPtr[0]; - int i; - do - { - ptr2 = memchr(ptr, 255, datalen); - - if (ptr2 == 0) - { - // no ff, so just send as is - - xxxsend(sock, ptr, datalen, 0); - i=0; - break; - } - - i=ptr2+1-ptr; - - xxsend(sock,ptr,i,0); - xxsend(sock,"\xff",1,0); - - datalen-=i; - ptr=ptr2+1; - } - while (datalen>0); - } -*/ - // Normal FBB Mode path - - BOOL ret = SendAndCheck(sockptr, MsgPtr, datalen, 0); - ReleaseBuffer(buffptr); - return ret; - } - - // Not FBB mode, or FBB and NEEDLF Replace cr with crlf - - { - unsigned char Out[1024]; - unsigned char c; - unsigned char * ptr2 = Out; - unsigned char * ptr = &MsgPtr[0]; - - while (datalen--) - { - c = (*ptr++); - - if (c == 13) - { - *(ptr2++) = 13; - *(ptr2++) = 10; - } - else - *(ptr2++) = c; - } - - ReleaseBuffer(buffptr); - return SendAndCheck(sockptr, Out, (int)(ptr2 - Out), 0); - } -} - -VOID ProcessTrimodeCommand(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, char * MsgPtr) -{ - struct STREAMINFO * STREAM = &TNC->Streams[sockptr->Number]; - int Port = 4; - - Debugprintf(MsgPtr); - - if (strcmp(MsgPtr, "CLOSE") == 0) - { - if (STREAM->Connected) - { - STREAM->ReportDISC = TRUE; - } - } - -// MYCALLSIGN XE2BNC - else - if (memcmp(MsgPtr, "MYCALLSIGN", 10) == 0) - { - char * call = &MsgPtr[11]; - - if (strlen(call) > 9) - call[9] = 0; - - memcpy(STREAM->MyCall, call, 10); - - ConvToAX25(call, &TNC->PortRecord->ATTACHEDSESSIONS[sockptr->Number]->L4USER[0]); - - strcpy(&TNCInfo[Port]->Streams[0].MyCall[0], call); - } - - -// TARGETCALLSIGN KE7XO - else - if (memcmp(MsgPtr, "TARGETCALLSIGN", 14) == 0) - { - char * call = &MsgPtr[15]; - - if (strlen(call) > 9) - call[9] = 0; - - memcpy(STREAM->RemoteCall, call, 10); - } -// INITIATECALL 50 - else - if (memcmp(MsgPtr, "INITIATECALL", 12) == 0) - { - char Cmd[80]; - int n; - - n = sprintf(Cmd,"C %s\r", STREAM->RemoteCall); - - SendtoNode(TNC, sockptr->Number, Cmd, n); - } - - -// CHANNEL 3586500,None,None - else - if (memcmp(MsgPtr, "CHANNEL", 7) == 0) - { - double Freq = atof(&MsgPtr[8]); - char Radiocmd[80]; - int n; - - strcpy(sockptr->Callsign, "G8BPQ"); - - n = sprintf(Radiocmd,"RADIO %f %s\r", Freq/1000000, "USB"); - - SendtoNode(TNC, sockptr->Number, Radiocmd, n); - } - - else - if (memcmp(MsgPtr, "PROTOCOL", 8) == 0) - { - // Attach the relevant port - - SendtoNode(TNC, sockptr->Number, "ATTACH 4\r", 9); - } - - else - if (strcmp(MsgPtr, "BUSY") == 0) - send(sockptr->socket, "BUSY False\r\n", 12,0); - - - send(sockptr->socket, "CMD\r\n", 5,0); - -// SendtoNode(TNC, sockptr->Number, NodeLine, len); -} - - -VOID ProcessTrimodeResponse(struct TNCINFO * TNC, struct STREAMINFO * STREAM, unsigned char * MsgPtr, int Msglen) -{ - MsgPtr[Msglen] = 0; - - if (STREAM->ConnectionInfo->TriModeConnected) - { - // Send over the Data Socket - - send(STREAM->ConnectionInfo->TriModeDataSock, MsgPtr, Msglen, 0); - - return; - } - - strlop(MsgPtr, 13); - Debugprintf(MsgPtr); - - if (memcmp(MsgPtr, "*** Connected to ", 17) == 0) - { - char Cmd[80]; - int n; - - n = sprintf(Cmd,"CONNECTED %s\r", &MsgPtr[17]); - - STREAM->ConnectionInfo->TriModeConnected = TRUE; - - send(STREAM->ConnectionInfo->socket, Cmd, n, 0); - } -} - -VOID ProcessTriModeDataMessage(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, struct STREAMINFO * STREAM) -{ - int len=0; - char NLMsg[3]={13,10,0}; - char RelayMsg[] = "No CMS connection available - using local BPQMail\r"; - struct TCPINFO * TCP = TNC->TCPInfo; - unsigned char Buffer[256]; - - ioctl(sock,FIONREAD,&len); - - if (len > 256) len = 256; - - len = recv(sock, Buffer, len, 0); - - if (len == SOCKET_ERROR || len ==0) - { - // Failed or closed - clear connection - - closesocket(sock); - return; - } - - SendtoNode(TNC, sockptr->Number, Buffer, len); -} - -extern struct DATAMESSAGE * REPLYBUFFER; -char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char * format, ...); - - -VOID RECONFIGTELNET (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) -{ - int Port = 0, index =0; - char * ptr, *Context; - struct PORTCONTROL * PORT = NULL; - struct TNCINFO * TNC; - char * ptr1, * ptr2; - char buf[256],errbuf[256]; - char * Config; - struct TCPINFO * TCP; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - Port = atoi(ptr); - - if (Port) - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - TNC = TNCInfo[Port]; - - if (TNC == NULL || TNC->Hardware != H_TELNET) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not a Telnet port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - TCP = TNC->TCPInfo; - - ptr = strtok_s(NULL, " ", &Context); - - if (ptr && _stricmp(ptr, "ALL") == 0) - { - // Use EXTRESTART Code - - PEXTPORTDATA PORTVEC = (PEXTPORTDATA) PORT; - PORTVEC->EXTRESTART = 1; - - Bufferptr = Cmdprintf(Session, Bufferptr, "Reconfig Telnet Ok\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (ptr && _stricmp(ptr, "USERS") == 0) - { - // Reconfig Users - - if (!ProcessConfig()) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Failed to reread config file - leaving config unchanged\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - Config = PortConfig[Port]; - - if (Config == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "No Config Entries found\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - // Don't free old user records - sessions may have pointers to them - - // Free the header - - if (TCP->UserRecPtr) - { - free(TCP->UserRecPtr); - TCP->UserRecPtr = NULL; - } - - TCP->NumberofUsers = 0; - - // Look for USER lines - - ptr1 = Config; - ptr2 = strchr(ptr1, 13); - - while(ptr2) - { - memcpy(buf, ptr1, ptr2 - ptr1 + 1); - buf[ptr2 - ptr1 + 1] = 0; - ptr1 = ptr2 + 2; - ptr2 = strchr(ptr1, 13); - strcpy(errbuf,buf); // save in case of erro - - if (_memicmp(buf, "USER=", 5) == 0 || _memicmp(buf, "USER ", 5) == 0) - { - char *User, *Pwd, *UserCall, *Secure, * Appl; - int End = (int)strlen(buf) -1; - struct UserRec * USER; - char Param[8][256]; - char * ptr1, * ptr2; - int n = 0; - char * value = &buf[5]; - - // USER=user,password,call,appl,SYSOP - - memset(Param, 0, 2048); - strlop(value, 13); - strlop(value, ';'); - - ptr1 = value; - - while (ptr1 && *ptr1 && n < 8) - { - ptr2 = strchr(ptr1, ','); - if (ptr2) *ptr2++ = 0; - - strcpy(&Param[n][0], ptr1); - strlop(Param[n++], ' '); - ptr1 = ptr2; - while(ptr1 && *ptr1 && *ptr1 == ' ') - ptr1++; - } - - - User = &Param[0][0]; - - if (_stricmp(User, "ANON") == 0) - { - strcpy(&Param[2][0], "ANON"); - strcpy(&Param[4][0], ""); // Dont allow SYSOP if ANON - } - - Pwd = &Param[1][0]; - UserCall = &Param[2][0]; - Appl = &Param[3][0]; - Secure = &Param[4][0]; - - if (User[0] == 0 || Pwd[0] == 0 || UserCall[0] == 0) // invalid record - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Bad USER Record %s\r", errbuf); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - _strupr(UserCall); - - if (TCP->NumberofUsers == 0) - TCP->UserRecPtr = malloc(sizeof(void *)); - else - TCP->UserRecPtr = realloc(TCP->UserRecPtr, (TCP->NumberofUsers+1) * sizeof(void *)); - - USER = zalloc(sizeof(struct UserRec)); - - TCP->UserRecPtr[TCP->NumberofUsers] = USER; - - USER->Callsign = _strdup(UserCall); - USER->Password = _strdup(Pwd); - USER->UserName = _strdup(User); - USER->Appl = zalloc(32); - USER->Secure = FALSE; - - if (_stricmp(Secure, "SYSOP") == 0) - USER->Secure = TRUE; - - if (Appl[0] && strcmp(Appl, "\"\"") != 0) - { - strcpy(USER->Appl, _strupr(Appl)); - strcat(USER->Appl, "\r\n"); - } - TCP->NumberofUsers++; - } - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "Reread Telnet Users Ok - %d USER Records\r", TCP->NumberofUsers); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid parameter - use either USERS or ALL \r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID SHOWTELNET(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD) -{ - // DISPLAY Telnet Server Status Mheard - - int Port = 0, index =0; - char * ptr, *Context; - struct PORTCONTROL * PORT = NULL; - int txlen = 0, n; - struct TNCINFO * TNC; - char msg[80]; - struct ConnectionInfo * sockptr; - int i; - char CMS[] = "CMS Disabled"; - - ptr = strtok_s(CmdTail, " ", &Context); - - if (ptr) - Port = atoi(ptr); - - if (Port) - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - TNC = TNCInfo[Port]; - - if (TNC == NULL || TNC->Hardware != H_TELNET) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "Not a Telnet port\r"); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - return; - } - - if (TNC->TCPInfo->CMS) - if (TNC->TCPInfo->CMSOK) - strcpy(CMS, "CMS Ok"); - else - strcpy(CMS, "No CMS"); - - Bufferptr = Cmdprintf(Session, Bufferptr, "Telnet Status for Port %d %s\r", Port, CMS); - - for (n = 1; n <= TNC->TCPInfo->CurrentSockets; n++) - { - sockptr=TNC->Streams[n].ConnectionInfo; - - if (!sockptr->SocketActive) - { - strcpy(msg,"Idle"); - } - else - { - if (sockptr->UserPointer == 0) - { - if (sockptr->HTTPMode) - { - char Addr[100]; - Tel_Format_Addr(sockptr, Addr); - - if (sockptr->WebSocks) - sprintf(msg, "Websock From %s", Addr); - else - sprintf(msg, "HTTP From %s", Addr); - - } - else if (sockptr->DRATSMode) - { - char Addr[100]; - Tel_Format_Addr(sockptr, Addr); - sprintf(msg, "DRATS From %s", Addr); - } - else - strcpy(msg,"Logging in"); - } - else - { - i=sprintf(msg,"%-10s %-10s %2d", - sockptr->UserPointer->UserName,sockptr->Callsign,sockptr->BPQStream); - } - } - Bufferptr = Cmdprintf(Session, Bufferptr, "%s\r", msg); - } - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - - -// Refresh any Web Socket Webmail index display -// Called whenever message database is changed - -#ifdef LINBPQ - -int DoRefreshWebMailIndex(); - -int RefreshWebMailIndex() -{ - DoRefreshWebMailIndex(); - return 0; -} - -#else - -// Have to pass request from BPQMail to DLL as socket can only be accessed in calling process -// Pass request back to WebMail via pipe - -// Code must run in bpq32 process, so set flag here and call code from Timer Routine - -extern BOOL NeedWebMailRefresh; - - -DllExport int APIENTRY RefreshWebMailIndex() -{ - NeedWebMailRefresh = 1; - return 0; -} - -#endif - -int DoRefreshWebMailIndex() -{ - // Loop through all sockets and pick out WebMail Index Connections - - int i, n; - struct ConnectionInfo * sockptr; - struct ConnectionInfo * sockcopy; - struct TNCINFO * TNC; - struct TCPINFO * TCP; - -#ifndef LINBPQ - NeedWebMailRefresh = 0; -#endif - - for (i = 0; i < 33; i++) - { - TNC = TNCInfo[i]; - - if (TNC && TNC->Hardware == H_TELNET) - { - TCP = TNC->TCPInfo; - - if (TCP) - { - for (n = 0; n <= TCP->MaxSessions; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - - if (sockptr->SocketActive) - { - if (sockptr->HTTPMode && sockptr->WebSocks && memcmp(sockptr->WebURL, "WMRefresh", 9) == 0) - { - sockcopy = malloc(sizeof(struct ConnectionInfo)); - sockptr->TNC = TNC; - sockptr->LastSendTime = REALTIMETICKS; - - memcpy(sockcopy, sockptr, sizeof(struct ConnectionInfo)); - - _beginthread(ProcessWebmailWebSockThread, 2048000, (VOID *)sockcopy); // Needs big stack - } - } - } - } - } - } - return 0; -} - diff --git a/TelnetV6.c b/TelnetV6.c index 54b8c92..287118b 100644 --- a/TelnetV6.c +++ b/TelnetV6.c @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses */ + // // Telnet Driver for BPQ Switch // @@ -113,7 +114,7 @@ extern int REALTIMETICKS; #define MaxSockets 26 struct UserRec RelayUser; -struct UserRec SyncUser = {"","Sync"};; +struct UserRec SyncUser = {"","Sync"}; struct UserRec CMSUser; struct UserRec HostUser = {"","Host"}; struct UserRec TriModeUser; @@ -953,13 +954,27 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) { if (sockptr->WebSocks == 0) { - if (sockptr->LastSendTime && (REALTIMETICKS - sockptr->LastSendTime) > 1500) // ~ 2.5 mins + if (sockptr->LastSendTime && (time(NULL) - sockptr->LastSendTime) > 150) // ~ 2.5 mins { closesocket(sockptr->socket); sockptr->SocketActive = FALSE; ShowConnections(TNC); } } + else if (memcmp(sockptr->WebURL, "rhp", 3) == 0) + { + // RHP Sockets (Used for WhatsPack) Need a timeout + // Normally keepalives are sent each way around every 9 mins + // Keepalives aren't sent when connecting so may need a bit longer + + if (sockptr->LastSendTime && (time(NULL) - sockptr->LastSendTime) > 20 * 60) // 20mins + { + ProcessRHPWebSockClosed(sockptr->socket); + closesocket(sockptr->socket); + sockptr->SocketActive = FALSE; + ShowConnections(TNC); + } + } } else { @@ -1174,7 +1189,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) TNC = TNCInfo[n]; TNC->Port = n; - TNC->Hardware = H_TELNET; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_TELNET; TNC->RIG = &TNC->DummyRig; // Not using Rig control, so use Dummy // Get Menu Handles @@ -1449,13 +1464,12 @@ void * TelnetExtInit(EXTPORTDATA * PortEntry) TCP = TNC->TCPInfo; TNC->Port = port; + TNC->PortRecord = PortEntry; - TNC->Hardware = H_TELNET; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_TELNET; PortEntry->MAXHOSTMODESESSIONS = TNC->TCPInfo->MaxSessions + 1; // Default - TNC->PortRecord = PortEntry; - if (PortEntry->PORTCONTROL.PORTCALL[0] != 0) ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); @@ -2473,15 +2487,11 @@ nosocks: if (sockptr->SocketActive && sockptr->Keepalive && L4LIMIT) { -#ifdef WIN32 - if ((REALTIMETICKS - sockptr->LastSendTime) > (L4LIMIT - 60) * 9) // PC Ticks are about 10% slow -#else - if ((REALTIMETICKS - sockptr->LastSendTime) > (L4LIMIT - 60) * 10) -#endif + if ((time(NULL) - sockptr->LastSendTime) > (L4LIMIT - 60)) // PC Ticks are about 10% slow { // Send Keepalive - sockptr->LastSendTime = REALTIMETICKS; + sockptr->LastSendTime = time(NULL); BuffertoNode(sockptr, "Keepalive\r", 10); } } @@ -2611,7 +2621,7 @@ nosocks: if (P3[0] == 'K' || P4[0] == 'K' || P5[0] == 'K' || P6[0] == 'K') { sockptr->Keepalive = TRUE; - sockptr->LastSendTime = REALTIMETICKS; + sockptr->LastSendTime = time(NULL); } if (P3[0] == 'S' || P4[0] == 'S' || P5[0] == 'S' || P6[0] == 'S') @@ -2843,7 +2853,7 @@ nosocks: SendtoNode(TNC, Stream, &sockptr->FromHostBuffer[sockptr->FromHostBuffGetptr], Msglen); sockptr->FromHostBuffGetptr += Msglen; - sockptr->LastSendTime = REALTIMETICKS; + sockptr->LastSendTime = time(NULL); } } } @@ -3100,7 +3110,10 @@ LRESULT CALLBACK TelWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPara TNC = TNCInfo[n]; TNC->Port = n; - TNC->Hardware = H_TELNET; + TNC->PortRecord = PortRecord; + + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_TELNET; + TNC->hDlg = SavehDlg; TNC->RIG = &TNC->DummyRig; // Not using Rig control, so use Dummy @@ -3131,8 +3144,6 @@ LRESULT CALLBACK TelWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPara ModifyMenu(TCP->hDisMenu,i - 1 ,MF_BYPOSITION | MF_STRING,IDM_DISCONNECT + 1, "."); } - TNC->PortRecord = PortRecord; - Sleep(500); OpenSockets(TNC); OpenSockets6(TNC); @@ -3755,7 +3766,7 @@ MsgLoop: BuffertoNode(sockptr, NodeLine, len); sockptr->InputLen = 0; - ShowConnections(TNC);; + ShowConnections(TNC); return 0; } @@ -3929,7 +3940,7 @@ MsgLoop: #ifndef LINBPQ ModifyMenu(TCP->hDisMenu, n - 1, MF_BYPOSITION | MF_STRING, IDM_DISCONNECT + n, MsgPtr); #endif - ShowConnections(TNC);; + ShowConnections(TNC); return 0; } @@ -4185,7 +4196,7 @@ int DataSocket_ReadRelay(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, #ifndef LINBPQ ModifyMenu(TCP->hDisMenu, n - 1, MF_BYPOSITION | MF_STRING, IDM_DISCONNECT + n, MsgPtr); #endif - ShowConnections(TNC);; + ShowConnections(TNC); return 0; @@ -4305,7 +4316,7 @@ int DataSocket_ReadRelay(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SendtoNode(TNC, sockptr->Number, TCP->RelayAPPL, (int)strlen(TCP->RelayAPPL)); - ShowConnections(TNC);; + ShowConnections(TNC); return 0; @@ -4490,7 +4501,7 @@ MsgLoop: WritetoTrace(Stream, MsgPtr, InputLen, sockptr->ADIF, 'R'); } - if (InputLen == 8 && memcmp(MsgPtr, ";;;;;;\r\n", 8) == 0) + if (InputLen == 8 && memcmp(MsgPtr, ";;;\r\n", 8) == 0) { // CMS Keepalive @@ -4804,7 +4815,7 @@ MsgLoop: ModifyMenu(TCP->hDisMenu, n - 1, MF_BYPOSITION | MF_STRING, IDM_DISCONNECT + n, MsgPtr); #endif - ShowConnections(TNC);; + ShowConnections(TNC); InputLen=InputLen-(MsgLen+1); @@ -4880,7 +4891,7 @@ MsgLoop: WriteLog (logmsg); } - ShowConnections(TNC);; + ShowConnections(TNC); InputLen=InputLen-(MsgLen+1); sockptr->InputLen=InputLen; @@ -4978,6 +4989,7 @@ struct RHPParamBlock unsigned char * Msg; int Len; SOCKET Socket; + struct ConnectionInfo * sockptr; }; @@ -5107,7 +5119,7 @@ int DataSocket_ReadHTTP(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, S { sockcopy = malloc(sizeof(struct ConnectionInfo)); sockptr->TNC = TNC; - sockptr->LastSendTime = REALTIMETICKS; + sockptr->LastSendTime = time(NULL); memcpy(sockcopy, sockptr, sizeof(struct ConnectionInfo)); @@ -5120,10 +5132,13 @@ int DataSocket_ReadHTTP(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, S struct RHPParamBlock * ParamBlock = malloc(sizeof(struct RHPParamBlock)); + ParamBlock->sockptr = sockptr; ParamBlock->Socket = sockptr->socket; ParamBlock->Len = Len; ParamBlock->Msg = malloc(Len + 10); memcpy(ParamBlock->Msg, Payload, Len); + sockptr->LastSendTime = time(NULL); + _beginthread(RHPThread, 0, (VOID *)ParamBlock); sockptr->InputLen = 0; @@ -5158,7 +5173,7 @@ int DataSocket_ReadHTTP(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, S sockcopy = malloc(sizeof(struct ConnectionInfo)); sockptr->TNC = TNC; - sockptr->LastSendTime = REALTIMETICKS; + sockptr->LastSendTime = time(NULL); memcpy(sockcopy, sockptr, sizeof(struct ConnectionInfo)); @@ -5265,7 +5280,7 @@ int DataSocket_Disconnect(struct TNCINFO * TNC, struct ConnectionInfo * sockptr ModifyMenu(TNC->TCPInfo->hDisMenu, n - 1, MF_BYPOSITION | MF_STRING, IDM_DISCONNECT + n, "."); #endif sockptr->SocketActive = FALSE; - ShowConnections(TNC);; + ShowConnections(TNC); } return 0; } @@ -7154,7 +7169,7 @@ int DoRefreshWebMailIndex() { sockcopy = malloc(sizeof(struct ConnectionInfo)); sockptr->TNC = TNC; - sockptr->LastSendTime = REALTIMETICKS; + sockptr->LastSendTime = time(NULL); memcpy(sockcopy, sockptr, sizeof(struct ConnectionInfo)); diff --git a/UIARQ.c b/UIARQ.c index 4d4b779..291d711 100644 --- a/UIARQ.c +++ b/UIARQ.c @@ -464,7 +464,7 @@ UINT UIARQExtInit(EXTPORTDATA * PortEntry) ptr=strchr(TNC->NodeCall, ' '); if (ptr) *(ptr) = 0; // Null Terminate - TNC->Hardware = H_UIARQ; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_UIARQ; if (TNC->BusyWait == 0) TNC->BusyWait = 10; diff --git a/UZ7HODrv.c b/UZ7HODrv.c index 0a417c7..3288510 100644 --- a/UZ7HODrv.c +++ b/UZ7HODrv.c @@ -1400,7 +1400,7 @@ void * UZ7HOExtInit(EXTPORTDATA * PortEntry) ptr=strchr(TNC->NodeCall, ' '); if (ptr) *(ptr) = 0; // Null Terminate - TNC->Hardware = H_UZ7HO; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_UZ7HO; UZ7HOChannel[port] = PortEntry->PORTCONTROL.CHANNELNUM-65; diff --git a/V4.c b/V4.c index 08f2f23..54d5e5d 100644 --- a/V4.c +++ b/V4.c @@ -971,13 +971,13 @@ void * V4ExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; + TNC->PortRecord = PortEntry; if (TNC->ProgramPath) TNC->WeStartedTNC = RestartTNC(TNC); - TNC->Hardware = H_V4; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_V4; - TNC->PortRecord = PortEntry; if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); diff --git a/VARA.c b/VARA.c index d9fc67e..4d46984 100644 --- a/VARA.c +++ b/VARA.c @@ -1163,6 +1163,7 @@ void * VARAExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; + TNC->PortRecord = PortEntry; TNC->ARDOPBuffer = malloc(8192); TNC->ARDOPDataBuffer = malloc(8192); @@ -1170,7 +1171,7 @@ void * VARAExtInit(EXTPORTDATA * PortEntry) if (TNC->ProgramPath) TNC->WeStartedTNC = 1; - TNC->Hardware = H_VARA; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_VARA; if (TNC->BusyWait == 0) TNC->BusyWait = 10; @@ -1178,8 +1179,6 @@ void * VARAExtInit(EXTPORTDATA * PortEntry) if (TNC->BusyHold == 0) TNC->BusyHold = 1; - TNC->PortRecord = PortEntry; - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); else @@ -1446,9 +1445,6 @@ VOID VARAThread(void * portptr) return; } - -// printf("Starting VARA Thread\n"); - // if on Windows and Localhost see if TNC is running #ifdef WIN32 @@ -1564,14 +1560,11 @@ TNCRunning: sinx.sin_addr.s_addr = INADDR_ANY; sinx.sin_port = 0; -// printf("Trying to connect to VARA TNC\n"); - if (connect(TNC->TCPSock,(LPSOCKADDR) &TNC->destaddr,sizeof(TNC->destaddr)) == 0) { // Connected successful goto VConnected; - } if (TNC->Alerted == FALSE) @@ -1727,6 +1720,7 @@ VConnected: GetSemaphore(&Semaphore, 52); VARAProcessReceivedControl(TNC); FreeSemaphore(&Semaphore); + Debugprintf("VARA Returned from processing control packet"); } if (FD_ISSET(TNC->TCPDataSock, &readfs)) @@ -2115,7 +2109,7 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) // Only allow VarAC mode for incomming sessions ProcessIncommingConnectEx(TNC, Call, 0, (TNC->NetRomMode == 0), TRUE); - + SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; if (Speed) @@ -2230,6 +2224,7 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) if (App < 32) { char AppName[13]; + char AppBuffer[64]; memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); AppName[12] = 0; @@ -2244,7 +2239,7 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) if (CheckAppl(TNC, AppName)) { - MsgLen = sprintf(Buffer, "%s\r", AppName); + MsgLen = sprintf(AppBuffer, "%s\r", AppName); buffptr = GetBuff(); @@ -2254,7 +2249,9 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) } buffptr->Len = MsgLen; - memcpy(buffptr->Data, Buffer, MsgLen); + memcpy(buffptr->Data, AppBuffer, MsgLen); + + Debugprintf("Calling Application %s", AppBuffer); C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); @@ -2429,7 +2426,7 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) // return; } - if (_memicmp(Buffer, "REGISTERED", 9) == 0) + if (_memicmp(Buffer, "LINK REGISTERED", 9) == 0) { strcat(Buffer, "\r"); WritetoTrace(TNC, Buffer, (int)strlen(Buffer)); @@ -2443,6 +2440,13 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) return; } + if (_memicmp(Buffer, "UNENCRYPTED LINK ", 11) == 0) + { + strcat(Buffer, "\r"); + WritetoTrace(TNC, Buffer, (int)strlen(Buffer)); + return; + } + if (_memicmp(Buffer, "MISSING SOUNDCARD", 17) == 0) { strcat(Buffer, "\r"); @@ -2668,7 +2672,7 @@ VOID VARAProcessReceivedControl(struct TNCINFO * TNC) { int InputLen, MsgLen; char * ptr, * ptr2; - char Buffer[4096]; + char Buffer[8192]; // shouldn't get several messages per packet, as each should need an ack // May get message split over packets @@ -2676,7 +2680,7 @@ VOID VARAProcessReceivedControl(struct TNCINFO * TNC) if (TNC->InputLen > 8000) // Shouldnt have packets longer than this TNC->InputLen=0; - InputLen=recv(TNC->TCPSock, &TNC->ARDOPBuffer[TNC->InputLen], 8192 - TNC->InputLen, 0); + InputLen=recv(TNC->TCPSock, &TNC->ARDOPBuffer[TNC->InputLen], 8191 - TNC->InputLen, 0); if (InputLen == 0 || InputLen == SOCKET_ERROR) { @@ -2699,12 +2703,18 @@ VOID VARAProcessReceivedControl(struct TNCINFO * TNC) TNC->InputLen += InputLen; + TNC->ARDOPBuffer[TNC->InputLen] = 0; + Debugprintf("VARA Processing buffer - %s", TNC->ARDOPBuffer); + loop: ptr = memchr(TNC->ARDOPBuffer, '\r', TNC->InputLen); if (ptr == 0) // CR in buffer + { + Debugprintf("VARA Part Packet Received - Waiting for rest"); return; // Wait for it + } ptr2 = &TNC->ARDOPBuffer[TNC->InputLen]; @@ -2727,9 +2737,10 @@ loop: if (TNC->InputLen < MsgLen) { TNC->InputLen = 0; + Debugprintf("VARA Corrupt multi command input"); return; } - memmove(TNC->ARDOPBuffer, ptr + 1, TNC->InputLen-MsgLen); + memmove(TNC->ARDOPBuffer, ptr + 1, TNC->InputLen - MsgLen); TNC->InputLen -= MsgLen; goto loop; diff --git a/Versions-skigdebian.h b/Versions-skigdebian.h deleted file mode 100644 index d5d92c3..0000000 --- a/Versions-skigdebian.h +++ /dev/null @@ -1,125 +0,0 @@ - -#ifdef Kernel - -#define Vers 5,2,9,2 -#define Verstring "5.2.9.2\0" -#define Datestring "September 2012" -#define VerComments "G8BPQ Packet Switch V5.2.9.2\0" -#define VerCopyright "Copyright © 2001-2012 John Wiseman G8BPQ\0" -#define VerDesc "BPQ32 Switch\0" - -#endif - -#define KVers 6,0,24,59 -#define KVerstring "6.0.24.59\0" - -#ifdef CKernel - -#define Vers KVers -#define Verstring KVerstring -#define Datestring "January 2025" -#define VerComments "G8BPQ Packet Switch (C Version)" KVerstring -#define VerCopyright "Copyright © 2001-2025 John Wiseman G8BPQ\0" -#define VerDesc "BPQ32 Switch\0" -#define VerProduct "BPQ32" - -#endif - -#ifdef TermTCP - -#define Vers 1,0,16,2 -#define Verstring "1.0.16.2\0" -#define VerComments "Internet Terminal for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2011-2025 John Wiseman G8BPQ\0" -#define VerDesc "Simple TCP Terminal Program for G8BPQ Switch\0" -#define VerProduct "BPQTermTCP" - -#endif - -#ifdef BPQTerm - -#define Vers 2,2,5,2 -#define Verstring "2.2.5.2\0" -#define VerComments "Simple Terminal for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 1999-2025 John Wiseman G8BPQ\0" -#define VerDesc "Simple Terminal Program for G8BPQ Switch\0" -#define VerProduct "BPQTerminal" - -#endif - -#ifdef BPQTermMDI - -#define Vers 2,2,0,3 -#define Verstring "2.2.0.3\0" -#define VerComments "MDI Terminal for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 1999-2025 John Wiseman G8BPQ\0" -#define VerDesc "MDI Terminal Program for G8BPQ Switch\0" - -#endif - -#ifdef MAIL - -#define Vers KVers -#define Verstring KVerstring -#define VerComments "Mail server for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2009-2025 John Wiseman G8BPQ\0" -#define VerDesc "Mail server for G8BPQ's 32 Bit Switch\0" -#define VerProduct "BPQMail" - -#endif - -#ifdef HOSTMODES - -#define Vers 1,1,8,1 -#define Verstring "1.1.8.1\0" -//#define SPECIALVERSION "Test 3" -#define VerComments "Host Modes Emulator for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2009-2019 John Wiseman G8BPQ\0" -#define VerDesc "Host Modes Emulator for G8BPQ's 32 Bit Switch\0" -#define VerProduct "BPQHostModes" - -#endif - - -#ifdef UIUTIL - -#define Vers 0,1,3,1 -#define Verstring "0.1.3.1\0" -#define VerComments "Beacon Utility for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2011-2019 John Wiseman G8BPQ\0" -#define VerDesc "Beacon Utility for G8BPQ Switch\0" -#define VerProduct "BPQUIUtil" - -#endif - -#ifdef AUTH - -#define Vers 0,1,0,0 -#define Verstring "0.1.0.0\0" -#define VerComments "Password Generation Utility for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2011-2025 John Wiseman G8BPQ\0" -#define VerDesc "Password Generation Utility for G8BPQ Switch\0" - -#endif - -#ifdef APRS - -#define Vers KVers -#define Verstring KVerstring -#define VerComments "APRS Client for G8BPQ Switch\0" -#define VerCopyright "Copyright © 2012-2025 John Wiseman G8BPQ\0" -#define VerDesc "APRS Client for G8BPQ Switch\0" -#define VerProduct "BPQAPRS" - -#endif - -#ifdef CHAT - -#define Vers KVers -#define Verstring KVerstring -#define VerComments "Chat server for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2009-2025 John Wiseman G8BPQ\0" -#define VerDesc "Chat server for G8BPQ's 32 Bit Switch\0" -#define VerProduct "BPQChat" - -#endif diff --git a/Versions.h b/Versions.h index 4d7bd3b..6098cd4 100644 --- a/Versions.h +++ b/Versions.h @@ -10,8 +10,8 @@ #endif -#define KVers 6,0,24,59 -#define KVerstring "6.0.24.59\0" +#define KVers 6,0,24,65 +#define KVerstring "6.0.24.65\0" #ifdef CKernel diff --git a/WINMOR.c b/WINMOR.c index 51b77e5..5faf722 100644 --- a/WINMOR.c +++ b/WINMOR.c @@ -1462,11 +1462,12 @@ void * WinmorExtInit(EXTPORTDATA * PortEntry) } TNC->Port = port; + TNC->PortRecord = PortEntry; if (TNC->ProgramPath) TNC->WeStartedTNC = RestartTNC(TNC); - TNC->Hardware = H_WINMOR; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_WINMOR; if (TNC->BusyWait == 0) TNC->BusyWait = 10; @@ -1474,7 +1475,6 @@ void * WinmorExtInit(EXTPORTDATA * PortEntry) if (TNC->BusyHold == 0) TNC->BusyHold = 1; - TNC->PortRecord = PortEntry; if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); diff --git a/WinRPR.c b/WinRPR.c index af1a7fb..fd4fb94 100644 --- a/WinRPR.c +++ b/WinRPR.c @@ -795,7 +795,8 @@ void * WinRPRExtInit(EXTPORTDATA * PortEntry) WritetoConsoleLocal(msg); TNC->Port = port; - TNC->Hardware = H_WINRPR; + TNC->PortRecord = PortEntry; + TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_WINRPR; // Set up DED addresses for streams @@ -811,8 +812,6 @@ void * WinRPRExtInit(EXTPORTDATA * PortEntry) PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream PortEntry->SCANCAPABILITIES = NONE; // Scan Control 3 stage/conlock - TNC->PortRecord = PortEntry; - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) memcpy(TNC->NodeCall, MYNODECALL, 10); else diff --git a/asmstrucs.h b/asmstrucs.h index 8a46075..343ea83 100644 --- a/asmstrucs.h +++ b/asmstrucs.h @@ -33,6 +33,7 @@ typedef int (FAR *FARPROCY)(); #define L4BUSY 0x80 // BNA - DONT SEND ANY MORE #define L4NAK 0x40 // NEGATIVE RESPONSE FLAG #define L4MORE 0x20 // MORE DATA FOLLOWS - FRAGMENTATION FLAG +#define L4COMP 0x10 // BPQ Specific use of spare it - data is compressed #define L4CREQ 1 // CONNECT REQUEST #define L4CACK 2 // CONNECT ACK @@ -40,6 +41,7 @@ typedef int (FAR *FARPROCY)(); #define L4DACK 4 // DISCONNECT ACK #define L4INFO 5 // INFORMATION #define L4IACK 6 // INFORMATION ACK +#define L4RESET 7 // Paula's extension extern char MYCALL[]; // 7 chars, ax.25 format @@ -170,6 +172,23 @@ typedef struct _TRANSPORTENTRY char APPL[16]; // Set if session initiated by an APPL int L4LIMIT; // Idle time for this Session + // Now support compressing NetRom Sessions. + // We collect as much data as possible before compressing and re-packetizing + + int AllowCompress; + 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; // @@ -195,6 +214,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) @@ -445,7 +467,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 @@ -467,12 +490,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 @@ -682,6 +705,7 @@ typedef struct PORTCONTROL struct PORTCONTROL * HookPort; int PortSlot; // Index in Port Table struct TNCINFO * TNC; // Associated TNC record + int HWType; // Hardware type of Driver. In here as external apps don't have access to TNC record int RIGPort; // Linked port for freq resporting unsigned int PERMITTEDAPPLS; // Appls allowed on this port (generalisation of BBSBANNED) char * CTEXT; // Port Specific CText diff --git a/cMain-skigdebian.c b/cMain-skigdebian.c deleted file mode 100644 index 4ae1dea..0000000 --- a/cMain-skigdebian.c +++ /dev/null @@ -1,2788 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -// -// C replacement for Main.asm -// -#define Kernel - -#define _CRT_SECURE_NO_DEPRECATE - -#pragma data_seg("_BPQDATA") - -//#include "windows.h" -//#include "winerror.h" - -#include "time.h" -#include "stdio.h" -#include - -#include "kernelresource.h" -#include "cheaders.h" -#include "tncinfo.h" -#include "mqtt.h" - -VOID L2Routine(struct PORTCONTROL * PORT, PMESSAGE Buffer); -VOID ProcessIframe(struct _LINKTABLE * LINK, PDATAMESSAGE Buffer); -VOID FindLostBuffers(); -VOID ReadMH(); -void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); -int upnpInit(); -void AISTimer(); -void ADSBTimer(); -VOID SendSmartID(struct PORTCONTROL * PORT); -int CanPortDigi(int Port); -int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); -void MQTTTimer(); -void SaveMH(); - -#include "configstructs.h" - -extern struct CONFIGTABLE xxcfg; -extern BOOL needAIS; -extern int needADSB; - -struct PORTCONFIG * PortRec; - -#define RNRSET 0x2 // RNR RECEIVED FROM OTHER END - -// STATION INFORMATION - -char DATABASESTART[14] = ""; -char xMAJORVERSION = 4; -char xMINORVERSION = 9; -char FILLER1[16] = ""; - -struct ROUTE * NEIGHBOURS = NULL; -int ROUTE_LEN = sizeof(struct ROUTE); -int MAXNEIGHBOURS = 20; - -struct DEST_LIST * DESTS = NULL; // NODE LIST -int DEST_LIST_LEN = sizeof(struct DEST_LIST); - -struct _LINKTABLE * LINKS = NULL; -int LINK_TABLE_LEN = sizeof (struct _LINKTABLE); -int MAXLINKS = 30; - - -char MYCALL[7] = ""; // DB 7 DUP (0) ; NODE CALLSIGN (BIT SHIFTED) -char MYALIASTEXT[6] = ""; // DB ' ' ; NODE ALIAS (KEEP TOGETHER) - -char MYALIASLOPPED[10]; -char MYCALLLOPPED[10]; - -UCHAR MYCALLWITHALIAS[13] = ""; - -UCHAR NETROMCALL[7] = ""; // Call used for NETROM (can be MYCALL) - -APPLCALLS APPLCALLTABLE[NumberofAppls] = {0}; - -UCHAR MYNODECALL[10] = ""; // NODE CALLSIGN (ASCII) -UCHAR MYNETROMCALL[10] = ""; // NETROM CALLSIGN (ASCII) -char NODECALLLOPPED[10]; - -VOID * FREE_Q = NULL; - -time_t TimeLoaded = 0; - -struct PORTCONTROL * PORTTABLE = NULL; -int NUMBEROFPORTS = 0; -int PORTENTRYLEN = sizeof(struct PORTCONTROL); - -struct DEST_LIST * ENDDESTLIST = NULL; // ; NODE LIST+1 -; - -VOID * BUFFERPOOL = NULL; // START OF BUFFER POOL -VOID * ENDBUFFERPOOL = NULL; - -int OBSINIT = 5; // INITIAL OBSOLESCENCE VALUE -int OBSMIN = 4; // MINIMUM TO BROADCAST -int L3INTERVAL = 60; // 'NODES' INTERVAL IN MINS -int IDINTERVAL = 20; // 'ID' BROADCAST INTERVAL -int BTINTERVAL = 20; // 'BT' BROADCAST INTERVAL -int MINQUAL = 10; // MIN QUALITY FOR AUTOUPDATES -int HIDENODES = 0; // N * COMMAND SWITCH -int BBSQUAL = 255; // QUALITY OF BBS RELATIVE TO NODE - -int NUMBEROFBUFFERS = 999; // PACKET BUFFERS - -int PACLEN = 100; //MAX PACKET SIZE - -// L2 SYSTEM TIMER RUNS AT 3 HZ - -int T3 = 3*61*3; // LINK VALIDATION TIMER (3 MINS) (+ a bit to reduce RR collisions) - -int L2KILLTIME = 16*60*3; // IDLE LINK TIMER (16 MINS) -int L3LIVES = 15; // MAX L3 HOPS -int L4N2 = 3; // LEVEL 4 RETRY COUNT -int L4LIMIT = 60*15; // IDLE SESSION LIMIT - 15 MINS -int L4DELAY = 5; // L4 DELAYED ACK TIMER - -int BBS = 1; // INCLUDE BBS SUPPORT -int NODE = 1; // INCLUDE SWITCH SUPPORT - -int FULL_CTEXT = 1; // CTEXT ON ALL CONNECTS IF NZ - -BOOL LogL4Connects = FALSE; -BOOL LogAllConnects = FALSE; -BOOL AUTOSAVEMH = TRUE; -extern BOOL ADIFLogEnabled; -extern UCHAR LogDirectory[260]; -extern BOOL EventsEnabled; -extern BOOL SaveAPRSMsgs; -BOOL M0LTEMap = FALSE; -BOOL MQTT = FALSE; -char MQTT_HOST[80] = ""; -int MQTT_PORT = 0; -char MQTT_USER[80] = ""; -char MQTT_PASS[80] = ""; - -int MQTT_Connecting = 0; -int MQTT_Connected = 0; - - -//TNCTABLE DD 0 -//NUMBEROFSTREAMS DD 0 - -extern VOID * ENDPOOL; -extern void * APPL_Q; // Queue of frames for APRS Appl - -extern BOOL APRSActive; - -#define BPQHOSTSTREAMS 64 - -// Although externally streams are numbered 1 to 64, internally offsets are 0 - 63 - -BPQVECSTRUC XDUMMY = {0}; // Needed to force correct order of following - -BPQVECSTRUC BPQHOSTVECTOR[BPQHOSTSTREAMS + 5] = {0}; - -BPQVECSTRUC * TELNETMONVECPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS]; -BPQVECSTRUC * AGWMONVECPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS + 1]; -BPQVECSTRUC * APRSMONVECPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS + 2]; -BPQVECSTRUC * IPHOSTVECTORPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS + 3]; - -int BPQVECLENGTH = sizeof(BPQVECSTRUC); - -int NODEORDER = 0; -UCHAR LINKEDFLAG = 0; - -UCHAR UNPROTOCALL[80] = ""; - -UCHAR ExcludeList[71] = ""; // 10 ENTRIES, 7 BYTES EACH - -char * INFOMSG = NULL; - -char * CTEXTMSG = NULL; -int CTEXTLEN = 0; - -UCHAR MYALIAS[7] = ""; // ALIAS IN AX25 FORM -UCHAR BBSALIAS[7] = ""; - -UCHAR AX25CALL[7] = ""; // WORK AREA FOR AX25 <> NORMAL CALL CONVERSION -UCHAR NORMCALL[10] = ""; // CALLSIGN IN NORMAL FORMAT -int NORMLEN = 0; // LENGTH OF CALL IN NORMCALL - -int CURRENTPORT = 0; // PORT FOR CURRENT MESSAGE -VOID * CURRENTPORTPTR = NULL; // PORT CONTROL TABLE ENTRY FOR CURRENT PORT - -int SDCBYTE = 0; // CONTROL BYTE FOR CURRENT FRAME - -VOID * BUFFER = NULL; // GENERAL SAVE AREA FOR BUFFER ADDR -VOID * ADJBUFFER = NULL; // BASE ADJUSED FOR DIGIS - -UCHAR TEMPFIELD[7] = ""; // ADDRESS WORK FILED - -void * TRACE_Q = NULL; // TRANSMITTED FRAMES TO BE TRACED - -int RANDOM = 0; // 'RANDOM' NUMBER FOR PERSISTENCE CALCS - -int L2TIMERFLAG = 0; // INCREMENTED AT 18HZ BY TIMER INTERRUPT -int L3TIMERFLAG = 0; // DITTO -int L4TIMERFLAG = 0; // DITTO - -char HEADERCHAR = '}'; // CHAR FOR _NODE HEADER MSGS - -VOID * LASTPOINTER = NULL; // PERVIOUS _NODE DURING CHAINING - -int REALTIMETICKS = 0; -int BGTIMER = 0; // TO CONTROL BG SCANS - -VOID * CONFIGPTR = NULL; // Internal Config Get Offset - -int AUTOSAVE = 0; // AUTO SAVE NODES ON EXIT FLAG -int L4APPL = 1; // Application for BBSCALL/ALIAS connects -int CFLAG = 0; // C =HOST Command - -VOID * IDMSG_Q = NULL; // ID/BEACONS WAITING TO BE SENT - -int NODESINPROGRESS = 0; -VOID * CURRENTNODE = NULL; // NEXT _NODE TO SEND -VOID * DESTHEADER = NULL; // HEAD OF SORTED NODES CHAIN - -int L3TIMER = 1; // TIMER FOR 'NODES' MESSAGE -int IDTIMER = 0; // TIMER FOR ID MESSAGE -int BTTIMER = 0; // TIMER FOR BT MESSAGE - -UCHAR * NEXTFREEDATA = NULL; // ADDRESS OF NEXT FREE BYTE of shared memory - -int NEEDMH = 0; - -struct DATAMESSAGE BTHDDR = {0,0,9,240,13}; -struct _MESSAGE IDHDDR = {0,0,23,0,0,3, 240}; - -VOID * IDMSG = &IDHDDR; - -//DD 0 ; CHAIN -// DB 0 ; PORT -int BTLENGTH = 9; // DW 9 ; LENGTH -// DB 0F0H ; PID -char BTEXTFLD[256] ="\r"; - -char BridgeMap[MaxBPQPortNo + 1][MaxBPQPortNo + 1] = {0}; - -// Keep Buffers at end - -#define DATABYTES 600000 // WAS 320000 - -UCHAR DATAAREA[DATABYTES] = ""; - -void ** Bufferlist[1000] = {0}; - -extern BOOL IPRequired; -extern BOOL PMRequired; -extern int MaxHops; -extern int MAXRTT; -extern USHORT CWTABLE[]; -extern struct _TRANSPORTENTRY * L4TABLE; -extern UCHAR ROUTEQUAL; -extern UINT BPQMsg; - -extern int NUMBEROFTNCPORTS; - -extern APPLCALLS APPLCALLTABLE[]; - -// LOOPBACK PORT ROUTINES - -VOID LINKINIT(PEXTPORTDATA PORTVEC) -{ - WritetoConsoleLocal("Loopback\n"); -} - -VOID LINKTX(PEXTPORTDATA PORTVEC, PMESSAGE Buffer) -{ - // LOOP BACK TO SWITCH - struct _LINKTABLE * LINK; - - LINK = Buffer->Linkptr; - - if (LINK) - { - if (LINK->L2TIMER) - LINK->L2TIMER = LINK->L2TIME; - - Buffer->Linkptr = 0; // CLEAR FLAG FROM BUFFER - } - - C_Q_ADD(&PORTVEC->PORTCONTROL.PORTRX_Q, Buffer); -} - - -VOID LINKRX() -{ -} - - -VOID LINKTIMER() -{ -} - -VOID LINKCLOSE() -{ -} - - -VOID EXTCLOSE() -{ -} - -BOOL KISSTXCHECK() -{ - return 0; -} - -BOOL LINKTXCHECK() -{ - return 0; -} - -void * Dummy(int fn, int port, PDATAMESSAGE buff) // Dummy for missing EXT Driver -{ - return 0; -} - -VOID EXTINIT(PEXTPORTDATA PORTVEC) -{ - // LOAD DLL - NAME IS IN PORT_DLL_NAME - - void *(* Startup) (PEXTPORTDATA PORTVEC); // ADDR OF Startup ROUTINE - - PORTVEC->PORT_EXT_ADDR = Dummy; - - Startup = InitializeExtDriver(PORTVEC); - - if (Startup == 0) - { - WritetoConsoleLocal("Driver installation failed\n"); - return; - } - - -// CALL THE ROUTINE TO START IT UP - -// Startup returns address of processing routine - - PORTVEC->PORT_EXT_ADDR = (void *(__cdecl *)(int,int,PDATAMESSAGE))Startup(PORTVEC);; - - if (PORTVEC->PORT_EXT_ADDR == 0) - { - WritetoConsoleLocal("Driver Initialisation failed\n"); - return; - } - -} - -VOID EXTTX(PEXTPORTDATA PORTVEC, MESSAGE * Buffer) -{ - struct _LINKTABLE * LINK; - struct PORTCONTROL * PORT = (struct PORTCONTROL *)PORTVEC; - -// RESET TIMER, unless BAYCOM - - if (PORT->KISSFLAGS == 255) // Used for BAYCOM - { - PORTVEC->PORT_EXT_ADDR(2, PORT->PORTNUMBER, (PDATAMESSAGE)Buffer); - - return; // Baycom driver passes frames to trace once sent - } - - LINK = Buffer->Linkptr; - - if (LINK) - { - if (LINK->L2TIMER) - LINK->L2TIMER = LINK->L2TIME; - - if (PORT->TNC == 0 || PORT->TNC->Hardware != H_KISSHF) - Buffer->Linkptr = 0; // CLEAR FLAG FROM BUFFER - } - - PORTVEC->PORT_EXT_ADDR(2, PORT->PORTNUMBER, (PDATAMESSAGE)Buffer); - - if (PORT->PROTOCOL == 10 && PORT->TNC && PORT->TNC->Hardware != H_KISSHF) - { - ReleaseBuffer(Buffer); - return; - } - - C_Q_ADD(&TRACE_Q, Buffer); - - return; - -} - -VOID EXTRX(PEXTPORTDATA PORTVEC) -{ - struct _MESSAGE * Message; - size_t Len; - struct PORTCONTROL * PORT = (struct PORTCONTROL *)PORTVEC; - -Loop: - - if (QCOUNT < 10) - return; - - Message = GetBuff(); - - if (Message == NULL) - return; - - Len = (size_t)PORTVEC->PORT_EXT_ADDR(1, PORT->PORTNUMBER, (PDATAMESSAGE)Message); - - if (Len == 0) - { - ReleaseBuffer((UINT *)Message); - return; - } - - if (PORT->PROTOCOL == 10) - { - // PACTOR Style Port - Negative values used to report events - for now -1 = Disconnected - - if (Len == -1) - { - int Sessno = Message->PORT; - TRANSPORTENTRY * Session; - - ReleaseBuffer((UINT *)Message); - - // GET RID OF ANY SESSION ENTRIES - - Session = PORTVEC->ATTACHEDSESSIONS[Sessno]; - - if (Session) - { - struct TNCINFO * TNC = PORTVEC->PORTCONTROL.TNC; - - CloseSessionPartner(Session); - - // is this the place to run DisconnectScript? - - if (TNC->DisconnectScript) - { - int n = 0; - struct DATAMESSAGE * Buffer; - - TRANSPORTENTRY Session = {0}; // = TNC->PortRecord->ATTACHEDSESSIONS[Sessno]; - - while (TNC->DisconnectScript[n]) - { - Buffer = GetBuff(); - if (Buffer) - { - Session.Secure_Session = 1; - Session.CIRCUITINDEX = -1; - Buffer->LENGTH = sprintf(Buffer->L2DATA, "%s\r", TNC->DisconnectScript[n++]) + (sizeof(void *) + 4); - CommandHandler(&Session, Buffer); - }; - } - } - - PORTVEC->ATTACHEDSESSIONS[Sessno] = NULL; - } - return; - } - } - - C_Q_ADD(&PORT->PORTRX_Q, (UINT *)Message); - - goto Loop; - - return; -} - -VOID EXTTIMER(PEXTPORTDATA PORTVEC) -{ - // USED TO SEND A RE-INIT IN THE CORRECT PROCESS - - if (PORTVEC->EXTRESTART) - { - PORTVEC->EXTRESTART = 0; //CLEAR - PORTVEC->PORT_EXT_ADDR(4, PORTVEC->PORTCONTROL.PORTNUMBER, 0); - } - - PORTVEC->PORT_EXT_ADDR(7, PORTVEC->PORTCONTROL.PORTNUMBER, 0); // Timer Routine -} - -VOID EXTSLOWTIMER(PEXTPORTDATA PORTVEC) -{ - PORTVEC->PORT_EXT_ADDR(8, PORTVEC->PORTCONTROL.PORTNUMBER, 0); // Timer Routine -} - -size_t EXTTXCHECK(PEXTPORTDATA PORTVEC, int Chan) -{ - uintptr_t Temp = Chan; - - return (size_t)PORTVEC->PORT_EXT_ADDR(3, PORTVEC->PORTCONTROL.PORTNUMBER, (void *)Temp); -} - -VOID PostDataAvailable(TRANSPORTENTRY * Session) -{ -#ifndef LINBPQ - if (Session->L4CIRCUITTYPE & BPQHOST) - { - BPQVECSTRUC * HostSess = Session->L4TARGET.HOST; - - if (HostSess) - { - if (HostSess->HOSTHANDLE) - { - PostMessage(HostSess->HOSTHANDLE, BPQMsg, HostSess->HOSTSTREAM, 2); - } - } - } -#endif -} - -VOID PostStateChange(TRANSPORTENTRY * Session) -{ -#ifndef LINBPQ - if (Session->L4CIRCUITTYPE & BPQHOST) - { - BPQVECSTRUC * HostSess = Session->L4TARGET.HOST; - - if (HostSess) - { - if (HostSess->HOSTHANDLE); - { - PostMessage(HostSess->HOSTHANDLE, BPQMsg, HostSess->HOSTSTREAM, 4); - } - } - } -#endif -} - -#ifdef LINBPQ - -#define HDLCTX KHDLCTX -#define HDLCRX KHDLCRX -#define HDLCTIMER KHDLCTIMER -#define HDLCCLOSE KHDLCCLOSE -#define HDLCTXCHECK KHDLCTXCHECK - -#define PC120INIT KHDLCINIT -#define DRSIINIT KHDLCINIT -#define TOSHINIT KHDLCINIT -#define RLC100INIT KHDLCINIT -#define BAYCOMINIT KHDLCINIT -#define PA0INIT KHDLCINIT - -int KHDLCINIT(PHDLCDATA PORTVEC); -void KHDLCTX(struct KISSINFO * KISS, PMESSAGE Buffer); -int KHDLCRX(PHDLCDATA PORTVEC); -void KHDLCTIMER(PHDLCDATA PORTVEC); -void KHDLCCLOSE(PHDLCDATA PORTVEC); -BOOL KHDLCTXCHECK(); - - -#else - -extern VOID PC120INIT(), DRSIINIT(), TOSHINIT(); -extern VOID RLC100INIT(), BAYCOMINIT(), PA0INIT(); - -extern VOID HDLCTX(); -extern VOID HDLCRX(); -extern VOID HDLCTIMER(); -extern VOID HDLCCLOSE(); -extern VOID HDLCTXCHECK(); - -#endif - -extern VOID KISSINIT(), KISSTX(), KISSRX(), KISSTIMER(), KISSCLOSE(); -extern VOID EXTINIT(PEXTPORTDATA PORTVEC), EXTTX(PEXTPORTDATA PORTVEC, MESSAGE * Buffer), LINKRX(), EXTRX(PEXTPORTDATA PORTVEC); -extern VOID LINKCLOSE(), EXTCLOSE() ,LINKTIMER(), EXTTIMER(PEXTPORTDATA PORTVEC); - -// VECTORS TO HARDWARE DEPENDENT ROUTINES - -VOID * INITCODE[12] = {KISSINIT, PC120INIT, DRSIINIT, TOSHINIT, KISSINIT, -RLC100INIT, RLC100INIT, LINKINIT, EXTINIT, BAYCOMINIT, PA0INIT, KISSINIT}; - -VOID * TXCODE[12] = {KISSTX, HDLCTX, HDLCTX, HDLCTX, KISSTX, - HDLCTX, HDLCTX, LINKTX, EXTTX, HDLCTX, HDLCTX, KISSTX}; - -VOID * RXCODE[12] = {KISSRX, HDLCRX, HDLCRX, HDLCRX, KISSRX, - HDLCRX, HDLCRX, LINKRX, EXTRX, HDLCRX, HDLCRX, KISSRX}; - -VOID * TIMERCODE[12] = {KISSTIMER, HDLCTIMER, HDLCTIMER, HDLCTIMER, KISSTIMER, - HDLCTIMER, HDLCTIMER, LINKTIMER, EXTTIMER, HDLCTIMER, HDLCTIMER, KISSTIMER}; - -VOID * CLOSECODE[12] = {KISSCLOSE, HDLCCLOSE, HDLCCLOSE, HDLCCLOSE, KISSCLOSE, - HDLCCLOSE, HDLCCLOSE, LINKCLOSE, EXTCLOSE, HDLCCLOSE, HDLCCLOSE, KISSCLOSE}; - -VOID * TXCHECKCODE[12] = {KISSTXCHECK, HDLCTXCHECK, HDLCTXCHECK, HDLCTXCHECK, KISSTXCHECK, - HDLCTXCHECK, HDLCTXCHECK, LINKTXCHECK, EXTTXCHECK, HDLCTXCHECK, HDLCTXCHECK, KISSTXCHECK}; - - -extern int BACKGROUND(); -extern int L2TimerProc(); -extern int L3TimerProc(); -extern int L4TimerProc(); -extern int L3FastTimer(); -extern int StatsTimer(); -extern int COMMANDHANDLER(); -VOID SDETX(struct _LINKTABLE * LINK); -extern int L4BG(); -extern int L3BG(); -extern int TNCTimerProc(); -extern int PROCESSIFRAME(); - -int xxxxx = MAXDATA; - -BOOL Start() -{ - struct CONFIGTABLE * cfg = &xxcfg; - struct APPLCONFIG * ptr1; - struct PORTCONTROL * PORT; - struct FULLPORTDATA * FULLPORT; // Including HW Data - struct FULLPORTDATA * NEXTPORT; // Including HW Data - struct _EXTPORTDATA * EXTPORT; - APPLCALLS * APPL; - struct ROUTE * ROUTE; - struct DEST_LIST * DEST; - struct CMDX * CMD; - int PortSlot = 1; - uintptr_t int3; - - unsigned char * ptr2 = 0, * ptr3, * ptr4; - USHORT * CWPTR; - int i, n; - - struct ROUTECONFIG * Rcfg; - - NEXTFREEDATA = &DATAAREA[0]; // For Reinit - - memset(DATAAREA, 0, DATABYTES); - - // Reinit everything in case of restart - - FREE_Q = 0; - TRACE_Q = 0; - IDMSG_Q = 0; - NUMBEROFPORTS = 0; - MAXBUFFS = 0; - QCOUNT = 0; - NUMBEROFNODES = 0; - DESTHEADER = 0; - NODESINPROGRESS = 0; - CURRENTNODE = 0; - L3TIMER = 1; // SEND NODES - - if (cfg->C_NODEALIAS[0] == 0) - memset(cfg->C_NODEALIAS, ' ', 10); - - TimeLoaded = time(NULL); - - AUTOSAVE = cfg->C_AUTOSAVE; - - if (cfg->C_L4APPL) - L4APPL = cfg->C_L4APPL; - - CFLAG = cfg->C_C; - - IPRequired = cfg->C_IP; - PMRequired = cfg->C_PM; - - if (cfg->C_MAXHOPS) - MaxHops = cfg->C_MAXHOPS; - - if (cfg->C_MAXRTT) - MAXRTT = cfg->C_MAXRTT * 100; - - if (cfg->C_NODE == 0 && cfg->C_BBS) - { - // USE BBS CALL FOR NODE if Set, otherwise find first APPLCALL - // Unless BBS also = 0 - - if (cfg->C_BBSCALL[0]) - { - memcpy(MYNODECALL, cfg->C_BBSCALL, 10); - memcpy(MYALIASTEXT, cfg->C_BBSALIAS, 6); - memcpy(MYALIASLOPPED, cfg->C_BBSALIAS, 10); - } - else - { - ptr1 = &cfg->C_APPL[0]; - - for (i = 0; i < NumberofAppls; i++) - { - if (ptr1->ApplCall[0] != ' ') - { - memcpy(MYNODECALL, &ptr1->ApplCall[0], 10); - memcpy(MYALIASTEXT, &ptr1->ApplAlias, 6); - memcpy(MYALIASLOPPED, &ptr1->ApplAlias, 10); - - break; - } - ptr1++; - } - } - - } - else - { - memcpy(MYNODECALL, cfg->C_NODECALL, 10); - memcpy(MYALIASTEXT, cfg->C_NODEALIAS, 6); - memcpy(MYALIASLOPPED, cfg->C_NODEALIAS, 10); - } - - strlop(MYALIASLOPPED, ' '); - - - // IF NO BBS, SET BOTH TO _NODE CALLSIGN - - if (cfg->C_BBS == 0) - { - memcpy(APPLCALLTABLE[0].APPLCALL_TEXT, cfg->C_NODECALL, 10); - memcpy(APPLCALLTABLE[0].APPLALIAS_TEXT, cfg->C_NODEALIAS, 10); - } - else - { - memcpy(APPLCALLTABLE[0].APPLCALL_TEXT, cfg->C_BBSCALL, 10); - memcpy(APPLCALLTABLE[0].APPLALIAS_TEXT, cfg->C_BBSALIAS, 10 ); - } - - BBSQUAL = cfg->C_BBSQUAL; - - // copy MYCALL to NETROMCALL - - memcpy(MYNETROMCALL, MYNODECALL, 10); - - // if NETROMCALL Defined, use it - - if (cfg->C_NETROMCALL[0] && cfg->C_NETROMCALL[0] != ' ') - memcpy(MYNETROMCALL, cfg->C_NETROMCALL, 10); - - strlop(MYNETROMCALL, ' '); - strlop(MYNODECALL, ' '); - - memcpy(NODECALLLOPPED, MYNODECALL, 10); - strlop(NODECALLLOPPED, ' '); - - APPLCALLTABLE[0].APPLQUAL = BBSQUAL; - - if (cfg->C_WASUNPROTO == 0 && cfg->C_BTEXT) - { - char * ptr1 = &cfg->C_BTEXT[0]; - char * ptr2 = BTHDDR.L2DATA; - int len = 120; - - BTHDDR.LENGTH = 1; // PID - - while ((*ptr1) && len--) - { - *(ptr2++) = *(ptr1++); - BTHDDR.LENGTH ++; - } - - } - - OBSINIT = cfg->C_OBSINIT; - OBSMIN = cfg->C_OBSMIN; - L3INTERVAL = cfg->C_NODESINTERVAL; - IDINTERVAL = cfg->C_IDINTERVAL; - if (IDINTERVAL) - IDTIMER = 2; - - BTINTERVAL = cfg->C_BTINTERVAL; - if (BTINTERVAL) - BTTIMER = 2; - - - MINQUAL = cfg->C_MINQUAL; - FULL_CTEXT = cfg->C_FULLCTEXT; - L3LIVES = cfg->C_L3TIMETOLIVE; - L4N2 = cfg->C_L4RETRIES; - L4DEFAULTWINDOW = cfg->C_L4WINDOW; - L4T1 = cfg->C_L4TIMEOUT; - -// MOV AX,C_BUFFERS -// MOV NUMBEROFBUFFERS,AX - - PACLEN = cfg->C_PACLEN; - T3 = cfg->C_T3 * 3; - L4LIMIT = cfg->C_IDLETIME; - if (L4LIMIT && L4LIMIT < 120) - L4LIMIT = 120; // Don't allow stupidly low - L2KILLTIME = L4LIMIT * 3; - L4DELAY = cfg->C_L4DELAY; - BBS = cfg->C_BBS; - NODE = cfg->C_NODE; - LINKEDFLAG = cfg->C_LINKEDFLAG; - MAXLINKS = cfg->C_MAXLINKS; - MAXDESTS = cfg->C_MAXDESTS; - MAXNEIGHBOURS = cfg->C_MAXNEIGHBOURS; - MAXCIRCUITS = cfg->C_MAXCIRCUITS; - HIDENODES = cfg->C_HIDENODES; - - LogL4Connects = cfg->C_LogL4Connects; - LogAllConnects = cfg->C_LogAllConnects; - AUTOSAVEMH = cfg->C_SaveMH; - ADIFLogEnabled = cfg->C_ADIF; - EventsEnabled = cfg->C_EVENTS; - SaveAPRSMsgs = cfg->C_SaveAPRSMsgs; - M0LTEMap = cfg->C_M0LTEMap; - MQTT = cfg->C_MQTT; - strcpy(MQTT_HOST, cfg->C_MQTT_HOST); - MQTT_PORT = cfg->C_MQTT_PORT; - strcpy(MQTT_USER, cfg->C_MQTT_USER); - strcpy(MQTT_PASS, cfg->C_MQTT_PASS); - - // Get pointers to PASSWORD and APPL1 commands - -// int APPL1 = 0; -//int PASSCMD = 0; - - CMD = &COMMANDS[0]; - n = 0; - - for (n = 0; n < NUMBEROFCOMMANDS; n++) - { - if (APPL1 == 0 && CMD->String[0] == '*') // First appl - { - APPLS = (char *)CMD; - APPL1 = n; - } - - if (PASSCMD == 0 && memcmp(CMD->String, "PASSWORD", 8) == 0) - PASSCMD = n; - - CMD++; - } - - -// SET UP APPLICATION LIST - - memset(&CMDALIAS[0][0], ' ', NumberofAppls * ALIASLEN ); - - ptr1 = (struct APPLCONFIG *)&xxcfg.C_APPL[0]; - ptr3 = &CMDALIAS[0][0]; - - for (i = 0; i < NumberofAppls; i++) - { - if (ptr1->Command[0] != ' ') - { - ptr2 = (char *)&COMMANDS[APPL1 + i]; - - memcpy(ptr2, ptr1, 12); - - // See if an Alias - - if (ptr1->CommandAlias[0] != ' ') - memcpy(ptr3, ptr1->CommandAlias, ALIASLEN); - - // SET LENGTH FIELD - - *(ptr2 + 12) = 0; // LENGTH - ptr4 = ptr2; - - while (*(ptr4) > 32) - { - ptr4++; - *(ptr2 + 12) = *(ptr2 + 12) + 1; - } - } - ptr1 ++; - ptr2 += CMDXLEN; - ptr3 += ALIASLEN; - } - - // Set up Exclude List - - memcpy(ExcludeList, cfg->C_EXCLUDE, 71); - - // SET UP PORT TABLE - - PortRec = &cfg->C_PORT[0];// (struct PORTCONFIG *)ptr2; - - PORTTABLE = (VOID *)NEXTFREEDATA; - FULLPORT = (struct FULLPORTDATA *)PORTTABLE; - - while (PortRec->PORTNUM) - { - // SET UP NEXT PORT PTR - - PORT = &FULLPORT->PORTCONTROL; - NEXTPORT = FULLPORT; - NEXTPORT++; - PORT->PORTPOINTER = (struct PORTCONTROL *)NEXTPORT; - - PORT->PORTNUMBER = (UCHAR)PortRec->PORTNUM; - PORT->PortSlot = PortSlot++; - memcpy(PORT->PORTDESCRIPTION, PortRec->ID, 30); - - PORT->PORTTYPE = (char)PortRec->TYPE; - - PORT->PORTINITCODE = INITCODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE - PORT->PORTTXROUTINE = TXCODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE - PORT->PORTRXROUTINE = RXCODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE - PORT->PORTTIMERCODE = TIMERCODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE - PORT->PORTCLOSECODE = CLOSECODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE - PORT->PORTTXCHECKCODE = TXCHECKCODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE - - - PORT->PROTOCOL = (char)PortRec->PROTOCOL; - PORT->IOBASE = PortRec->IOADDR; - - if (PortRec->SerialPortName && PortRec->SerialPortName[0]) - PORT->SerialPortName = _strdup(PortRec->SerialPortName); - else - { - if (PORT->IOBASE > 0 && PORT->IOBASE < 256) - { - char Name[80]; -#ifndef WIN32 - sprintf(Name, "com%d", PORT->IOBASE); -#else - sprintf(Name, "COM%d", PORT->IOBASE); -#endif - PORT->SerialPortName = _strdup(Name); - } - else - PORT->SerialPortName = _strdup("NOPORT"); - - } - PORT->INTLEVEL = (char)PortRec->INTLEVEL; - PORT->BAUDRATE = PortRec->SPEED; - - if (PORT->BAUDRATE == 49664) - PORT->BAUDRATE = (int)115200; - - PORT->CHANNELNUM = (char)PortRec->CHANNEL; - PORT->PORTQUALITY = (UCHAR)PortRec->QUALITY; - PORT->NormalizeQuality = !PortRec->NoNormalize; - PORT->IgnoreUnlocked = PortRec->IGNOREUNLOCKED; - PORT->INP3ONLY = PortRec->INP3ONLY; - - PORT->PORTWINDOW = (UCHAR)PortRec->MAXFRAME; - - if (PortRec->PROTOCOL == 0 || PORT->PORTTYPE == 22) // KISS or I2C - PORT->PORTTXDELAY = PortRec->TXDELAY /10; - else - PORT->PORTTXDELAY = PortRec->TXDELAY; - - if (PortRec->PROTOCOL == 0 || PORT->PORTTYPE == 22) // KISS or I2C - PORT->PORTSLOTTIME = (UCHAR)PortRec->SLOTTIME / 10; - else - PORT->PORTSLOTTIME = (UCHAR)PortRec->SLOTTIME; - - PORT->PORTPERSISTANCE = (UCHAR)PortRec->PERSIST; - PORT->FULLDUPLEX = (UCHAR)PortRec->FULLDUP; - - PORT->SOFTDCDFLAG = (UCHAR)PortRec->SOFTDCD; - PORT->PORTT1 = PortRec->FRACK / 333; - PORT->PORTT2 = PortRec->RESPTIME /333; - PORT->PORTN2 = (UCHAR)PortRec->RETRIES; - - PORT->PORTPACLEN = (UCHAR)PortRec->PACLEN; - PORT->QUAL_ADJUST = (UCHAR)PortRec->QUALADJUST; - - PORT->DIGIFLAG = PortRec->DIGIFLAG; - if (PortRec->DIGIPORT && CanPortDigi(PortRec->DIGIPORT)) - PORT->DIGIPORT = PortRec->DIGIPORT; - PORT->DIGIMASK = PortRec->DIGIMASK; - PORT->USERS = (UCHAR)PortRec->USERS; - - // PORTTAILTIME - if KISS, set a default, and cnvert to ticks - - if (PORT->PORTTYPE == 0) - { - if (PortRec->TXTAIL) - PORT->PORTTAILTIME = PortRec->TXTAIL / 10; - else - PORT->PORTTAILTIME = 3; // 10ths - } - else - - //; ON HDLC, TAIL TIMER IS USED TO HOLD RTS FOR 'CONTROLLED FULL DUP' - Val in seconds - - PORT->PORTTAILTIME = (UCHAR)PortRec->TXTAIL; - - PORT->PORTBBSFLAG = (char)PortRec->ALIAS_IS_BBS; - PORT->PORTL3FLAG = (char)PortRec->L3ONLY; - PORT->KISSFLAGS = PortRec->KISSOPTIONS; - PORT->PORTINTERLOCK = (UCHAR)PortRec->INTERLOCK; - PORT->NODESPACLEN = (UCHAR)PortRec->NODESPACLEN; - PORT->TXPORT = (UCHAR)PortRec->TXPORT; - - PORT->PORTMINQUAL = PortRec->MINQUAL; - - if (PortRec->MAXDIGIS) - PORT->PORTMAXDIGIS = PortRec->MAXDIGIS; - else - PORT->PORTMAXDIGIS = 8; - - PORT->PortNoKeepAlive = PortRec->DefaultNoKeepAlives; - PORT->PortUIONLY = PortRec->UIONLY; - PORT->TXPORT = (UCHAR)PortRec->TXPORT; - - // SET UP CWID - - if (PortRec->CWIDTYPE == 'o') - PORT->CWTYPE = 'O'; - else - PORT->CWTYPE = PortRec->CWIDTYPE; - - ptr2 = &PortRec->CWID[0]; - CWPTR = &PORT->CWID[0]; - - PORT->CWIDTIMER = (29 - PORT->PORTNUMBER) * 600; // TICKSPERMINUTE - PORT->CWPOINTER = &PORT->CWID[0]; - - for (i = 0; i < 8; i++) // MAX ID LENGTH - { - char c = *(ptr2++); - if (c < 32) - break; - if (c > 'Z') - continue; - - c -= '/'; // Table stats at / - c &= 127; - - *(CWPTR) = CWTABLE[c]; - CWPTR++; - } - - // SEE IF LINK CALLSIGN/ALIAS SPECIFIED - - if (PortRec->PORTCALL[0]) - ConvToAX25(PortRec->PORTCALL, PORT->PORTCALL); - - if (PortRec->PORTALIAS[0]) - ConvToAX25(PortRec->PORTALIAS, PORT->PORTALIAS); - - if (PortRec->PORTALIAS2[0]) - ConvToAX25(PortRec->PORTALIAS2, PORT->PORTALIAS2); - - if (PortRec->DLLNAME[0]) - { - EXTPORT = (struct _EXTPORTDATA *)PORT; - memcpy(EXTPORT->PORT_DLL_NAME, PortRec->DLLNAME, 16); - } - if (PortRec->BCALL[0]) - ConvToAX25(PortRec->BCALL, PORT->PORTBCALL); - - PORT->XDIGIS = PortRec->XDIGIS; // Crossband digi aliases - - memcpy(&PORT->PORTIPADDR, &PortRec->IPADDR, 4); - PORT->ListenPort = PortRec->ListenPort; - - if (PortRec->TCPPORT) - { - PORT->KISSTCP = TRUE; - PORT->IOBASE = PortRec->TCPPORT; - if (PortRec->IPADDR == 0) - PORT->KISSSLAVE = TRUE; - } - - if (PortRec->WL2K) - memcpy(&PORT->WL2KInfo, PortRec->WL2K, sizeof(struct WL2KInfo)); - - PORT->RIGPort = PortRec->RIGPORT; - - if (PortRec->HavePermittedAppls) - PORT->PERMITTEDAPPLS = PortRec->PERMITTEDAPPLS; - else - PORT->PERMITTEDAPPLS = 0xffffffff; // Default to all - - PORT->Hide = PortRec->Hide; - - PORT->SmartIDInterval = PortRec->SmartID; - - if (PortRec->KissParams && (PORT->PORTTYPE == 0 || PORT->PORTTYPE == 22)) - { - struct KISSINFO * KISS = (struct KISSINFO *)PORT; - UCHAR KissString[128]; - int KissLen = 0; - unsigned char * Kissptr = KissString; - char * ptr; - char * Context; - - ptr = strtok_s(PortRec->KissParams, " ", &Context); - - while (ptr && ptr[0] && KissLen < 120) - { - *(Kissptr++) = atoi (ptr); - KissLen++; - ptr = strtok_s(NULL, " ", &Context); - } - - KISS->KISSCMD = malloc(256); - - KISS->KISSCMDLEN = KissEncode(KissString, KISS->KISSCMD, KissLen); - KISS->KISSCMD = realloc(KISS->KISSCMD, KISS->KISSCMDLEN); - } - - PORT->SendtoM0LTEMap = PortRec->SendtoM0LTEMap; - PORT->PortFreq = PortRec->PortFreq; - - PORT->M0LTEMapInfo = PortRec->M0LTEMapInfo; - - PORT->QtSMPort = PortRec->QtSMPort; - - if (PortRec->BBSFLAG) // Appl 1 not permitted - BBSFLAG=NOBBS - PORT->PERMITTEDAPPLS &= 0xfffffffe; // Clear bottom bit - - - // SEE IF PERMITTED LINK CALLSIGNS SPECIFIED - - ptr2 = &PortRec->VALIDCALLS[0]; - - if (*(ptr2)) - { - ptr3 = (char *)PORT->PORTPOINTER; // Permitted Calls follows Port Info - PORT->PERMITTEDCALLS = ptr3; - - while (*(ptr2) > 32) - { - ConvToAX25(ptr2, ptr3); - ptr3 += 7; - PORT->PORTPOINTER = (struct PORTCONTROL *)ptr3; - if (strchr(ptr2, ',')) - { - ptr2 = strchr(ptr2, ','); - ptr2++; - } - else - break; - } - - ptr3 ++; // Terminating NULL - - // Round to word boundary (for ARM5 etc) - - int3 = (uintptr_t)ptr3; - int3 += 7; - int3 &= 0xfffffffffffffff8; - ptr3 = (UCHAR *)int3; - - PORT->PORTPOINTER = (struct PORTCONTROL *)ptr3; - } - - // SEE IF PORT UNPROTO ADDR SPECIFIED - - ptr2 = &PortRec->UNPROTO[0]; - - if (*(ptr2)) - { - ptr3 = (char *)PORT->PORTPOINTER; // Unproto follows port info - PORT->PORTUNPROTO = ptr3; - - while (*(ptr2) > 32) - { - ConvToAX25(ptr2, ptr3); - ptr3 += 7; - PORT->PORTPOINTER = (struct PORTCONTROL *)ptr3; - if (strchr(ptr2, ',')) - { - ptr2 = strchr(ptr2, ','); - ptr2++; - } - else - break; - } - - ptr3 ++; // Terminating NULL - - // Round to word boundsaty (for ARM5 etc) - - int3 = (uintptr_t)ptr3; - int3 += 7; - int3 &= 0xfffffffffffffff8; - ptr3 = (UCHAR *)int3; - - PORT->PORTPOINTER = (struct PORTCONTROL *)ptr3; - } - - // ADD MH AREA IF NEEDED - - if (PortRec->MHEARD != 'N') - { - NEEDMH = 1; // Include MH in Command List - - ptr3 = (char *)PORT->PORTPOINTER; // Permitted Calls follows Port Info - PORT->PORTMHEARD = (PMHSTRUC)ptr3; - - ptr3 += (MHENTRIES + 1)* sizeof(MHSTRUC); - - // Round to word boundsaty (for ARM5 etc) - - int3 = (uintptr_t)ptr3; - int3 += 7; - int3 &= 0xfffffffffffffff8; - ptr3 = (UCHAR *)int3; - - PORT->PORTPOINTER = (struct PORTCONTROL *)ptr3; - } - - PortRec++; - NUMBEROFPORTS ++; - FULLPORT = (struct FULLPORTDATA *)PORT->PORTPOINTER; - } - - PORT->PORTPOINTER = NULL; // End of list - - NEXTFREEDATA = (UCHAR *)FULLPORT; - - // SET UP APPLICATION CALLS AND ALIASES - - APPL = &APPLCALLTABLE[0]; - - ptr1 = (struct APPLCONFIG *)&xxcfg.C_APPL[0]; - - i = NumberofAppls; - - if (ptr1->ApplCall[0] == ' ') - { - // APPL1CALL IS NOT SPECIFED - LEAVE VALUES SET FROM BBSCALL - - APPL++; - ptr1++; - i--; - } - - while (i) - { - memcpy(APPL->APPLCALL_TEXT, ptr1->ApplCall, 10); - ConvToAX25(APPL->APPLCALL_TEXT, APPL->APPLCALL); - memcpy(APPL->APPLALIAS_TEXT, ptr1->ApplAlias, 10); - ConvToAX25(APPL->APPLALIAS_TEXT, APPL->APPLALIAS); - ConvToAX25(ptr1->L2Alias, APPL->L2ALIAS); - memcpy(APPL->APPLCMD, ptr1->Command, 12); - - APPL->APPLQUAL = ptr1->ApplQual; - - if (ptr1->CommandAlias[0] != ' ') - { - APPL->APPLHASALIAS = 1; - memcpy(APPL->APPLALIASVAL, &ptr1->CommandAlias[0], 48); - } - - APPL++; - ptr1++; - i--; - } - - // SET UP VARIOUS CONTROL TABLES - - LINKS = (VOID *)NEXTFREEDATA; - NEXTFREEDATA += MAXLINKS * sizeof(struct _LINKTABLE); - - DESTS = (VOID *)NEXTFREEDATA; - NEXTFREEDATA += MAXDESTS * sizeof(struct DEST_LIST); - ENDDESTLIST = (VOID *)NEXTFREEDATA; - - NEIGHBOURS = (VOID *)NEXTFREEDATA; - NEXTFREEDATA += MAXNEIGHBOURS * sizeof(struct ROUTE); - - L4TABLE = (VOID *)NEXTFREEDATA; - - NEXTFREEDATA += MAXCIRCUITS * sizeof(TRANSPORTENTRY); - - // SET UP DEFAULT ROUTES LIST - - Rcfg = &cfg->C_ROUTE[0]; - - ROUTE = NEIGHBOURS; - - while (Rcfg->call[0]) - { - int FRACK; - char * VIA; - char axcall[8]; - - ConvToAX25(Rcfg->call, ROUTE->NEIGHBOUR_CALL); - - // if VIA convert digis - - VIA = strstr(Rcfg->call, "VIA"); - - if (VIA) - { - VIA += 4; - - if (ConvToAX25(VIA, axcall)) - { - memcpy(ROUTE->NEIGHBOUR_DIGI1, axcall, 7); - - VIA = strchr(VIA, ' '); - - if (VIA) - { - VIA++; - - if (ConvToAX25(VIA, axcall)) - memcpy(ROUTE->NEIGHBOUR_DIGI2, axcall, 7); - - } - } - } - - ROUTE->NEIGHBOUR_QUAL = Rcfg->quality; - ROUTE->NEIGHBOUR_PORT = Rcfg->port; - - PORT = GetPortTableEntryFromPortNum(ROUTE->NEIGHBOUR_PORT); - - if (Rcfg->pwind & 0x40) - ROUTE->NoKeepAlive = 1; - else - if (PORT != NULL) - ROUTE->NoKeepAlive = PORT->PortNoKeepAlive; - - if (Rcfg->pwind & 0x80 || (PORT && PORT->INP3ONLY)) - { - ROUTE->INP3Node = 1; - ROUTE->NoKeepAlive = 0; // Cant have INP3 and NOKEEPALIVES - } - - ROUTE->NBOUR_MAXFRAME = Rcfg->pwind & 0x3f; - - FRACK = Rcfg->pfrack; - ROUTE->NBOUR_FRACK = FRACK / 333; - ROUTE->NBOUR_PACLEN = Rcfg->ppacl; - ROUTE->OtherendsRouteQual = ROUTE->OtherendLocked = Rcfg->farQual; - - ROUTE->NEIGHBOUR_FLAG = 1; // Locked - - Rcfg++; - ROUTE++; - } - - // SET UP INFO MESSAGE - - ptr2 = &cfg->C_INFOMSG[0]; - ptr3 = NEXTFREEDATA; - - INFOMSG = ptr3; - - while ((*ptr2)) - { - *(ptr3++) = *(ptr2++); - } - *ptr3++ = 0; // Null Terminate - - NEXTFREEDATA = ptr3; - - // SET UP CTEXT MESSAGE - - ptr2 = &cfg->C_CTEXT[0]; - ptr3 = NEXTFREEDATA; - - CTEXTMSG = ptr3; - - while ((*ptr2)) - { - *(ptr3++) = *(ptr2++); - } - - CTEXTLEN = (int)(ptr3 - (unsigned char *)CTEXTMSG); - - NEXTFREEDATA = ptr3; - - // SET UP ID MESSAGE - - IDHDDR.DEST[0] = 'I'+'I'; - IDHDDR.DEST[1] = 'D'+'D'; - IDHDDR.DEST[2] = 0x40; - IDHDDR.DEST[3] = 0x40; - IDHDDR.DEST[4] = 0x40; - IDHDDR.DEST[5] = 0x40; - IDHDDR.DEST[6] = 0xe0; // ; ID IN AX25 FORM - - IDHDDR.CTL = 3; - IDHDDR.PID = 0xf0; - - ptr2 = &cfg->C_IDMSG[0]; - ptr3 = &IDHDDR.L2DATA[0]; - - while ((*ptr2)) - { - *(ptr3++) = *(ptr2++); - } - - IDHDDR.LENGTH = (int)(ptr3 - (unsigned char *)&IDHDDR); - - int3 = (uintptr_t)NEXTFREEDATA; - int3 += 7; - int3 &= 0xfffffffffffffff8; - NEXTFREEDATA = (UCHAR *)int3; - ENDBUFFERPOOL = NEXTFREEDATA + DATABYTES; // So init will work, set to actual end later - - BUFFERPOOL = NEXTFREEDATA; - - Consoleprintf("PORTS %p LINKS %p DESTS %p ROUTES %p L4 %p BUFFERS %p\n", - PORTTABLE, LINKS, DESTS, NEIGHBOURS, L4TABLE, BUFFERPOOL); - - Debugprintf("PORTS %p LINKS %p DESTS %p ROUTES %p L4 %p BUFFERS %p END POOL %p", - PORTTABLE, LINKS, DESTS, NEIGHBOURS, L4TABLE, BUFFERPOOL, DATAAREA + DATABYTES); - - i = NUMBEROFBUFFERS; - - NUMBEROFBUFFERS = 0; - - while (i-- && NEXTFREEDATA < (DATAAREA + DATABYTES - (512 + 8192))) // Keep 8K free for anything that needs shared memory - { - Bufferlist[NUMBEROFBUFFERS] = (void **)NEXTFREEDATA; - - ReleaseBuffer((UINT *)NEXTFREEDATA); - NEXTFREEDATA += BUFFALLOC; // was BUFFLEN - - NUMBEROFBUFFERS++; - MAXBUFFS++; - } - - ENDBUFFERPOOL = NEXTFREEDATA; - - - // Copy Bridge Map - - memcpy(BridgeMap, &cfg->CfgBridgeMap, sizeof(BridgeMap)); - -// MOV EAX,_NEXTFREEDATA -// CALL HEXOUT - - // SET UP OUR CALLIGN(S) - - ConvToAX25(MYNETROMCALL, NETROMCALL); - - ConvToAX25(MYNODECALL, MYCALL); - memcpy(&IDHDDR.ORIGIN[0], MYCALL, 7); - IDHDDR.ORIGIN[6] |= 0x61; // SET CMD END AND RESERVED BITS - - ConvToAX25(MYALIASTEXT, MYALIAS); - - // SET UP INITIAL DEST ENTRY FOR APPLICATIONS (IF BOTH NODE AND BBS NEEDED) - // Actually wrong - we need to set up application node entries even if node = 0 - DEST = DESTS; - - // If NODECALL isn't same as NETROMCALL, Add Dest Entry for NODECALL - - if (memcmp(NETROMCALL, MYCALL, 7) != 0) - { - memcpy(DEST->DEST_CALL, MYCALL, 7); - memcpy(DEST->DEST_ALIAS, MYALIASTEXT, 6); - - DEST->DEST_STATE = 0x80; // SPECIAL ENTRY - DEST->NRROUTE[0].ROUT_QUALITY = 255; - DEST->NRROUTE[0].ROUT_OBSCOUNT = 255; - DEST++; - NUMBEROFNODES++; - } - - if (BBS) - { - // Add Application Entries - - APPL = &APPLCALLTABLE[0]; - i = NumberofAppls; - - while (i--) - { - if (APPL->APPLQUAL) - { - memcpy(DEST->DEST_CALL, APPL->APPLCALL, 13); - DEST->DEST_STATE = 0x80; // SPECIAL ENTRY - DEST->NRROUTE[0].ROUT_QUALITY = (UCHAR)APPL->APPLQUAL; - DEST->NRROUTE[0].ROUT_OBSCOUNT = 255; - APPL->NODEPOINTER = DEST; - - DEST++; - - NUMBEROFNODES++; - } - APPL++; - } - } - - // Read Node and MH Recovery Files - - ReadNodes(); - - if (AUTOSAVEMH) - ReadMH(); // Only if AutoSave configured - - // set up stream number in BPQHOSTVECTOR - - for (i = 0; i < 64; i++) - { - BPQHOSTVECTOR[i].HOSTSTREAM = i + 1; - } - - memcpy(MYCALLWITHALIAS, MYCALL, 7); - memcpy(&MYCALLWITHALIAS[7], MYALIASTEXT, 6); - - // Set random start value for NETROM Session ID - - NEXTID = (rand() % 254) + 1; - - GetPortCTEXT(0, 0, 0, 0); - - upnpInit(); - - lastSaveSecs = CurrentSecs = lastSlowSecs = time(NULL); - - return 0; -} - -BOOL CompareCalls(UCHAR * c1, UCHAR * c2) -{ - // COMPARE AX25 CALLSIGNS IGNORING EXTRA BITS IN SSID - - if (memcmp(c1, c2, 6)) - return FALSE; // No Match - - if ((c1[6] & 0x1e) == (c2[6] & 0x1e)) - return TRUE; - - return FALSE; -} -BOOL CompareAliases(UCHAR * c1, UCHAR * c2) -{ - // COMPARE first 6 chars of AX25 CALLSIGNS - - if (memcmp(c1, c2, 6)) - return FALSE; // No Match - - return TRUE; -} -BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE) -{ - struct ROUTE * ROUTE = NEIGHBOURS; - struct ROUTE * FIRSTSPARE = NULL; - int n = MAXNEIGHBOURS; - - while (n--) - { - if (ROUTE->NEIGHBOUR_CALL[0] == 0) // Spare - if (FIRSTSPARE == NULL) - FIRSTSPARE = ROUTE; - - if (ROUTE->NEIGHBOUR_PORT != Port) - { - ROUTE++; - continue; - } - if (CompareCalls(ROUTE->NEIGHBOUR_CALL, Call)) - { - *REQROUTE = ROUTE; - return TRUE; - } - ROUTE++; - } - - // ENTRY NOT FOUND - FIRSTSPARE HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL - - *REQROUTE = FIRSTSPARE; - return FALSE; -} - -BOOL FindDestination(UCHAR * Call, struct DEST_LIST ** REQDEST) -{ - struct DEST_LIST * DEST = DESTS; - struct DEST_LIST * FIRSTSPARE = NULL; - int n = MAXDESTS; - - while (n--) - { - if (DEST->DEST_CALL[0] == 0) // Spare - { - if (FIRSTSPARE == NULL) - FIRSTSPARE = DEST; - - DEST++; - continue; - } - if (CompareCalls(DEST->DEST_CALL, Call)) - { - *REQDEST = DEST; - return TRUE; - } - DEST++; - } - - // ENTRY NOT FOUND - FIRSTSPARE HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL - - *REQDEST = FIRSTSPARE; - return FALSE; -} - -extern UCHAR BPQDirectory[]; - -#define LINE_MAX 256 - - -// Reload saved MH file - -VOID ReadMH() -{ - char FN[260]; - FILE *fp; - char line[LINE_MAX]; - UCHAR axcall[7]; - char * ptr, *digi, *locptr, *locend; - char * Context, * Context2; - char seps[] = " \n"; - int Port; - struct PORTCONTROL * PORT = NULL; - MHSTRUC * MH; - int count = MHENTRIES; - char * Digiptr; - BOOL Digiused; - char * HasStar; - - // Set up pointer to BPQNODES file - - if (BPQDirectory[0] == 0) - { - strcpy(FN,"MHSave.txt"); - } - else - { - strcpy(FN,BPQDirectory); - strcat(FN,"/"); - strcat(FN,"MHSave.txt"); - } - - if ((fp = fopen(FN, "r")) == NULL) - { - return; - } - - while (fgets(line, LINE_MAX, fp) != NULL) - { - if (memcmp(line, "Port:", 5) == 0) - { - Port = atoi(&line[5]); - PORT = GetPortTableEntryFromPortNum(Port); - if (PORT) - MH = PORT->PORTMHEARD; - else - MH = NULL; - - continue; - } - - // 1548777630 N9LYA-8 Jan 29 16:00:30 - - if (MH) - { - ptr = strtok_s(line, seps, &Context); - - if (ptr == NULL) - continue; - - MH->MHTIME = atoi(ptr); - - ptr = strtok_s(NULL, seps, &Context); - - if (ptr == NULL) - continue; - - MH->MHCOUNT = atoi(ptr); - - // Get LOC and Freq First before strtok messes with line - - locptr = strchr(Context, '|'); - - if (locptr == NULL) - continue; - - locend = strchr(++locptr, '|'); - - if (locend == NULL) - continue; - - if ((locend - locptr) == 6) - - memcpy(MH->MHLocator, locptr, 6); - - locend++; - - strlop(locend, '\n'); - - if (strlen(locend) < 12) - - strcpy(MH->MHFreq, locend); - - ptr = strtok_s(NULL, "|\n", &Context); - - if (ptr == NULL) - continue; - - if (ConvToAX25(ptr, axcall) == FALSE) - continue; // Duff - - memcpy(MH->MHCALL, axcall, 7); - - if (ptr[10] != ' ') - MH->MHDIGI = ptr[10]; - - // SEE IF ANY DIGIS - - digi = strstr(ptr, " via "); - - if (digi) - { - digi = digi + 5; - Digiptr = &MH->MHDIGIS[0][0]; - - if (strchr(ptr, '*')) - Digiused = 1; // At least one digi used - else - Digiused = 0; - - digi = strtok_s(digi, ",\n", &Context2); - - while(digi) - { - HasStar = strlop(digi, '*'); - - if (ConvToAX25(digi, axcall) == FALSE) - break; - - memcpy(Digiptr, axcall, 7); - - if (Digiused) - Digiptr[6] |= 0x80; // Set used - - if (HasStar) - Digiused = 0; // Only last used has * - - Digiptr += 7; - - digi = strtok_s(NULL, ",/n", &Context2); - } - - *(--Digiptr) |= 1; // Set end of address on last - - } - else - { - // No Digis - - MH->MHCALL[6] |= 1; // Set end of address - } - - MH++; - } - } - - fclose(fp); - return; -} - - -VOID ReadNodes() -{ - char FN[260]; - FILE *fp; - char line[LINE_MAX]; - UCHAR axcall[7]; - char * ptr; - char * Context; - char seps[] = " \r"; - int Port, Qual; - struct PORTCONTROL * PORT; - - // Set up pointer to BPQNODES file - - if (BPQDirectory[0] == 0) - { - strcpy(FN,"BPQNODES.dat"); - } - else - { - strcpy(FN,BPQDirectory); - strcat(FN,"/"); - strcat(FN,"BPQNODES.dat"); - } - - if ((fp = fopen(FN, "r")) == NULL) - { - WritetoConsoleLocal( - "Route/Node recovery file BPQNODES.dat not found - Continuing without it\n"); - return; - } - - // Read the saved ROUTES/NODES file - - while (fgets(line, LINE_MAX, fp) != NULL) - { - if (memcmp(line, "ROUTE ADD", 9) == 0) - { - struct ROUTE * ROUTE = NULL; - - // FORMAT IS ROUTE ADD CALLSIGN PORT QUAL (VIA .... - - ptr = strtok_s(&line[10], seps, &Context); - - if (ConvToAX25(ptr, axcall) == FALSE) - continue; // DUff - - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) continue; - Port = atoi(ptr); - - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == NULL) - continue; // Port has gone - - if (FindNeighbour(axcall, Port, &ROUTE)) - continue; // Already added from ROUTES: - - if (ROUTE == NULL) - continue; // Tsble Full - - memcpy(ROUTE->NEIGHBOUR_CALL, axcall, 7); - ROUTE->NEIGHBOUR_PORT = Port; - - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) continue; - Qual = atoi(ptr); - - ROUTE->NEIGHBOUR_QUAL = Qual; - - ptr = strtok_s(NULL, seps, &Context); // MAXFRAME - 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 - - if (ptr[0] == '!') - { -// ROUTE->NEIGHBOUR_FLAG = 1; // LOCKED ROUTE - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) continue; - } - - // SEE IF ANY DIGIS - - if (ptr[0] == 'V') - { - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) continue; - - if (ConvToAX25(ptr, axcall) == FALSE) - continue; // DUff - - memcpy(ROUTE->NEIGHBOUR_DIGI1, axcall, 7); - - ROUTE->NEIGHBOUR_FLAG = 1; // LOCKED ROUTE - Digi'ed routes must be locked - - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) continue; - - // See if another digi or MAXFRAME - - if (strlen(ptr) > 2) - { - if (ConvToAX25(ptr, axcall) == FALSE) - continue; // DUff - - memcpy(ROUTE->NEIGHBOUR_DIGI2, axcall, 7); - - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) continue; - } - } - - Qual = atoi(ptr); - ROUTE->NBOUR_MAXFRAME = Qual; - - ptr = strtok_s(NULL, seps, &Context); // FRACK - if (ptr == NULL) continue; - Qual = atoi(ptr); - ROUTE->NBOUR_FRACK = Qual; - - ptr = strtok_s(NULL, seps, &Context); // PACLEN - if (ptr == NULL) continue; - Qual = atoi(ptr); - ROUTE->NBOUR_PACLEN = Qual; - - ptr = strtok_s(NULL, seps, &Context); // INP3 - if (ptr == NULL) continue; - Qual = atoi(ptr); - - // We now take Nokeepalives from the PORT, unless specifically - // Requested - - ROUTE->NoKeepAlive = PORT->PortNoKeepAlive; - - if (Qual & 4) - ROUTE->NoKeepAlive = TRUE; - - if ((Qual & 1) || PORT->INP3ONLY) - { - ROUTE->NoKeepAlive = FALSE; - ROUTE->INP3Node = TRUE; - } - - ptr = strtok_s(NULL, seps, &Context); // INP3 - if (ptr == NULL) continue; - - if (ROUTE->NEIGHBOUR_FLAG == 0 || ROUTE->OtherendLocked == 0); // Not LOCKED ROUTE - ROUTE->OtherendsRouteQual = atoi(ptr); - - continue; - } - - if (memcmp(line, "NODE ADD", 8) == 0) - { - // FORMAT IS NODE ADD ALIAS:CALL ROUTE QUAL - - dest_list * DEST = NULL; - struct ROUTE * ROUTE = NULL; - char * ALIAS; - char FULLALIAS[6] = " "; - int SavedOBSINIT = OBSINIT; - - if (line[9] == ':') - { - // No alias - - Context = &line[10]; - } - else - { - ALIAS = strtok_s(&line[9], ":", &Context); - - if (ALIAS == NULL) - continue; - - memcpy(FULLALIAS, ALIAS, (int)strlen(ALIAS)); - } - - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) - continue; - - if (ConvToAX25(ptr, axcall) == FALSE) - continue; // Duff - - if (CompareCalls(axcall, MYCALL)) - continue; // Shoiuldn't happen, but to be safe! - - if (FindDestination(axcall, &DEST)) - continue; - - if (DEST == NULL) - continue; // Tsble Full - - memcpy(DEST->DEST_CALL, axcall, 7); - memcpy(DEST->DEST_ALIAS, FULLALIAS, 6); - - NUMBEROFNODES++; -RouteLoop: - // GET NEIGHBOURS FOR THIS DESTINATION - CALL PORT QUAL - - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) continue; - - if (ConvToAX25(ptr, axcall) == FALSE) - continue; // DUff - - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) continue; - Port = atoi(ptr); - - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) continue; - Qual = atoi(ptr); - - if (Context[0] == '!') - { - OBSINIT = 255; //; SPECIAL FOR LOCKED - } - - if (FindNeighbour(axcall, Port, &ROUTE)) - { - PROCROUTES(DEST, ROUTE, Qual); - } - - OBSINIT = SavedOBSINIT; - - goto RouteLoop; - } - } - - fclose(fp); - -// loadedmsg DB cr,lf,lf,'Switch loaded and initialised OK',lf,0 - - return; -} - -int DelayBuffers = 0; - -void sendModeReport(); -void sendFreqReport(); - -VOID TIMERINTERRUPT() -{ - // Main Processing loop - CALLED EVERY 100 MS - - int i; - struct PORTCONTROL * PORT = PORTTABLE; - PMESSAGE Buffer; - struct _LINKTABLE * LINK; - struct _MESSAGE * Message; - int toPort; - - CurrentSecs = time(NULL); - - BGTIMER++; - REALTIMETICKS++; - L2TIMERFLAG++; // INCREMENT FLAG FOR BG - L3TIMERFLAG++; // INCREMENT FLAG FOR BG - L4TIMERFLAG++; // INCREMENT FLAG FOR BG - -// CALL PORT TIMER ROUTINES - - for (i = 0; i < NUMBEROFPORTS; i++) - { - PORT->PORTTIMERCODE(PORT); - - // Check Smart ID timer - - if (PORT->SmartIDNeeded && PORT->SmartIDNeeded < time(NULL)) - SendSmartID(PORT); - - PORT = PORT->PORTPOINTER; - } - - // CHECK FOR TIMER ACTIVITY - - if (L2TIMERFLAG >= 3) - { - L2TIMERFLAG -= 3; - L2TimerProc(); // 300 mS - } - - if (CurrentSecs - lastSlowSecs >= 60) // 1 PER MIN - { - lastSlowSecs = CurrentSecs; - - L3TimerProc(); - - if (needAIS) - AISTimer(); - - if (needADSB) - ADSBTimer(); - - if (APRSActive) - Debugprintf("BPQ32 Heartbeat Buffers %d APRS Queues %d %d", QCOUNT, C_Q_COUNT(&APRSMONVECPTR->HOSTTRACEQ), C_Q_COUNT(&APPL_Q)); - else - Debugprintf("BPQ32 Heartbeat Buffers %d", QCOUNT); - - StatsTimer(); - - // Call EXT Port Slow Timer - - PORT = PORTTABLE; - - for (i = 0; i < NUMBEROFPORTS; i++) - { - if (PORT->PROTOCOL == 10) - { - PEXTPORTDATA PORTVEC = (PEXTPORTDATA)PORT; - EXTSLOWTIMER(PORTVEC); - } - - PORT = PORT->PORTPOINTER; - } - - // Call Mode Map support routine - - sendFreqReport(); - sendModeReport(); - - if (MQTT) - MQTTTimer(); - -/* - if (QCOUNT < 200) - { - if (DelayBuffers == 0) - { - FindLostBuffers(); - DelayBuffers = 10; - } - else - { - DelayBuffers--; - } - } -*/ - } - - // Check Autosave Nodes and MH timer - - if (CurrentSecs - lastSaveSecs >= 3600) // 1 per hour - { - lastSaveSecs = CurrentSecs; - - if (AUTOSAVE == 1) - SaveNodes(); - if (AUTOSAVEMH == 1) - SaveMH(); - } - - if (L4TIMERFLAG >= 10) // 1 PER SEC - { - L4TIMERFLAG -= 10; - - L3FastTimer(); - L4TimerProc(); - } - - // SEE IF ANY FRAMES TO TRACE - - Buffer = Q_REM(&TRACE_Q); - - while (Buffer) - { - // IF BUFFER HAS A LINK TABLE ENTRY ON END, RESET TIMEOUT - - LINK = Buffer->Linkptr; - - if (LINK) - { - if (LINK->L2TIMER) - LINK->L2TIMER = LINK->L2TIME; - - Buffer->Linkptr = 0; // CLEAR FLAG FROM BUFFER - } - - Message = (struct _MESSAGE *)Buffer; - Message->PORT |= 0x80; // Set TX Bit - - BPQTRACE(Message, FALSE); // Dont send TX'ed frames to APRS - ReleaseBuffer(Buffer); - - Buffer = Q_REM(&TRACE_Q); - } - - // CHECK FOR MESSAGES RECEIVED FROM COMMS LINKS - - PORT = PORTTABLE; - - for (i = 0; i < NUMBEROFPORTS; i++) - { - int Sent = 0; - - CURRENTPORT = PORT->PORTNUMBER; // PORT NUMBER - CURRENTPORTPTR = PORT; - - Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTRX_Q); - - while (Buffer) - { - Message = (struct _MESSAGE *) Buffer; - if (CURRENTPORT == 30) - Sent = Sent; - - if (PORT->PROTOCOL == 10) - { - int Sessno = Message->PORT; - PEXTPORTDATA PORTVEC = (PEXTPORTDATA)PORT; - TRANSPORTENTRY * Session; - TRANSPORTENTRY * Partner; - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - { - - // KISSHF - May be L2 packet or Test Response - - if (Message->DEST[0] != 240) // Should only be ax.25 address field - goto L2Packet; - } - - // PACTOR Style Message - - InOctets[PORT->PORTNUMBER] += Message->LENGTH - (MSGHDDRLEN + 1); - PORT->L2FRAMESFORUS++; - - Session = PORTVEC->ATTACHEDSESSIONS[Sessno]; - - if (Session == NULL) - { - // TNC not attached - discard - - ReleaseBuffer(Buffer); - Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTRX_Q); - continue; - } - - Session->L4KILLTIMER = 0; // Reset Idle Timeout - - Partner = Session->L4CROSSLINK; - - if (Partner == NULL) - { - // No Crosslink - pass to command handler - - CommandHandler(Session, (PDATAMESSAGE)Buffer); - break; - } - - if (Partner->L4STATE < 5) - { - // MESSAGE RECEIVED BEFORE SESSION IS UP - CANCEL SESSION - // AND PASS MESSAGE TO COMMAND HANDLER - - if (Partner->L4CIRCUITTYPE & L2LINK) // L2 SESSION? - { - // MUST CANCEL L2 SESSION - - LINK = Partner->L4TARGET.LINK; - LINK->CIRCUITPOINTER = NULL; // CLEAR REVERSE LINK - - LINK->L2STATE = 4; // DISCONNECTING - LINK->L2TIMER = 1; // USE TIMER TO KICK OFF DISC - - LINK->L2RETRIES = LINK->LINKPORT->PORTN2 - 2; //ONLY SEND DISC ONCE - } - - CLEARSESSIONENTRY(Partner); - Session->L4CROSSLINK = 0; // CLEAR CROSS LINK - CommandHandler(Session, (struct DATAMESSAGE *)Buffer); - break; - } - - C_Q_ADD(&Partner->L4TX_Q, Buffer); - PostDataAvailable(Partner); - Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTRX_Q); - continue; - } - - -L2Packet: - // TIME STAMP IT - - time(&Message->Timestamp); - - Message->PORT = CURRENTPORT; - - if (MQTT && PORT->PROTOCOL == 0) - MQTTKISSRX(Buffer); - - // Bridge if requested - - for (toPort = 1; toPort <= MaxBPQPortNo; toPort++) - { - if (BridgeMap[CURRENTPORT][toPort]) - { - MESSAGE * BBuffer = GetBuff(); - struct PORTCONTROL * BPORT; - - if (BBuffer) - { - memcpy(BBuffer, Message, Message->LENGTH); - BBuffer->PORT = toPort; - BPORT = GetPortTableEntryFromPortNum(toPort); - - if (BPORT) - { - if (BPORT->SmartIDInterval && BPORT->SmartIDNeeded == 0) - { - // Using Smart ID, but none scheduled - - BPORT->SmartIDNeeded = time(NULL) + BPORT->SmartIDInterval; - } - PUT_ON_PORT_Q(BPORT, BBuffer); - } - else - ReleaseBuffer(BBuffer); - } - } - } - - L2Routine(PORT, Buffer); - - Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTRX_Q); - continue; - } - - // End of RX_Q - - Sent = 0; - - while (PORT->PORTTX_Q && Sent < 5) - { - int ret; - void * PACTORSAVEQ; - - Buffer = PORT->PORTTX_Q; - Message = (struct _MESSAGE *) Buffer; - - ret = PORT->PORTTXCHECKCODE(PORT, Message->PORT); - - // Busy but not connected means TNC has gone - clear queue - - if (ret == 1) - { - MESSAGE * Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTTX_Q); - - if (Buffer == 0) - break; // WOT!! - -// Debugprintf("Busy but not connected - discard message %s", Buffer->L2DATA); - - ReleaseBuffer(Buffer); - break; - } - - ret = ret & 0xff; // Only check bottom byte - - if (ret == 0) // Not busy - { - MESSAGE * Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTTX_Q); - - if (Buffer == 0) - break; // WOT!! - - if (PORT->PORTDISABLED) - { - ReleaseBuffer(Buffer); - break; - } - - PORT->L2FRAMESSENT++; - OutOctets[PORT->PORTNUMBER] += Buffer->LENGTH - MSGHDDRLEN; - - PORT->PORTTXROUTINE((struct _EXTPORTDATA *)PORT, Buffer); - Sent++; - - continue; - } - - // If a Pactor Port, some channels could be busy whilst others are not. - - if (PORT->PROTOCOL != 10) - break; // BUSY - - // Try passing any other messages on the queue to the node. - - PACTORSAVEQ = 0; - -PACTORLOOP: - - Buffer = PORT->PORTTX_Q; - - if (Buffer == NULL) - goto ENDOFLIST; - - Message = (struct _MESSAGE *) Buffer; - ret = PORT->PORTTXCHECKCODE(PORT, Message->PORT); - ret = ret & 0xff; // Only check bottom byte - - if (ret) // Busy - { - // Save it - - Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTTX_Q); - C_Q_ADD(&PACTORSAVEQ, Buffer); - goto PACTORLOOP; - } - - Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTTX_Q); - - if (PORT->PORTDISABLED) - { - ReleaseBuffer(Buffer); - goto PACTORLOOP; - } - - PORT->L2FRAMESSENT++; - OutOctets[PORT->PORTNUMBER] += Message->LENGTH; - - PORT->PORTTXROUTINE((struct _EXTPORTDATA *)PORT, Buffer); - Sent++; - - if (Sent < 5) - goto PACTORLOOP; // SEE IF MORE - -ENDOFLIST: - // Move the saved frames back onto Port Q - - PORT->PORTTX_Q = PACTORSAVEQ; - break; - } - - PORT->PORTRXROUTINE((struct _EXTPORTDATA *)PORT); // SEE IF MESSAGE RECEIVED - PORT = PORT->PORTPOINTER; - } - -/* -; -; CHECK FOR INCOMING MESSAGES ON LINK CONTROL TABLE - -; BY NOW ONLY 'I' FRAMES WILL BE PRESENT - -; LEVEL 2 PROTOCOL HANDLING IS DONE IN MESSAGE RECEIVE CODE -; AND LINK HANDLING INTERRUPT ROUTINES -; -*/ - - LINK = LINKS; - i = MAXLINKS; - - while (i--) - { - if (LINK->LINKCALL[0]) - { - Buffer = Q_REM(&LINK->RX_Q); - - while (Buffer) - { - ProcessIframe(LINK, (PDATAMESSAGE)Buffer); - - Buffer =(PMESSAGE)Q_REM((void *)&LINK->RX_Q); - } - - // CHECK FOR OUTGOING MSGS - - if (LINK->L2STATE >= 5) // CANT SEND TEXT TILL CONNECTED - { - // CMP VER1FLAG[EBX],1 - // JE SHORT MAINL35 ; NEED TO RETRY WITH I FRAMES IF VER 1 - - // CMP L2RETRIES[EBX],0 - // JNE SHORT MAINL40 ; CANT SEND TEXT IF RETRYING - - if ((LINK->L2FLAGS & RNRSET) == 0) - SDETX(LINK); - } - } - LINK++; - } - - L4BG(); // DO LEVEL 4 PROCESSING - L3BG(); - TNCTimerProc(); -} - -VOID DoListenMonitor(TRANSPORTENTRY * L4, MESSAGE * Msg) -{ - uint64_t SaveMMASK = MMASK; - BOOL SaveMTX = MTX; - BOOL SaveMCOM = MCOM; - BOOL SaveMUI = MUIONLY; - PDATAMESSAGE Buffer; - char MonBuffer[1024]; - int len; - struct tm * TM; - UCHAR * monchars = (UCHAR *)Msg; - - if (CountFramesQueuedOnSession(L4) > 10) - return; - - if (monchars[21] == 3 && monchars[22] == 0xcf && monchars[23] == 0xff) // Netrom Nodes - return; - - IntSetTraceOptionsEx(L4->LISTEN, 1, 0, 0); - - TM = gmtime(&Msg->Timestamp); - sprintf(MonBuffer, "%02d:%02d:%02d ", TM->tm_hour, TM->tm_min, TM->tm_sec); - - len = IntDecodeFrame(Msg, &MonBuffer[9], Msg->Timestamp, L4->LISTEN, FALSE, TRUE); - - IntSetTraceOptionsEx(SaveMMASK, SaveMTX, SaveMCOM, SaveMUI); - - if (len == 0) - return; - - len += 9; - - if (len > 256) - len = 256; - - Buffer = GetBuff(); - - if (Buffer) - { - char * ptr = &Buffer->L2DATA[0]; - Buffer->PID = 0xf0; - - memcpy(ptr, MonBuffer, len); - - Buffer->LENGTH = (USHORT)len + 4 + sizeof(void *); - - C_Q_ADD(&L4->L4TX_Q, Buffer); - - PostDataAvailable(L4); - } -} - -DllExport int APIENTRY DllBPQTRACE(MESSAGE * Msg, BOOL TOAPRS) -{ - int ret; - GetSemaphore(&Semaphore, 88); - ret = BPQTRACE(Msg, TOAPRS); - FreeSemaphore(&Semaphore); - return ret; -} - -int BPQTRACE(MESSAGE * Msg, BOOL TOAPRS) -{ - // ATTACH A COPY OF FRAME TO ANY BPQ HOST PORTS WITH MONITORING ENABLED - - TRANSPORTENTRY * L4 = L4TABLE; - - MESSAGE * Buffer; - int i = BPQHOSTSTREAMS + 2; // Include Telnet and AGW Stream - - if (TOAPRS) - i++; // Include APRS Stream - - while(i) - { - i--; - - if (QCOUNT < 100) - return FALSE; - - if (BPQHOSTVECTOR[i].HOSTAPPLFLAGS & 0x80) // Trace Enabled? - { - Buffer = GetBuff(); - if (Buffer) - { - memcpy(&Buffer->PORT, &Msg->PORT, BUFFLEN - sizeof(void *)); // Dont copy chain word - C_Q_ADD(&BPQHOSTVECTOR[i].HOSTTRACEQ, Buffer); - -#ifndef LINBPQ - if (BPQHOSTVECTOR[i].HOSTHANDLE) - PostMessage(BPQHOSTVECTOR[i].HOSTHANDLE, BPQMsg, BPQHOSTVECTOR[i].HOSTSTREAM, 1); -#endif - } - } - - } - - // Also pass to any users LISTENING on this port - - i = MAXCIRCUITS; - - if (QCOUNT < 300) - return FALSE; // Until I add by session flow control - - while (i--) - { - if (L4->LISTEN) - if ((((uint64_t)1 << ((Msg->PORT & 0x7f) - 1)) & L4->LISTEN)) - // if ((Msg->PORT & 0x7f) == L4->LISTEN) - DoListenMonitor(L4, Msg); - - L4++; - } - - return TRUE; -} -; - -VOID INITIALISEPORTS() -{ - char INITMSG[80]; - struct PORTCONTROL * PORT = PORTTABLE; - - while (PORT) - { - sprintf(INITMSG, "Initialising Port %02d ", PORT->PORTNUMBER); - WritetoConsoleLocal(INITMSG); - - PORT->PORTINITCODE(PORT); - PORT = PORT->PORTPOINTER; - } -} - -VOID FindLostBuffers() -{ - void ** Buff; - int n, i; - unsigned int rev; - - UINT CodeDump[16]; - char codeText[65] = ""; - unsigned char * codeByte = (unsigned char *) CodeDump; - - PBPQVECSTRUC HOSTSESS = BPQHOSTVECTOR; - struct _TRANSPORTENTRY * L4; // Pointer to Session - - struct DEST_LIST * DEST = DESTS; - - struct ROUTE * Routes = NEIGHBOURS; - int MaxRoutes = MAXNEIGHBOURS; - int Queued; - char Call[10]; - - n = MAXDESTS; - - Debugprintf("Looking for missing Buffers"); - - while (n--) - { - if (DEST->DEST_CALL[0] && DEST->DEST_Q) // Spare - { - Debugprintf("DEST Queue %s %d", DEST->DEST_ALIAS, C_Q_COUNT(&DEST->DEST_Q)); - } - - DEST++; - } - - n = 0; - - while (n < BPQHOSTSTREAMS + 4) - { - // Check Trace Q - - if (HOSTSESS->HOSTTRACEQ) - { - int Count = C_Q_COUNT(&HOSTSESS->HOSTTRACEQ); - - Debugprintf("Trace Buffers Stream %d Count %d", n, Count); - - L4 = HOSTSESS->HOSTSESSION; - - if (L4 && (L4->L4TX_Q || L4->L4RX_Q || L4->L4HOLD_Q || L4->L4RESEQ_Q)) - Debugprintf("Stream %d %d %d %d %d", n, C_Q_COUNT(&L4->L4TX_Q), - C_Q_COUNT(&L4->L4RX_Q), C_Q_COUNT(&L4->L4HOLD_Q), C_Q_COUNT(&L4->L4RESEQ_Q)); - - } - n++; - HOSTSESS++; - } - - n = MAXCIRCUITS; - L4 = L4TABLE; - - while (n--) - { - if (L4->L4USER[0] == 0) - { - L4++; - continue; - } - if (L4->L4TX_Q || L4->L4RX_Q || L4->L4HOLD_Q || L4->L4RESEQ_Q) - Debugprintf("L4 %d TX %d RX %d HOLD %d RESEQ %d", MAXCIRCUITS - n, C_Q_COUNT(&L4->L4TX_Q), - C_Q_COUNT(&L4->L4RX_Q), C_Q_COUNT(&L4->L4HOLD_Q), C_Q_COUNT(&L4->L4RESEQ_Q)); - L4++; - } - - // Routes - - while (MaxRoutes--) - { - if (Routes->NEIGHBOUR_CALL[0] != 0) - { - Call[ConvFromAX25(Routes->NEIGHBOUR_CALL, Call)] = 0; - if (Routes->NEIGHBOUR_LINK) - { - Queued = COUNT_AT_L2(Routes->NEIGHBOUR_LINK); // SEE HOW MANY QUEUED - if (Queued) - Debugprintf("Route %s %d", Call, Queued); - } - } - Routes++; - } - - // Build list of buffers, then mark off all on free Q - - Buff = BUFFERPOOL; - n = 0; - - for (i = 0; i < NUMBEROFBUFFERS; i++) - { - Bufferlist[n++] = Buff; - Buff += (BUFFALLOC / sizeof(void *)); - } - - Buff = FREE_Q; - - while (Buff) - { - n = NUMBEROFBUFFERS; - - while (n--) - { - if (Bufferlist[n] == Buff) - { - Bufferlist[n] = 0; - break; - } - } - Buff = *Buff; - } - n = NUMBEROFBUFFERS; - - while (n--) - { - if (Bufferlist[n]) - { - char * fileptr = (char *)Bufferlist[n]; - MESSAGE * Msg = (MESSAGE *)Bufferlist[n]; - - memcpy(CodeDump, Bufferlist[n], 64); - - for (i = 0; i < 64; i++) - { - if (codeByte[i] > 0x1f && codeByte[i] < 0x80) - codeText[i] = codeByte[i]; - else - codeText[i] = '.'; - } - - for (i = 0; i < 16; i++) - { - rev = (CodeDump[i] & 0xff) << 24; - rev |= (CodeDump[i] & 0xff00) << 8; - rev |= (CodeDump[i] & 0xff0000) >> 8; - rev |= (CodeDump[i] & 0xff000000) >> 24; - - CodeDump[i] = rev; - } - - Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ", - Bufferlist[n], CodeDump[0], CodeDump[1], CodeDump[2], CodeDump[3], CodeDump[4], CodeDump[5], CodeDump[6], CodeDump[7]); - - Debugprintf(" %08x %08x %08x %08x %08x %08x %08x %08x %d", - CodeDump[8], CodeDump[9], CodeDump[10], CodeDump[11], CodeDump[12], CodeDump[13], CodeDump[14], CodeDump[15], Msg->Process); - - Debugprintf(" %s %s", &fileptr[400], codeText); - } - } - - // rebuild list for buffer check - Buff = BUFFERPOOL; - n = 0; - - for (i = 0; i < NUMBEROFBUFFERS; i++) - { - Bufferlist[n++] = Buff; - Buff += (BUFFALLOC / sizeof(void *)); - } -} - -void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode) -{ - UCHAR FN[MAX_PATH]; - FILE * LogHandle; - time_t T; - struct tm * tm; - char LogMsg[256]; - int MsgLen; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(FN,"%s/logs/ConnectLog_%02d%02d%02d.log", LogDirectory, tm->tm_year - 100, tm->tm_mon + 1, tm->tm_mday); - - LogHandle = fopen(FN, "ab"); - - if (LogHandle == NULL) - return; - - MsgLen = sprintf(LogMsg, "%02d:%02d:%02d Call from %s to %s Mode %s\r\n", tm->tm_hour, tm->tm_min, tm->tm_sec, fromCall, toCall, Mode); - - fwrite(LogMsg , 1, MsgLen, LogHandle); - fclose(LogHandle); -} - - - diff --git a/cMain.c b/cMain.c index ea68401..f370490 100644 --- a/cMain.c +++ b/cMain.c @@ -15,7 +15,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ +*/ + // // C replacement for Main.asm @@ -139,6 +140,10 @@ 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; @@ -822,6 +827,15 @@ BOOL Start() MQTT_PORT = cfg->C_MQTT_PORT; 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 @@ -1338,7 +1352,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++; @@ -1843,12 +1857,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; } @@ -1865,7 +1878,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; @@ -1921,6 +1934,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/cheaders.h b/cheaders.h index c4f6c85..4b765a2 100644 --- a/cheaders.h +++ b/cheaders.h @@ -1,451 +1,450 @@ -// -// Prototypes for BPQ32 Node Functions -// - - -#define DllImport - -#define EXCLUDEBITS - -#define _WINSOCK_DEPRECATED_NO_WARNINGS - -#include "compatbits.h" - -#include "asmstrucs.h" - -BOOL CheckExcludeList(UCHAR * Call); - -Dll int ConvFromAX25(unsigned char * incall,unsigned char * outcall); -Dll BOOL ConvToAX25(unsigned char * callsign, unsigned char * ax25call); -DllExport BOOL ConvToAX25Ex(unsigned char * callsign, unsigned char * ax25call); -int WritetoConsoleLocal(char * buff); -VOID Consoleprintf(const char * format, ...); -VOID FreeConfig(); -int GetListeningPortsPID(int Port); - -void * InitializeExtDriver(PEXTPORTDATA PORTVEC); - -VOID PutLengthinBuffer(PDATAMESSAGE buff, USHORT datalen); // Needed for arm5 portability -int GetLengthfromBuffer(PDATAMESSAGE buff); -int IntDecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp, uint64_t Mask, BOOL APRS, BOOL MCTL); -int IntSetTraceOptionsEx(uint64_t mask, int mtxparam, int mcomparam, int monUIOnly); -int CountBits64(uint64_t in); - - -#define GetSemaphore(Semaphore,ID) _GetSemaphore(Semaphore, ID, __FILE__, __LINE__) - -#define GetBuff() _GetBuff(__FILE__, __LINE__) -#define ReleaseBuffer(s) _ReleaseBuffer(s, __FILE__, __LINE__) -#define CheckGuardZone() _CheckGuardZone(__FILE__, __LINE__) - -#define Q_REM(s) _Q_REM(s, __FILE__, __LINE__) -#define Q_REM_NP(s) _Q_REM_NP(s, __FILE__, __LINE__) - -#define C_Q_ADD(s, b) _C_Q_ADD(s, b, __FILE__, __LINE__) - -void _CheckGuardZone(char * File, int Line); - -VOID * _Q_REM(VOID **Q, char * File, int Line); -VOID * _Q_REM_NP(VOID *Q, char * File, int Line); - -int _C_Q_ADD(VOID *Q, VOID *BUFF, char * File, int Line); - -UINT _ReleaseBuffer(VOID *BUFF, char * File, int Line); - -VOID * _GetBuff(char * File, int Line); -int _C_Q_ADD(VOID *PQ, VOID *PBUFF, char * File, int Line); - -int C_Q_COUNT(VOID *Q); - -DllExport char * APIENTRY GetApplCall(int Appl); -DllExport char * APIENTRY GetApplAlias(int Appl); -DllExport int APIENTRY FindFreeStream(); -DllExport int APIENTRY DeallocateStream(int stream); -DllExport int APIENTRY SessionState(int stream, int * state, int * change); -DllExport int APIENTRY SetAppl(int stream, int flags, int mask); -DllExport int APIENTRY GetMsg(int stream, char * msg, int * len, int * count ); -DllExport int APIENTRY GetConnectionInfo(int stream, char * callsign, - int * port, int * sesstype, int * paclen, - int * maxframe, int * l4window); - -#define LIBCONFIG_STATIC -#include "libconfig.h" - -int GetIntValue(config_setting_t * group, char * name); -BOOL GetStringValue(config_setting_t * group, char * name, char * value, int maxlen); -VOID SaveIntValue(config_setting_t * group, char * name, int value); -VOID SaveStringValue(config_setting_t * group, char * name, char * value); - -int EncryptPass(char * Pass, char * Encrypt); -VOID DecryptPass(char * Encrypt, unsigned char * Pass, unsigned int len); -Dll VOID APIENTRY CreateOneTimePassword(char * Password, char * KeyPhrase, int TimeOffset); -Dll BOOL APIENTRY CheckOneTimePassword(char * Password, char * KeyPhrase); - -DllExport int APIENTRY TXCount(int stream); -DllExport int APIENTRY RXCount(int stream); -DllExport int APIENTRY MONCount(int stream); - -VOID ReadNodes(); -int BPQTRACE(MESSAGE * Msg, BOOL APRS); - -VOID CommandHandler(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer); - -VOID PostStateChange(TRANSPORTENTRY * Session); - -VOID InnerCommandHandler(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer); -VOID DoTheCommand(TRANSPORTENTRY * Session); -char * MOVEANDCHECK(TRANSPORTENTRY * Session, char * Bufferptr, char * Source, int Len); -VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer); -char * strlop(char * buf, char delim); -BOOL CompareCalls(UCHAR * c1, UCHAR * c2); - -VOID PostDataAvailable(TRANSPORTENTRY * Session); -int WritetoConsoleLocal(char * buff); -char * CHECKBUFFER(TRANSPORTENTRY * Session, char * Bufferptr); -VOID CLOSECURRENTSESSION(TRANSPORTENTRY * Session); - -VOID SendCommandReply(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer, int Len); - -struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum); - -int cCOUNT_AT_L2(struct _LINKTABLE * LINK); -VOID SENDL4CONNECT(TRANSPORTENTRY * Session); - -VOID CloseSessionPartner(TRANSPORTENTRY * Session); -int COUNTNODES(struct ROUTE * ROUTE); -int DecodeNodeName(char * NodeName, char * ptr);; -VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer); -int cCOUNT_AT_L2(struct _LINKTABLE * LINK); -void * zalloc(int len); -BOOL FindDestination(UCHAR * Call, struct DEST_LIST ** REQDEST); - -BOOL ProcessConfig(); - -VOID PUT_ON_PORT_Q(struct PORTCONTROL * PORT, MESSAGE * Buffer); -VOID CLEAROUTLINK(struct _LINKTABLE * LINK); -VOID TellINP3LinkGone(struct ROUTE * Route); -VOID CLEARACTIVEROUTE(struct ROUTE * ROUTE, int Reason); - -// Reason Equates - -#define NORMALCLOSE 0 -#define RETRIEDOUT 1 -#define SETUPFAILED 2 -#define LINKLOST 3 -#define LINKSTUCK 4 - -int COUNT_AT_L2(struct _LINKTABLE * LINK); -VOID SENDIDMSG(); -VOID SENDBTMSG(); -VOID INP3TIMER(); -VOID REMOVENODE(dest_list * DEST); -BOOL ACTIVATE_DEST(struct DEST_LIST * DEST); -VOID TellINP3LinkSetupFailed(struct ROUTE * Route); -BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE); -VOID PROCROUTES(struct DEST_LIST * DEST, struct ROUTE * ROUTE, int Qual); -BOOL L2SETUPCROSSLINK(PROUTE ROUTE); -VOID REMOVENODE(dest_list * DEST); -char * SetupNodeHeader(struct DATAMESSAGE * Buffer); -VOID L4CONNECTFAILED(TRANSPORTENTRY * L4); -int CountFramesQueuedOnSession(TRANSPORTENTRY * Session); -VOID CLEARSESSIONENTRY(TRANSPORTENTRY * Session); -VOID __cdecl Debugprintf(const char * format, ...); - -int APIENTRY Restart(); -int APIENTRY Reboot(); -int APIENTRY Reconfig(); -Dll int APIENTRY SaveNodes (); - - -struct SEM; - -void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line); -void FreeSemaphore(struct SEM * Semaphore); - -void MySetWindowText(HWND hWnd, char * Msg); - -Dll int APIENTRY SessionControl(int stream, int command, int Mask); - -HANDLE OpenCOMPort(VOID * pPort, int speed, BOOL SetDTR, BOOL SetRTS, BOOL Quiet, int Stopbits); -int ReadCOMBlock(HANDLE fd, char * Block, int MaxLength); -BOOL WriteCOMBlock(HANDLE fd, char * Block, int BytesToWrite); -VOID CloseCOMPort(HANDLE fd); - -VOID initUTF8(); -int Is8Bit(unsigned char *cpt, int len); -int WebIsUTF8(unsigned char *ptr, int len); -int IsUTF8(unsigned char *ptr, int len); -int Convert437toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF); -int Convert1251toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF); -int Convert1252toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF); -int TrytoGuessCode(unsigned char * Char, int Len); - - -#define CMD_TO_APPL 1 // PASS COMMAND TO APPLICATION -#define MSG_TO_USER 2 // SEND 'CONNECTED' TO USER -#define MSG_TO_APPL 4 // SEND 'CONECTED' TO APPL -#define CHECK_FOR_ESC 8 // Look for ^d (^D) to disconnect session) - -#define UI 3 -#define SABM 0x2F -#define DISC 0x43 -#define DM 0x0F -#define UA 0x63 -#define FRMR 0x87 -#define RR 1 -#define RNR 5 -#define REJ 9 - -// V2.2 Types - -#define SREJ 0x0D -#define SABME 0x6F -#define XID 0xAF -#define TEST 0xE3 - -#define SUPPORT2point2 1 - -// XID Optional Functions - -#define OPMustHave 0x02A080 // Sync TEST 16 bit FCS Extended Address -#define OPSREJ 4 -#define OPSREJMult 0x200000 -#define OPREJ 2 -#define OPMod8 0x400 -#define OPMod128 0x800 - -#define BPQHOSTSTREAMS 64 - -extern TRANSPORTENTRY * L4TABLE; -extern unsigned char NEXTID; -extern int MAXCIRCUITS; -extern int L4DEFAULTWINDOW; -extern int L4T1; -extern APPLCALLS APPLCALLTABLE[]; -extern char * APPLS; -extern int NEEDMH; -extern int RFOnly; - -extern char SESSIONHDDR[]; - -extern UCHAR NEXTID; - -extern struct ROUTE * NEIGHBOURS; -extern int MAXNEIGHBOURS; - -extern struct ROUTE * NEIGHBOURS; -extern int ROUTE_LEN; -extern int MAXNEIGHBOURS; - -extern struct DEST_LIST * DESTS; // NODE LIST -extern struct DEST_LIST * ENDDESTLIST; -extern int DEST_LIST_LEN; -extern int MAXDESTS; // MAX NODES IN SYSTEM - -extern struct _LINKTABLE * LINKS; -extern int LINK_TABLE_LEN; -extern int MAXLINKS; - - - -extern char MYCALL[]; // DB 7 DUP (0) ; NODE CALLSIGN (BIT SHIFTED) -extern char MYALIASTEXT[]; // {" " ; NODE ALIAS (KEEP TOGETHER) - -extern UCHAR MYCALLWITHALIAS[13]; -extern APPLCALLS APPLCALLTABLE[NumberofAppls]; - -extern UCHAR MYNODECALL[]; // NODE CALLSIGN (ASCII) -extern char NODECALLLOPPED[]; // NODE CALLSIGN (ASCII). Null terminated -extern UCHAR MYNETROMCALL[]; // NETROM CALLSIGN (ASCII) - -extern UCHAR NETROMCALL[]; // NETORM CALL (AX25) - -extern VOID * FREE_Q; - -extern struct PORTCONTROL * PORTTABLE; -extern int NUMBEROFPORTS; - - -extern int OBSINIT; // INITIAL OBSOLESCENCE VALUE -extern int OBSMIN; // MINIMUM TO BROADCAST -extern int L3INTERVAL; // "NODES" INTERVAL IN MINS -extern int IDINTERVAL; // "ID" BROADCAST INTERVAL -extern int BTINTERVAL; // "BT" BROADCAST INTERVAL -extern int MINQUAL; // MIN QUALITY FOR AUTOUPDATES -extern int HIDENODES; // N * COMMAND SWITCH -extern int BBSQUAL; // QUALITY OF BBS RELATIVE TO NODE - -extern int NUMBEROFBUFFERS; // PACKET BUFFERS -extern int PACLEN; //MAX PACKET SIZE - -// L2 SYSTEM TIMER RUNS AT 3 HZ - -extern int T3; // LINK VALIDATION TIMER (3 MINS) (+ a bit to reduce RR collisions) - -extern int L2KILLTIME; // IDLE LINK TIMER (16 MINS) -extern int L3LIVES; // MAX L3 HOPS -extern int L4N2; // LEVEL 4 RETRY COUNT -extern int L4LIMIT; // IDLE SESSION LIMIT - 15 MINS -extern int L4DELAY; // L4 DELAYED ACK TIMER - -extern int BBS; // INCLUDE BBS SUPPORT -extern int NODE; // INCLUDE SWITCH SUPPORT - -extern int FULL_CTEXT; // CTEXT ON ALL CONNECTS IF NZ - - -// Although externally streams are numbered 1 to 64, internally offsets are 0 - 63 - -extern BPQVECSTRUC DUMMYVEC; // Needed to force correct order of following - -extern BPQVECSTRUC BPQHOSTVECTOR[BPQHOSTSTREAMS + 5]; - -extern int NODEORDER; -extern UCHAR LINKEDFLAG; - -extern UCHAR UNPROTOCALL[80]; - - -extern char * INFOMSG; - -extern char * CTEXTMSG; -extern int CTEXTLEN; - -extern UCHAR MYALIAS[7]; // ALIAS IN AX25 FORM -extern UCHAR BBSALIAS[7]; - -extern VOID * TRACE_Q; // TRANSMITTED FRAMES TO BE TRACED - -extern char HEADERCHAR; // CHAR FOR _NODE HEADER MSGS - -extern int AUTOSAVE; // AUTO SAVE NODES ON EXIT FLAG -extern int L4APPL; // Application for BBSCALL/ALIAS connects -extern int CFLAG; // C =HOST Command - -extern VOID * IDMSG_Q; // ID/BEACONS WAITING TO BE SENT - -extern struct DATAMESSAGE BTHDDR; -extern struct _MESSAGE IDHDDR; - -extern VOID * IDMSG; - -extern int L3TIMER; // TIMER FOR 'NODES' MESSAGE -extern int IDTIMER; // TIMER FOR ID MESSAGE -extern int BTTIMER; // TIMER FOR BT MESSAGE - -extern int STATSTIME; - - -extern BOOL IPRequired; -extern int MaxHops; -extern int MAXRTT; -extern USHORT CWTABLE[]; -extern TRANSPORTENTRY * L4TABLE; -extern UCHAR ROUTEQUAL; -extern UINT BPQMsg; -extern UCHAR ExcludeList[]; - - -extern APPLCALLS APPLCALLTABLE[]; - -extern char VersionStringWithBuild[]; -extern char VersionString[]; - -extern int MAXHEARDENTRIES; -extern int MHLEN; - -extern int APPL1; -extern int PASSCMD; -extern int NUMBEROFCOMMANDS; - -extern char * ConfigBuffer; - -extern char * WL2KReportLine[]; - -extern struct CMDX COMMANDS[]; - -extern int QCOUNT, MAXBUFFS, MAXCIRCUITS, L4DEFAULTWINDOW, L4T1, CMDXLEN; -extern char CMDALIAS[ALIASLEN][NumberofAppls]; - -extern int SEMGETS; -extern int SEMRELEASES; -extern int SEMCLASHES; -extern int MINBUFFCOUNT; - -extern UCHAR BPQDirectory[]; -extern UCHAR BPQProgramDirectory[]; - -extern UCHAR WINMOR[]; -extern UCHAR PACTORCALL[]; - -extern UCHAR MCOM; -extern UCHAR MUIONLY; -extern UCHAR MTX; -extern uint64_t MMASK; - -extern UCHAR NODECALL[]; // NODES in ax.25 - -extern int L4CONNECTSOUT; -extern int L4CONNECTSIN; -extern int L4FRAMESTX; -extern int L4FRAMESRX; -extern int L4FRAMESRETRIED; -extern int OLDFRAMES; -extern int L3FRAMES; - -extern char * PortConfig[]; -extern struct SEM Semaphore; -extern UCHAR AuthorisedProgram; // Local Variable. Set if Program is on secure list - -extern int REALTIMETICKS; - -extern time_t CurrentSecs; -extern time_t lastSlowSecs; -extern time_t lastSaveSecs; - -// SNMP Variables - -extern int InOctets[64]; -extern int OutOctets[64]; - -extern BOOL CloseAllNeeded; -extern int CloseOnError; - -extern char * PortConfig[70]; -extern struct TNCINFO * TNCInfo[71]; // Records are Malloc'd - -#define MaxBPQPortNo 63 // Port 64 reserved for BBS Mon -#define MAXBPQPORTS 63 - -// IP, APRS use port ocnfig slots above the real port range - -#define IPConfigSlot MaxBPQPortNo + 1 -#define PortMapConfigSlot MaxBPQPortNo + 2 -#define APRSConfigSlot MaxBPQPortNo + 3 - - -extern char * UIUIDigi[MaxBPQPortNo + 1]; -extern char UIUIDEST[MaxBPQPortNo + 1][11]; // Dest for Beacons -extern UCHAR FN[MaxBPQPortNo + 1][256]; // Filename -extern int Interval[MaxBPQPortNo + 1]; // Beacon Interval (Mins) -extern char Message[MaxBPQPortNo + 1][1000]; // Beacon Text - -extern int MinCounter[MaxBPQPortNo + 1]; // Interval Countdown -extern BOOL SendFromFile[MaxBPQPortNo + 1]; - -extern BOOL MQTT; -extern char MQTT_HOST[80]; -extern int MQTT_PORT; -extern char MQTT_USER[80]; -extern char MQTT_PASS[80]; - -DllExport uint64_t APIENTRY GetPortFrequency(int PortNo, char * FreqStringMhz); - - -void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK); -void hookL2SessionDeleted(struct _LINKTABLE * LINK); -void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK); - -void hookL4SessionAttempt(void * STREAM, char * remotecall, char * ourcall); -void hookL4SessionAccepted(void * STREAM, char * remotecall, char * ourcall); -void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM); +// +// Prototypes for BPQ32 Node Functions +// + +#define DllImport + +#define EXCLUDEBITS + +#define _WINSOCK_DEPRECATED_NO_WARNINGS + +#include "compatbits.h" + +#include "asmstrucs.h" + +BOOL CheckExcludeList(UCHAR * Call); + +Dll int ConvFromAX25(unsigned char * incall,unsigned char * outcall); +Dll BOOL ConvToAX25(unsigned char * callsign, unsigned char * ax25call); +DllExport BOOL ConvToAX25Ex(unsigned char * callsign, unsigned char * ax25call); +int WritetoConsoleLocal(char * buff); +VOID Consoleprintf(const char * format, ...); +VOID FreeConfig(); +int GetListeningPortsPID(int Port); + +void * InitializeExtDriver(PEXTPORTDATA PORTVEC); + +VOID PutLengthinBuffer(PDATAMESSAGE buff, USHORT datalen); // Needed for arm5 portability +int GetLengthfromBuffer(PDATAMESSAGE buff); +int IntDecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp, uint64_t Mask, BOOL APRS, BOOL MCTL); +int IntSetTraceOptionsEx(uint64_t mask, int mtxparam, int mcomparam, int monUIOnly); +int CountBits64(uint64_t in); + + +#define GetSemaphore(Semaphore,ID) _GetSemaphore(Semaphore, ID, __FILE__, __LINE__) + +#define GetBuff() _GetBuff(__FILE__, __LINE__) +#define ReleaseBuffer(s) _ReleaseBuffer(s, __FILE__, __LINE__) +#define CheckGuardZone() _CheckGuardZone(__FILE__, __LINE__) + +#define Q_REM(s) _Q_REM(s, __FILE__, __LINE__) +#define Q_REM_NP(s) _Q_REM_NP(s, __FILE__, __LINE__) + +#define C_Q_ADD(s, b) _C_Q_ADD(s, b, __FILE__, __LINE__) + +void _CheckGuardZone(char * File, int Line); + +VOID * _Q_REM(VOID **Q, char * File, int Line); +VOID * _Q_REM_NP(VOID *Q, char * File, int Line); + +int _C_Q_ADD(VOID *Q, VOID *BUFF, char * File, int Line); + +UINT _ReleaseBuffer(VOID *BUFF, char * File, int Line); + +VOID * _GetBuff(char * File, int Line); +int _C_Q_ADD(VOID *PQ, VOID *PBUFF, char * File, int Line); + +int C_Q_COUNT(VOID *Q); + +DllExport char * APIENTRY GetApplCall(int Appl); +DllExport char * APIENTRY GetApplAlias(int Appl); +DllExport int APIENTRY FindFreeStream(); +DllExport int APIENTRY DeallocateStream(int stream); +DllExport int APIENTRY SessionState(int stream, int * state, int * change); +DllExport int APIENTRY SetAppl(int stream, int flags, int mask); +DllExport int APIENTRY GetMsg(int stream, char * msg, int * len, int * count ); +DllExport int APIENTRY GetConnectionInfo(int stream, char * callsign, + int * port, int * sesstype, int * paclen, + int * maxframe, int * l4window); + +#define LIBCONFIG_STATIC +#include "libconfig.h" + +int GetIntValue(config_setting_t * group, char * name); +BOOL GetStringValue(config_setting_t * group, char * name, char * value, int maxlen); +VOID SaveIntValue(config_setting_t * group, char * name, int value); +VOID SaveStringValue(config_setting_t * group, char * name, char * value); + +int EncryptPass(char * Pass, char * Encrypt); +VOID DecryptPass(char * Encrypt, unsigned char * Pass, unsigned int len); +Dll VOID APIENTRY CreateOneTimePassword(char * Password, char * KeyPhrase, int TimeOffset); +Dll BOOL APIENTRY CheckOneTimePassword(char * Password, char * KeyPhrase); + +DllExport int APIENTRY TXCount(int stream); +DllExport int APIENTRY RXCount(int stream); +DllExport int APIENTRY MONCount(int stream); + +VOID ReadNodes(); +int BPQTRACE(MESSAGE * Msg, BOOL APRS); + +VOID CommandHandler(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer); + +VOID PostStateChange(TRANSPORTENTRY * Session); + +VOID InnerCommandHandler(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer); +VOID DoTheCommand(TRANSPORTENTRY * Session); +char * MOVEANDCHECK(TRANSPORTENTRY * Session, char * Bufferptr, char * Source, int Len); +VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer); +char * strlop(char * buf, char delim); +BOOL CompareCalls(UCHAR * c1, UCHAR * c2); + +VOID PostDataAvailable(TRANSPORTENTRY * Session); +int WritetoConsoleLocal(char * buff); +char * CHECKBUFFER(TRANSPORTENTRY * Session, char * Bufferptr); +VOID CLOSECURRENTSESSION(TRANSPORTENTRY * Session); + +VOID SendCommandReply(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer, int Len); + +struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum); + +int cCOUNT_AT_L2(struct _LINKTABLE * LINK); +VOID SENDL4CONNECT(TRANSPORTENTRY * Session); + +VOID CloseSessionPartner(TRANSPORTENTRY * Session); +int COUNTNODES(struct ROUTE * ROUTE); +int DecodeNodeName(char * NodeName, char * ptr);; +VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer); +int cCOUNT_AT_L2(struct _LINKTABLE * LINK); +void * zalloc(int len); +BOOL FindDestination(UCHAR * Call, struct DEST_LIST ** REQDEST); + +BOOL ProcessConfig(); + +VOID PUT_ON_PORT_Q(struct PORTCONTROL * PORT, MESSAGE * Buffer); +VOID CLEAROUTLINK(struct _LINKTABLE * LINK); +VOID TellINP3LinkGone(struct ROUTE * Route); +VOID CLEARACTIVEROUTE(struct ROUTE * ROUTE, int Reason); + +// Reason Equates + +#define NORMALCLOSE 0 +#define RETRIEDOUT 1 +#define SETUPFAILED 2 +#define LINKLOST 3 +#define LINKSTUCK 4 + +int COUNT_AT_L2(struct _LINKTABLE * LINK); +VOID SENDIDMSG(); +VOID SENDBTMSG(); +VOID INP3TIMER(); +VOID REMOVENODE(dest_list * DEST); +BOOL ACTIVATE_DEST(struct DEST_LIST * DEST); +VOID TellINP3LinkSetupFailed(struct ROUTE * Route); +BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE); +VOID PROCROUTES(struct DEST_LIST * DEST, struct ROUTE * ROUTE, int Qual); +BOOL L2SETUPCROSSLINK(PROUTE ROUTE); +VOID REMOVENODE(dest_list * DEST); +char * SetupNodeHeader(struct DATAMESSAGE * Buffer); +VOID L4CONNECTFAILED(TRANSPORTENTRY * L4); +int CountFramesQueuedOnSession(TRANSPORTENTRY * Session); +VOID CLEARSESSIONENTRY(TRANSPORTENTRY * Session); +VOID __cdecl Debugprintf(const char * format, ...); + +int APIENTRY Restart(); +int APIENTRY Reboot(); +int APIENTRY Reconfig(); +Dll int APIENTRY SaveNodes (); + + +struct SEM; + +void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line); +void FreeSemaphore(struct SEM * Semaphore); + +void MySetWindowText(HWND hWnd, char * Msg); + +Dll int APIENTRY SessionControl(int stream, int command, int Mask); + +HANDLE OpenCOMPort(VOID * pPort, int speed, BOOL SetDTR, BOOL SetRTS, BOOL Quiet, int Stopbits); +int ReadCOMBlock(HANDLE fd, char * Block, int MaxLength); +BOOL WriteCOMBlock(HANDLE fd, char * Block, int BytesToWrite); +VOID CloseCOMPort(HANDLE fd); + +VOID initUTF8(); +int Is8Bit(unsigned char *cpt, int len); +int WebIsUTF8(unsigned char *ptr, int len); +int IsUTF8(unsigned char *ptr, int len); +int Convert437toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF); +int Convert1251toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF); +int Convert1252toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF); +int TrytoGuessCode(unsigned char * Char, int Len); + + +#define CMD_TO_APPL 1 // PASS COMMAND TO APPLICATION +#define MSG_TO_USER 2 // SEND 'CONNECTED' TO USER +#define MSG_TO_APPL 4 // SEND 'CONECTED' TO APPL +#define CHECK_FOR_ESC 8 // Look for ^d (^D) to disconnect session) + +#define UI 3 +#define SABM 0x2F +#define DISC 0x43 +#define DM 0x0F +#define UA 0x63 +#define FRMR 0x87 +#define RR 1 +#define RNR 5 +#define REJ 9 + +// V2.2 Types + +#define SREJ 0x0D +#define SABME 0x6F +#define XID 0xAF +#define TEST 0xE3 + +#define SUPPORT2point2 1 + +// XID Optional Functions + +#define OPMustHave 0x02A080 // Sync TEST 16 bit FCS Extended Address +#define OPSREJ 4 +#define OPSREJMult 0x200000 +#define OPREJ 2 +#define OPMod8 0x400 +#define OPMod128 0x800 + +#define BPQHOSTSTREAMS 64 + +extern TRANSPORTENTRY * L4TABLE; +extern unsigned char NEXTID; +extern int MAXCIRCUITS; +extern int L4DEFAULTWINDOW; +extern int L4T1; +extern APPLCALLS APPLCALLTABLE[]; +extern char * APPLS; +extern int NEEDMH; +extern int RFOnly; + +extern char SESSIONHDDR[]; + +extern UCHAR NEXTID; + +extern struct ROUTE * NEIGHBOURS; +extern int MAXNEIGHBOURS; + +extern struct ROUTE * NEIGHBOURS; +extern int ROUTE_LEN; +extern int MAXNEIGHBOURS; + +extern struct DEST_LIST * DESTS; // NODE LIST +extern struct DEST_LIST * ENDDESTLIST; +extern int DEST_LIST_LEN; +extern int MAXDESTS; // MAX NODES IN SYSTEM + +extern struct _LINKTABLE * LINKS; +extern int LINK_TABLE_LEN; +extern int MAXLINKS; + + + +extern char MYCALL[]; // DB 7 DUP (0) ; NODE CALLSIGN (BIT SHIFTED) +extern char MYALIASTEXT[]; // {" " ; NODE ALIAS (KEEP TOGETHER) + +extern UCHAR MYCALLWITHALIAS[13]; +extern APPLCALLS APPLCALLTABLE[NumberofAppls]; + +extern UCHAR MYNODECALL[]; // NODE CALLSIGN (ASCII) +extern char NODECALLLOPPED[]; // NODE CALLSIGN (ASCII). Null terminated +extern UCHAR MYNETROMCALL[]; // NETROM CALLSIGN (ASCII) + +extern UCHAR NETROMCALL[]; // NETORM CALL (AX25) + +extern VOID * FREE_Q; + +extern struct PORTCONTROL * PORTTABLE; +extern int NUMBEROFPORTS; + + +extern int OBSINIT; // INITIAL OBSOLESCENCE VALUE +extern int OBSMIN; // MINIMUM TO BROADCAST +extern int L3INTERVAL; // "NODES" INTERVAL IN MINS +extern int IDINTERVAL; // "ID" BROADCAST INTERVAL +extern int BTINTERVAL; // "BT" BROADCAST INTERVAL +extern int MINQUAL; // MIN QUALITY FOR AUTOUPDATES +extern int HIDENODES; // N * COMMAND SWITCH +extern int BBSQUAL; // QUALITY OF BBS RELATIVE TO NODE + +extern int NUMBEROFBUFFERS; // PACKET BUFFERS +extern int PACLEN; //MAX PACKET SIZE + +// L2 SYSTEM TIMER RUNS AT 3 HZ + +extern int T3; // LINK VALIDATION TIMER (3 MINS) (+ a bit to reduce RR collisions) + +extern int L2KILLTIME; // IDLE LINK TIMER (16 MINS) +extern int L3LIVES; // MAX L3 HOPS +extern int L4N2; // LEVEL 4 RETRY COUNT +extern int L4LIMIT; // IDLE SESSION LIMIT - 15 MINS +extern int L4DELAY; // L4 DELAYED ACK TIMER + +extern int BBS; // INCLUDE BBS SUPPORT +extern int NODE; // INCLUDE SWITCH SUPPORT + +extern int FULL_CTEXT; // CTEXT ON ALL CONNECTS IF NZ + + +// Although externally streams are numbered 1 to 64, internally offsets are 0 - 63 + +extern BPQVECSTRUC DUMMYVEC; // Needed to force correct order of following + +extern BPQVECSTRUC BPQHOSTVECTOR[BPQHOSTSTREAMS + 5]; + +extern int NODEORDER; +extern UCHAR LINKEDFLAG; + +extern UCHAR UNPROTOCALL[80]; + + +extern char * INFOMSG; + +extern char * CTEXTMSG; +extern int CTEXTLEN; + +extern UCHAR MYALIAS[7]; // ALIAS IN AX25 FORM +extern UCHAR BBSALIAS[7]; + +extern VOID * TRACE_Q; // TRANSMITTED FRAMES TO BE TRACED + +extern char HEADERCHAR; // CHAR FOR _NODE HEADER MSGS + +extern int AUTOSAVE; // AUTO SAVE NODES ON EXIT FLAG +extern int L4APPL; // Application for BBSCALL/ALIAS connects +extern int CFLAG; // C =HOST Command + +extern VOID * IDMSG_Q; // ID/BEACONS WAITING TO BE SENT + +extern struct DATAMESSAGE BTHDDR; +extern struct _MESSAGE IDHDDR; + +extern VOID * IDMSG; + +extern int L3TIMER; // TIMER FOR 'NODES' MESSAGE +extern int IDTIMER; // TIMER FOR ID MESSAGE +extern int BTTIMER; // TIMER FOR BT MESSAGE + +extern int STATSTIME; + + +extern BOOL IPRequired; +extern int MaxHops; +extern int MAXRTT; +extern USHORT CWTABLE[]; +extern TRANSPORTENTRY * L4TABLE; +extern UCHAR ROUTEQUAL; +extern UINT BPQMsg; +extern UCHAR ExcludeList[]; + + +extern APPLCALLS APPLCALLTABLE[]; + +extern char VersionStringWithBuild[]; +extern char VersionString[]; + +extern int MAXHEARDENTRIES; +extern int MHLEN; + +extern int APPL1; +extern int PASSCMD; +extern int NUMBEROFCOMMANDS; + +extern char * ConfigBuffer; + +extern char * WL2KReportLine[]; + +extern struct CMDX COMMANDS[]; + +extern int QCOUNT, MAXBUFFS, MAXCIRCUITS, L4DEFAULTWINDOW, L4T1, CMDXLEN; +extern char CMDALIAS[ALIASLEN][NumberofAppls]; + +extern int SEMGETS; +extern int SEMRELEASES; +extern int SEMCLASHES; +extern int MINBUFFCOUNT; + +extern UCHAR BPQDirectory[]; +extern UCHAR BPQProgramDirectory[]; + +extern UCHAR WINMOR[]; +extern UCHAR PACTORCALL[]; + +extern UCHAR MCOM; +extern UCHAR MUIONLY; +extern UCHAR MTX; +extern uint64_t MMASK; + +extern UCHAR NODECALL[]; // NODES in ax.25 + +extern int L4CONNECTSOUT; +extern int L4CONNECTSIN; +extern int L4FRAMESTX; +extern int L4FRAMESRX; +extern int L4FRAMESRETRIED; +extern int OLDFRAMES; +extern int L3FRAMES; + +extern char * PortConfig[]; +extern struct SEM Semaphore; +extern UCHAR AuthorisedProgram; // Local Variable. Set if Program is on secure list + +extern int REALTIMETICKS; + +extern time_t CurrentSecs; +extern time_t lastSlowSecs; +extern time_t lastSaveSecs; + +// SNMP Variables + +extern int InOctets[64]; +extern int OutOctets[64]; + +extern BOOL CloseAllNeeded; +extern int CloseOnError; + +extern char * PortConfig[70]; +extern struct TNCINFO * TNCInfo[71]; // Records are Malloc'd + +#define MaxBPQPortNo 63 // Port 64 reserved for BBS Mon +#define MAXBPQPORTS 63 + +// IP, APRS use port ocnfig slots above the real port range + +#define IPConfigSlot MaxBPQPortNo + 1 +#define PortMapConfigSlot MaxBPQPortNo + 2 +#define APRSConfigSlot MaxBPQPortNo + 3 + + +extern char * UIUIDigi[MaxBPQPortNo + 1]; +extern char UIUIDEST[MaxBPQPortNo + 1][11]; // Dest for Beacons +extern UCHAR FN[MaxBPQPortNo + 1][256]; // Filename +extern int Interval[MaxBPQPortNo + 1]; // Beacon Interval (Mins) +extern char Message[MaxBPQPortNo + 1][1000]; // Beacon Text + +extern int MinCounter[MaxBPQPortNo + 1]; // Interval Countdown +extern BOOL SendFromFile[MaxBPQPortNo + 1]; + +extern BOOL MQTT; +extern char MQTT_HOST[80]; +extern int MQTT_PORT; +extern char MQTT_USER[80]; +extern char MQTT_PASS[80]; + +DllExport uint64_t APIENTRY GetPortFrequency(int PortNo, char * FreqStringMhz); + + +void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK); +void hookL2SessionDeleted(struct _LINKTABLE * LINK); +void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK); + +void hookL4SessionAttempt(void * STREAM, char * remotecall, char * ourcall); +void hookL4SessionAccepted(void * STREAM, char * remotecall, char * ourcall); +void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM); diff --git a/config.c b/config.c index 02b8d4a..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" +"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}; /* 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} ; // 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); @@ -370,8 +373,7 @@ static char *pkeywords[] = "BCALL", "DIGIMASK", "NOKEEPALIVES", "COMPORT", "DRIVER", "WL2KREPORT", "UIONLY", "UDPPORT", "IPADDR", "I2CBUS", "I2CDEVICE", "UDPTXPORT", "UDPRXPORT", "NONORMALIZE", "IGNOREUNLOCKEDROUTES", "INP3ONLY", "TCPPORT", "RIGPORT", "PERMITTEDAPPLS", "HIDE", -"SMARTID", "KISSCOMMAND", "SendtoM0LTEMap", "PortFreq", "M0LTEMapInfo", "QTSMPort", -"MQTT", "MQTT_HOST", "MQTT_PORT", "MQTT_USER", "MQTT_PASS"}; /* parameter keywords */ +"SMARTID", "KISSCOMMAND", "SendtoM0LTEMap", "PortFreq", "M0LTEMapInfo", "QTSMPort"}; /* parameter keywords */ static void * poffset[] = { @@ -616,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 831456d..a7e51a8 100644 --- a/configstructs.h +++ b/configstructs.h @@ -170,7 +170,11 @@ struct CONFIGTABLE int C_MQTT_PORT; 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 diff --git a/mailapi.c b/mailapi.c index 2aa1b9b..064fa92 100644 --- a/mailapi.c +++ b/mailapi.c @@ -852,7 +852,14 @@ double LatFromLOC = 0; double LonFromLOC = 0; #endif +void SendBBSDataToPktMapThread(); + void SendBBSDataToPktMap() +{ + _beginthread(SendBBSDataToPktMapThread, 0, 0); +} + +void SendBBSDataToPktMapThread() { char Request[64]; char * Params; diff --git a/makefile~ b/makefile~ deleted file mode 100644 index 58534d7..0000000 --- a/makefile~ +++ /dev/null @@ -1,43 +0,0 @@ -# LinBPQ Makefile - -# To exclude i2c support run make noi2c - -OBJS = pngwtran.o pngrtran.o pngset.o pngrio.o pngwio.o pngtrans.o pngrutil.o pngwutil.o\ - pngread.o pngwrite.o png.o pngerror.o pngget.o pngmem.o APRSIconData.o AISCommon.o\ - upnp.o APRSStdPages.o HSMODEM.o WinRPR.o KISSHF.o TNCEmulators.o bpqhdlc.o SerialPort.o\ - adif.o WebMail.o utf8Routines.o VARA.o LzFind.o Alloc.o LzmaDec.o LzmaEnc.o LzmaLib.o \ - Multicast.o ARDOP.o IPCode.o FLDigi.o linether.o CMSAuth.o APRSCode.o BPQtoAGW.o KAMPactor.o\ - AEAPactor.o HALDriver.o MULTIPSK.o BBSHTMLConfig.o ChatHTMLConfig.o BBSUtilities.o bpqaxip.o\ - BPQINP3.o BPQNRR.o cMain.o Cmd.o CommonCode.o HTMLCommonCode.o compatbits.o config.o datadefs.o \ - FBBRoutines.o HFCommon.o Housekeeping.o HTTPcode.o kiss.o L2Code.o L3Code.o L4Code.o lzhuf32.o \ - MailCommands.o MailDataDefs.o LinBPQ.o MailRouting.o MailTCP.o MBLRoutines.o md5.o Moncode.o \ - NNTPRoutines.o RigControl.o TelnetV6.o WINMOR.o TNCCode.o UZ7HODrv.o WPRoutines.o \ - SCSTrackeMulti.o SCSPactor.o SCSTracker.o HanksRT.o UIRoutines.o AGWAPI.o AGWMoncode.o \ - DRATS.o FreeDATA.o base64.o Events.o nodeapi.o mailapi.o mqtt.o - -# Configuration: - -CC = gcc - -all: CFLAGS = -DLINBPQ -MMD -g -fcommon -all: LDFLAGS = -l:libpaho-mqtt3a.a -l:libjansson.a -all: linbpq - - -nomqtt: CFLAGS = -DLINBPQ -MMD -fcommon -g -DNOMQTT -nomqtt: linbpq - -noi2c: CFLAGS = -DLINBPQ -MMD -DNOI2C -g -fcommon -noi2c: linbpq - - -linbpq: $(OBJS) - gcc $(OBJS) -Xlinker -Map=output.map -l:libminiupnpc.a -lrt -lm -lz $(LDFLAGS) -lpthread -lconfig -lpcap -o linbpq - sudo setcap "CAP_NET_ADMIN=ep CAP_NET_RAW=ep CAP_NET_BIND_SERVICE=ep" linbpq - --include *.d - -clean : - rm *.d - rm linbpq $(OBJS) - diff --git a/nodeapi-skigdebian.c b/nodeapi-skigdebian.c deleted file mode 100644 index a675a9e..0000000 --- a/nodeapi-skigdebian.c +++ /dev/null @@ -1,858 +0,0 @@ -// basic JASON API to BPQ Node - -// Authentication is via Telnet USER records. - - -#define _CRT_SECURE_NO_DEPRECATE - -#include "cheaders.h" -#include -#include "tncinfo.h" -#include "asmstrucs.h" -#include "kiss.h" - -// Constants -#define TOKEN_SIZE 32 // Length of the authentication token -#define TOKEN_EXPIRATION 7200 // Token expiration time in seconds (2 hours) - -// Token data structure -typedef struct Token { - char token[TOKEN_SIZE + 1]; - time_t expiration_time; - struct Token* next; -} Token; - -typedef struct API -{ - char *URL; - int URLLen; - int (* APIRoutine)(char * response, char * token, char * param); - int Auth; -} API; - -// Auth defines - -#define AuthNone 0 -#define AuthUser 1 -#define Auth BBSUser 2 -#define AuthSysop 4 - -// Function prototypes -void handle_request(SOCKET client_socket, char * request, char * response); -int verify_token(const char* token); -void remove_expired_tokens(); -char* fetch_data(const char* endpoint); -int request_token(char * response); -int send_http_response(char * response, const char* msg); -int create_json_response(char * response, char* access_token, int expires_in, char* scope); -void add_token_to_list(Token* token); - -Token* find_token(const char* token); -Token* generate_token(); - -int sendPortList(char * response, char * token, char * Rest); -int sendNodeList(char * response, char * token, char * Rest); -int sendUserList(char * response, char * token, char * Rest); -int sendInfo(char * response, char * token, char * Rest); -int sendLinks(char * response, char * token, char * Rest); -int sendPortMHList(char * response, char * token, char * Rest); -int sendWhatsPacState(char * response, char * token, char * param); -int sendWhatsPacConfig(char * response, char * token, char * param); - -void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT); -DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot); - -// Token list -Token* token_list = NULL; - - -struct API APIList[] = -{ - "/api/ports", 10, sendPortList, 0, - "/api/nodes", 10, sendNodeList, 0, - "/api/info", 9, sendInfo, 0, - "/api/links", 10, sendLinks, 0, - "/api/users", 10, sendUserList, 0, - "/api/mheard", 11, sendPortMHList, 0, - "/api/v1/config", 14, sendWhatsPacConfig, 0, - "/api/v1/state", 13, sendWhatsPacState, 0 -}; - -int APICount = sizeof(APIList) / sizeof(struct API); - -extern int HTTPPort; - - -int xx() -{ - while (1) - { - // Remove expired tokens - remove_expired_tokens(); - - // Handle the client request - // handle_request(); - } - return 0; -} - -int APIProcessHTTPMessage(char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE) -{ - const char * auth_header = "Authorization: Bearer "; - char * token_begin = strstr(request, auth_header); - char token[TOKEN_SIZE + 1]= ""; - int Flags = 0, n; - - // Node Flags isn't currently used - - char * Tok; - char * param; - - if (token_begin) - { - // Using Auth Header - - // Extract the token from the request (assuming it's present in the request headers) - - if (token_begin == NULL) - { - Debugprintf("Invalid request: No authentication token provided.\n"); - return send_http_response(response, "403 (Forbidden)"); - } - - token_begin += strlen(auth_header); // Move to the beginning of the token - strncpy(token, token_begin, TOKEN_SIZE); - token[TOKEN_SIZE] = '\0'; // Null-terminate the token - - param = strlop(URL, '?'); - } - else - { - // There may be a token as first param, but if auth not needed may be misisng - - Tok = strlop(URL, '?'); - param = strlop(Tok, '&'); - - if (Tok && strlen(Tok) == TOKEN_SIZE) - { - // assume auth token - - strcpy(token, Tok); - } - else param = Tok; - } - - remove_expired_tokens(); // Tidy up - - // Check if the request is for token generation - - if (strcmp(Method, "OPTIONS") == 0) - { - // CORS Request - - char Resp[] = - "HTTP/1.1 200 OK\r\n" - "Access-Control-Allow-Origin: *\r\n" - "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n" - "Access-Control-Allow-Headers: authorization"; - - return send_http_response(response, Resp); - } - - if (strcmp(Method, "GET") != 0) - return send_http_response(response, "403 (Bad Method)"); - - if (_stricmp(URL, "/api/request_token") == 0) - return request_token(response); - -/* -if (token[0] == 0) - { - // Extract the token from the request (assuming it's present in the request headers) - if (token_begin == NULL) - { - Debugprintf("Invalid request: No authentication token provided.\n"); - return send_http_response(response, "403 (Forbidden)"); - } - token_begin += strlen(auth_header); // Move to the beginning of the token - strncpy(token, token_begin, TOKEN_SIZE); - token[TOKEN_SIZE] = '\0'; // Null-terminate the token - } - - // Verify the token - if (!verify_token(token)) - { - Debugprintf("Invalid authentication token.\n"); - return send_http_response(response, "401 Unauthorized"); - } - - */ - - // Determine the requested API endpoint - - for (n = 0; n < APICount; n++) - { - struct API * APIEntry; - char * rest; - - APIEntry = &APIList[n]; - - if (_memicmp(URL, APIEntry->URL, APIEntry->URLLen) == 0) - { - rest = &request[4 + APIEntry->URLLen]; // Anything following? - - if (rest[0] == ' ' || rest[0] == '/' || rest[0] == '?') - return APIEntry->APIRoutine(response, token, rest); - } - - } - - return send_http_response(response, "401 Invalid API Call"); -} - -int request_token(char * response) -{ - Token * token = generate_token(); - char scope[] = "create"; - - printf("Token generated: %s\n", token->token); - - sprintf(response, "{\"access_token\":\"%s\", \"expires_at\":%ld,\"scope\":\"create\"}\r\n", - token->token, token->expiration_time); - - return strlen(response); -} - -Token * generate_token() -{ - // Generate a random authentication token - - int i; - - Token * token = malloc(sizeof(Token)); - for (i = 0; i < TOKEN_SIZE; i++) - { - token->token[i] = 'A' + rand() % 26; // Random uppercase alphabet character - } - token->token[TOKEN_SIZE] = '\0'; // Null-terminate the token - token->expiration_time = time(NULL) + TOKEN_EXPIRATION; // Set token expiration time - add_token_to_list(token); - return token; -} - -// Function to add the token to the token_list - -void add_token_to_list(Token* token) -{ - if (token_list == NULL) - { - token_list = token; - token->next = NULL; - } - else - { - Token* current = token_list; - - while (current->next != NULL) - current = current->next; - - current->next = token; - token->next = NULL; - } -} - -int verify_token(const char* token) -{ - // Find the token in the token list - Token * existing_token = find_token(token); - - if (existing_token != NULL) - { - // Check if the token has expired - time_t current_time = time(NULL); - if (current_time > existing_token->expiration_time) - { - // Token has expired, remove it from the token list - remove_expired_tokens(); - return 0; - } - // Token is valid - return 1; - } - - // Token doesn't exist in the token list - return 0; -} - -void remove_expired_tokens() -{ - time_t current_time = time(NULL); - Token* current_token = token_list; - Token* prev_token = NULL; - Token* next_token; - - while (current_token != NULL) - { - if (current_time > current_token->expiration_time) - { - // Token has expired, remove it from the token list - if (prev_token == NULL) - { - token_list = current_token->next; - } else { - prev_token->next = current_token->next; - } - next_token = current_token->next; - free(current_token); - current_token = next_token; - } else { - prev_token = current_token; - current_token = current_token->next; - } - } -} - -Token * find_token(const char* token) -{ - Token* current_token = token_list; - while (current_token != NULL) - { - if (strcmp(current_token->token, token) == 0) - { - return current_token; - } - current_token = current_token->next; - } - return NULL; -} - -int send_http_response(char * response, const char* msg) -{ - return sprintf(response, "HTTP/1.1 %s\r\nContent-Length: 0\r\nConnection: close\r\n\r\n", msg); -} - -/* -{ -"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3", -"expires_in":3600, -"scope":"create" -} -*/ - -/* -{"ports":[ -{"ID":"My Port", "Driver":"KISS", "Number":2, "State":"Active"), -{ ...}, -{...} -]} -*/ - -extern int MasterPort[MAXBPQPORTS+1]; // Pointer to first BPQ port for a specific MPSK or UZ7HO host - -int sendPortList(char * response, char * token, char * param) -{ - char * Array = 0; - int ArrayLen = 0; - int ArrayPtr = 0; - - struct _EXTPORTDATA * ExtPort; - struct PORTCONTROL * Port; - struct PORTCONTROL * SAVEPORT; - int PortNo; - - int count; - char DLL[20]; - char Status[32]="Unknown"; - char ID[33]; - char * ptr; - - ArrayPtr += sprintf(&response[ArrayPtr], "{\"ports\":[\r\n"); - - for (count = 1; count <= NUMBEROFPORTS; count++) - { - Port = GetPortTableEntryFromSlot(count); - ExtPort = (struct _EXTPORTDATA *)Port; - PortNo = Port->PORTNUMBER; - - if (Port->PORTTYPE == 0x10) - { - strcpy(DLL, ExtPort->PORT_DLL_NAME); - strlop(DLL, '.'); - strlop(DLL, ' '); - } - else if (Port->PORTTYPE == 0) - strcpy(DLL, "ASYNC"); - - else if (Port->PORTTYPE == 22) - strcpy(DLL, "I2C"); - - else if (Port->PORTTYPE == 14) - strcpy(DLL, "INTERNAL"); - - else if (Port->PORTTYPE > 0 && Port->PORTTYPE < 14) - strcpy(DLL, "HDLC"); - - - if (Port->PortStopped) - { - strcpy(Status, "Stopped"); - - } - else - { - if (Port->PORTTYPE == 0) - { - struct KISSINFO * KISS = (struct KISSINFO *)Port; - NPASYINFO KPort; - - SAVEPORT = Port; - - if (KISS->FIRSTPORT && KISS->FIRSTPORT != KISS) - { - // Not first port on device - - Port = (struct PORTCONTROL *)KISS->FIRSTPORT; - KPort = KISSInfo[PortNo]; - } - - KPort = KISSInfo[PortNo]; - - if (KPort) - { - // KISS like - see if connected - - if (Port->PORTIPADDR.s_addr || Port->KISSSLAVE) - { - // KISS over UDP or TCP - - if (Port->KISSTCP) - { - if (KPort->Connected) - strcpy(Status, "Open "); - else - if (Port->KISSSLAVE) - strcpy(Status, "Listen"); - else - strcpy(Status, "Closed"); - } - else - strcpy(Status, "UDP"); - } - else - if (KPort->idComDev) // Serial port Open - strcpy(Status, "Open "); - else - strcpy(Status, "Closed"); - - - Port = SAVEPORT; - } - } - - if (Port->PORTTYPE == 14) // Loopback - strcpy(Status, "Open "); - - else if (Port->PORTTYPE == 16) // External - { - if (Port->PROTOCOL == 10) // 'HF' Port - { - struct TNCINFO * TNC = TNCInfo[PortNo]; - - if (TNC) - { - switch (TNC->Hardware) // Hardware Type - { - case H_SCS: - case H_KAM: - case H_AEA: - case H_HAL: - case H_TRK: - case H_SERIAL: - - // Serial - - if (TNC->hDevice) - strcpy(Status, "Open "); - else - strcpy(Status, "Closed"); - - break; - - case H_UZ7HO: - - if (TNCInfo[MasterPort[PortNo]]->CONNECTED) - strcpy(Status, "Open "); - else - strcpy(Status, "Closed"); - - break; - - case H_WINMOR: - case H_V4: - - case H_MPSK: - case H_FLDIGI: - case H_UIARQ: - case H_ARDOP: - case H_VARA: - case H_KISSHF: - case H_WINRPR: - case H_FREEDATA: - - // TCP - - if (TNC->CONNECTED) - { - if (TNC->Streams[0].Attached) - strcpy(Status, "In Use"); - else - strcpy(Status, "Open "); - } - else - strcpy(Status, "Closed"); - - break; - - case H_TELNET: - - strcpy(Status, "Open "); - } - } - } - else - { - // External but not HF - AXIP, BPQETHER VKISS, ?? - - struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)Port; - - strcpy(Status, "Open "); - } - } - } - - strlop(Status, ' '); - strcpy(ID, Port->PORTDESCRIPTION); - ptr = &ID[29]; - while (*(ptr) == ' ') - { - *(ptr--) = 0; - } - - ArrayPtr += sprintf(&response[ArrayPtr], " {\"ID\":\"%s\", \"Driver\":\"%s\", \"Number\":%d,\"State\":\"%s\"},\r\n", - ID, DLL, Port->PORTNUMBER, Status); - } - - ArrayPtr -= 3; // remove trailing comma - ArrayPtr += sprintf(&response[ArrayPtr], "\r\n]}\r\n"); - - return ArrayPtr; -} - -/* -{"Nodes":[ -{"Call":"xx", "Alias":"xx", "Nbour1 ":"xx", "Quality":192), -{ ...}, -{...} -]} -*/ - -extern int MaxNodes; -extern struct DEST_LIST * DESTS; // NODE LIST -extern int DEST_LIST_LEN; - - -int sendNodeList(char * response, char * token, char * param) -{ - int ArrayPtr = 0; - - int count, len, i; - char Normcall[10], Portcall[10]; - char Alias[7]; - struct DEST_LIST * Dests = DESTS ; - // struct ROUTE * Routes; - - Dests = DESTS; - MaxNodes = MAXDESTS; - - ArrayPtr += sprintf(&response[ArrayPtr], "{\"nodes\":[\r\n"); - - Dests-=1; - - for (count = 0; count < MaxNodes; count++) - { - Dests+=1; - - if (Dests->DEST_CALL[0] == 0) - continue; - - len = ConvFromAX25(Dests->DEST_CALL, Normcall); - Normcall[len] = 0; - - memcpy(Alias, Dests->DEST_ALIAS, 6); - - Alias[6]=0; - - for (i=0;i<6;i++) - { - if (Alias[i] == ' ') - Alias[i] = 0; - } - - - ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\":\"%s\", \"Alias\":\"%s\", \"Routes\":[", Normcall, Alias); - - - // Add an array with up to 6 objects (3 NR + 3 INP3 Neighbours - - if (Dests->NRROUTE[0].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[0].ROUT_NEIGHBOUR->INP3Node == 0) - { - len = ConvFromAX25(Dests->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); - Portcall[len] = 0; - - ArrayPtr += sprintf(&response[ArrayPtr], "{\"Call\":\"%s\", \"Port\":%d, \"Quality\":%d},", - Portcall, Dests->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, Dests->NRROUTE[0].ROUT_QUALITY); - - - // if (Dests->NRROUTE[0].ROUT_OBSCOUNT > 127) - // { - // len=sprintf(&line[cursor],"! "); - // cursor+=len; - // } - - - if (Dests->NRROUTE[1].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[1].ROUT_NEIGHBOUR->INP3Node == 0) - { - len=ConvFromAX25(Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); - Portcall[len]=0; - - - - ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\":\"%s\", \"Port\":%d, \"Quality\":%d},", - Portcall, Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, Dests->NRROUTE[1].ROUT_QUALITY); - //if (Dests->NRROUTE[1].ROUT_OBSCOUNT > 127) - //{ - //len=sprintf(&line[cursor],"! "); - //cursor+=len; - //} - - } - - if (Dests->NRROUTE[2].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[2].ROUT_NEIGHBOUR->INP3Node == 0) - { - len=ConvFromAX25(Dests->NRROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); - Portcall[len]=0; - - - ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\":\"%s\", \"Port\":%d, \"Quality\":%d},", - Portcall, Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, Dests->NRROUTE[1].ROUT_QUALITY); - - //if (Dests->NRROUTE[2].ROUT_OBSCOUNT > 127) - //{ - //len=sprintf(&line[cursor],"! "); - //cursor+=len; - - } - ArrayPtr -= 1; // remove comma - } - - ArrayPtr += sprintf(&response[ArrayPtr], "]},\r\n"); - } - - ArrayPtr -= 3; // remove comma - ArrayPtr += sprintf(&response[ArrayPtr], "\r\n]}"); - - return ArrayPtr; -} - - -int sendUserList(char * response, char * token, char * param) -{ - int ArrayPtr = 0; - int n = MAXCIRCUITS; - TRANSPORTENTRY * L4 = L4TABLE; -// TRANSPORTENTRY * Partner; - int MaxLinks = MAXLINKS; - char State[12] = "", Type[12] = "Uplink"; - char LHS[50] = "", MID[10] = "", RHS[50] = ""; -// char Line[100]; - char Normcall[10]; - int len; - - ArrayPtr += sprintf(&response[ArrayPtr], "{\"users\":[\r\n"); - - while (n--) - { - if (L4->L4USER[0]) - { - RHS[0] = MID[0] = 0; - - len = ConvFromAX25(L4->L4USER, Normcall); - Normcall[len] = 0; - - ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\": \"%s\"},\r\n", Normcall); - L4++; - } - } - - if (ArrayPtr == 12) //empty list - { - ArrayPtr -=2; - ArrayPtr += sprintf(&response[ArrayPtr], "]}\r\n"); - } - else - { - ArrayPtr -= 3; // remove trailing comma - ArrayPtr += sprintf(&response[ArrayPtr], "\r\n]}\r\n"); - } - return ArrayPtr; -} - -extern char MYALIASLOPPED[]; -extern char TextVerstring[]; -extern char LOCATOR[]; - -int sendInfo(char * response, char * token, char * param) -{ - char call[10]; - - memcpy(call, MYNODECALL, 10); - strlop(call, ' '); - - sprintf(response, "{\"info\":{\"NodeCall\":\"%s\", \"Alias\":\"%s\", \"Locator\":\"%s\", \"Version\":\"%s\"}}\r\n", - call, MYALIASLOPPED, LOCATOR, TextVerstring); - - return strlen(response); -} - -int sendLinks(char * response, char * token, char * param) -{ - struct _LINKTABLE * Links = LINKS; - int MaxLinks = MAXLINKS; - int count; - char Normcall1[10]; - char Normcall2[10]; - char State[12] = "", Type[12] = "Uplink"; - int axState; - int cctType; - int ReplyLen = 0; - ReplyLen += sprintf(&response[ReplyLen],"{\"links\":[\r\n"); - - for (count=0; countLINKCALL[0] != 0) - { - int len = ConvFromAX25(Links->LINKCALL, Normcall1); - Normcall1[len] = 0; - - len = ConvFromAX25(Links->OURCALL, Normcall2); - Normcall2[len] = 0; - - - axState = Links->L2STATE; - - if (axState == 2) - strcpy(State, "Connecting"); - else if (axState == 3) - strcpy(State, "FRMR"); - else if (axState == 4) - strcpy(State, "Closing"); - else if (axState == 5) - strcpy(State, "Active"); - else if (axState == 6) - strcpy(State, "REJ Sent"); - - cctType = Links->LINKTYPE; - - if (cctType == 1) - strcpy(Type, "Uplink"); - else if (cctType == 2) - strcpy(Type, "Downlink"); - else if (cctType == 3) - strcpy(Type, "Node-Node"); - - - - ReplyLen += sprintf(&response[ReplyLen], "{\"farCall\": \"%s\",\"ourCall\": \"%s\", \"port\": \"%d\", \"state\": \"%s\", \"linkType\": \"%s\", \"ax25Version\": \"%d\"},\r\n", - Normcall1, Normcall2, Links->LINKPORT->PORTNUMBER, - State, Type, 2 - Links->VER1FLAG ); - Links+=1; - } - } - - if (ReplyLen < 13) - ReplyLen -= 2; // no links - else - ReplyLen -= 3; // remove trailing comma - - ReplyLen+= sprintf(&response[ReplyLen], "\r\n]}\r\n"); - - return ReplyLen; -} - -int sendPortMHList(char * response, char * token, char * param) -{ - struct PORTCONTROL * PORTVEC ; - int n; - int port = 0; - - if (param[0] = '?' || param[0] == '/') - port = atoi(¶m[1]); - - PORTVEC = GetPortTableEntryFromPortNum(port); - response[0] = 0; - - if (PORTVEC == 0) - return send_http_response(response, "401 Invalid API Call"); - - n = sprintf(response,"{\"mheard\":[\r\n"); - - BuildPortMH(&response[n], PORTVEC ); - - if (response[n] == 0) // No entries - { - response[strlen(response) - 2] = '\0'; // remove \r\n - strcat(response, "]}\r\n"); - } - else - { - response[strlen(response)-3 ] = '\0'; // remove ,\r\n - strcat(response, "\r\n]}\r\n"); -// printf("MH for port %d:\r\n%s\r\n", PORTVEC->PORTNUMBER, response); - } - return strlen(response); -} - -// WhatsPac configuration interface -// WhatsPac also uses Paula's Remote Host Protocol (RHP). This is in a separate module - -extern int WhatsPacConfigured; - - -int sendWhatsPacState(char * response, char * token, char * param) -{ - if (WhatsPacConfigured) - sprintf(response, "{\"configured\": true}\r\n"); - else - sprintf(response, "{\"configured\": false}\r\n"); - - return strlen(response); -} - - -int sendWhatsPacConfig(char * response, char * token, char * param) -{ - char Template[] = - "{\"MODE\": 0," - "\"RHPPORT\": \"%d\"," - "\"AGWPORT\": \"7000\"," - "\"INTERFACES\": [{\"INTERFACE\": 1,\"PROTOCOL\": \"KISS\",\"TYPE\": \"TCP\",\"IOADDR\": \"127.0.0.1\",\"INTNUM\": 8100}]," - "\"PORTS\": [{\"PORT\": 1,\"ID\": \"RHPPORT\", \"INTERFACENUM\": 1}]}"; - - sprintf(response, Template, HTTPPort); - - return strlen(response); -} - - - - diff --git a/nodeapi.c b/nodeapi.c index 592d92a..538d78d 100644 --- a/nodeapi.c +++ b/nodeapi.c @@ -2,7 +2,6 @@ // Authentication is via Telnet USER records. - #define _CRT_SECURE_NO_DEPRECATE #include "cheaders.h" @@ -26,7 +25,7 @@ typedef struct API { char *URL; int URLLen; - int (* APIRoutine)(char * response, char * token, char * param); + int (* APIRoutine)(char * response, char * token, char * param, int Local); int Auth; } API; @@ -34,7 +33,7 @@ typedef struct API #define AuthNone 0 #define AuthUser 1 -#define Auth BBSUser 2 +#define AuthBBSUser 2 #define AuthSysop 4 // Function prototypes @@ -50,14 +49,14 @@ void add_token_to_list(Token* token); Token* find_token(const char* token); Token* generate_token(); -int sendPortList(char * response, char * token, char * Rest); -int sendNodeList(char * response, char * token, char * Rest); -int sendUserList(char * response, char * token, char * Rest); -int sendInfo(char * response, char * token, char * Rest); -int sendLinks(char * response, char * token, char * Rest); -int sendPortMHList(char * response, char * token, char * Rest); -int sendWhatsPacState(char * response, char * token, char * param); -int sendWhatsPacConfig(char * response, char * token, char * param); +int sendPortList(char * response, char * token, char * Rest, int Local); +int sendNodeList(char * response, char * token, char * Rest, int Local); +int sendUserList(char * response, char * token, char * Rest, int Local); +int sendInfo(char * response, char * token, char * Rest, int Local); +int sendLinks(char * response, char * token, char * Rest, int Local); +int sendPortMHList(char * response, char * token, char * Rest, int Local); +int sendWhatsPacState(char * response, char * token, char * param, int Local); +int sendWhatsPacConfig(char * response, char * token, char * param, int Local); void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT); DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot); @@ -74,8 +73,8 @@ struct API APIList[] = "/api/links", 10, sendLinks, 0, "/api/users", 10, sendUserList, 0, "/api/mheard", 11, sendPortMHList, 0, - "/api/v1/config", 14, sendWhatsPacConfig, 0, - "/api/v1/state", 13, sendWhatsPacState, 0 + "/api/v1/config", 14, sendWhatsPacConfig, AuthSysop, + "/api/v1/state", 13, sendWhatsPacState, AuthSysop }; int APICount = sizeof(APIList) / sizeof(struct API); @@ -159,6 +158,14 @@ int APIProcessHTTPMessage(char * response, char * Method, char * URL, char * req return send_http_response(response, Resp); } + if (strcmp(Method, "POST") == 0) + { + if (_stricmp(URL, "/api/v1/config") == 0) + { + return send_http_response(response, "200 (OK)"); + } + } + if (strcmp(Method, "GET") != 0) return send_http_response(response, "403 (Bad Method)"); @@ -202,7 +209,7 @@ if (token[0] == 0) rest = &request[4 + APIEntry->URLLen]; // Anything following? if (rest[0] == ' ' || rest[0] == '/' || rest[0] == '?') - return APIEntry->APIRoutine(response, token, rest); + return APIEntry->APIRoutine(response, token, rest, LOCAL); } } @@ -349,7 +356,7 @@ int send_http_response(char * response, const char* msg) extern int MasterPort[MAXBPQPORTS+1]; // Pointer to first BPQ port for a specific MPSK or UZ7HO host -int sendPortList(char * response, char * token, char * param) +int sendPortList(char * response, char * token, char * param, int Local) { char * Array = 0; int ArrayLen = 0; @@ -561,7 +568,7 @@ extern struct DEST_LIST * DESTS; // NODE LIST extern int DEST_LIST_LEN; -int sendNodeList(char * response, char * token, char * param) +int sendNodeList(char * response, char * token, char * param, int Local) { int ArrayPtr = 0; @@ -665,7 +672,7 @@ int sendNodeList(char * response, char * token, char * param) } -int sendUserList(char * response, char * token, char * param) +int sendUserList(char * response, char * token, char * param, int Local) { int ArrayPtr = 0; int n = MAXCIRCUITS; @@ -711,7 +718,7 @@ extern char MYALIASLOPPED[]; extern char TextVerstring[]; extern char LOCATOR[]; -int sendInfo(char * response, char * token, char * param) +int sendInfo(char * response, char * token, char * param, int Local) { char call[10]; @@ -724,7 +731,7 @@ int sendInfo(char * response, char * token, char * param) return strlen(response); } -int sendLinks(char * response, char * token, char * param) +int sendLinks(char * response, char * token, char * param, int Local) { struct _LINKTABLE * Links = LINKS; int MaxLinks = MAXLINKS; @@ -789,7 +796,7 @@ int sendLinks(char * response, char * token, char * param) return ReplyLen; } -int sendPortMHList(char * response, char * token, char * param) +int sendPortMHList(char * response, char * token, char * param, int Local) { struct PORTCONTROL * PORTVEC ; int n; @@ -828,8 +835,11 @@ int sendPortMHList(char * response, char * token, char * param) extern int WhatsPacConfigured; -int sendWhatsPacState(char * response, char * token, char * param) +int sendWhatsPacState(char * response, char * token, char * param, int Local) { + if (Local == 0) + return send_http_response(response, "401 Not Authorised"); + if (WhatsPacConfigured) sprintf(response, "{\"configured\": true}\r\n"); else @@ -839,7 +849,7 @@ int sendWhatsPacState(char * response, char * token, char * param) } -int sendWhatsPacConfig(char * response, char * token, char * param) +int sendWhatsPacConfig(char * response, char * token, char * param, int Local) { char Template[] = "{\"MODE\": 0," @@ -848,6 +858,9 @@ int sendWhatsPacConfig(char * response, char * token, char * param) "\"INTERFACES\": [{\"INTERFACE\": 1,\"PROTOCOL\": \"KISS\",\"TYPE\": \"TCP\",\"IOADDR\": \"127.0.0.1\",\"INTNUM\": 8100}]," "\"PORTS\": [{\"PORT\": 1,\"ID\": \"RHPPORT\", \"INTERFACENUM\": 1}]}"; + if (Local == 0) + return send_http_response(response, "401 Not Authorised"); + sprintf(response, Template, HTTPPort); return strlen(response); diff --git a/tncinfo.h b/tncinfo.h index 5840f7c..efbd1a5 100644 --- a/tncinfo.h +++ b/tncinfo.h @@ -871,9 +871,10 @@ typedef struct TNCINFO VOID * zalloc(int len); -BOOL ReadConfigFile(int Port, int ProcLine()); +BOOL ReadConfigFile(int Port, int ProcLine(char * buf, int Port)); int GetLine(char * buf); -BOOL CreatePactorWindow(struct TNCINFO * TNC, char * ClassName, char * WindowTitle, int RigControlRow, WNDPROC WndProc, int Width, int Height, VOID ForcedCloseProc()); +BOOL CreatePactorWindow(struct TNCINFO * TNC, char * ClassName, char * WindowTitle, int RigControlRow, WNDPROC WndProc, + int Width, int Height, VOID ForcedCloseProc(struct TNCINFO * TNC, int Stream)); char * CheckAppl(struct TNCINFO * TNC, char * Appl); BOOL SendReporttoWL2K(struct TNCINFO * TNC); struct WL2KInfo * DecodeWL2KReportLine(char * buf);