diff --git a/.svn/entries b/.svn/entries deleted file mode 100644 index 48082f7..0000000 --- a/.svn/entries +++ /dev/null @@ -1 +0,0 @@ -12 diff --git a/.svn/format b/.svn/format deleted file mode 100644 index 48082f7..0000000 --- a/.svn/format +++ /dev/null @@ -1 +0,0 @@ -12 diff --git a/.svn/pristine/00/0091dc3ec6a47e062a4f7f1c098c31c1e17d2eae.svn-base b/.svn/pristine/00/0091dc3ec6a47e062a4f7f1c098c31c1e17d2eae.svn-base deleted file mode 100644 index 7b44895..0000000 --- a/.svn/pristine/00/0091dc3ec6a47e062a4f7f1c098c31c1e17d2eae.svn-base +++ /dev/null @@ -1,1849 +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 -*/ - -// -// Interface to allow G8BPQ switch to use HSMODEM TNC - - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include - -#ifndef WIN32 -#ifndef MACBPQ -#include -#endif -#endif - - -#include "cheaders.h" - -#pragma pack(1) - -struct BroadcastMsg -{ - unsigned char Type; - unsigned char initialVolTX; - unsigned char initialVolRX; - unsigned char AudioTimespan; - unsigned char intialVolSpeaker; - unsigned char initalVolMic; - unsigned char Retransmits; - unsigned char SendAudio; - unsigned char RTTYAutoSync; - unsigned char Speed; - char playbackDevice[100]; - char captureDevice[100]; - char Callsign[20]; - char Locator[10]; - char Name[20]; -}; - -struct FileHeader -{ - unsigned char Type; - unsigned char Info; // 0 - First, 1 - Continuation 2 Last 3 - Only - char filename[50]; - unsigned short CRC; // of filename = transfer id - unsigned char Size[3]; // Big endian - unsigned char Data[164]; -}; - -struct FileData -{ - unsigned char Type; - unsigned char Info; // 0 - First, 1 - Continuation 2 Last 3 - Only - unsigned char Data[219]; -}; - -#pragma pack() - -struct HSFILEINFO -{ - struct HSFILEINFO * Next; // May want to chain entries for partial files - - char fileName[50]; - unsigned short CRC; // Used as a transfer ID - int fileSize; - int Sequence; - int State; - int Type; - time_t LastRX; - unsigned char goodBlocks[1024]; - unsigned char * Data; - int dataPointer; - int lastBlock; - int lostBlocks; - unsigned char * txData; - int txSize; - int txLeft; -}; - - -struct HSMODEMINFO -{ - struct HSFILEINFO * File; - - int Mode; - char * Capture; // Capture Device Name - char * Playback; // Playback Device Name - int Seq; // To make CRC more Unique - int txFifo; - int rxFifo; - int Sync; - int DCD; -}; - - -int KillTNC(struct TNCINFO * TNC); -int RestartTNC(struct TNCINFO * TNC); - -extern int (WINAPI FAR *GetModuleFileNameExPtr)(); -extern int (WINAPI FAR *EnumProcessesPtr)(); - -#include "bpq32.h" - -#include "tncinfo.h" - -static int Socket_Data(int sock, int error, int eventcode); - -VOID MoveWindows(struct TNCINFO * TNC); -static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen); -int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error); -BOOL HSMODEMWriteCommBlock(struct TNCINFO * TNC); -void HSMODEMCheckRX(struct TNCINFO * TNC); -int HSMODEMSendData(struct TNCINFO * TNC, UCHAR * data, int txlen); -int HSMODEMSendSingleData(struct TNCINFO * TNC, UCHAR * FN, UCHAR * data, int txlen); -int HSMODEMSendCommand(struct TNCINFO * TNC, UCHAR * data); -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); -VOID SendInitScript(struct TNCINFO * TNC); -int HSMODEMGetLine(char * buf); -int ProcessEscape(UCHAR * TXMsg); -BOOL KAMStartPort(struct PORTCONTROL * PORT); -BOOL KAMStopPort(struct PORTCONTROL * PORT); -void SendPoll(struct TNCINFO * TNC); -void SendMode(struct TNCINFO * TNC); - -static char ClassName[]="HSMODEMSTATUS"; -static char WindowTitle[] = "HSMODEM"; -static int RigControlRow = 205; - -#ifndef LINBPQ -#include -#endif - -extern int SemHeldByAPI; - -static RECT Rect; - -static int ProcessLine(char * buf, int Port); - -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - -static int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC = TNCInfo[Port]; - char errbuf[256]; - - strcpy(errbuf, buf); - - ptr = strtok(buf, " \t\n\r"); - - if (ptr == NULL) return (TRUE); - - if (*ptr =='#') return (TRUE); // comment - - if (*ptr ==';') return (TRUE); // comment - - - if (_stricmp(buf, "ADDR")) - return FALSE; // Must start with ADDR - - ptr = strtok(NULL, " \t\n\r"); - - BPQport = Port; - p_ipad = ptr; - - TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); - memset(TNC, 0, sizeof(struct TNCINFO)); - - TNC->HSModemInfo = zalloc(sizeof(struct HSMODEMINFO)); - TNC->HSModemInfo->File = zalloc(sizeof(struct HSFILEINFO)); - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - if (p_ipad == NULL) - p_ipad = strtok(NULL, " \t\n\r"); - - if (p_ipad == NULL) return (FALSE); - - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - WINMORport = atoi(p_port); - - TNC->TCPPort = WINMORport; - - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(WINMORport + 2); // We only receive on Port + 2 - - TNC->HostName = malloc(strlen(p_ipad)+1); - - if (TNC->HostName == NULL) return TRUE; - - strcpy(TNC->HostName,p_ipad); - - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - DecodePTTString(TNC, ptr); - ptr = strtok(NULL, " \t\n\r"); - } - } - } - - if (ptr) - { - if (_memicmp(ptr, "PATH", 4) == 0) - { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); - } - } - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if (_memicmp(buf, "CAPTURE", 7) == 0) - { - TNC->HSModemInfo->Capture = _strdup(&buf[8]); - strlop(TNC->HSModemInfo->Capture, 13); - } - else if (_memicmp(buf, "PLAYBACK", 8) == 0) - { - TNC->HSModemInfo->Playback = _strdup(&buf[9]); - strlop(TNC->HSModemInfo->Playback, 13); - } - else if (_memicmp(buf, "MODE ", 5) == 0) - TNC->HSModemInfo->Mode = atoi(&buf[5]); - else if (_memicmp(buf, "LOGDIR ", 7) == 0) - TNC->LogPath = _strdup(&buf[7]); - else - strcat (TNC->InitScript, buf); - } - - return (TRUE); -} - -static char * Config; -static char * ptr1, * ptr2; - -int HSMODEMGetLine(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 SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - -static time_t ltime; - - - -static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen) -{ - if (TNC->hDevice) - { - // HSMODEM mode. Queue to Hostmode driver - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = EncLen; - memcpy(&buffptr->Data[0], Encoded, EncLen); - - C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr); - TNC->Streams[Stream].FramesQueued++; - - return; - } -} - - -VOID HSMODEMChangeMYC(struct TNCINFO * TNC, char * Call) -{ - UCHAR TXMsg[100]; - int datalen; - - if (strcmp(Call, TNC->CurrentMYC) == 0) - return; // No Change - - strcpy(TNC->CurrentMYC, Call); - - datalen = sprintf(TXMsg, "MYCALL %s\r", Call); - HSMODEMSendCommand(TNC, TXMsg); -} - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - int datalen; - PMSGWITHLEN buffptr; -// char txbuff[500]; - unsigned int bytes,txlen = 0; - UCHAR * TXMsg; - - size_t Param; - int Stream = 0; - HKEY hKey=0; - struct TNCINFO * TNC = TNCInfo[port]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct ScanEntry * Scan; - - if (TNC == NULL) - return 0; // Port not defined - - switch (fn) - { - case 7: - - // 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances - - // G7TAJ's code to record activity for stats display - - if ( TNC->BusyFlags && CDBusy ) - TNC->PortRecord->PORTCONTROL.ACTIVE += 2; - - if ( TNC->PTTState ) - TNC->PortRecord->PORTCONTROL.SENDING += 2; - - if (TNC->CONNECTED) - { - TNC->CONNECTED--; - - if (TNC->CONNECTED == 0) - { - sprintf(TNC->WEB_COMMSSTATE, "Connection to HSMODEM lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - } - - TNC->PollDelay++; - - if (TNC->PollDelay > 20) - { - TNC->PollDelay = 0; - - SendPoll(TNC); - } - - return 0; - - case 1: // poll - - HSMODEMCheckRX(TNC); - - while (TNC->PortRecord->UI_Q) - { - int datalen; - char * Buffer; - char FECMsg[512]; - char Call[12] = " "; - struct _MESSAGE * buffptr; - int CallLen; - char * ptr = FECMsg; - - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - -/* if (TNC->CONNECTED == 0 || - TNC->Streams[0].Connecting || - TNC->Streams[0].Connected) - { - // discard if TNC not connected or sesison active - - ReleaseBuffer(buffptr); - continue; - } -*/ - datalen = buffptr->LENGTH - MSGHDDRLEN; - Buffer = &buffptr->DEST[0]; // Raw Frame - Buffer[datalen] = 0; - - // Frame has ax.25 format header. Convert to Text - - CallLen = ConvFromAX25(Buffer + 7, Call); // Origin - memcpy(ptr, Call, CallLen); - ptr += CallLen; - - *ptr++ = '!'; - - CallLen = ConvFromAX25(Buffer, Call); // Dest - memcpy(ptr, Call, CallLen); - ptr += CallLen; - - Buffer += 14; // TO Digis - datalen -= 14; - - while ((Buffer[-1] & 1) == 0) - { - *ptr++ = ','; - CallLen = ConvFromAX25(Buffer, Call); - memcpy(ptr, Call, CallLen); - ptr += CallLen; - Buffer += 7; // End of addr - datalen -= 7; - } - - *ptr++ = '_'; - *ptr++ = 'U'; // UI Frame - *ptr++ = 0; // delimit calls - - if (Buffer[0] == 3) // UI - { - Buffer += 2; - datalen -= 2; - } - - HSMODEMSendSingleData(TNC, FECMsg, Buffer, datalen); - - ReleaseBuffer(buffptr); - } - - - if (TNC->DiscPending) - { - TNC->DiscPending--; - - if (TNC->DiscPending == 0) - { - // Too long in Disc Pending - Kill and Restart TNC - } - } - - - for (Stream = 0; Stream <= 2; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->NeedDisc) - { - STREAM->NeedDisc--; - - if (STREAM->NeedDisc == 0) - { - // Send the DISCONNECT - - HSMODEMSendCommand(TNC, "DISCONNECT\r"); - } - } - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] && STREAM->Attached == 0) - { - // New Attach - - int calllen; - char Msg[80]; - - Debugprintf("HSMODEM New Attach Stream %d", Stream); - - STREAM->Attached = TRUE; - - calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, TNC->Streams[Stream].MyCall); - TNC->Streams[Stream].MyCall[calllen] = 0; - - - HSMODEMChangeMYC(TNC, TNC->Streams[0].MyCall); - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - //sprintf(TNC->WEB_TNCSTATE, "In Use by %s", TNC->Streams[0].MyCall); - //MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Stop Scanning - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command( (TRANSPORTENTRY *) -1, Msg); - } - - if (STREAM->Attached) - CheckForDetach(TNC, Stream, STREAM, TidyClose, ForcedClose, CloseComplete); - - } - - // See if any frames for this port - - for (Stream = 0; Stream <= 2; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->BPQtoPACTOR_Q) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)Q_REM(&STREAM->BPQtoPACTOR_Q); - UCHAR * data = &buffptr->Data[0]; - STREAM->FramesQueued--; - txlen = (int)buffptr->Len; - STREAM->bytesTXed += txlen; - - bytes=HSMODEMSendData(TNC, data, txlen); - WritetoTrace(TNC, data, txlen); - } - - if (STREAM->PACTORtoBPQ_Q != 0) - { - buffptr = (PMSGWITHLEN)Q_REM(&STREAM->PACTORtoBPQ_Q); - - datalen = (int)buffptr->Len; - - buff->PORT = Stream; // Compatibility with Kam Driver - 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); - } - - if (STREAM->ReportDISC) // May need a delay so treat as a counter - { - STREAM->ReportDISC--; - if (STREAM->ReportDISC == 0) - { - buff->PORT = Stream; -// STREAM->Connected = 0; -// STREAM->Attached = 0; - return -1; - } - } - } - return (0); - - case 2: // send - - Stream = buff->PORT; - - if (!TNC->CONNECTED) - { - // Send Error Response - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = 21; - memcpy(&buffptr->Data[0], "No Connection to TNC\r", 21); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return 0; // Don't try if not connected - } - - STREAM = &TNC->Streams[Stream]; - - if (TNC->SwallowSignon) - { - TNC->SwallowSignon = FALSE; // Discard *** connected - return 0; - } - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - TXMsg = &buff->L2DATA[0]; - TXMsg[txlen] = 0; - - // for now just send, but allow sending control - // characters with \\ or ^ escape - - if (STREAM->Connected) - { - STREAM->PacketsSent++; - - bytes=HSMODEMSendData(TNC, TXMsg, txlen); - TNC->Streams[Stream].BytesOutstanding += bytes; // So flow control works - will be updated by BUFFER response - STREAM->bytesTXed += bytes; -// WritetoTrace(TNC, &buff->L2DATA[0], txlen); - - return 1; - } - - if (_memicmp(&buff->L2DATA[0], "D\r", 2) == 0 || _memicmp(&buff->L2DATA[0], "BYE\r", 4) == 0) - { - STREAM->ReportDISC = TRUE; // Tell Node - return 0; - } - - - // See if Local command (eg RADIO) - - if (_memicmp(&buff->L2DATA[0], "RADIO ", 6) == 0) - { - char cmd[56]; - - strcpy(cmd, &buff->L2DATA[6]); - sprintf(&buff->L2DATA[0], "%d %s", TNC->Port, cmd); - - - if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK, &buff->L2DATA[0])) - { - } - else - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return 1; // No buffers, so ignore - - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", &buff->L2DATA[0]); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return 1; - } - - if (_memicmp(&buff->L2DATA[0], "OVERRIDEBUSY", 12) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - TNC->OverrideBusy = TRUE; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "HSMODEM} OK\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - if (_memicmp(&buff->L2DATA[0], "MODE ", 5) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - TNC->HSModemInfo->Mode = atoi(&buff->L2DATA[5]); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "HSMODEM} OK\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - SendMode(TNC); - - return 0; - - } - - - // See if a Connect Command. If so, start codec and set Connecting - - if (toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect - { - char Connect[80]; - char * ptr = strchr(&buff->L2DATA[2], 13); - - if (ptr) - *ptr = 0; - - _strupr(&buff->L2DATA[2]); - - if (strlen(&buff->L2DATA[2]) > 9) - buff->L2DATA[11] = 0; - - txlen = sprintf(Connect, "C %s\r", &buff->L2DATA[2]); - - HSMODEMChangeMYC(TNC, TNC->Streams[0].MyCall); - - // See if Busy - - if (InterlockedCheckBusy(TNC)) - { - // Channel Busy. Unless override set, wait - - if (TNC->OverrideBusy == 0) - { - // Save Command, and wait up to 10 secs - - sprintf(TNC->WEB_TNCSTATE, "Waiting for clear channel"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - TNC->ConnectCmd = _strdup(Connect); - TNC->BusyDelay = TNC->BusyWait * 10; // BusyWait secs - return 0; - } - } - - TNC->OverrideBusy = FALSE; - - memset(TNC->Streams[0].RemoteCall, 0, 10); - strcpy(TNC->Streams[0].RemoteCall, &buff->L2DATA[2]); - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", STREAM->MyCall, STREAM->RemoteCall); - HSMODEMSendCommand(TNC, Connect); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = TRUE; - return 0; - - } - - // Normal data. Send to TNC - - - HSMODEMSendData(TNC, TXMsg, txlen); - - return 0; - - case 3: - - // CHECK IF OK TO SEND (And check TNC Status) - - Stream = (int)(size_t)buff; - - // I think we should check buffer space for all comms modes - - { - int Queued; - int Outstanding = TNC->Streams[Stream].BytesOutstanding; - - if (Stream == 0) - Queued = TNC->Streams[13].FramesQueued; // ARDOP Native Mode Send Queue - else - Queued = TNC->Streams[Stream].FramesQueued; - - Outstanding = Queued = 0; - - if (Queued > 4 || Outstanding > 8500) - return (1 | (TNC->HostMode | TNC->CONNECTED) << 8 | STREAM->Disconnecting << 15); - } - - if (TNC->Streams[Stream].Attached == 0) - return (TNC->CONNECTED != 0) << 8 | 1; - - return ((TNC->CONNECTED != 0) << 8 | TNC->Streams[Stream].Disconnecting << 15); // OK - - - case 4: // reinit7 - - return 0; - - case 5: // Close - - return 0; - - case 6: // Scan Stop Interface - - Param = (size_t)buff; - - if (Param == 2) // Check Permission (Shouldn't happen) - { - Debugprintf("Scan Check Permission called on ARDOP"); - return 1; // OK to change - } - - if (Param == 1) // Request Permission - { - if (!TNC->CONNECTED) - return 0; // No connection so no interlock - - if (TNC->ConnectPending == 0 && TNC->PTTState == 0) - { - HSMODEMSendCommand(TNC, "CONOK OFF"); - TNC->GavePermission = TRUE; - return 0; // OK to Change - } - - if (TNC->ConnectPending) - TNC->ConnectPending--; // Time out if set too long - - return TRUE; - } - - if (Param == 3) // Release Permission - { - if (TNC->GavePermission) - { - TNC->GavePermission = FALSE; - if (TNC->ARDOPCurrentMode[0] != 'S') // Skip - HSMODEMSendCommand(TNC, "CONOK ON"); - } - return 0; - } - - // Param is Address of a struct ScanEntry - - Scan = (struct ScanEntry *)buff; - return 0; - } - return 0; -} - -VOID HSMODEMReleaseTNC(struct TNCINFO * TNC) -{ - // Set mycall back to Node or Port Call, and Start Scanner - - UCHAR TXMsg[1000]; - - HSMODEMChangeMYC(TNC, TNC->NodeCall); - - // Start Scanner - - sprintf(TXMsg, "%d SCANSTART 15", TNC->Port); - - Rig_Command( (TRANSPORTENTRY *) -1, TXMsg); - - ReleaseOtherPorts(TNC); - -} - -VOID HSMODEMSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC) -{ - HSMODEMSendCommand(TNC, "CONOK OFF\r"); -} - -VOID HSMODEMReleasePort(struct TNCINFO * TNC) -{ - HSMODEMSendCommand(TNC, "CONOK ON\r"); -} - - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, "" - "" - "VARA Status" - "

HSMODEM Status" - "

", - TNC->Port); - - - Len += sprintf(&Buff[Len], ""); - - Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); - Len += sprintf(&Buff[Len], "", TNC->WEB_CHANSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_PROTOSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); -// Len += sprintf(&Buff[Len], "", TNC->WEB_RESTARTS); - Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Channel State%s
Proto State%s
Traffic%s
TNC Restarts
"); - - Len += sprintf(&Buff[Len], "", TNC->WebBuffer); - Len = DoScanLine(TNC, Buff, Len); - - return Len; -} - -#ifndef LINBPQ - -#define BGCOLOUR RGB(236,233,216) -HBRUSH RedBrush = NULL; -HBRUSH GreenBrush; -HBRUSH BlueBrush; -static HBRUSH bgBrush = NULL; - -extern HWND ClientWnd, FrameWnd; -extern int OffsetH, OffsetW; - -extern HMENU hMainFrameMenu; -extern HMENU hBaseMenu; -extern HANDLE hInstance; - -extern HKEY REGTREE; - - - -static LRESULT CALLBACK PacWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - MINMAXINFO * mmi; - PAINTSTRUCT ps; - HDC hdc; - - int i; - struct TNCINFO * TNC; - - HKEY hKey; - char Key[80]; - int retCode, disp; - - for (i=0; i<41; 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_CREATE: - - break; - - case WM_PAINT: - - hdc = BeginPaint(hWnd, &ps); - - TextOut(hdc, 10, 162, "RX", 4); - TextOut(hdc, 10, 182, "TX", 4); - - if (TNC->HSModemInfo->Sync) - TextOut(hdc, 305, 162, "Sync", 4); - -// SelectObject(ps.hdc, RedBrush); - SelectObject(ps.hdc, GreenBrush); -// SelectObject(ps.hdc, GetStockObject(GRAY_BRUSH)); - - Rectangle(ps.hdc, 40, 165, TNC->HSModemInfo->rxFifo + 42, 175); - SelectObject(ps.hdc, RedBrush); - Rectangle(ps.hdc, 40, 185, (TNC->HSModemInfo->txFifo * 10) + 42, 195); - - EndPaint(hWnd, &ps); - break; - - case WM_GETMINMAXINFO: - - if (TNC->ClientHeight) - { - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = TNC->ClientWidth; - mmi->ptMaxSize.y = TNC->ClientHeight; - mmi->ptMaxTrackSize.x = TNC->ClientWidth; - mmi->ptMaxTrackSize.y = TNC->ClientHeight; - } - - break; - - - case WM_MDIACTIVATE: - { - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - - if (TNC->hMenu) - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)TNC->hMenu, "Actions"); - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - -// SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) TNC->hMenu, (LPARAM) TNC->hWndMenu); - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - // call DrawMenuBar after the menu items are set - DrawMenuBar(FrameWnd); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - } - - - - case WM_INITMENUPOPUP: - - if (wParam == (WPARAM)TNC->hMenu) - { - if (TNC->ProgramPath) - { - if (strstr(TNC->ProgramPath, " TNC") || strstr(TNC->ProgramPath, "ARDOP") || strstr(TNC->ProgramPath, "VARA")) - { - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_ENABLED); - - break; - } - } - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_GRAYED); - } - - break; - - case WM_COMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - case WINMOR_KILL: - - KillTNC(TNC); - break; - - case WINMOR_RESTART: - - KillTNC(TNC); - RestartTNC(TNC); - break; - - case WINMOR_RESTARTAFTERFAILURE: - - TNC->RestartAfterFailure = !TNC->RestartAfterFailure; - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", TNC->Port); - - retCode = RegCreateKeyEx(REGTREE, Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - RegSetValueEx(hKey,"TNC->RestartAfterFailure",0,REG_DWORD,(BYTE *)&TNC->RestartAfterFailure, 4); - RegCloseKey(hKey); - } - break; - - case ARDOP_ABORT: - - if (TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SIZING: - case WM_SIZE: - - MoveWindows(TNC); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - - case SC_RESTORE: - - TNC->Minimized = FALSE; - break; - - case SC_MINIMIZE: - - TNC->Minimized = TRUE; - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - 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_DESTROY: - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); -} -#endif - - - -VOID * HSMODEMExtInit(EXTPORTDATA * PortEntry) -{ - int port; - char Msg[255]; - char * ptr; - struct TNCINFO * TNC; - char * TempScript; - u_long param = 1; - int ret; - - port=PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - - TNC = TNCInfo[port]; - - if (TNC == NULL) - { - // Not defined in Config file - - sprintf(Msg," ** Error - no info in BPQ32.cfg for this port\n"); - WritetoConsole(Msg); - - return ExtProc; - } - -#ifndef LINBPQ - - if (bgBrush == NULL) - { - bgBrush = CreateSolidBrush(BGCOLOUR); - RedBrush = CreateSolidBrush(RGB(255,0,0)); - GreenBrush = CreateSolidBrush(RGB(0,255,0)); - BlueBrush = CreateSolidBrush(RGB(0,0,255)); - } - -#endif - - Consoleprintf("HSMODEM Host %s %d", TNC->HostName, TNC->TCPPort); - - TNC->Port = port; - TNC->PortRecord = PortEntry; - - TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_HSMODEM; - - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) - memcpy(TNC->NodeCall, MYNODECALL, 10); - else - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - - if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) - TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; - - PortEntry->PORTCONTROL.PROTOCOL = 10; - PortEntry->PORTCONTROL.PORTQUALITY = 0; - - if (TNC->PacketChannels > 1) - TNC->PacketChannels = 1; - - PortEntry->MAXHOSTMODESESSIONS = TNC->PacketChannels + 1; - - PortEntry->SCANCAPABILITIES = SIMPLE; // Scan Control - pending connect only - PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream - - PortEntry->PORTCONTROL.UICAPABLE = TRUE; - - if (PortEntry->PORTCONTROL.PORTPACLEN == 0) - PortEntry->PORTCONTROL.PORTPACLEN = 236; - - TNC->SuspendPortProc = HSMODEMSuspendPort; - TNC->ReleasePortProc = HSMODEMReleasePort; - - PortEntry->PORTCONTROL.PORTSTARTCODE = KAMStartPort; - PortEntry->PORTCONTROL.PORTSTOPCODE = KAMStopPort; - - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - // Set Essential Params and MYCALL - - // Put overridable ones on front, essential ones on end - - TempScript = zalloc(1000); - - // cant think of any yet - - if (TNC->InitScript) - { - strcat(TempScript, TNC->InitScript); - free(TNC->InitScript); - } - - TNC->InitScript = TempScript; - - // Set MYCALL - - sprintf(Msg, "MYCALL %s\r", TNC->NodeCall); - strcat(TNC->InitScript, Msg); - - strcpy(TNC->CurrentMYC, TNC->NodeCall); - - if (TNC->WL2K == NULL) - if (PortEntry->PORTCONTROL.WL2KInfo.RMSCall[0]) // Alrerady decoded - TNC->WL2K = &PortEntry->PORTCONTROL.WL2KInfo; - - PortEntry->PORTCONTROL.TNC = TNC; - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 520; - TNC->WebWinY = 500; - TNC->WebBuffer = zalloc(5000); - - TNC->WEB_COMMSSTATE = zalloc(100); - TNC->WEB_TNCSTATE = zalloc(100); - TNC->WEB_CHANSTATE = zalloc(100); - TNC->WEB_BUFFERS = zalloc(100); - TNC->WEB_PROTOSTATE = zalloc(100); - TNC->WEB_RESTARTTIME = zalloc(100); - TNC->WEB_RESTARTS = zalloc(100); - - TNC->WEB_MODE = zalloc(20); - TNC->WEB_TRAFFIC = zalloc(100); - - -#ifndef LINBPQ - - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 500, 450, ForcedClose); - - CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,6,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,6,386,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,28,106,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,28,520,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,50,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,50,200,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Channel State", WS_CHILD | WS_VISIBLE, 10,72,110,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_CHANSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,72,144,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Proto State", WS_CHILD | WS_VISIBLE,10,94,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_PROTOSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,94,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,116,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "0 0 0 0", WS_CHILD | WS_VISIBLE,116,116,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "TNC Restarts", WS_CHILD | WS_VISIBLE,10,138,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTS = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE,116,138,20,20 , TNC->hDlg, NULL, hInstance, NULL); - CreateWindowEx(0, "STATIC", "Last Restart", WS_CHILD | WS_VISIBLE,140,138,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTTIME = CreateWindowEx(0, "STATIC", "Never", WS_CHILD | WS_VISIBLE,250,138,200,20, TNC->hDlg, NULL, hInstance, NULL); - - TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, - 0,170,250,300, TNC->hDlg, NULL, hInstance, NULL); - - TNC->ClientHeight = 450; - TNC->ClientWidth = 500; - - TNC->hMenu = CreatePopupMenu(); - - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_KILL, "Kill VARA TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTART, "Kill and Restart VARA TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTARTAFTERFAILURE, "Restart TNC after failed Connection"); - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - AppendMenu(TNC->hMenu, MF_STRING, ARDOP_ABORT, "Abort Current Session"); - - MoveWindows(TNC); -#endif - - - // Open and bind UDP socket - - TNC->TCPSock = socket(AF_INET,SOCK_DGRAM,0); - - if (TNC->TCPSock == INVALID_SOCKET) - { - WritetoConsole("Failed to create UDP socket for HSMODEM"); - ret = WSAGetLastError(); - } - else - ioctl (TNC->TCPSock, FIONBIO, ¶m); - - ret = bind(TNC->TCPSock, (struct sockaddr *) &TNC->destaddr, sizeof(struct sockaddr_in)); - - if (ret != 0) - { - // Bind Failed - - ret = WSAGetLastError(); - sprintf(Msg, "Bind Failed for UDP port %d - error code = %d", TNC->TCPPort + 2, ret); - WritetoConsole(Msg); - } - - -// SendInitScript(TNC); - - time(&TNC->lasttime); // Get initial time value - - return ExtProc; -} - - -VOID TidyClose(struct TNCINFO * TNC, int Stream) -{ - // If all acked, send disc - - if (TNC->Streams[Stream].BytesOutstanding == 0) - HSMODEMSendCommand(TNC, "DISCONNECT\r"); -} - -VOID ForcedClose(struct TNCINFO * TNC, int Stream) -{ - HSMODEMSendCommand(TNC, "DISCONNECT\r"); -} - - - -VOID CloseComplete(struct TNCINFO * TNC, int Stream) -{ - if (Stream == 0) - { - HSMODEMReleaseTNC(TNC); - } -} - -VOID HSMODEMAbort(struct TNCINFO * TNC) -{ - HSMODEMSendCommand(TNC, "ABORT\r"); -} - -// Host Mode Stuff (we reuse some routines in SCSPactor) - -VOID HSMODEMDoTermModeTimeout(struct TNCINFO * TNC) -{ - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->ReinitState == 0) - { - //Checking if in Terminal Mode - Try to set back to Term Mode - - TNC->ReinitState = 1; - return; - } - - if (TNC->ReinitState == 1) - { - // Forcing back to Term Mode - - TNC->ReinitState = 0; - return; - } - - if (TNC->ReinitState == 3) - { - return; - } -} - -RECT Rect1 = {30, 160, 400, 195}; - - -VOID HSMODEMProcessTNCMessage(struct TNCINFO * TNC, unsigned char * Msg, int Len) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FileHeader * FH; - struct HSMODEMINFO * Modem = TNC->HSModemInfo; - struct HSFILEINFO * Info = Modem->File; - int fileLen, Seq, Offset; - - // Any message indicates Ok - - Msg[Len] = 0; - - if (TNC->CONNECTED == 0) - { - // Just come up - - sprintf(TNC->WEB_COMMSSTATE, "Connected to HSMODEM"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - SendMode(TNC); - } - - TNC->CONNECTED = 100; // time out after 10 secs - - /* - 3: responses to broadcast messages (see: GUI Interface: UDP/IP/Initialization) - 1: received payload data - 4: FFT data for a spectrum monitor - 5: IQ data for a constellation display - 6: received RTTY characters - */ - switch (Msg[0]) - { - case 1: - /* - Byte 0 ... 0x01 - Byte 1 ... frame type (which was inserted by the sender) - Byte 2 ... frame counter MSB - Byte 3 ... frame counter LSB (10 bits used) - Byte 4 ... frame information (which was inserted by the sender) - Byte 5 ... unused - Byte 6 ... measured line speed MSB - Byte 7 ... measured line speed LSB - Bytes 8-10 ... unused - Bytes 11-229 ... 219 bytes payload return; - - 1 … BER Test Pattern - 2 … Image - 3 … Ascii File - 4 … HTML File - 5 … Binary File - 6 … Voice Audio (for Codec 2 or Opus) - 7 … UserInfo - */ - - Seq = Msg[2] << 8 | Msg[3]; - - switch (Msg[1]) - { - case 1: - case 6: - case 7: - - Debugprintf("%d %d %02x %s %s %s", Msg[1], Seq, Msg[4], &Msg[11], &Msg[31], &Msg[41]); - return; - - case 2: - case 3: - case 4: - case 5: - - // File transfer types - - switch (Msg[4]) - { - case 0: - case 3: - - // File Header - - FH = (struct FileHeader *) &Msg[9]; - - if (FH->CRC == Info->CRC) - { - Debugprintf("Dup Header %X", Info->CRC); - return; - } - - Info->CRC = FH->CRC; - - fileLen = FH->Size[0] * 65536 + FH->Size[1] * 256 + FH->Size[2]; - - Info->Data = zalloc(fileLen + 512); - - if (Info->Data == NULL) - return; - - Info->fileSize = fileLen; - strcpy(Info->fileName, FH->filename); - - memset(Info->goodBlocks, 0, 1024); - Info->goodBlocks[0] = 1; - - Info->lastBlock = 0; - Info->lostBlocks = 0; - Info->LastRX = time(NULL); - - Debugprintf("%d %d %04X %02x %s %d %s", Msg[1], Seq, FH->CRC, Msg[4], - FH->filename, fileLen, FH->Data); - - memcpy(Info->Data, FH->Data, 164); - Info->dataPointer = 164; - break; - - case 1: - case 2: - - // Data Frame - - if (Seq == Info->lastBlock) - { - Debugprintf("Duplicate data frame %d", Seq); - return; - } - - Info->lastBlock++; - - if (Info->lastBlock != Seq) - Info->lostBlocks += Seq - Info->lastBlock; - - Info->goodBlocks[Seq] = 1; - - Offset = (Seq - 1) * 221 + 164; - - memcpy(&Info->Data[Offset], &Msg[11], 221); - - Debugprintf("%d %d %02x %s %d %s", Msg[1], Seq, Msg[4], &Msg[11]); - break; - - default: - - Debugprintf("%d %d %02x %s %d %s", Msg[1], Seq, Msg[4], &Msg[11]); - return; - - } - - // End of Data Frame Case - - if (Msg[4] == 2 || Msg[4] == 3) - { - // Last Frame - check file - - if (Info->lostBlocks == 0) - { - // filename is encoding of calls and frame type - - struct _MESSAGE * buffptr; - -// FILE * fp1 = fopen(Info->fileName, "wb"); -// int WriteLen; - -// if (fp1) -// { -// WriteLen = (int)fwrite(Info->Data, 1, Info->fileSize, fp1); -// fclose(fp1); -// } - - if (strchr(Info->fileName, '!')) - { - // Callsigns encoded in filename - - - - char * Origin = &Info->fileName[0]; - char * Type = strlop(Origin, '_'); - char * Dest = strlop(Origin, '!'); - unsigned char * Packet; - - - // Convert to ax.25 format - - buffptr = GetBuff(); - - // Convert to ax.25 format - - if (buffptr == 0) - return; // No buffers, so ignore - - Type = strlop(Origin, '_'); - - Packet = &buffptr->ORIGIN[0]; - - buffptr->PORT = TNC->Port; - buffptr->LENGTH = 16 + MSGHDDRLEN + Info->fileSize; - - ConvToAX25(Origin, buffptr->ORIGIN); - ConvToAX25(Dest, buffptr->DEST); - - - while (strchr(Dest, ',')) - { - Dest = strlop(Dest, ','); // Next digi - Packet += 7; - ConvToAX25(Dest, Packet); - buffptr->LENGTH += 7; - } - - Packet[6] |= 1; // Set end of address - - Packet += 7; - - *(Packet++) = 3; - *(Packet++) = 0xF0; - - memcpy(Packet, Info->Data, Info->fileSize); - time(&buffptr->Timestamp); - - BPQTRACE((MESSAGE *)buffptr, TRUE); - } - } - - return; - } - } - - return; - - case 4: // FFT data for a spectrum monitor - - Modem->txFifo = Msg[1]; - Modem->rxFifo = Msg[2]; - Modem->DCD = Msg[3]; - Modem->Sync = Msg[4]; - -#ifndef LINBPQ - InvalidateRect(TNC->hDlg, &Rect1, TRUE); -#endif - -// if (Info->Sync || Info->txFifo) -// Debugprintf("%d %d %d %d", Info->txFifo, Info->rxFifo, Info->DCD, Info->Sync); - /* - Byte 0 ... 0x04 - Byte 1 ... usage of the TX fifo (used by the transmitter to sync its data - output to the modem). This is a value between 0..255. During - an active transmission keep it above 4. - Byte 2 ... usage of RX fifo (not important, but can be displayed to the - user). A very high RX fifo usage indicates the the computer - is too slow for HSmodem. - Byte 3 ... 0 or 1. Indicates that an RF level was detected - Byte 4 ... 0 or 1. Indicates that the HSmodem receiver is synchronized - with a signal - Byte 5 ... maximum audio level (0..100%) of the audio input from the - transceiver. Can be used to detect clipping. - Byte 6 ... maximum audio level (0..100%) of the audio output to the - transceiver. Can be used to detect clipping. - Byte 7 ... in RTTY mode this is the auto-locked RTTY frequency MSB - Byte 8 ... and LSB - Byte 9 ... RTTY: 0=tx off, 1=txon - Byte 10 to the end ... FFT spectrum data, beginning at 0 Hz to 4kHz with - a resolution of 10 Hz -*/ - return; - - - case 5: // IQ data for a constellation display - return; - - case 6: //received RTTY characters - return; - } - - return; - - - buffptr = GetBuff(); - - if (buffptr == 0) - { - return; // No buffers, so ignore - } - - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", TNC->RXBuffer); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - -} - -extern char LOC[7]; - -void SendMode(struct TNCINFO * TNC) -{ - unsigned char Msg[221] = ""; - int ret; - - Msg[0] = 16; - Msg[1] = TNC->HSModemInfo->Mode; - - TNC->destaddr.sin_port = htons(TNC->TCPPort + 1); // Data Port - TNC->destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - - ret = sendto(TNC->TCPSock, (char *)&Msg, 221, 0, (struct sockaddr *)&TNC->destaddr, sizeof(struct sockaddr)); - - return; -} - -void SendPoll(struct TNCINFO * TNC) -{ - struct BroadcastMsg PollMsg = {0x3c, 100, 100, 0, 50, 50, 1, 0, 0, 9}; - int ret; - - strcpy(&PollMsg.captureDevice[0], TNC->HSModemInfo->Capture); - strcpy(&PollMsg.playbackDevice[0], TNC->HSModemInfo->Playback); -// strcpy(&PollMsg.playbackDevice[0], "CABLE Input (VB-Audio Virtual Cable)"); - - strcpy(&PollMsg.Callsign[0], TNC->NodeCall); - strcpy(&PollMsg.Locator[0], LOC); - strcpy(&PollMsg.Name[0], "1234567890"); - - TNC->destaddr.sin_port = htons(TNC->TCPPort); // Command Port - TNC->destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - - ret = sendto(TNC->TCPSock, (char *)&PollMsg, 260, 0, (struct sockaddr *)&TNC->destaddr, sizeof(struct sockaddr)); - - return; -} -/* - unsigned char Type; - unsigned char Info; // 0 - First, 1 - Continuation 2 Last 3 - Only - char filename[50]; - unsigned short CRC; // of filename = transfer id - unsigned char Size[3]; // Big endian - unsigned char Data[163]; -*/ - -unsigned short int compute_crc(unsigned char *buf,int len); - -int HSMODEMSendSingleData(struct TNCINFO * TNC, UCHAR * FN, UCHAR * data, int txlen) -{ - struct FileHeader Msg; - unsigned short int crc; - int ret, fragLen = txlen; - struct HSMODEMINFO * Modem = TNC->HSModemInfo; - struct HSFILEINFO * Info = Modem->File; - - char Seq[60] = ""; - - sprintf(Seq, "%04X%s", Modem->Seq++, FN); - - crc = compute_crc(Seq, 60); - - crc ^= 0xffff; - - memset(&Msg, 0, sizeof(struct FileHeader)); - - Msg.Type = 5; // Binary Data - Msg.Info = 3; // Only Fragment - - if (txlen > 163) - { - // Need to send as multiple fragments - - fragLen = 164; - Info->txData = malloc(txlen + 512); - memcpy(Info->txData, data, txlen); - Info->txSize = txlen; - Info->txLeft = txlen - 164; - Msg.Info = 0; // First Fragment - } - - strcpy(Msg.filename, FN); - memcpy(Msg.Data, data, txlen); - memcpy(&Msg.CRC, &crc, 2); - Msg.Size[0] = txlen >> 16; - Msg.Size[1] = txlen >> 8;; - Msg.Size[2] = txlen; - - TNC->destaddr.sin_port = htons(TNC->TCPPort + 1); // Data Port - TNC->destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - - ret = sendto(TNC->TCPSock, (char *)&Msg, 221, 0, (struct sockaddr *)&TNC->destaddr, sizeof(struct sockaddr)); - memset(&Msg, 0, sizeof(struct FileHeader)); - - return ret; -} - -int HSMODEMSendData(struct TNCINFO * TNC, UCHAR * data, int txlen) -{ - struct FileHeader Msg; - - memset(&Msg, 0, sizeof(struct FileHeader)); - - Msg.Type = 5; // Binary Data - Msg.Info = 3; // Only Fragment - - - return 0; -} - -void HSMODEMCheckRX(struct TNCINFO * TNC) -{ - int Len = 0; - unsigned char Buff[2000]; - - struct sockaddr_in rxaddr; - int addrlen = sizeof(struct sockaddr_in); - - Len = recvfrom(TNC->TCPSock, Buff, 2000, 0, (struct sockaddr *)&rxaddr, &addrlen); - - while (1) - { - if (Len == -1) - { -// Debugprintf("%d", GetLastError()); - Len = 0; - return; - } - TNC->RXLen = Len; - HSMODEMProcessTNCMessage(TNC, Buff, Len); - - Len = recvfrom(TNC->TCPSock, Buff, 2000, 0, (struct sockaddr *)&rxaddr, &addrlen); - - } - return; - - return; -} - -int HSMODEMWriteCommBlock(struct TNCINFO * TNC) -{ - if (TNC->hDevice) - return WriteCOMBlock(TNC->hDevice, TNC->TXBuffer, TNC->TXLen); - - return 0; -} - - -int HSMODEMSendCommand(struct TNCINFO * TNC, UCHAR * data) -{ - if (TNC->hDevice) - return WriteCOMBlock(TNC->hDevice, data, (int)strlen(data)); - - return 0; -} - - \ No newline at end of file diff --git a/.svn/pristine/00/00f45c26df7e4f1074cf4c08420c9395d2189e16.svn-base b/.svn/pristine/00/00f45c26df7e4f1074cf4c08420c9395d2189e16.svn-base deleted file mode 100644 index 714e04d..0000000 --- a/.svn/pristine/00/00f45c26df7e4f1074cf4c08420c9395d2189e16.svn-base +++ /dev/null @@ -1,216 +0,0 @@ -// Includes code from MiniUPnPc, used subject to the following conditions: - -/* - -MiniUPnPc -Copyright (c) 2005-2020, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#define MINIUPNP_STATICLIB - -#include -#ifdef _WIN32 -#include "upnpcommands.h" -#include "miniupnpc.h" -#include "upnperrors.h" -#include -#endif -#ifdef LINBPQ -#ifndef MACBPQ -#ifndef WIN32 -#include -#include -#include -#include -#endif -#endif -#endif -#ifdef MACBPQ -#include -#include -#include -#include -#endif -int AddMap(char * controlURL, char * eport, char * iport, char * proto); -int DeleteMap(char * controlURL, char * eport, char * iport, char * proto); - -void Consoleprintf(const char * format, ...); - -struct UPNP -{ - struct UPNP * Next; - char * Protocol; - char * LANport; - char * WANPort; -}; - -extern struct UPNP * UPNPConfig; - -char * controlURL = 0; -char * servicetype = 0; -char iaddr[] = "IP"; -char * inClient = NULL; -#ifdef LINBPQ -char desc[] = "LinBPQ "; -#else -char desc[] = "BPQ32 "; -#endif -char * remoteHost = NULL; -char * leaseDuration = NULL; - -struct UPNPDev * devlist = 0; -char lanaddr[64] = "unset"; /* my ip address on the LAN */ -char wanaddr[64] = "unset"; /* my ip address on the LAN */ -struct UPNPUrls urls; -struct IGDdatas data; - -int i; -const char * rootdescurl = 0; -const char * multicastif = 0; -const char * minissdpdpath = 0; -#ifdef UPNP_LOCAL_PORT_ANY -int localport = UPNP_LOCAL_PORT_ANY; -#else -int localport = 0; -#endif -int retcode = 0; -int error = 0; -int ipv6 = 0; -int ignore = 0; -unsigned char ttl = 2; - - -int upnpInit() -{ - struct UPNP * Config = UPNPConfig; - int i; -#ifdef WIN32 - WSADATA wsaData; - int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); - if(nResult != NO_ERROR) - { - fprintf(stderr, "WSAStartup() failed.\n"); - return -1; - } -#endif - - while (Config) - { - if (devlist == NULL) - { -#if MINIUPNPC_API_VERSION == 10 - devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, &error); -#else - devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error); -#endif - if (devlist == NULL) - { - Consoleprintf("Failed to find a UPNP device"); - return 0; - } - -#if MINIUPNPC_API_VERSION >= 18 - i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr)); -#else - i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); -#endif - } - - AddMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol); - Config = Config->Next; - } - - return 0; -} - -int upnpClose() -{ - struct UPNP * Config = UPNPConfig; - int i; - - while (Config) - { - if (devlist == NULL) - { -#if MINIUPNPC_API_VERSION == 10 - devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, &error); -#else - devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error); -#endif - if (devlist == NULL) - { - Consoleprintf("Failed to find a UPNP device"); - return 0; - } - -#if MINIUPNPC_API_VERSION >= 18 - i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr)); -#else - i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); -#endif - } - - DeleteMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol); - Config = Config->Next; - } - - return 0; -} - -int AddMap(char * controlURL, char * eport, char * iport, char * proto) -{ - int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - eport, iport, lanaddr, desc, - proto, remoteHost, leaseDuration); - - if (r != UPNPCOMMAND_SUCCESS) - { - Consoleprintf("UPNP AddPortMapping(%s, %s, %s) failed with code %d (%s)", eport, iport, lanaddr, r, strupnperror(r)); - return -2; - } - Consoleprintf("UPNP AddPortMapping(%s, %s, %s) Succeeded", eport, iport, lanaddr, r); - return 0; -} - -int DeleteMap(char * controlURL, char * eport, char * iport, char * proto) -{ - int r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport, proto, remoteHost); - - if(r != UPNPCOMMAND_SUCCESS) - { - Consoleprintf("UPNP DeletePortMapping(%s, %s, %s) failed with code %d (%s)", eport, iport, lanaddr, r, strupnperror(r)); - return -2; - } - Consoleprintf("UPNP DeletePortMapping(%s, %s, %s) Succeeded", eport, iport, lanaddr, r); - - return 0; -} - - - - diff --git a/.svn/pristine/01/0166e0c783c5b8e5a6c55b1369dfe5459e2f71f2.svn-base b/.svn/pristine/01/0166e0c783c5b8e5a6c55b1369dfe5459e2f71f2.svn-base deleted file mode 100644 index fdbb96b..0000000 --- a/.svn/pristine/01/0166e0c783c5b8e5a6c55b1369dfe5459e2f71f2.svn-base +++ /dev/null @@ -1,243 +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 - -#include "compatbits.h" -#include -#include "asmstrucs.h" -#include "tncinfo.h" - -VOID __cdecl Debugprintf(const char * format, ...); - -#ifndef WIN32 - -#define APIENTRY -#define DllExport -#define VOID void - -#else -#include -#endif - -extern BOOL EventsEnabled; -void MQTTReportSession(char * Msg); -extern int MQTT; - - -extern char Modenames[19][10]; - -// Runs use specified routine on certain event -#ifndef WIN32 - -void RunEventProgram(char * Program, char * Param) -{ - char * arg_list[] = {Program, NULL, NULL}; - pid_t child_pid; - - if (EventsEnabled == 0) - return; - - signal(SIGCHLD, SIG_IGN); // Silently (and portably) reap children. - - if (Param && Param[0]) - arg_list[1] = Param; - - // Fork and Exec Specified program - - // Duplicate this process. - - child_pid = fork (); - - if (child_pid == -1) - { - printf ("Event fork() Failed\n"); - return; - } - - 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", arg_list[0]); - exit(0); // Kill the new process - } - -#else - -DllExport void APIENTRY RunEventProgram(char * Program, char * Param) -{ - int n = 0; - char cmdLine[256]; - - STARTUPINFO SInfo; // pointer to STARTUPINFO - PROCESS_INFORMATION PInfo; // pointer to PROCESS_INFORMATION - - if (EventsEnabled == 0) - return; - - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - sprintf(cmdLine, "%s %s", Program, Param); - - if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE,0 ,NULL ,NULL, &SInfo, &PInfo)) - Debugprintf("Failed to Start %s Error %d ", Program, GetLastError()); - -#endif - - return; -} - -void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK) -{ - // Incoming SABM - - LINK->ConnectTime = time(NULL); - LINK->bytesTXed = LINK->bytesRXed = 0; - - strcpy(LINK->callingCall, remotecall); - strcpy(LINK->receivingCall, ourcall); - strcpy(LINK->Direction, "In"); -} - -void hookL2SessionDeleted(struct _LINKTABLE * LINK) -{ - // calculate session time and av bytes/min in and out - - if (LINK->ConnectTime) - { - if (LINK->bytesTXed == 0 && LINK->bytesRXed == 0) - { - // assume failed connect and ignore for now - maybe log later - - } - else - { - char Msg[256]; - char timestamp[16]; - time_t sessionTime = time(NULL) - LINK->ConnectTime; - double avBytesSent = LINK->bytesTXed / (sessionTime / 60.0); - double avBytesRXed = LINK->bytesRXed / (sessionTime / 60.0); - time_t Now = time(NULL); - struct tm * TM = localtime(&Now); - - sprintf(timestamp, "%02d:%02d:%02d", TM->tm_hour, TM->tm_min, TM->tm_sec); - - if (sessionTime == 0) - sessionTime = 1; // Or will get divide by zero error - - Debugprintf("KISS Session Stats Port %d %s %s %d secs Bytes Sent %d BPM %4.2f Bytes Received %d %4.2f BPM ", - LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, sessionTime, LINK->bytesTXed, avBytesSent, LINK->bytesRXed, avBytesRXed, timestamp); - - - sprintf(Msg, "{\"mode\": \"%s\", \"direction\": \"%s\", \"port\": %d, \"callfrom\": \"%s\", \"callto\": \"%s\", \"time\": %d, \"bytesSent\": %d," - "\"BPMSent\": %4.2f, \"BytesReceived\": %d, \"BPMReceived\": %4.2f, \"timestamp\": \"%s\"}", - "KISS", LINK->Direction, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, sessionTime, - LINK->bytesTXed, avBytesSent, LINK->bytesRXed, avBytesRXed, timestamp); - - if (MQTT) - MQTTReportSession(Msg); - } - - LINK->ConnectTime = 0; - } - - if (LINK->Sent && LINK->Received && (LINK->SentAfterCompression || LINK->ReceivedAfterExpansion)) - Debugprintf("L2 Compression Stats %s %s TX %d %d %d%% RX %d %d %d%%", LINK->callingCall, LINK->receivingCall, - LINK->Sent, LINK->SentAfterCompression, ((LINK->Sent - LINK->SentAfterCompression) * 100) / LINK->Sent, - LINK->Received, LINK->ReceivedAfterExpansion, ((LINK->ReceivedAfterExpansion - LINK->Received) * 100) / LINK->Received); - -} - -void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK) -{ - LINK->ConnectTime = time(NULL); - LINK->bytesTXed = LINK->bytesRXed = 0; - - strcpy(LINK->callingCall, ourcall); - strcpy(LINK->receivingCall, remotecall); - strcpy(LINK->Direction, "Out"); -} - -void hookL4SessionAttempt(struct STREAMINFO * STREAM, char * remotecall, char * ourcall) -{ - // Outgoing Connect - - STREAM->ConnectTime = time(NULL); - STREAM->bytesTXed = STREAM->bytesRXed = 0; - - strcpy(STREAM->callingCall, ourcall); - strcpy(STREAM->receivingCall, remotecall); - strcpy(STREAM->Direction, "Out"); -} - -void hookL4SessionAccepted(struct STREAMINFO * STREAM, char * remotecall, char * ourcall) -{ - // Incoming Connect - - STREAM->ConnectTime = time(NULL); - STREAM->bytesTXed = STREAM->bytesRXed = 0; - - strcpy(STREAM->callingCall, remotecall); - strcpy(STREAM->receivingCall, ourcall); - strcpy(STREAM->Direction, "In"); -} - -void hookL4SessionDeleted(struct TNCINFO * TNC, struct STREAMINFO * STREAM) -{ - char Msg[256]; - - char timestamp[16]; - - if (STREAM->ConnectTime) - { - time_t sessionTime = time(NULL) - STREAM->ConnectTime; - double avBytesRXed = STREAM->bytesRXed / (sessionTime / 60.0); - double avBytesSent = STREAM->bytesTXed / (sessionTime / 60.0); - time_t Now = time(NULL); - struct tm * TM = localtime(&Now); - sprintf(timestamp, "%02d:%02d:%02d", TM->tm_hour, TM->tm_min, TM->tm_sec); - - if (sessionTime == 0) - sessionTime = 1; // Or will get divide by zero error - - sprintf(Msg, "{\"mode\": \"%s\", \"direction\": \"%s\", \"port\": %d, \"callfrom\": \"%s\", \"callto\": \"%s\", \"time\": %d, \"bytesSent\": %d," - "\"BPMSent\": %4.2f, \"BytesReceived\": %d, \"BPMReceived\": %4.2f, \"timestamp\": \"%s\"}", - Modenames[TNC->Hardware - 1], STREAM->Direction, TNC->Port, STREAM->callingCall, STREAM->receivingCall, sessionTime, - STREAM->bytesTXed, avBytesSent, STREAM->bytesRXed, avBytesRXed, timestamp); - - if (MQTT) - MQTTReportSession(Msg); - - STREAM->ConnectTime = 0; - } -} - - diff --git a/.svn/pristine/01/01ea0d74258aeb1aaca3b61c3205e84a4ae6371b.svn-base b/.svn/pristine/01/01ea0d74258aeb1aaca3b61c3205e84a4ae6371b.svn-base deleted file mode 100644 index 48f87d0..0000000 --- a/.svn/pristine/01/01ea0d74258aeb1aaca3b61c3205e84a4ae6371b.svn-base +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef TELNETSERVER -#define TELNETSERVER - -#ifndef LINBPQ -//#include "resource.h" -#endif -#define WSA_ACCEPT WM_USER + 1 -#define WSA_CONNECT WM_USER + 2 -#define WSA_DATA WM_USER + 3 - -#define InputBufferLen 100000 - -struct ConnectionInfo -{ - int Number; // Number of record - for Connections display - SOCKET socket; - union - { - struct sockaddr_in6 sin6; - struct sockaddr_in sin; - }; - BOOL SocketActive; - int BPQStream; - char Callsign[10]; - BOOL GotHeader; - unsigned char InputBuffer[InputBufferLen]; - int InputLen; - struct UserRec * UserPointer; - int Retries; - int LoginState; // 1 = user ok, 2 = password ok - BOOL DoingCommand; // Processing Telnet Command - BOOL DoEcho; // Telnet Echo option accepted - BOOL CMSSession; // Set if connect to CMS - BOOL FBBMode; // Pure TCP for FBB forwarding - BOOL NeedLF; // FBB mode, but with cr > crlf outbound - BOOL RelayMode; // Pure TCP for RMS Relay Emulation forwarding - BOOL DRATSMode; // HTML Terminal Emulator - BOOL SyncMode; // RMS Relay Sync - BOOL HTTPMode; // HTTP Server - BOOL APIMode; // REST API Server - BOOL TriMode; // Trimode emulation - BOOL TriModeConnected; // Set when remote session is connected - now send data to DataSock - SOCKET TriModeDataSock; // Data Socket - BOOL Auth; // Set if User is flagged as a Secure User - BOOL BPQTermMode; // Set if connected to BPQTermTCP - BOOL ClientSession; // Set if acting as a client (ie Linux HOST Mode) - BOOL MonitorNODES; // Monitor Control Flags - unsigned long long MMASK; - BOOL MCOM; - BOOL MonitorColour; - BOOL MTX; - BOOL MUIOnly; - int CMSIndex; // Pointer to CMS used for this connect - UCHAR * FromHostBuffer; // Somewhere to store msg from CMS - it sends the whole message at once - int FromHostBufferSize; - int FromHostBuffPutptr; - int FromHostBuffGetptr; - - struct TNCINFO * TNC; // Used to pass TCP struct to http code (for passwood list) - - time_t ConnectTime; - BOOL UTF8; // Set if BPQTerminal in UTF8 Mode - BOOL RelaySession; // Set if connection to RMS Relay - BOOL LogonSent; // To ignore second callsign: prompt - char Signon[100]; // User/Pass/Appl for Outgoing Connects - BOOL Keepalive; // For HOST (esp CCC) Keepalives - time_t LastSendTime; - BOOL NoCallsign; // Don't Send Callsign to host if no Signon - UCHAR * ResendBuffer; // Used if send() returns EWOULDBLOCK - int ResendLen; // Len to resend - - struct ADIF * ADIF; // ADIF Logging info - int WebSocks; - char WebURL[32]; // URL for WebSocket Connection - int WebSecure; // Set if secure session -}; - - -#define Disconnect(stream) SessionControl(stream,2,0) -#define Connect(stream) SessionControl(stream,1,0) - -#define SE 240 // End of subnegotiation parameters -#define NOP 241 //No operation -#define xDM 242 //Data mark Indicates the position of a Synch event within the data stream. This should always be accompanied by a TCP urgent notification. -#define BRK 243 //Break Indicates that the "break" or "attention" key was hi. -#define IPx 244 //Suspend Interrupt or abort the process to which the NVT is connected. -#define AO 245 //Abort output Allows the current process to run to completion but does not send its output to the user. -#define AYT 246 //Are you there Send back to the NVT some visible evidence that the AYT was received. -#define EC 247 //Erase character The receiver should delete the last preceding undeleted character from the data stream. -#define EL 248 //Erase line Delete characters from the data stream back to but not including the previous CRLF. -#define GA 249 //Go ahead Under certain circumstances used to tell the other end that it can transmit. -#define SB 250 //Subnegotiation Subnegotiation of the indicated option follows. -#define WILL 251 //will Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option. -#define WONT 252 //wont Indicates the refusal to perform, or continue performing, the indicated option. -#define DOx 253 //do Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option. -#define DONT 254 //dont Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option. -#define IAC 255 - -#define suppressgoahead 3 //858 -#define xStatus 5 //859 -#define echo 1 //857 -#define timingmark 6 //860 -#define terminaltype 24 //1091 -#define windowsize 31 //1073 -#define terminalspeed 32 //1079 -#define remoteflowcontrol 33 //1372 -#define linemode 34 //1184 -#define environmentvariables 36 //1408 - -#endif - diff --git a/.svn/pristine/03/037b7a71a9a62b41bdee83bd30d4b81006bcecf1.svn-base b/.svn/pristine/03/037b7a71a9a62b41bdee83bd30d4b81006bcecf1.svn-base deleted file mode 100644 index f703662..0000000 --- a/.svn/pristine/03/037b7a71a9a62b41bdee83bd30d4b81006bcecf1.svn-base +++ /dev/null @@ -1,1560 +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 Fvoideven 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 -*/ - -// Mail and Chat Server for BPQ32 Packet Switch -// -// White Pages Database Support Routines - -#include "bpqmail.h" - -#define GetSemaphore(Semaphore,ID) _GetSemaphore(Semaphore, ID, __FILE__, __LINE__) -void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line); - -int CurrentWPIndex; -char CurrentWPCall[10]; - -time_t LASTWPSendTime; - - -VOID DoWPUpdate(WPRec *WP, char Type, char * Name, char * HA, char * QTH, char * ZIP, time_t WPDate); -VOID Do_Save_WPRec(HWND hDlg); -VOID SaveInt64Value(config_setting_t * group, char * name, long long value); -VOID SaveIntValue(config_setting_t * group, char * name, int value); -VOID SaveStringValue(config_setting_t * group, char * name, char * value); -BOOL GetStringValue(config_setting_t * group, char * name, char * value, int maxlen); -void MQTTMessageEvent(void* message); - -WPRec * AllocateWPRecord() -{ - WPRec * WP = zalloc(sizeof (WPRec)); - - GetSemaphore(&AllocSemaphore, 0); - - WPRecPtr=realloc(WPRecPtr,(++NumberofWPrecs+1) * sizeof(void *)); - WPRecPtr[NumberofWPrecs]= WP; - - FreeSemaphore(&AllocSemaphore); - - return WP; -} - -int BadCall(char * Call) -{ - if (_stricmp(Call, "RMS") == 0) - return 1; - - if (_stricmp(Call, "SYSTEM") == 0) - return 1; - - if (_stricmp(Call, "SWITCH") == 0) - return 1; - - if (_stricmp(Call, "SYSOP") == 0) - return 1; - - if (_memicmp(Call, "SMTP", 4) == 0) - return 1; - - if (_memicmp(Call, "SMTP:", 5) == 0) - return 1; - - if (_stricmp(Call, "AMPR") == 0) - return 1; - - if (_stricmp(Call, "FILE") == 0) - return 1; - - if (_memicmp(Call, "MCAST", 5) == 0) - return 1; - - if (_memicmp(Call, "SYNC", 5) == 0) - return 1; - - return 0; -} - -extern config_t cfg; - -VOID GetWPDatabase() -{ - WPRec WPRec; - FILE * Handle; - int ReadLen; - WPRecP WP; - char CfgName[MAX_PATH]; - long long val; - config_t wpcfg; - config_setting_t * group, * wpgroup; - int i = 1; - struct stat STAT; - - // If WP info is in main config file, use it - - group = config_lookup (&cfg, "WP"); - - if (group) - { - // Set up control record - - WPRecPtr = malloc(sizeof(void *)); - WPRecPtr[0] = zalloc(sizeof(WPRec)); - NumberofWPrecs = 0; - - while (1) - { - char Key[16]; - char Record[1024]; - char * ptr, * ptr2; - unsigned int n; - - sprintf(Key, "R%d", i++); - - GetStringValue(group, Key, Record, 1024); - - if (Record[0] == 0) // End of List - return; - - memset(&WPRec, 0, sizeof(WPRec)); - - WP = &WPRec; - - ptr = Record; - ptr2 = strlop(ptr, '|'); - if (ptr) strcpy(&WP->callsign[0], ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - if (ptr) strcpy(&WP->name[0], ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - if (ptr) WP->Type = atoi(ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - if (ptr) WP->changed = atoi(ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - if (ptr) WP->seen = atoi(ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - if (ptr) strcpy(&WP->first_homebbs[0], ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - if (ptr) strcpy(&WP->secnd_homebbs[0], ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - if (ptr) strcpy(&WP->first_zip[0], ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - if (ptr) strcpy(&WP->secnd_zip[0], ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - - if (ptr == NULL) continue; - - if (strlen(ptr) > 30) - ptr[30] = 0; - - strcpy(&WP->first_qth[0], ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - - if (ptr == NULL) continue; - - if (strlen(ptr) > 30) - ptr[30] = 0; - - strcpy(&WP->secnd_qth[0], ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - - if (ptr) WP->last_modif = atol(ptr); - - ptr = ptr2; - ptr2 = strlop(ptr, '|'); - - if (ptr) - { - WP->last_seen = atol(ptr); - - // Check Call - - for (n = 1; n < strlen(WP->callsign); n++) // skip first which may also be digit - { - if (isdigit(WP->callsign[n])) - { - // Has a digit. Check Last is not digit - - if (isalpha(WP->callsign[strlen(WP->callsign) - 1])) - { - WP = LookupWP(WPRec.callsign); - if (WP == NULL) - WP = AllocateWPRecord(); - - memcpy(WP, &WPRec, sizeof(WPRec)); - goto WPOK; - } - } - } - Debugprintf("Bad WP Call %s", WP->callsign); - } -WPOK:; - } - return; - } - - // If text format exists use it - - strcpy(CfgName, WPDatabasePath); - strlop(CfgName, '.'); - strcat(CfgName, ".cfg"); - - if (stat(CfgName, &STAT) == -1) - goto tryOld; - - config_init(&wpcfg); - - if (!config_read_file(&wpcfg, CfgName)) - { - char Msg[256]; - sprintf(Msg, "Config File %s Line %d - %s\n", CfgName, - config_error_line(&wpcfg), config_error_text(&wpcfg)); - - printf("%s", Msg); - config_destroy(&wpcfg); - goto tryOld; - } - - // Set up control record - - WPRecPtr = malloc(sizeof(void *)); - WPRecPtr[0] = zalloc(sizeof(WPRec)); - NumberofWPrecs = 0; - - while (1) - { - char Key[16]; - char Temp[128]; - - sprintf(Key, "R%d", i++); - - wpgroup = config_lookup(&wpcfg, Key); - - if (wpgroup == NULL) // End of List - { - config_destroy(&wpcfg); - return; - } - - memset(&WPRec, 0, sizeof(WPRec)); - - GetStringValue(wpgroup, "c", WPRec.callsign, 6); - GetStringValue(wpgroup, "n", WPRec.name, 12); - - WPRec.Type = GetIntValue(wpgroup, "T"); - WPRec.changed = GetIntValue(wpgroup, "ch"); - WPRec.seen = GetIntValue(wpgroup, "s"); - - GetStringValue(wpgroup, "h", WPRec.first_homebbs, 40); - GetStringValue(wpgroup, "sh", WPRec.secnd_homebbs, 40); - GetStringValue(wpgroup, "z", WPRec.first_zip, 8); - GetStringValue(wpgroup, "sz", WPRec.secnd_zip, 8); - - GetStringValue(wpgroup, "q", Temp, 30); - Temp[30] = 0; - strcpy(WPRec.first_qth, Temp); - - GetStringValue(wpgroup, "sq", Temp, 30); - Temp[30] = 0; - strcpy(WPRec.secnd_qth, Temp); - - val = GetIntValue(wpgroup, "m"); - WPRec.last_modif = val; - val = GetIntValue(wpgroup, "ls"); - WPRec.last_seen = val; - - _strupr(WPRec.callsign); - - strlop(WPRec.callsign, ' '); - - if (strlen(WPRec.callsign) > 2) - { - if (strchr(WPRec.callsign, ':')) - continue; - - if (BadCall(WPRec.callsign)) - continue; - - WP = LookupWP(WPRec.callsign); - - if (WP == NULL) - WP = AllocateWPRecord(); - - memcpy(WP, &WPRec, sizeof(WPRec)); - } - } - -tryOld: - - Handle = fopen(WPDatabasePath, "rb"); - - if (Handle == NULL) - { - // Initialise a new File - - WPRecPtr = malloc(sizeof(void *)); - WPRecPtr[0] = malloc(sizeof(WPRec)); - memset(WPRecPtr[0], 0, sizeof(WPRec)); - NumberofWPrecs = 0; - - return; - } - - - // Get First Record - - ReadLen = fread(&WPRec, 1, sizeof(WPRec), Handle); - - if (ReadLen == 0) - { - // Duff file - - memset(&WPRec, 0, sizeof(WPRec)); - } - - // Set up control record - - WPRecPtr = malloc(sizeof(void *)); - WPRecPtr[0] = malloc(sizeof(WPRec)); - memcpy(WPRecPtr[0], &WPRec, sizeof(WPRec)); - - NumberofWPrecs = 0; - -Next: - - ReadLen = fread(&WPRec, 1, sizeof(WPRec), Handle); - - if (ReadLen == sizeof(WPRec)) - { - _strupr(WPRec.callsign); - - strlop(WPRec.callsign, ' '); - - if (strlen(WPRec.callsign) > 2) - { - if (strchr(WPRec.callsign, ':')) - goto Next; - - if (BadCall(WPRec.callsign)) - goto Next; - - WP = LookupWP(WPRec.callsign); - - if (WP == NULL) - WP = AllocateWPRecord(); - - memcpy(WP, &WPRec, sizeof(WPRec)); - } - goto Next; - } - - fclose(Handle); - SaveWPDatabase(); -} - -VOID CopyWPDatabase() -{ - char Backup[MAX_PATH]; - char Orig[MAX_PATH]; - - return; - - strcpy(Backup, WPDatabasePath); - strcat(Backup, ".bak"); - - CopyFile(WPDatabasePath, Backup, FALSE); - - strcpy(Backup, WPDatabasePath); - strlop(Backup, '.'); - strcat(Backup, ".cfg.bak"); - - strcpy(Orig, WPDatabasePath); - strlop(Orig, '.'); - strcat(Orig, ".cfg"); - CopyFile(Orig, Backup, FALSE); -} - -VOID SaveWPDatabase() -{ -// SaveConfig(ConfigName); // WP config is now in main config file - - int i; - config_setting_t *root, *group; - config_t cfg; - char Key[16]; - WPRec * WP; - char CfgName[MAX_PATH]; - long long val; - - memset((void *)&cfg, 0, sizeof(config_t)); - - config_init(&cfg); - - root = config_root_setting(&cfg); - - for (i = 0; i <= NumberofWPrecs; i++) - { - WP = WPRecPtr[i]; - sprintf(Key, "R%d", i); - - group = config_setting_add(root, Key, CONFIG_TYPE_GROUP); - - SaveStringValue(group, "c", &WP->callsign[0]); - SaveStringValue(group, "n", &WP->name[0]); - SaveIntValue(group, "T", WP->Type); - SaveIntValue(group, "ch", WP->changed); - SaveIntValue(group, "s", WP->seen); - SaveStringValue(group, "h", &WP->first_homebbs[0]); - SaveStringValue(group, "sh", &WP->secnd_homebbs[0]); - SaveStringValue(group, "z", &WP->first_zip[0]); - SaveStringValue(group, "sz", &WP->secnd_zip[0]); - SaveStringValue(group, "q", &WP->first_qth[0]); - SaveStringValue(group, "sq", &WP->secnd_qth[0]); - val = WP->last_modif; - SaveInt64Value(group, "m", val); - val = WP->last_seen; - SaveInt64Value(group, "ls", val); - } - - strcpy(CfgName, WPDatabasePath); - strlop(CfgName, '.'); - strcat(CfgName, ".cfg"); - - Debugprintf("Saving WP Database to %s\n", CfgName); - - config_write_file(&cfg, CfgName); - config_destroy(&cfg); - -} - -WPRec * LookupWP(char * Call) -{ - WPRec * ptr = NULL; - int i; - - for (i=1; i <= NumberofWPrecs; i++) - { - ptr = WPRecPtr[i]; - - if (_stricmp(ptr->callsign, Call) == 0) return ptr; - } - - return NULL; -} - -char * FormatWPDate(time_t Datim) -{ - struct tm *tm; - static char Date[]="xx-xxx-xx "; - - tm = gmtime(&Datim); - - if (tm) - { - if (tm->tm_year >= 100) - sprintf_s(Date, sizeof(Date), "%02d-%3s-%02d", - tm->tm_mday, month[tm->tm_mon], tm->tm_year - 100); - else - sprintf_s(Date, sizeof(Date), ""); - } - return Date; -} - -#ifndef LINBPQ - -int Do_WP_Sel_Changed(HWND hDlg) -{ - // Update WP display with newly selected rec - - WPRec * WP; - int Sel = SendDlgItemMessage(hDlg, IDC_WP, CB_GETCURSEL, 0, 0); - char Type[] = " "; - - if (Sel == -1) - SendDlgItemMessage(hDlg, IDC_WP, WM_GETTEXT, Sel, (LPARAM)(LPCTSTR)&CurrentWPCall); - else - SendDlgItemMessage(hDlg, IDC_WP, CB_GETLBTEXT, Sel, (LPARAM)(LPCTSTR)&CurrentWPCall); - - for (CurrentWPIndex = 1; CurrentWPIndex <= NumberofWPrecs; CurrentWPIndex++) - { - WP = WPRecPtr[CurrentWPIndex]; - - if (_stricmp(WP->callsign, CurrentWPCall) == 0) - { - - SetDlgItemText(hDlg, IDC_WPNAME, WP->name); - SetDlgItemText(hDlg, IDC_HOMEBBS1, WP->first_homebbs); - SetDlgItemText(hDlg, IDC_HOMEBBS2, WP->secnd_homebbs); - SetDlgItemText(hDlg, IDC_QTH1, WP->first_qth); - SetDlgItemText(hDlg, IDC_QTH2, WP->secnd_qth); - SetDlgItemText(hDlg, IDC_ZIP1, WP->first_zip); - SetDlgItemText(hDlg, IDC_ZIP2, WP->secnd_zip); - Type[0] = WP->Type; - SetDlgItemText(hDlg, IDC_TYPE, Type); - SetDlgItemInt(hDlg, IDC_CHANGED, WP->changed, FALSE); - SetDlgItemInt(hDlg, IDC_SEEN, WP->seen, FALSE); - - SetDlgItemText(hDlg, IDC_LASTSEEN, FormatWPDate(WP->last_seen)); - SetDlgItemText(hDlg, IDC_LASTMODIFIED, FormatWPDate(WP->last_modif)); - - return 0; - } - } - - CurrentWPIndex = -1; - - return 0; -} - -INT_PTR CALLBACK InfoDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); - - -VOID Do_Save_WPRec(HWND hDlg) -{ - WPRec * WP; - char Type[] = " "; - BOOL OK1; - - if (CurrentWPIndex == -1) - { - sprintf(InfoBoxText, "Please select a WP Record to save"); - DialogBox(hInst, MAKEINTRESOURCE(IDD_USERADDED_BOX), hWnd, InfoDialogProc); - return; - } - - WP = WPRecPtr[CurrentWPIndex]; - - if (strcmp(CurrentWPCall, WP->callsign) != 0) - { - sprintf(InfoBoxText, "Inconsistancy detected - record not saved"); - DialogBox(hInst, MAKEINTRESOURCE(IDD_USERADDED_BOX), hWnd, InfoDialogProc); - return; - } - - GetDlgItemText(hDlg, IDC_WPNAME, WP->name, 13); - GetDlgItemText(hDlg, IDC_HOMEBBS1, WP->first_homebbs, 41); - GetDlgItemText(hDlg, IDC_HOMEBBS2, WP->secnd_homebbs, 41); - GetDlgItemText(hDlg, IDC_QTH1, WP->first_qth, 31); - GetDlgItemText(hDlg, IDC_QTH2, WP->secnd_qth, 31); - GetDlgItemText(hDlg, IDC_ZIP1, WP->first_zip, 31); - GetDlgItemText(hDlg, IDC_ZIP2, WP->secnd_zip, 31); - WP->last_modif = time(NULL); - WP->seen = GetDlgItemInt(hDlg, IDC_SEEN, &OK1, FALSE); - - WP->Type = 'U'; - WP->changed = 1; - - SaveWPDatabase(); - - sprintf(InfoBoxText, "WP information saved"); - DialogBox(hInst, MAKEINTRESOURCE(IDD_USERADDED_BOX), hWnd, InfoDialogProc); -} - -VOID Do_Delete_WPRec(HWND hDlg) -{ - WPRec * WP; - int n; - - if (CurrentWPIndex == -1) - { - sprintf(InfoBoxText, "Please select a WP Record to delete"); - DialogBox(hInst, MAKEINTRESOURCE(IDD_USERADDED_BOX), hWnd, InfoDialogProc); - return; - } - - WP = WPRecPtr[CurrentWPIndex]; - - if (strcmp(CurrentWPCall, WP->callsign) != 0) - { - sprintf(InfoBoxText, "Inconsistancy detected - record not deleted"); - DialogBox(hInst, MAKEINTRESOURCE(IDD_USERADDED_BOX), hWnd, InfoDialogProc); - return; - } - - for (n = CurrentWPIndex; n < NumberofWPrecs; n++) - { - WPRecPtr[n] = WPRecPtr[n+1]; // move down all following entries - } - - NumberofWPrecs--; - - SendDlgItemMessage(hDlg, IDC_WP, CB_RESETCONTENT, 0, 0); - - for (n = 1; n <= NumberofWPrecs; n++) - { - SendDlgItemMessage(hDlg, IDC_WP, CB_ADDSTRING, 0, (LPARAM)WPRecPtr[n]->callsign); - } - - - sprintf(InfoBoxText, "WP record for %s deleted", WP->callsign); - DialogBox(hInst, MAKEINTRESOURCE(IDD_USERADDED_BOX), hWnd, InfoDialogProc); - - free(WP); - - SaveWPDatabase(); - - return; - -} - -INT_PTR CALLBACK WPEditDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - int Command, n; - - UNREFERENCED_PARAMETER(lParam); - switch (message) - { - - case WM_INITDIALOG: - - for (n = 1; n <= NumberofWPrecs; n++) - { - SendDlgItemMessage(hDlg, IDC_WP, CB_ADDSTRING, 0, (LPARAM)WPRecPtr[n]->callsign); - } - - 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); - - switch (Command) - { - - case IDOK: - case IDCANCEL: - - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - - case IDC_WP: - - // Msg Selection Changed - - Do_WP_Sel_Changed(hDlg); - - return TRUE; - - case IDC_SAVEWP: - - Do_Save_WPRec(hDlg); - return TRUE; - - case IDC_DELETEWP: - - Do_Delete_WPRec(hDlg); - return TRUE; - } - break; - } - - return (INT_PTR)FALSE; -} -#endif - -VOID GetWPBBSInfo(char * Rline) -{ - // Update WP with /I records for each R: Line - - // R:111206/1636Z 29130@N9PMO.#SEWI.WI.USA.NOAM [Racine, WI] FBB7.00i - - struct tm rtime; - time_t RLineTime; - int Age; - - WPRec * WP; - char ATBBS[200]; - char Call[200]; - char QTH[200] = ""; - int RLen; - - char * ptr1; - char * ptr2; - - - memset(&rtime, 0, sizeof(struct tm)); - - if (Rline[10] == '/') - { - // Dodgy 4 char year - - sscanf(&Rline[2], "%04d%02d%02d/%02d%02d", - &rtime.tm_year, &rtime.tm_mon, &rtime.tm_mday, &rtime.tm_hour, &rtime.tm_min); - rtime.tm_year -= 1900; - rtime.tm_mon--; - } - else if (Rline[8] == '/') - { - sscanf(&Rline[2], "%02d%02d%02d/%02d%02d", - &rtime.tm_year, &rtime.tm_mon, &rtime.tm_mday, &rtime.tm_hour, &rtime.tm_min); - - if (rtime.tm_year < 90) - rtime.tm_year += 100; // Range 1990-2089 - rtime.tm_mon--; - } - - // Otherwise leave date as zero, which should be rejected - - if ((RLineTime = mktime(&rtime)) != (time_t)-1 ) - { - Age = (time(NULL) - RLineTime)/86400; - - if ( Age < -1) - return; // in the future - - if (Age > BidLifetime || Age > MaxAge) - return; // Too old - } - - ptr1 = strchr(Rline, '@'); - ptr2 = strchr(Rline, '\r'); - - if (!ptr1) - return; // Duff - - if (*++ptr1 == ':') - ptr1++; // Format 2 - - - if (ptr2 == NULL) - return; // No CR on end - - RLen = ptr2 - ptr1; - - if (RLen > 200) - return; - - memcpy(ATBBS, ptr1, RLen); - ATBBS[RLen] = 0; - - ptr2 = strchr(ATBBS, ' '); - - if (ptr2) - *ptr2 = 0; - - strcpy(Call, ATBBS); - strlop(Call, '.'); - - ptr2 = memchr(ptr1, '[', RLen); - - if (ptr2) - { - ptr1= memchr(ptr2, ']', RLen); - if (ptr1) - memcpy(QTH, ptr2 + 1, ptr1 - ptr2 - 1); - } - - if (BadCall(Call)) - return; - - WP = LookupWP(Call); - - if (!WP) - { - // Not Found - - WP = AllocateWPRecord(); - - strcpy(WP->callsign, Call); - strcpy(WP->first_homebbs, ATBBS); - strcpy(WP->secnd_homebbs, ATBBS); - - if (QTH[0]) - { - strcpy(WP->first_qth, QTH); - strcpy(WP->secnd_qth, QTH); - } - - WP->last_modif = RLineTime; - WP->last_seen = RLineTime; - - WP->Type = 'I'; - WP->changed = TRUE; - - return; - } - - if (WP->last_modif >= RLineTime || WP->Type != 'I') - return; - - // Update 2nd if changed - - if (strcmp(WP->secnd_homebbs , ATBBS) != 0) - { - strcpy(WP->secnd_homebbs, ATBBS); - WP->last_modif = RLineTime; - } - - if (QTH[0] && strcmp(WP->secnd_qth , QTH) != 0) - { - strcpy(WP->secnd_qth, QTH); - WP->last_modif = RLineTime; - } - - return; -} - - - - -VOID GetWPInfoFromRLine(char * From, char * FirstRLine, time_t RLineTime) -{ - /* The /G suffix denotes that the information in this line has been gathered by examining - the header of a message to GUESS at which BBS the sender is registered. The HomeBBS of the User - is assumed to be the BBS shown in the first R: header line. The date associated with this - information is the date shown on this R: header line. - */ - - // R:930101/0000 1530@KA6FUB.#NOCAL.CA.USA.NOAM - - // R:930101/0000 @:KA6FUB.#NOCAL.CA.USA.NOAM #:1530 - - // The FirstRLine pointer points to the message, so shouldnt be changed - - WPRec * WP; - char ATBBS[200]; - int RLen; - - char * ptr1 = strchr(FirstRLine, '@'); - char * ptr2 = strchr(FirstRLine, '\r'); - - if (BadCall(From)) - return; - - if (!ptr1) - return; // Duff - - if (*++ptr1 == ':') - ptr1++; // Format 2 - - RLen = ptr2 - ptr1; - - if (RLen > 200) - return; - - memcpy(ATBBS, ptr1, RLen); - ATBBS[RLen] = 0; - - ptr2 = strchr(ATBBS, ' '); - - if (ptr2) - *ptr2 = 0; - - if (strlen(ATBBS) > 40) - ATBBS[40] = 0; - - WP = LookupWP(From); - - if (!WP) - { - // Not Found - - WP = AllocateWPRecord(); - - strcpy(WP->callsign, From); - strcpy(WP->first_homebbs, ATBBS); - strcpy(WP->secnd_homebbs, ATBBS); - - WP->last_modif = RLineTime; - WP->last_seen = RLineTime; - - WP->Type = 'G'; - WP->changed = TRUE; - - return; - } - - if (WP->last_modif >= RLineTime) - return; - - // Update 2nd if changed - - if (strcmp(WP->secnd_homebbs , ATBBS) != 0) - { - strcpy(WP->secnd_homebbs, ATBBS); - WP->last_modif = RLineTime; - } - - return; -} - -VOID ProcessWPMsg(char * MailBuffer, int Size, char * FirstRLine) -{ - char * ptr1 = MailBuffer; - char * ptr2; - WPRec * WP; - char WPLine[200]; - int WPLen; - - ptr1[Size] = 0; - - ptr1 = FirstRLine; - - if (ptr1 == NULL) - return; - - while (*ptr1) - { - ptr2 = strchr(ptr1, '\r'); - - if (ptr2 == 0) // No CR in buffer - return; - - WPLen = ptr2 - ptr1; - - if (WPLen > 128) - return; - - if ((memcmp(ptr1, "On ", 3) == 0) && (WPLen < 200)) - { - char * Date; - char * Call; - char * AT; - char * HA; - char * zip; - char * ZIP; - char * Name; - char * QTH = NULL; - char * Context; - char seps[] = " \r"; - - // Make copy of string, as strtok messes with it - - memcpy(WPLine, ptr1, WPLen); - WPLine[WPLen] = 0; - - Date = strtok_s(WPLine+3, seps, &Context); - Call = strtok_s(NULL, seps, &Context); - AT = strtok_s(NULL, seps, &Context); - HA = strtok_s(NULL, seps, &Context); - zip = strtok_s(NULL, seps, &Context); - ZIP = strtok_s(NULL, seps, &Context); - Name = strtok_s(NULL, seps, &Context); - QTH = strtok_s(NULL, "\r", &Context); // QTH may have spaces - - if (Date == 0 || Call == 0 || AT == 0 || ZIP == 0 || Name == 0 || QTH == 0) - return; - - if (strlen(HA) > 40) - return; - if (strlen(ZIP) > 8) - return; - if (strlen(Name) > 12) - return; - if (strlen(QTH) > 30) - return; - - if (AT[0] == '@' && (QTH)) - { - struct tm rtime; - time_t WPDate; - char Type; - char * TypeString; - - if (memcmp(Name, "?", 2) == 0) Name = NULL; - if (memcmp(ZIP, "?", 2) == 0) ZIP = NULL; - if (memcmp(QTH, "?", 2) == 0) QTH = NULL; - - memset(&rtime, 0, sizeof(struct tm)); - - sscanf(Date, "%02d%02d%02d", - &rtime.tm_year, &rtime.tm_mon, &rtime.tm_mday); - - rtime.tm_year += 100; - rtime.tm_mon--; - -/* -This process freshens the database, following receipt of the new or changed information detailed above. - -The update subroutine will first look for an entry in the database for the callsign which matches the received information. -If it does not exist then a completely new record will be created in the database and the information be used to fill what -fields it can, in both the active and the temporary components. The date will be then changed to the one associated with the -update information. - -If the record does already exist, then the unknown fields of both the temporary and active fields will be filled in, and -those fields already known in the temporary part will be replaced by the new information if the date new information is -younger than that already on file. The date will then be -adjusted such that it is consistent with the updated information. - -If the new information is of the /U category, then the current fields will be replaced by the new information in both -the primary and secondary (Active and Temporary) parts of the record, as this information has been input directly from -the user. If the information was of another category then only the secondary (Temporary) part of the record will be -updated, so the Active or primary record will remain unchanged at this time. - -If a field is changed, a flag giving the update request type is then validated. If the /U flag is already validated, -it will not be replaced. This flag will be used in case the WP update messages are validated. -*/ - if ((WPDate = mktime(&rtime)) != (time_t)-1 ) - { - WPDate -= (time_t)_MYTIMEZONE; - TypeString = strlop(Call, '/'); - - if (strlen(Call) < 3 || strlen(Call) > 6) - return; - - if (TypeString) - Type = TypeString[0]; - else - Type = 'G'; - - if (strchr(Call, ':')) - break; - - if (BadCall(Call)) - break; - - WP = LookupWP(Call); - - if (WP) - { - // Found, so update - - DoWPUpdate(WP, Type, Name, HA, QTH, ZIP, WPDate); - } - else - { - WP = AllocateWPRecord(); - - strcpy(WP->callsign, Call); - if (Name) strcpy(WP->name, Name); - strcpy(WP->first_homebbs, HA); - strcpy(WP->secnd_homebbs, HA); - - if (QTH) - { - strcpy(WP->first_qth, QTH); - strcpy(WP->secnd_qth, QTH);; - } - if (ZIP) - { - strcpy(WP->first_zip, ZIP); - strcpy(WP->secnd_zip, ZIP); - } - - WP->Type = Type; - WP->last_modif = WPDate; - WP->last_seen = WPDate; - WP->changed = TRUE; - WP->seen++; - } - } - } - } - - ptr1 = ++ptr2; - if (*ptr1 == '\n') - ptr1++; - } - - SaveWPDatabase(); - - return; -} - -VOID DoWPUpdate(WPRec * WP, char Type, char * Name, char * HA, char * QTH, char * ZIP, time_t WPDate) -{ - // First Update any unknown field - - if(Name) - if (WP->name == NULL) {strcpy(WP->name, Name); WP->last_modif = WPDate; WP->changed = TRUE;} - - if (QTH) - { - if (WP->first_qth == NULL) {strcpy(WP->first_qth, QTH); WP->last_modif = WPDate; WP->changed = TRUE;} - if (WP->secnd_qth == NULL) {strcpy(WP->secnd_qth, QTH); WP->last_modif = WPDate; WP->changed = TRUE;} - } - if (ZIP) - { - if (WP->first_zip == NULL) {strcpy(WP->first_zip, ZIP); WP->last_modif = WPDate; WP->changed = TRUE;} - if (WP->secnd_zip == NULL) {strcpy(WP->secnd_zip, ZIP); WP->last_modif = WPDate; WP->changed = TRUE;} - } - - WP->last_seen = WPDate; - WP->seen++; - - // Now Update Temp Fields if update is newer than original - - if (WP->last_modif >= WPDate) - return; - - if (Type == 'U') // Definitive Update - { - if (strcmp(WP->first_homebbs , HA) != 0) - { - strcpy(WP->first_homebbs, HA); strcpy(WP->secnd_homebbs, HA); WP->last_modif = WPDate; WP->changed = TRUE; - } - - if (Name) - { - if (strcmp(WP->name , Name) != 0) - { - strcpy(WP->name, Name); - WP->last_modif = WPDate; - WP->changed = TRUE; - } - } - - if (QTH) - { - if (strcmp(WP->first_qth , QTH) != 0) - { - strcpy(WP->first_qth, QTH); - strcpy(WP->secnd_qth, QTH); - WP->last_modif = WPDate; - WP->changed = TRUE; - } - } - - if (ZIP) - { - if (strcmp(WP->first_zip , ZIP) != 0) - { - strcpy(WP->first_zip, ZIP); - strcpy(WP->secnd_zip, ZIP); - WP->last_modif = WPDate; - WP->changed = TRUE; - } - } - - WP->Type = Type; - - return; - } - - // Non-Definitive - only update second copy - - if (strcmp(WP->secnd_homebbs , HA) != 0) {strcpy(WP->secnd_homebbs, HA); WP->last_modif = WPDate; WP->Type = Type;} - - if (Name) - if (strcmp(WP->name , Name) != 0) {strcpy(WP->name, Name); WP->last_modif = WPDate; WP->Type = Type;} - - if (QTH) - if (strcmp(WP->secnd_qth , QTH) != 0) {strcpy(WP->secnd_qth, QTH); WP->last_modif = WPDate; WP->Type = Type;} - - if (ZIP) - if (strcmp(WP->secnd_zip , ZIP) != 0) {strcpy(WP->secnd_zip, ZIP); WP->last_modif = WPDate; WP->Type = Type;} - - return; -} - -VOID UpdateWPWithUserInfo(struct UserInfo * user) -{ - WPRec * WP = LookupWP(user->Call); - - if (strchr(user->Call, ':')) - return; - - if (BadCall(user->Call)) - return; - - if (!WP) - { - WP = AllocateWPRecord(); - strcpy(WP->callsign, user->Call); - } - - // Update Record - - if (user->HomeBBS[0]) - { - strcpy(WP->first_homebbs, user->HomeBBS); - strcpy(WP->secnd_homebbs, user->HomeBBS); - } - - if (user->Address[0]) - { - char Temp[127]; - strcpy(Temp, user->Address); - Temp[30] = 0; - - strcpy(WP->first_qth, Temp); - strcpy(WP->secnd_qth, Temp); - } - - if (user->ZIP[0]) - { - strcpy(WP->first_zip, user->ZIP); - strcpy(WP->secnd_zip, user->ZIP ); - } - - if (user->Name[0]) - strcpy(WP->name, user->Name); - - WP->last_modif = WP->last_seen = time(NULL); - - WP->changed = TRUE; - WP->Type = 'U'; - - SaveWPDatabase(); - -} - -VOID DoWPLookup(ConnectionInfo * conn, struct UserInfo * user, char Type, char *Param) -{ - // Process the I call command - - WPRec * ptr = NULL; - int i; - char ATBBS[100]; - char * HA; - char * Rest; - - _strupr(Param); - Type = toupper(Type); - - switch (Type) - { - case 0: - - for (i=1; i <= NumberofWPrecs; i++) - { - ptr = WPRecPtr[i]; - - if (wildcardcompare(ptr->callsign, Param)) - { - nodeprintf(conn, "%s %s %s %s %s\r", ptr->callsign, ptr->first_homebbs, - ptr->name, ptr->first_zip, ptr->first_qth); - } - } - - return; - - case'@': // AT BBS - - for (i=1; i <= NumberofWPrecs; i++) - { - ptr = WPRecPtr[i]; - - strcpy(ATBBS, ptr->first_homebbs); - strlop(ATBBS,'.'); - - if (wildcardcompare(ATBBS, Param)) - { - nodeprintf(conn, "%s %s %s %s %s\r", ptr->callsign, ptr->first_homebbs, ptr->name, ptr->first_zip, ptr->first_qth); - } - } - - case'H': // Hierarchic Element - - for (i=1; i <= NumberofWPrecs; i++) - { - ptr = WPRecPtr[i]; - - strcpy(ATBBS, ptr->first_homebbs); - - Rest = strlop(ATBBS,'.'); - - if (Rest == 0) - continue; - - HA = strtok_s(Rest, ".", &Rest); - - while (HA) - { - if (wildcardcompare(HA, Param)) - { - nodeprintf(conn, "%s %s %s %s %s\r", ptr->callsign, ptr->first_homebbs, ptr->name, ptr->first_zip, ptr->first_qth); - } - - HA = strtok_s(NULL, ".", &Rest); - } - } - return; - - case'Z': // ZIP - - for (i=1; i <= NumberofWPrecs; i++) - { - ptr = WPRecPtr[i]; - - if (ptr->first_zip[0] == 0) - continue; - - if (wildcardcompare(ptr->first_zip, Param)) - { - nodeprintf(conn, "%s %s %s %s %s\r", ptr->callsign, ptr->first_homebbs, ptr->name, ptr->first_zip, ptr->first_qth); - } - } - return; - } - nodeprintf(conn, "Invalid I command option %c\r", Type); -} -/* -On 111120 N4ZKF/I @ N4ZKF.#NFL.FL.USA.NOAM zip 32118 Dave 32955 -On 111120 F6IQF/I @ F6IQF.FRPA.FRA.EU zip ? ? f6iqf.dyndns.org -On 111121 W9JUN/I @ W9JUN.W9JUN.#SEIN.IN.US.NOAM zip 47250 Don NORTH VERNON, IN -On 111120 KR8ZY/U @ KR8ZY zip ? john ? -On 111120 N0DEC/G @ N0ARY.#NCA.CA.USA.NOAM zip ? ? ? - -From: N0JAL -To: WP -Type/Status: B$ -Date/Time: 22-Nov 10:15Z -Bid: 95F7N0JAL -Title: WP Update - -R:111122/1500Z 35946@KD6PGI.OR.USA.NOAM BPQ1.0.4 -R:111122/1020 16295@K7ZS.OR.USA.NOAM -R:111122/1015 38391@N0JAL.OR.USA.NOAM - -On 111121 N0JAL @ N0JAL.OR.USA.NOAM zip ? Sai Damascus, Oregon CN85sj - -*/ - -VOID UpdateWP() -{ - // If 2nd copy of info has been unchanged for 30 days, copy to active fields - - WPRec * ptr = NULL; - int i; - char * via = NULL; - int MsgLen = 0; - char MailBuffer[100100]; - char * Buffptr = MailBuffer; - int WriteLen=0; - char HDest[61] = "WP"; - char WPMsgType = 'P'; - time_t NOW = time(NULL); - time_t UpdateLimit = NOW - (86400 * 30); // 30 days - LASTWPSendTime = NOW - (86400 * 5); // 5 days max - - for (i=1; i <= NumberofWPrecs; i++) - { - ptr = WPRecPtr[i]; - - // DO we have a new field, and if so is it different? - - if ((ptr->secnd_homebbs[0] && _stricmp(ptr->first_homebbs, ptr->secnd_homebbs)) - || (ptr->secnd_qth[0] && _stricmp(ptr->first_qth, ptr->secnd_qth)) - || (ptr->secnd_zip[0] && _stricmp(ptr->first_zip, ptr->secnd_zip))) - { - // Have new data - - if (ptr->last_modif < UpdateLimit) - { - // Stable for 30 days - - if (ptr->secnd_homebbs[0]) - strcpy(ptr->first_homebbs, ptr->secnd_homebbs); - if (ptr->secnd_qth[0]) - strcpy(ptr->first_qth, ptr->secnd_qth); - if (ptr->secnd_zip[0]) - strcpy(ptr->first_zip, ptr->secnd_zip); - - ptr->last_modif = NOW; - - } - } - } -} - -int CreateWPMessage() -{ - // Include all messages with Type of U whach have changed since LASTWPSendTime - - WPRec * ptr = NULL; - int i; - struct tm *tm; - struct MsgInfo * Msg; - char * via = NULL; - char BID[13]; - BIDRec * BIDRec; - int MsgLen = 0; - char MailBuffer[100100]; - char * Buffptr = MailBuffer; - char MsgFile[MAX_PATH]; - FILE * hFile; - int WriteLen=0; - char ** To = SendWPAddrs; - - LASTWPSendTime = time(NULL) - (86400 * 5); // 5 days max - - for (i=1; i <= NumberofWPrecs; i++) - { - ptr = WPRecPtr[i]; - -// if (ptr->last_modif > LASTWPSendTime && ptr->Type == 'U' && ptr->first_homebbs[0]) - if (ptr->changed && ptr->last_modif > LASTWPSendTime && ptr->first_homebbs[0]) - { - tm = gmtime((time_t *)&ptr->last_modif); - MsgLen += sprintf(Buffptr, "On %02d%02d%02d %s/%c @ %s zip %s %s %s\r\n", - tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, - ptr->callsign, ptr->Type, ptr->first_homebbs, - (ptr->first_zip[0]) ? ptr->first_zip : "?", - (ptr->name[0]) ? ptr->name : "?", - (ptr->first_qth[0]) ? ptr->first_qth : "?"); - - Buffptr = &MailBuffer[MsgLen]; - - ptr->changed = FALSE; - - if (MsgLen > 100000) - break; - } - } - - if (MsgLen == 0) - return TRUE; - - while(To[0]) - { - char TO[256]; - char * VIA; - - Msg = AllocateMsgRecord(); - - // Set number here so they remain in sequence - - Msg->number = ++LatestMsg; - Msg->length = MsgLen; - MsgnotoMsg[Msg->number] = Msg; - - strcpy(Msg->from, BBSName); - - strcpy(TO, To[0]); - - VIA = strlop(TO, '@'); - - if (VIA) - { - if (strlen(VIA) > 40) - VIA[40] = 0; - strcpy(Msg->via, VIA); - } - strcpy(Msg->to, TO); - - strcpy(Msg->title, "WP Update"); - - Msg->type = (SendWPType) ? 'P' : 'B'; - Msg->status = 'N'; - - sprintf_s(BID, sizeof(BID), "%d_%s", LatestMsg, BBSName); - - strcpy(Msg->bid, BID); - - Msg->datereceived = Msg->datechanged = Msg->datecreated = time(NULL); - - BIDRec = AllocateBIDRecord(); - - strcpy(BIDRec->BID, Msg->bid); - BIDRec->mode = Msg->type; - BIDRec->u.msgno = LOWORD(Msg->number); - BIDRec->u.timestamp = LOWORD(time(NULL)/86400); - - sprintf_s(MsgFile, sizeof(MsgFile), "%s/m_%06d.mes", MailDir, Msg->number); - - hFile = fopen(MsgFile, "wb"); - - if (hFile) - { - fwrite(MailBuffer, 1, Msg->length, hFile); - fclose(hFile); - } - - MatchMessagetoBBSList(Msg, 0); - - BuildNNTPList(Msg); // Build NNTP Groups list - -#ifndef NOMQTT - if (MQTT) - MQTTMessageEvent(Msg); -#endif - To++; - } - - SaveMessageDatabase(); - SaveBIDDatabase(); - - return TRUE; -} - -VOID CreateWPReport() -{ - int i; - char Line[200]; - int len; - char File[100]; - FILE * hFile; - WPRec * WP = NULL; - - sprintf_s(File, sizeof(File), "%s/wp.txt", BaseDir); - - hFile = fopen(File, "wb"); - - if (hFile == NULL) - return; - -// len = sprintf(Line, " Call Connects Connects Messages Messages Bytes Bytes Rejected Rejected\r\n"); -// WriteFile(hFile, Line, len, &written, NULL); -// len = sprintf(Line, " In Out Rxed Sent Rxed Sent In Out\r\n\r\n"); -// WriteFile(hFile, Line, len, &written, NULL); - - - for (i=1; i <= NumberofWPrecs; i++) - { - WP = WPRecPtr[i]; - - len = sprintf(Line, "%-7s,%c,%s,%s,%s,%s,%s,%s,%s,%d,%s,%s\r\n", - WP->callsign, WP->Type, WP->first_homebbs, WP->first_qth, WP->first_zip, - WP->secnd_homebbs, WP->secnd_qth, WP->secnd_zip, WP->name, WP->changed, - FormatWPDate((time_t)WP->last_modif), - FormatWPDate((time_t)WP->last_seen)); - - fwrite(Line, 1, len, hFile); - } - fclose(hFile); -} - - - - - - diff --git a/.svn/pristine/03/0381960f1d4a4876281c5e925e69f5634d57b798.svn-base b/.svn/pristine/03/0381960f1d4a4876281c5e925e69f5634d57b798.svn-base deleted file mode 100644 index 8c35faa..0000000 --- a/.svn/pristine/03/0381960f1d4a4876281c5e925e69f5634d57b798.svn-base +++ /dev/null @@ -1,1573 +0,0 @@ - -/* pngpread.c - read a png file in push mode - * - * libpng version 1.2.8 - December 3, 2004 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2004 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - -/* push model modes */ -#define PNG_READ_SIG_MODE 0 -#define PNG_READ_CHUNK_MODE 1 -#define PNG_READ_IDAT_MODE 2 -#define PNG_SKIP_MODE 3 -#define PNG_READ_tEXt_MODE 4 -#define PNG_READ_zTXt_MODE 5 -#define PNG_READ_DONE_MODE 6 -#define PNG_READ_iTXt_MODE 7 -#define PNG_ERROR_MODE 8 - -void PNGAPI -png_process_data(png_structp png_ptr, png_infop info_ptr, - png_bytep buffer, png_size_t buffer_size) -{ - png_push_restore_buffer(png_ptr, buffer, buffer_size); - - while (png_ptr->buffer_size) - { - png_process_some_data(png_ptr, info_ptr); - } -} - -/* What we do with the incoming data depends on what we were previously - * doing before we ran out of data... - */ -void /* PRIVATE */ -png_process_some_data(png_structp png_ptr, png_infop info_ptr) -{ - switch (png_ptr->process_mode) - { - case PNG_READ_SIG_MODE: - { - png_push_read_sig(png_ptr, info_ptr); - break; - } - case PNG_READ_CHUNK_MODE: - { - png_push_read_chunk(png_ptr, info_ptr); - break; - } - case PNG_READ_IDAT_MODE: - { - png_push_read_IDAT(png_ptr); - break; - } -#if defined(PNG_READ_tEXt_SUPPORTED) - case PNG_READ_tEXt_MODE: - { - png_push_read_tEXt(png_ptr, info_ptr); - break; - } -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - case PNG_READ_zTXt_MODE: - { - png_push_read_zTXt(png_ptr, info_ptr); - break; - } -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - case PNG_READ_iTXt_MODE: - { - png_push_read_iTXt(png_ptr, info_ptr); - break; - } -#endif - case PNG_SKIP_MODE: - { - png_push_crc_finish(png_ptr); - break; - } - default: - { - png_ptr->buffer_size = 0; - break; - } - } -} - -/* Read any remaining signature bytes from the stream and compare them with - * the correct PNG signature. It is possible that this routine is called - * with bytes already read from the signature, either because they have been - * checked by the calling application, or because of multiple calls to this - * routine. - */ -void /* PRIVATE */ -png_push_read_sig(png_structp png_ptr, png_infop info_ptr) -{ - png_size_t num_checked = png_ptr->sig_bytes, - num_to_check = 8 - num_checked; - - if (png_ptr->buffer_size < num_to_check) - { - num_to_check = png_ptr->buffer_size; - } - - png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), - num_to_check); - png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check); - - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) - { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); - } - else - { - if (png_ptr->sig_bytes >= 8) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } - } -} - -void /* PRIVATE */ -png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_IHDR; - PNG_IDAT; - PNG_IEND; - PNG_PLTE; -#if defined(PNG_READ_bKGD_SUPPORTED) - PNG_bKGD; -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - PNG_cHRM; -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - PNG_gAMA; -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - PNG_hIST; -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - PNG_iCCP; -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - PNG_iTXt; -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - PNG_oFFs; -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - PNG_pCAL; -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - PNG_pHYs; -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - PNG_sBIT; -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - PNG_sCAL; -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - PNG_sRGB; -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - PNG_sPLT; -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - PNG_tEXt; -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - PNG_tIME; -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - PNG_tRNS; -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - PNG_zTXt; -#endif -#endif /* PNG_USE_LOCAL_ARRAYS */ - /* First we make sure we have enough data for the 4 byte chunk name - * and the 4 byte chunk length before proceeding with decoding the - * chunk data. To fully decode each of these chunks, we also make - * sure we have enough data in the buffer for the 4 byte CRC at the - * end of every chunk (except IDAT, which is handled separately). - */ - if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) - { - png_byte chunk_length[4]; - - if (png_ptr->buffer_size < 8) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - } - - if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); - } - else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); - - png_ptr->process_mode = PNG_READ_DONE_MODE; - png_push_have_end(png_ptr, info_ptr); - } -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_ptr->mode |= PNG_HAVE_IDAT; - png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); - if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_ptr->mode |= PNG_HAVE_PLTE; - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - } - } -#endif - else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); - } - else if (!png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) - { - /* If we reach an IDAT chunk, this means we have read all of the - * header chunks, and we can start reading the image (or if this - * is called after the image has been read - we have an error). - */ - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - { - if (png_ptr->push_length == 0) - return; - - if (png_ptr->mode & PNG_AFTER_IDAT) - png_error(png_ptr, "Too many IDAT's found"); - } - - png_ptr->idat_size = png_ptr->push_length; - png_ptr->mode |= PNG_HAVE_IDAT; - png_ptr->process_mode = PNG_READ_IDAT_MODE; - png_push_have_info(png_ptr, info_ptr); - png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; - png_ptr->zstream.next_out = png_ptr->row_buf; - return; - } -#if defined(PNG_READ_gAMA_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_bKGD_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); - } -#endif - else - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); - } - - png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; -} - -void /* PRIVATE */ -png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) -{ - png_ptr->process_mode = PNG_SKIP_MODE; - png_ptr->skip_length = skip; -} - -void /* PRIVATE */ -png_push_crc_finish(png_structp png_ptr) -{ - if (png_ptr->skip_length && png_ptr->save_buffer_size) - { - png_size_t save_size; - - if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) - save_size = (png_size_t)png_ptr->skip_length; - else - save_size = png_ptr->save_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - - png_ptr->skip_length -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (png_ptr->skip_length && png_ptr->current_buffer_size) - { - png_size_t save_size; - - if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) - save_size = (png_size_t)png_ptr->skip_length; - else - save_size = png_ptr->current_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_ptr->skip_length -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } - if (!png_ptr->skip_length) - { - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_crc_finish(png_ptr, 0); - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } -} - -void PNGAPI -png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) -{ - png_bytep ptr; - - ptr = buffer; - if (png_ptr->save_buffer_size) - { - png_size_t save_size; - - if (length < png_ptr->save_buffer_size) - save_size = length; - else - save_size = png_ptr->save_buffer_size; - - png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); - length -= save_size; - ptr += save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (length && png_ptr->current_buffer_size) - { - png_size_t save_size; - - if (length < png_ptr->current_buffer_size) - save_size = length; - else - save_size = png_ptr->current_buffer_size; - - png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } -} - -void /* PRIVATE */ -png_push_save_buffer(png_structp png_ptr) -{ - if (png_ptr->save_buffer_size) - { - if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) - { - png_size_t i,istop; - png_bytep sp; - png_bytep dp; - - istop = png_ptr->save_buffer_size; - for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; - i < istop; i++, sp++, dp++) - { - *dp = *sp; - } - } - } - if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > - png_ptr->save_buffer_max) - { - png_size_t new_max; - png_bytep old_buffer; - - if (png_ptr->save_buffer_size > PNG_SIZE_MAX - - (png_ptr->current_buffer_size + 256)) - { - png_error(png_ptr, "Potential overflow of save_buffer"); - } - new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; - old_buffer = png_ptr->save_buffer; - png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, - (png_uint_32)new_max); - png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); - png_free(png_ptr, old_buffer); - png_ptr->save_buffer_max = new_max; - } - if (png_ptr->current_buffer_size) - { - png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, - png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); - png_ptr->save_buffer_size += png_ptr->current_buffer_size; - png_ptr->current_buffer_size = 0; - } - png_ptr->save_buffer_ptr = png_ptr->save_buffer; - png_ptr->buffer_size = 0; -} - -void /* PRIVATE */ -png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, - png_size_t buffer_length) -{ - png_ptr->current_buffer = buffer; - png_ptr->current_buffer_size = buffer_length; - png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; - png_ptr->current_buffer_ptr = png_ptr->current_buffer; -} - -void /* PRIVATE */ -png_push_read_IDAT(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_IDAT; -#endif - if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) - { - png_byte chunk_length[4]; - - if (png_ptr->buffer_size < 8) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - - if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_error(png_ptr, "Not enough compressed data"); - return; - } - - png_ptr->idat_size = png_ptr->push_length; - } - if (png_ptr->idat_size && png_ptr->save_buffer_size) - { - png_size_t save_size; - - if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) - { - save_size = (png_size_t)png_ptr->idat_size; - /* check for overflow */ - if((png_uint_32)save_size != png_ptr->idat_size) - png_error(png_ptr, "save_size overflowed in pngpread"); - } - else - save_size = png_ptr->save_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); - png_ptr->idat_size -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (png_ptr->idat_size && png_ptr->current_buffer_size) - { - png_size_t save_size; - - if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) - { - save_size = (png_size_t)png_ptr->idat_size; - /* check for overflow */ - if((png_uint_32)save_size != png_ptr->idat_size) - png_error(png_ptr, "save_size overflowed in pngpread"); - } - else - save_size = png_ptr->current_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_ptr->idat_size -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } - if (!png_ptr->idat_size) - { - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_crc_finish(png_ptr, 0); - png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; - png_ptr->mode |= PNG_AFTER_IDAT; - } -} - -void /* PRIVATE */ -png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, - png_size_t buffer_length) -{ - int ret; - - if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length) - png_error(png_ptr, "Extra compression data"); - - png_ptr->zstream.next_in = buffer; - png_ptr->zstream.avail_in = (uInt)buffer_length; - for(;;) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK) - { - if (ret == Z_STREAM_END) - { - if (png_ptr->zstream.avail_in) - png_error(png_ptr, "Extra compressed data"); - if (!(png_ptr->zstream.avail_out)) - { - png_push_process_row(png_ptr); - } - - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - else if (ret == Z_BUF_ERROR) - break; - else - png_error(png_ptr, "Decompression Error"); - } - if (!(png_ptr->zstream.avail_out)) - { - if (( -#if defined(PNG_READ_INTERLACING_SUPPORTED) - png_ptr->interlaced && png_ptr->pass > 6) || - (!png_ptr->interlaced && -#endif - png_ptr->row_number == png_ptr->num_rows)) - { - if (png_ptr->zstream.avail_in) - png_warning(png_ptr, "Too much data in IDAT chunks"); - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - png_push_process_row(png_ptr); - png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; - png_ptr->zstream.next_out = png_ptr->row_buf; - } - else - break; - } -} - -void /* PRIVATE */ -png_push_process_row(png_structp png_ptr) -{ - png_ptr->row_info.color_type = png_ptr->color_type; - png_ptr->row_info.width = png_ptr->iwidth; - png_ptr->row_info.channels = png_ptr->channels; - png_ptr->row_info.bit_depth = png_ptr->bit_depth; - png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; - - png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); - - png_read_filter_row(png_ptr, &(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->prev_row + 1, - (int)(png_ptr->row_buf[0])); - - png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, - png_ptr->rowbytes + 1); - - if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) - png_do_read_transformations(png_ptr); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) - /* blow up interlaced rows to full size */ - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) - { - if (png_ptr->pass < 6) -/* old interface (pre-1.0.9): - png_do_read_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); - */ - png_do_read_interlace(png_ptr); - - switch (png_ptr->pass) - { - case 0: - { - int i; - for (i = 0; i < 8 && png_ptr->pass == 0; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */ - } - if (png_ptr->pass == 2) /* pass 1 might be empty */ - { - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - if (png_ptr->pass == 4 && png_ptr->height <= 4) - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - if (png_ptr->pass == 6 && png_ptr->height <= 4) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 1: - { - int i; - for (i = 0; i < 8 && png_ptr->pass == 1; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 2) /* skip top 4 generated rows */ - { - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 2: - { - int i; - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 4) /* pass 3 might be empty */ - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 3: - { - int i; - for (i = 0; i < 4 && png_ptr->pass == 3; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 4) /* skip top two generated rows */ - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 4: - { - int i; - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 6) /* pass 5 might be empty */ - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 5: - { - int i; - for (i = 0; i < 2 && png_ptr->pass == 5; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 6) /* skip top generated row */ - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 6: - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - if (png_ptr->pass != 6) - break; - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - } - else -#endif - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } -} - -void /* PRIVATE */ -png_read_push_finish_row(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; - - /* Width of interlace block. This is not currently used - if you need - * it, uncomment it here and in png.h - const int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; - */ - - /* Height of interlace block. This is not currently used - if you need - * it, uncomment it here and in png.h - const int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; - */ -#endif - - png_ptr->row_number++; - if (png_ptr->row_number < png_ptr->num_rows) - return; - - if (png_ptr->interlaced) - { - png_ptr->row_number = 0; - png_memset_check(png_ptr, png_ptr->prev_row, 0, - png_ptr->rowbytes + 1); - do - { - png_ptr->pass++; - if ((png_ptr->pass == 1 && png_ptr->width < 5) || - (png_ptr->pass == 3 && png_ptr->width < 3) || - (png_ptr->pass == 5 && png_ptr->width < 2)) - png_ptr->pass++; - - if (png_ptr->pass > 7) - png_ptr->pass--; - if (png_ptr->pass >= 7) - break; - - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - - png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, - png_ptr->iwidth) + 1; - - if (png_ptr->transformations & PNG_INTERLACE) - break; - - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - - } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); - } -} - -#if defined(PNG_READ_tEXt_SUPPORTED) -void /* PRIVATE */ -png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place tEXt"); - /* to quiet some compiler warnings */ - if(info_ptr == NULL) return; - } - -#ifdef PNG_MAX_MALLOC_64K - png_ptr->skip_length = 0; /* This may not be necessary */ - - if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ - { - png_warning(png_ptr, "tEXt chunk too large to fit in memory"); - png_ptr->skip_length = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_tEXt_MODE; -} - -void /* PRIVATE */ -png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp text; - png_charp key; - int ret; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - -#if defined(PNG_MAX_MALLOC_64K) - if (png_ptr->skip_length) - return; -#endif - - key = png_ptr->current_text; - - for (text = key; *text; text++) - /* empty loop */ ; - - if (text != key + png_ptr->current_text_size) - text++; - - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr->key = key; -#ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; -#endif - text_ptr->text = text; - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - png_ptr->current_text = NULL; - - if (ret) - png_warning(png_ptr, "Insufficient memory to store text chunk."); - } -} -#endif - -#if defined(PNG_READ_zTXt_SUPPORTED) -void /* PRIVATE */ -png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place zTXt"); - /* to quiet some compiler warnings */ - if(info_ptr == NULL) return; - } - -#ifdef PNG_MAX_MALLOC_64K - /* We can't handle zTXt chunks > 64K, since we don't have enough space - * to be able to store the uncompressed data. Actually, the threshold - * is probably around 32K, but it isn't as definite as 64K is. - */ - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "zTXt chunk too large to fit in memory"); - png_push_crc_skip(png_ptr, length); - return; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_zTXt_MODE; -} - -void /* PRIVATE */ -png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp text; - png_charp key; - int ret; - png_size_t text_size, key_size; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - - key = png_ptr->current_text; - - for (text = key; *text; text++) - /* empty loop */ ; - - /* zTXt can't have zero text */ - if (text == key + png_ptr->current_text_size) - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - return; - } - - text++; - - if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */ - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - return; - } - - text++; - - png_ptr->zstream.next_in = (png_bytep )text; - png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - - (text - key)); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - key_size = text - key; - text_size = 0; - text = NULL; - ret = Z_STREAM_END; - - while (png_ptr->zstream.avail_in) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - png_ptr->current_text = NULL; - png_free(png_ptr, key); - png_free(png_ptr, text); - return; - } - if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) - { - if (text == NULL) - { - text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out - + key_size + 1)); - png_memcpy(text + key_size, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - png_memcpy(text, key, key_size); - text_size = key_size + png_ptr->zbuf_size - - png_ptr->zstream.avail_out; - *(text + text_size) = '\0'; - } - else - { - png_charp tmp; - - tmp = text; - text = (png_charp)png_malloc(png_ptr, text_size + - (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out - + 1)); - png_memcpy(text, tmp, text_size); - png_free(png_ptr, tmp); - png_memcpy(text + text_size, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; - *(text + text_size) = '\0'; - } - if (ret != Z_STREAM_END) - { - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - else - { - break; - } - - if (ret == Z_STREAM_END) - break; - } - - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - - if (ret != Z_STREAM_END) - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - png_free(png_ptr, text); - return; - } - - png_ptr->current_text = NULL; - png_free(png_ptr, key); - key = text; - text += key_size; - - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; - text_ptr->key = key; -#ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; -#endif - text_ptr->text = text; - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - - if (ret) - png_warning(png_ptr, "Insufficient memory to store text chunk."); - } -} -#endif - -#if defined(PNG_READ_iTXt_SUPPORTED) -void /* PRIVATE */ -png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place iTXt"); - /* to quiet some compiler warnings */ - if(info_ptr == NULL) return; - } - -#ifdef PNG_MAX_MALLOC_64K - png_ptr->skip_length = 0; /* This may not be necessary */ - - if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ - { - png_warning(png_ptr, "iTXt chunk too large to fit in memory"); - png_ptr->skip_length = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_iTXt_MODE; -} - -void /* PRIVATE */ -png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) -{ - - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp key; - int comp_flag; - png_charp lang; - png_charp lang_key; - png_charp text; - int ret; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - -#if defined(PNG_MAX_MALLOC_64K) - if (png_ptr->skip_length) - return; -#endif - - key = png_ptr->current_text; - - for (lang = key; *lang; lang++) - /* empty loop */ ; - - if (lang != key + png_ptr->current_text_size) - lang++; - - comp_flag = *lang++; - lang++; /* skip comp_type, always zero */ - - for (lang_key = lang; *lang_key; lang_key++) - /* empty loop */ ; - lang_key++; /* skip NUL separator */ - - for (text = lang_key; *text; text++) - /* empty loop */ ; - - if (text != key + png_ptr->current_text_size) - text++; - - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = comp_flag + 2; - text_ptr->key = key; - text_ptr->lang = lang; - text_ptr->lang_key = lang_key; - text_ptr->text = text; - text_ptr->text_length = 0; - text_ptr->itxt_length = png_strlen(text); - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_ptr->current_text = NULL; - - png_free(png_ptr, text_ptr); - if (ret) - png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); - } -} -#endif - -/* This function is called when we haven't found a handler for this - * chunk. If there isn't a problem with the chunk itself (ie a bad chunk - * name or a critical chunk), the chunk is (currently) silently ignored. - */ -void /* PRIVATE */ -png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - png_uint_32 skip=0; - png_check_chunk_name(png_ptr, png_ptr->chunk_name); - - if (!(png_ptr->chunk_name[0] & 0x20)) - { -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - && png_ptr->read_user_chunk_fn == NULL -#endif - ) -#endif - png_chunk_error(png_ptr, "unknown critical chunk"); - - /* to quiet compiler warnings about unused info_ptr */ - if (info_ptr == NULL) - return; - } - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) - { - png_unknown_chunk chunk; - -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name); - chunk.data = (png_bytep)png_malloc(png_ptr, length); - png_crc_read(png_ptr, chunk.data, length); - chunk.size = length; -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - if(png_ptr->read_user_chunk_fn != NULL) - { - /* callback to user unknown chunk handler */ - if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0) - { - if (!(png_ptr->chunk_name[0] & 0x20)) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS) - png_chunk_error(png_ptr, "unknown critical chunk"); - } - png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); - } - else -#endif - png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); - png_free(png_ptr, chunk.data); - } - else -#endif - skip=length; - png_push_crc_skip(png_ptr, skip); -} - -void /* PRIVATE */ -png_push_have_info(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->info_fn != NULL) - (*(png_ptr->info_fn))(png_ptr, info_ptr); -} - -void /* PRIVATE */ -png_push_have_end(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->end_fn != NULL) - (*(png_ptr->end_fn))(png_ptr, info_ptr); -} - -void /* PRIVATE */ -png_push_have_row(png_structp png_ptr, png_bytep row) -{ - if (png_ptr->row_fn != NULL) - (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, - (int)png_ptr->pass); -} - -void PNGAPI -png_progressive_combine_row (png_structp png_ptr, - png_bytep old_row, png_bytep new_row) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - const int FARDATA png_pass_dsp_mask[7] = - {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; -#endif - if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ - png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); -} - -void PNGAPI -png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, - png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, - png_progressive_end_ptr end_fn) -{ - png_ptr->info_fn = info_fn; - png_ptr->row_fn = row_fn; - png_ptr->end_fn = end_fn; - - png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); -} - -png_voidp PNGAPI -png_get_progressive_ptr(png_structp png_ptr) -{ - return png_ptr->io_ptr; -} -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/.svn/pristine/03/03939e911e3c5083483e599efbc794dcbc354e8c.svn-base b/.svn/pristine/03/03939e911e3c5083483e599efbc794dcbc354e8c.svn-base deleted file mode 100644 index 7f870ff..0000000 --- a/.svn/pristine/03/03939e911e3c5083483e599efbc794dcbc354e8c.svn-base +++ /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 RHP.o - -# Configuration: - -CC = gcc - -all: CFLAGS = -DLINBPQ -MMD -g -rdynamic -fcommon -all: LDFLAGS = -l:libpaho-mqtt3a.a -l:libjansson.a -all: linbpq - - -nomqtt: CFLAGS = -DLINBPQ -MMD -fcommon -g -rdynamic -DNOMQTT -nomqtt: linbpq - -noi2c: CFLAGS = -DLINBPQ -MMD -DNOI2C -g -rdynamic -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/.svn/pristine/03/03b559519d295623ca3bf53396185358ecec2f30.svn-base b/.svn/pristine/03/03b559519d295623ca3bf53396185358ecec2f30.svn-base deleted file mode 100644 index fbdf53d..0000000 --- a/.svn/pristine/03/03b559519d295623ca3bf53396185358ecec2f30.svn-base +++ /dev/null @@ -1,232 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {8EFA1E59-8654-4A23-8102-AA77A074D57C} - CBPQ32 - Win32Proj - 10.0.17763.0 - - - - DynamicLibrary - v141 - NotSet - false - - - DynamicLibrary - v141 - MultiByte - - - - - - - - - - - - - - <_ProjectFileVersion>15.0.28127.55 - - - $(SolutionDir)$(Configuration)\ - C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(Configuration)\ - true - - - $(SolutionDir)$(Configuration)\ - C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(Configuration)\ - false - - - - 3 - ..\CInclude - true - - - Disabled - ..\CInclude;..\CommonSource;..\CKernel;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;BPQ32_EXPORTS;MDIKERNEL;_USE_32BIT_TIME_T;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - All - c:\devprogs\bpq32\listings\debug\ - true - Level3 - EditAndContinue - - - /section:_BPQDATA,srw %(AdditionalOptions) - WS2_32.Lib;winmm.lib;DbgHelp.lib;comctl32.lib;Iphlpapi.lib;setupapi.lib;..\lib\libconfig.lib;miniupnpc.lib;zlibstat.lib;%(AdditionalDependencies) - c:\DevProgs\BPQ32\bpq32.dll - false - LIBCMTD.lib;%(IgnoreSpecificDefaultLibraries) - ..\CommonSource\bpq32.def - true - true - c:\DevProgs\BPQ32\bpqdev.map - true - Windows - 8000000 - 4000000 - false - - 0x42000000 - ..\lib\bpq32.lib - MachineX86 - false - - - C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(Configuration)\$(ProjectName).bsc - - - "C:\Program Files\7-Zip\7z.exe" a C:\DevProgs\BPQ32\bpq32.zip C:\DevProgs\BPQ32\bpq32.dll && myxcopy /y c:\DevProgs\BPQ32\bpq32.dll c:\windows\SysWOW64\bpq32.dll && del C:\DevProgs\BPQ32\bpq32.dll - - - - - 3 - $(IntDir)$(ProjectName) - ..\CInclude - true - true - true - true - - - /D "MDIKERNEL" %(AdditionalOptions) - Disabled - false - ..\CInclude;..\CommonSource;..\CKernel;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;BPQ32_EXPORTS;MDIKERNEL;_USE_32BIT_TIME_T;%(PreprocessorDefinitions) - MultiThreaded - - All - c:\devprogs\bpq32\listings\ - Level3 - ProgramDatabase - - - /section:_BPQDATA,srw %(AdditionalOptions) - WS2_32.Lib;winmm.lib;DbgHelp.lib;comctl32.lib;setupapi.lib;..\lib\libconfig.lib;miniupnpc.lib;zlibstat.lib;%(AdditionalDependencies) - C:\DevProgs\BPQ32\bpq32.dll - ..\CommonSource\bpq32.def - true - c:\DevProgs\BPQ32\bpq32.pdb - true - c:\DevProgs\BPQ32\bpqpdn.map - true - Windows - true - true - - 0x42000000 - C:\Dev\Msdev2005\Projects\BPQ32\lib\bpq32.lib - MachineX86 - - - C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(Configuration)\$(ProjectName).bsc - - - "C:\Program Files\7-Zip\7z.exe" a C:\DevProgs\BPQ32\bpq32.zip C:\DevProgs\BPQ32\bpq32.dll && myxcopy /y c:\DevProgs\BPQ32\bpq32.dll c:\windows\SysWOW64\bpq32.dll && del C:\DevProgs\BPQ32\bpq32.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.svn/pristine/03/03cdb3a39c72fcf8c096e1920eefb311364f6a66.svn-base b/.svn/pristine/03/03cdb3a39c72fcf8c096e1920eefb311364f6a66.svn-base deleted file mode 100644 index aafa0e3..0000000 --- a/.svn/pristine/03/03cdb3a39c72fcf8c096e1920eefb311364f6a66.svn-base +++ /dev/null @@ -1,6780 +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 end of session code (58) -// 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) -// Fix L4 RTT (66) -// Fix RigConrol with Chanxx but no other settings (66) -// Add option to compress L2 frames (67) -// Sort Routes displays (67) -// Fix Ardop session premature close (70) -// Add timestamps to log entries in Web Driver windows (70) -// Generate stack backtrace if SIGSEGV or SIGABRT occur (Linux) (70) -// Remove some debug logging from L2 code (70) -// Fix compiling LinBPQ with nomqtt option (70) -// Improve handling of binary data in RHP interface (70) -// Fix sending KISS commands to multiport or multidropped TNCs (70) -// Add MHUV and MHLV commands (Verbose listing with timestamps in clock time) (70) -// Improvements to INP3 (71) -// Improvements to KAM driver including support for GTOR connects (71) -// Support IPv6 for Telnet outward connects (72) -// Fix decaying NETROM routes (72) -// Add OnlyVer2point0 config command (72) -// Add option to allow AX/UDP on a network using NAT (72) -// Include AGWAPI fixes from Martin KD6YAM to enable use with Paracon terminal (72) -// Fix 64 bit compatiblility issues with AGWAPI (73) -// Fix KAM Pactor Interlock (73) -// Fix Node map reporting, broken in .73 (74) -// Fixes to build on FreeBSD and NetBSD from jg1uaa (77) -// Fix to L4Compress from Steve G7TAJ (77) -// Fix possible FRMR when RNR is cleared by SREJ (78) -// Fix error in .77 L4Compress fix (mine, not Steve's!) (78) - -#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(); - - srand(time(NULL)); - - 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[len], "\\\r\n", RegLine); - strcat(RegLine, "\\\r\n"); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - len = 2; - } - - len += sprintf(&RegLine[len], "%02x,", 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[len], "\\\r\n"); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - len = 2; - } - - len += sprintf(&RegLine[len], "%02x,", Value[k]); - if (len > 76) - { - len += sprintf(&RegLine[len], "\\\r\n"); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - } - len += sprintf(&RegLine[len], "00,"); - } - - 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/.svn/pristine/04/048651e525d8fb5c544330e2b48b108f54a00e3d.svn-base b/.svn/pristine/04/048651e525d8fb5c544330e2b48b108f54a00e3d.svn-base deleted file mode 100644 index 53dd522..0000000 --- a/.svn/pristine/04/048651e525d8fb5c544330e2b48b108f54a00e3d.svn-base +++ /dev/null @@ -1,71 +0,0 @@ - -//Microsoft Developer Studio generated resource script. -// -//#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "windows.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.K.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK -#pragma code_page(1252) -#endif //_WIN32 - - -#define BPQICON 400 - -BPQICON ICON DISCARDABLE "..\\bpqicon.ico" - -// -// Version -// -#define TEXTVER "2. 0. 1. 1\0" -#define BINVER 2, 0, 1, 1 - -VS_VERSION_INFO VERSIONINFO - FILEVERSION BINVER - PRODUCTVERSION BINVER - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080904b0" - BEGIN - VALUE "Comments", "Program to hold BPQ32.dll in memory\0" - VALUE "CompanyName", " \0" - VALUE "FileDescription", "bpq32\0" - VALUE "FileVersion", TEXTVER - VALUE "InternalName", "bpq32\0" - VALUE "LegalCopyright", "Copyright © 2006-2011 G8BPQ\0" - VALUE "OriginalFilename", "bpq32.exe\0" - VALUE "ProductName", " bpq32\0" - VALUE "ProductVersion", TEXTVER - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1200 - END -END - - -#endif // not APSTUDIO_INVOKED diff --git a/.svn/pristine/04/04f3425d2266f8ab7e39728796f66092f2be0511.svn-base b/.svn/pristine/04/04f3425d2266f8ab7e39728796f66092f2be0511.svn-base deleted file mode 100644 index 8d243b1..0000000 --- a/.svn/pristine/04/04f3425d2266f8ab7e39728796f66092f2be0511.svn-base +++ /dev/null @@ -1,3356 +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 -*/ - -// -// DLL to provide AXIP support for G8BPQ switch in a -// 32bit environment, -// -// Uses BPQ EXTERNAL interface -// - -// Version 1.1 August 2001 -// -// Send to all matching entries in map table -// (Mainly for NODES braodcasts to multiple stations) -// - -// Version 1.2 September 2001 -// -// Support UDP as well as raw IP - -// Version 1.3 October 2001 -// -// Allow host names as well as numeric IP addresses -// -// Version 1.4 November 2002 -// -// Implement keepalive for NAT routers -// - -// Version 1.5 December 2004 -// -// Implement a "MHEARD" facility -// - - -// Version 1.6 August 2005 -// -// Treat NULL string in Registry as use current directory - - -// Version 1.7 December 2005 -// -// Create a separate thread to open sockets to avoid hang on XP SP2 - - -// Version 1.8 January 2006 -// -// Get config file location from Node (will check bpq directory) - - -// Version 1.9 March 2006 -// -// Allow multiple listening UDP ports -// Kick off resolver on EXTRESTART -// Remove redundant DYNAMIC processing - -// Version 1.10 October 2006 -// -// Add "Minimize to Tray" option -// Write diagnostics to BPQ console window instead of STDOUT - -// Version 1.11 October 2007 -// -// Sort MHeard and discard last entry if full -// Add Commands to re-read config file and manually add an ARP entry - -// Version 1.12 February 2008 -// -// Check received length -// Changes for unload of bpq32.dll -// Add Close Driver function -// Dynamic Load of bpq32.dll - -// Version 1.13 October 2008 -// -// Add Linux-style config of broadcast addressess - -// Version 1.13.2 January 2009 -// -// Add Start Minimized Option - -// Version 1.13.3 February 2009 -// -// Save Window positions - -// Version 1.13.4 March 2009 -// -// Fix loop on config file error - -// Version 1.14.1 April 2009 -// -// Add option to reject messages if sender is not in ARP Table -// Add option to add received calls to ARP Table - -// Version 1.15.1 May 2009 -// -// Add IP/TCP option - -// Version 1.15.2 August 2009 -// -// Extra Debug Output in TCP Mode -// Fix problem if TCP entry was first in table -// Include TCP sessions in MHEARD -// Add T flag to Resolver window fot TCP Sessions -// Set SO_KEEPALIVE and SO_CONDITIONAL_ACCEPT socket options - -// Version 1.15.4 August 2009 - -// Recycle Listening Socket if no connect for 60 mins -// Clear data connections if no data for 60 mins -// Repaint MH Window after clear. - -// Version 1.15.5 Spetmber 2010 - -// Add option to get config from bpq32.dll -// Moved to BPQ32.dll - no separate version number onw. - -// October 2010 - -// Allow multiple axip ports. - -// June 2011 - -// Add IPv6 support - -#define _CRT_SECURE_NO_DEPRECATE - -#include "cheaders.h" -#ifndef WIN32 -#include -#include -#include -#endif -#include "bpq32.h" - -#ifndef LINBPQ -#include "kernelresource.h" -#include -#endif - -#include - -#define WSA_ACCEPT WM_USER + 1 -#define WSA_DATA WM_USER + 2 -#define WSA_CONNECT WM_USER + 3 - -// Cater for only systems without IPV6_V6ONLY - -#ifndef IPV6_V6ONLY -#define IPV6_V6ONLY 0x27 -#endif - -#ifndef MAXGETHOSTSTRUCT -#define MAXGETHOSTSTRUCT 1024 -#endif - - -#define FEND 0xC0 // KISS CONTROL CODES -#define FESC 0xDB -#define TFEND 0xDC -#define TFESC 0xDD - -int ResolveDelay = 0; - - -extern BOOL StartMinimized; - -VOID * zalloc(int len); - -int ResetExtDriver(int num); -BOOL ProcessConfig(); -VOID FreeConfig(); - -extern UCHAR BPQDirectory[]; - - -extern int OffsetH, OffsetW; - -static void ResolveNames(struct AXIPPORTINFO * PORT); -void OpenSockets(struct AXIPPORTINFO * PORT); -void CloseSockets(struct AXIPPORTINFO * PORT); - - -static int CONVFROMAX25(char * incall, char * outcall); -void CreateMHWindow(struct AXIPPORTINFO * PORT); -int Update_MH_List(struct AXIPPORTINFO * PORT, UCHAR * ipad, char * call, char proto, short port, BOOL IPv6); -int Update_MH_KeepAlive(struct AXIPPORTINFO * PORT, struct in_addr ipad, char proto, short port); -unsigned short int compute_crc(unsigned char *buf,int l); -unsigned int find_arp(unsigned char * call); -BOOL add_arp_entry(struct AXIPPORTINFO * PORT, unsigned char * call, UCHAR * ip, int len, int port,unsigned char * name, - int keepalive, BOOL BCFlag, BOOL AutoAdded, int TCPMode, int SourcePort, BOOL IPv6, int noUpdate, int useSourcePort); -BOOL add_bc_entry(struct AXIPPORTINFO * PORT, unsigned char * call, int len); -BOOL convtoax25(unsigned char * callsign, unsigned char * ax25call, int * calllen); -static BOOL ReadConfigFile(int Port); -static int ProcessLine(char * buf, struct AXIPPORTINFO * PORT); -int CheckKeepalives(struct AXIPPORTINFO * PORT); -BOOL CopyScreentoBuffer(char * buff, struct AXIPPORTINFO * PORT); -int DumpFrameInHex(unsigned char * msg, int len); -VOID SendFrame(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp_table, UCHAR * buff, int txlen); -BOOL CheckSourceisResolvable(struct AXIPPORTINFO * PORT, char * call, int FromPort, VOID * rxaddr, int ToPort); -int DataSocket_Read(struct arp_table_entry * sockptr, SOCKET sock); -int GetMessageFromBuffer(struct AXIPPORTINFO * PORT, char * Buffer); -int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); -int KissDecode(UCHAR * inbuff, int len); -int Socket_Accept(int SocketId); -int Socket_Connect(int SocketId, int Error); -int Socket_Data(int sock, int error, int eventcode); -VOID TCPConnectThread(struct arp_table_entry * arp); -VOID __cdecl Debugprintf(const char * format, ...); -VOID __cdecl Consoleprintf(const char * format, ...); -BOOL OpenListeningSocket(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp); -VOID Format_Addr(unsigned char * Addr, char * Output, BOOL IPV6); -static void CreateResolverWindow(struct AXIPPORTINFO * PORT); -VOID SaveMDIWindowPos(HWND hWnd, char * RegKey, char * Value, BOOL Minimized); -VOID SaveAXIPCache(struct AXIPPORTINFO * PORT); -VOID GetAXIPCache(struct AXIPPORTINFO * PORT); - - -union -{ - struct sockaddr_in sinx; - struct sockaddr_in6 sinx6; -} sinx; -/* -union -{ - struct sockaddr_in destaddr; - struct sockaddr_in6 destaddr6; -} destaddr; -*/ - -#define IP_AXIP 93 // IP Protocol for AXIP - -#pragma pack(1) - -struct iphdr { -// unsigned int version:4; // Version of IP -// unsigned int h_len:4; // length of the header - unsigned char h_lenvers; // Version + length of the header - unsigned char tos; // Type of service - unsigned short total_len; // total length of the packet - unsigned short ident; // unique identifier - unsigned short frag_and_flags; // flags - unsigned char ttl; - unsigned char proto; // protocol (TCP, UDP etc) - unsigned short checksum; // IP checksum - - unsigned int sourceIP; - unsigned int destIP; - -}; - -#pragma pack() - - -#define TCPMaster 1 -#define TCPSlave 2 - -#define TCPListening 1 -#define TCPConnecting 2 -#define TCPConnected 4 - -#ifndef LINBPQ - -LOGFONT LFTTYFONT ; - -extern HFONT hFont ; - -RECT ResRect; -RECT MHRect; - -extern HKEY REGTREE; - -extern HWND ClientWnd, FrameWnd; -extern HMENU hMainFrameMenu, hBaseMenu, hWndMenu; -extern HBRUSH bgBrush; - -#endif - -//struct tagMSG Msg; - -//char buf[MAXGETHOSTSTRUCT]; - -int addrlen6 = sizeof(struct sockaddr_in6); -int addrlen = sizeof(struct sockaddr_in); - -extern unsigned short CRCTAB[]; -unsigned int AXIPInst = 0; - -char CantReplyList[512] = ""; // To suppress duplicate "Can't Reply" messages - -DWORD n; - -struct AXIPPORTINFO * Portlist[MaxBPQPortNo + 1]; - -int InitAXIP(int Port); - -int CurrentResEntries; - -static char ConfigClassName[]="CONFIG"; - -HANDLE hInstance; - -VOID SaveAXIPWindowPos(int port) -{ -#ifndef LINBPQ - struct AXIPPORTINFO * PORT; - char Key[80]; - - PORT = Portlist[port]; - - if (PORT == NULL) - return; - - sprintf(Key, "PACTOR\\PORT%d", port); - - SaveMDIWindowPos(PORT->hMHWnd, Key, "MHSize", PORT->MHMinimized); - SaveMDIWindowPos(PORT->hResWnd, Key, "ResSize", PORT->ResMinimized); -#endif - return; -} - - -static size_t ExtProc(int fn, int port, PMESSAGE buff) -{ - struct iphdr * iphdrptr; - int len,txlen=0,err,index,digiptr,i; - unsigned short int crc; - char rxbuff[5000]; - char axcall[7]; - char errmsg[100]; - union - { - struct sockaddr_in rxaddr; - struct sockaddr_in6 rxaddr6; - } RXaddr; - struct AXIPPORTINFO * PORT = Portlist[port]; - - switch (fn) - { - case 1: // poll - - // - // Check Keepalive timers - // - time(&PORT->ltime); - - if (PORT->ltime-PORT->lasttime >9 ) - { - PORT->lasttime=PORT->ltime; - CheckKeepalives(PORT); - } - - if (PORT->needip) - { - char call[7]; - - len = recvfrom(PORT->sock,rxbuff,500,0,(struct sockaddr *)&RXaddr.rxaddr,&addrlen); - - if (len == -1) - { - err = WSAGetLastError(); - } - else - { - iphdrptr=(struct iphdr *)&rxbuff; - - if (len == ntohs(iphdrptr->total_len)) - { - len-=20; // IP HEADER - - if (memcmp(&rxbuff[20], "Keepalive", 9) == 0 ) - { - if (PORT->MHEnabled) - Update_MH_KeepAlive(PORT, RXaddr.rxaddr.sin_addr,'I',93); - - return 0; - } - crc = compute_crc(&rxbuff[20], len); - - if (crc == 0xf0b8) // Good CRC - { - len-=2; // Remove CRC - - if (len > MAXDATA) - { - sprintf(errmsg,"BPQAXIP Invalid Msg Len=%d Source=%s",len,inet_ntoa(RXaddr.rxaddr.sin_addr)); - OutputDebugString(errmsg); - DumpFrameInHex(&rxbuff[20], len); - return 0; - } - - memcpy(&buff->DEST, &rxbuff[20],len); - len += (3 + sizeof(void *)); - - PutLengthinBuffer((PDATAMESSAGE)buff, len); // Needed for arm5 portability - - memcpy(call, &buff->ORIGIN, 7); - call[6] &= 0x7e; // Mask End of Address bit - - // - // Do MH Proccessing if enabled - // - - if (PORT->MHEnabled) - Update_MH_List(PORT, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, &buff->ORIGIN[0], 'I', 93, 0); - - // Check Exclude - - if (CheckExcludeList(call) == 0) - return 0; - - - if (PORT->Checkifcanreply) - { - if (CheckSourceisResolvable(PORT, call, 0, &RXaddr, 0)) - - return 1; - - else - // Can't reply. If AutoConfig is set, add to table and accept, else reject - - if (PORT->AutoAddARP) - return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, 7, 0, inet_ntoa(RXaddr.rxaddr.sin_addr), 0, PORT->AutoAddBC, TRUE, 0, 0, FALSE, 0, 0); - else - { - char From[11] = "|"; - From[ConvFromAX25(call, &From[1]) + 1] = 0; - if (strstr(CantReplyList, From) == 0) - { - if (strlen(CantReplyList) < 500); - strcat(CantReplyList, From); - Debugprintf("AXIP Packet from %s dropped - can't reply", &From[1]); - } - return 0; - } - } - else - return(1); - } - // - // CRC Error - // - - sprintf(errmsg,"BPQAXIP Invalid CRC=%d Source=%s",crc,inet_ntoa(RXaddr.rxaddr.sin_addr)); - OutputDebugString(errmsg); - - return (0); - } - - // - // Bad Length - // - - return (0); - } - } - - for (i=0;iNumberofUDPPorts;i++) - { - char call[7]; - - if (PORT->IPv6[i]) - len = recvfrom(PORT->udpsock[i],rxbuff,500,0,(struct sockaddr *)&RXaddr.rxaddr, &addrlen6); - else - len = recvfrom(PORT->udpsock[i],rxbuff,500,0,(struct sockaddr *)&RXaddr.rxaddr, &addrlen); - - if (len == -1) - { - err = WSAGetLastError(); - } - else - { - if (memcmp(rxbuff, "Keepalive", 9) == 0 ) - { - if (PORT->MHEnabled) - Update_MH_KeepAlive(PORT, RXaddr.rxaddr.sin_addr, 'U', PORT->udpport[i]); - - continue; - } - - crc = compute_crc(&rxbuff[0], len); - - if (crc == 0xf0b8) // Good CRC - { - len-=2; // Remove CRC - - if (len > MAXDATA) - { - sprintf(errmsg,"BPQAXIP Invalid Msg Len=%d Source=%s Port %d",len,inet_ntoa(RXaddr.rxaddr.sin_addr),PORT->udpport[i]); - OutputDebugString(errmsg); - DumpFrameInHex(&rxbuff[0], len); - return 0; - } - - memcpy(&buff->DEST, &rxbuff[0], len); - - len += (3 + sizeof(void *)); - - PutLengthinBuffer((PDATAMESSAGE)buff, len); - - memcpy(call, &buff->ORIGIN, 7); - - call[6] &= 0x7e; // Mask End of Address bit - - // - // Do MH Proccessing if enabled - // - - if (PORT->MHEnabled) - if (PORT->IPv6[i]) - Update_MH_List(PORT, (UCHAR *)&RXaddr.rxaddr6.sin6_addr, &buff->ORIGIN[0], 'U', PORT->udpport[i], TRUE); - else - Update_MH_List(PORT, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, &buff->ORIGIN[0], 'U', PORT->udpport[i], FALSE); - - // Check Exclude - - if (CheckExcludeList(call) == 0) - return 0; - - if (PORT->Checkifcanreply) - { - if (CheckSourceisResolvable(PORT, call, htons(RXaddr.rxaddr.sin_port), &RXaddr, PORT->udpport[i])) - return 1; - else - { - // Can't reply. If AutoConfig is set, add to table and accept, else reject - - if (PORT->AutoAddARP) - if (PORT->IPv6[i]) - { - char Addr[80]; - Format_Addr((UCHAR *)&RXaddr.rxaddr6.sin6_addr, Addr, TRUE); - return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr6.sin6_addr, 7, htons(RXaddr.rxaddr6.sin6_port), Addr, 0, PORT->AutoAddBC, TRUE, 0, PORT->udpport[i], TRUE, 0, 0); - } - else - return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, 7, htons(RXaddr.rxaddr.sin_port), inet_ntoa(RXaddr.rxaddr.sin_addr), 0, PORT->AutoAddBC, TRUE, 0, PORT->udpport[i], FALSE, 0, 0); - else - { - char From[11] = "|"; - From[ConvFromAX25(call, &From[1]) + 1] = 0; - if (strstr(CantReplyList, From) == 0) - { - if (strlen(CantReplyList) < 500); - strcat(CantReplyList, From); - Debugprintf("AXIP Packet from %s dropped - can't reply", &From[1]); - } - return 0; - } - } - } - else - return(1); - } - - // - // CRC Error - // - - sprintf(errmsg,"BPQAXIP Invalid CRC=%d Source=%s Port %d",crc,inet_ntoa(RXaddr.rxaddr.sin_addr),PORT->udpport[i]); - Debugprintf(errmsg); - rxbuff[len] = 0; - Debugprintf(rxbuff); - - - return (0); - } - } - - if (PORT->NeedTCP) - { - len = GetMessageFromBuffer(PORT, rxbuff); - - if (len) - { - len = KissDecode(rxbuff, len-1); // Len includes FEND - len -= 2; // Ignore Checksum - - if (len < MAXDATA) - { - memcpy(&buff->DEST, &rxbuff[0], len); - len += (3 + sizeof(void *)); - - PutLengthinBuffer((PDATAMESSAGE)buff, len); // fix big endian issue - return 1; - } - else - { - Debugprintf("Oversized AX/TCP frame %d", len); - return 0; - } - } - } - - return (0); - - case 2: // send - -// txlen=(buff[6]<<8) + buff[5] - 5; // Len includes buffer header (7) but we add crc - - txlen = GetLengthfromBuffer((PDATAMESSAGE)buff) - (MSGHDDRLEN - 2); // 2 for CRC - - crc=compute_crc(&buff->DEST[0], txlen - 2); - crc ^= 0xffff; - - buff->DEST[txlen - 2] = (crc & 0xff); - buff->DEST[txlen - 1] = (crc >> 8); - - memcpy(axcall, &buff->DEST, 7); // Set to send to dest addr - - // if digis are present, scan down list for first non-used call - - if (buff->ORIGIN[6] == 0) - { - // end of addr bit not set, so scan digis - - digiptr = 13; // start of first digi - - while (((buff->ORIGIN[digiptr] & 0x80) == 0x80) && ((buff->ORIGIN[digiptr] & 0x1) == 0)) - { - // This digi has been used, and it is not the last - - digiptr+=7; - } - - // if this has not been used, use it - - if ((buff->ORIGIN[digiptr] & 0x80) == 0) - memcpy(axcall,&buff->ORIGIN[digiptr - 6], 7); // get next call - } - - axcall[6] &= 0x7e; - -// If addresses to a broadcast address, send to all entries - - for (i=0; i< PORT->NumberofBroadcastAddreses; i++) - { - if (memcmp(axcall, PORT->BroadcastAddresses[i].callsign, 7) == 0) - { - for (index = 0; index < PORT->arp_table_len; index++) - { - if (PORT->arp_table[index].BCFlag) - SendFrame(PORT, &PORT->arp_table[index], &buff->DEST[0], txlen); - } - return 0; - } - } - -// Send to all matching calls in arp table - - index = 0; - - while (index < PORT->arp_table_len) - { - if (memcmp(PORT->arp_table[index].callsign,axcall,PORT->arp_table[index].len) == 0) - { - SendFrame(PORT, &PORT->arp_table[index],&buff->DEST[0], txlen); - } - index++; - } - return (0); - - case 3: // CHECK IF OK TO SEND - - return (0); // OK - - case 4: // reinit - - CloseSockets(PORT); - - if (ProcessConfig()) - { - FreeConfig(); - ReadConfigFile(port); - } - else - Consoleprintf("Failed to reread config file - leaving config unchanged"); - - _beginthread(OpenSockets, 0, PORT ); - - GetAXIPCache(PORT); - - ResolveDelay = 2; -#ifndef LINBPQ - InvalidateRect(PORT->hResWnd,NULL,TRUE); -#endif - break; - - case 5: // Terminate - - CloseSockets(PORT); -#ifndef LINBPQ - SendMessage(PORT->hMHWnd, WM_CLOSE, 0, 0); - SendMessage(PORT->hResWnd, WM_CLOSE, 0, 0); -#endif - break; - } - return (0); -} - -VOID SendFrame(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp_table, UCHAR * buff, int txlen) -{ - int i; - SOCKET txsock, SourceSocket; - - if (arp_table->TCPMode) - { - if (arp_table->TCPState == TCPConnected) - { - char outbuff[1000]; - int newlen; - - newlen = KissEncode(buff, outbuff, txlen); - send(arp_table->TCPSock, outbuff, newlen, 0); - } - - return; - } - - // Select source port by choosing right socket - - // First Set Default for Protocol - - for (i = 0; i < PORT->NumberofUDPPorts; i++) - { - if (PORT->IPv6[i] == arp_table->IPv6) - { - SourceSocket = PORT->udpsock[i]; // Use as source socket, therefore source port - break; - } - } - - for (i = 0; i < PORT->NumberofUDPPorts; i++) - { - if (PORT->udpport[i] == arp_table->SourcePort && PORT->IPv6[i] == arp_table->IPv6) - { - SourceSocket = PORT->udpsock[i]; // Use as source socket, therefore source port - break; - } - } - - if (arp_table->error == 0) - { - int sent = 0; - - if (arp_table->port == 0) txsock = PORT->sock; else txsock = SourceSocket; - - if (arp_table->IPv6) - sent = sendto(txsock, buff, txlen, 0, (struct sockaddr *)&arp_table->destaddr6, sizeof(arp_table->destaddr6)); - else - if (arp_table->destaddr.sin_addr.s_addr) - sent = sendto(txsock, buff, txlen, 0, (struct sockaddr *)&arp_table->destaddr, sizeof(arp_table->destaddr)); - - if (sent != txlen) - { - int i = GetLastError(); -// perror("Sendto"); - } - - // reset Keepalive Timer - - arp_table->keepalive=arp_table->keepaliveinit; - } -} - -unsigned short int compute_crc_ccitt(unsigned char *buf, int len); -unsigned short CCCITTChecksum(unsigned char* data, unsigned int length); - -VOID * AXIPExtInit(struct PORTCONTROL * PortEntry) -{ -// char Msg[10] = {0xD0, 01, 00, 0x11, 00, 0x0B}; -// unsigned short crc; - -// crc = CCCITTChecksum(Msg, 4); - -// crc = CalcCRC(Msg, 4); - - WritetoConsole("AXIP "); - - InitAXIP(PortEntry->PORTNUMBER); - - WritetoConsole("\n"); - - return ExtProc; -} - -int InitAXIP(int Port) -{ - struct AXIPPORTINFO * PORT; - - // - // Read config first, to get UDP info if needed - // - - if (!ReadConfigFile(Port)) - return (FALSE); - - PORT = Portlist[Port]; - - if (PORT == NULL) - return FALSE; - - PORT->Port = Port; - - GetAXIPCache(PORT); // Prime resolver from cache - - // - // Start Resolver Thread if needed - // - - if (PORT->NeedResolver) - { - CreateResolverWindow(PORT); - _beginthread(ResolveNames, 0, PORT ); - } - - time(&PORT->lasttime); // Get initial time value - - _beginthread(OpenSockets, 0, PORT ); - - // Start TCP outward connect threads - // - // Open MH window if needed - - if (PORT->MHEnabled) - CreateMHWindow(PORT); - - return (TRUE); -} - -void OpenSockets(struct AXIPPORTINFO * PORT) -{ - char Msg[255]; - int err; - u_long param=1; - BOOL bcopt=TRUE; - int i; - int index = 0; - struct arp_table_entry * arp; - - // Moved from InitAXIP, to avoid hang if started too early on XP SP2 - - // Create and bind socket - - if (PORT->needip) - { - PORT->sock=socket(AF_INET,SOCK_RAW,IP_AXIP); - - if (PORT->sock == INVALID_SOCKET) - { - err = WSAGetLastError(); - sprintf(Msg, "AXIP Failed to create RAW socket - Error %d\n", err); - WritetoConsole(Msg); - } - else - { - - ioctl (PORT->sock,FIONBIO,¶m); - - setsockopt (PORT->sock,SOL_SOCKET,SO_BROADCAST,(const char FAR *)&bcopt,4); - - sinx.sinx.sin_family = AF_INET; - sinx.sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sinx.sin_port = 0; - - if (bind(PORT->sock, (struct sockaddr *) &sinx, sizeof(sinx)) != 0 ) - { - // - // Bind Failed - // - err = WSAGetLastError(); - sprintf(Msg, "Bind Failed for RAW socket - error code = %d", err); - WritetoConsole(Msg); - return; - } - } - } - - for (i=0;iNumberofUDPPorts;i++) - { - int ret; - - if (PORT->IPv6[i]) - PORT->udpsock[i]=socket(AF_INET6,SOCK_DGRAM,0); - else - PORT->udpsock[i]=socket(AF_INET,SOCK_DGRAM,0); - - if (PORT->udpsock[i] == INVALID_SOCKET) - { - WritetoConsole("Failed to create UDP socket"); - err = WSAGetLastError(); - continue; - } - - ioctl (PORT->udpsock[i],FIONBIO,¶m); - - setsockopt (PORT->udpsock[i],SOL_SOCKET,SO_BROADCAST,(const char FAR *)&bcopt,4); - -#ifndef WIN32 - - if (PORT->IPv6[i]) - if (setsockopt(PORT->udpsock[i], IPPROTO_IPV6, IPV6_V6ONLY, ¶m, sizeof(param)) < 0) - perror("setting option IPV6_V6ONLY"); - -#endif - - if (PORT->IPv6[i]) - { - sinx.sinx.sin_family = AF_INET6; - memset (&sinx.sinx6.sin6_addr, 0, 16); - } - else - { - sinx.sinx.sin_family = AF_INET; - sinx.sinx.sin_addr.s_addr = INADDR_ANY; - } - - sinx.sinx.sin_port = htons(PORT->udpport[i]); - - if (PORT->IPv6[i]) - ret = bind(PORT->udpsock[i], (struct sockaddr *) &sinx.sinx, sizeof(sinx.sinx6)); - else - ret = bind(PORT->udpsock[i], (struct sockaddr *) &sinx.sinx, sizeof(sinx.sinx)); - - if (ret != 0) - { - // Bind Failed - - err = WSAGetLastError(); - sprintf(Msg, "Bind Failed for UDP socket %d - error code = %d", PORT->udpport[i], err); - WritetoConsole(Msg); - continue; - } - } - - // Open any TCP sockets - - while (index < PORT->arp_table_len) - { - arp = &PORT->arp_table[index++]; - - if (arp->TCPMode == TCPMaster) - { - arp->TCPBuffer=malloc(4000); - arp->TCPState = 0; - - if (arp->TCPThreadID == 0) - { - arp->TCPThreadID = _beginthread(TCPConnectThread, 0, arp); - Debugprintf("TCP Connect thread created for %s Handle %x", arp->hostname, arp->TCPThreadID); - } - continue; - } - - if (arp->TCPMode == TCPSlave) - { - OpenListeningSocket(PORT, arp); - } - } -} -int OpenListeningSocket(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp) -{ - char Msg[255]; - struct sockaddr_in * psin; - BOOL bOptVal = TRUE; - struct sockaddr_in local_sin; /* Local socket - internet style */ - u_long param = 1; - arp->TCPBuffer = malloc(4000); - arp->TCPState = 0; - - arp->TCPListenSock = socket(AF_INET, SOCK_STREAM, 0); - - ioctl (arp->TCPListenSock, FIONBIO, ¶m); - - if (arp->TCPListenSock == INVALID_SOCKET) - { - sprintf(Msg, "socket() failed error %d", WSAGetLastError()); - WritetoConsole(Msg); - return FALSE; - } - -// Debugprintf("TCP Listening Socket Created - socket %d port %d ", arp->TCPListenSock, arp->port); - - setsockopt (arp->TCPListenSock, SOL_SOCKET, SO_REUSEADDR, (char *)¶m,4); - - psin=&local_sin; - psin->sin_family = AF_INET; - psin->sin_addr.s_addr = htonl(INADDR_ANY); // Local Host Only - - psin->sin_port = htons(arp->port); /* Convert to network ordering */ - - if (bind(arp->TCPListenSock , (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) - { - sprintf(Msg, "bind(sock) failed Port %d Error %d\n", arp->port, WSAGetLastError()); - Debugprintf(Msg); - closesocket(arp->TCPListenSock); - - return FALSE; - } - - if (listen(arp->TCPListenSock, 1) < 0) - { - sprintf(Msg, "listen(sock) failed Error %d", WSAGetLastError()); - Debugprintf(Msg); - closesocket(arp->TCPListenSock); - return FALSE; - } - - arp->TCPState = TCPListening; - return TRUE; -} - -void CloseSockets(struct AXIPPORTINFO * PORT) -{ - int i; - int index = 0; - struct arp_table_entry * arp; - - if (PORT->needip) - closesocket(PORT->sock); - - for (i=0;iNumberofUDPPorts;i++) - { - closesocket(PORT->udpsock[i]); - } - - // Close any open or listening TCP sockets - - while (index < PORT->arp_table_len) - { - arp = &PORT->arp_table[index++]; - - if (arp->TCPMode == TCPMaster) - { - if (arp->TCPState) - { - closesocket(arp->TCPSock); - arp->TCPSock = 0; - } - continue; - } - - if (arp->TCPMode == TCPSlave) - { - if (arp->TCPState) - { - closesocket(arp->TCPSock); - arp->TCPSock = 0; - } - - closesocket(arp->TCPListenSock); - continue; - } - } - return ; -} - -#ifndef LINBPQ - -static LRESULT CALLBACK AXResWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - PAINTSTRUCT ps; - HDC hdc; - HFONT hOldFont ; - char line[100]; - char outcall[10]; - int index,displayline; - struct AXIPPORTINFO * PORT; - MINMAXINFO * mmi; - int nScrollCode,nPos; - int i, Port; - char Flags[10]; - struct arp_table_entry * arp; - - // Find our PORT Entry - - for (Port = 1; Port < 33; Port++) - { - PORT = Portlist[Port]; - if (PORT == NULL) - continue; - - if (PORT->hResWnd == hWnd) - break; - } - - if (PORT == NULL) - return DefMDIChildProc(hWnd, message, wParam, lParam); - - i=1; - - switch (message) - { - case WM_GETMINMAXINFO: - - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = 600; - mmi->ptMaxSize.y = PORT->MaxResWindowlength; - mmi->ptMaxTrackSize.x = 55600; - mmi->ptMaxTrackSize.y = PORT->MaxResWindowlength; - - 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_PTR)PORT->hResMenu, "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_CHAR: - - if (PORT->MHEnabled == FALSE && PORT->MHAvailable) - { - PORT->MHEnabled=TRUE; - CreateMHWindow(PORT); - ShowWindow(PORT->hMHWnd, SW_RESTORE); // In case Start Minimized set - } - break; - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - - if (wmId == BPQREREAD) - { - CloseSockets(PORT); - - if (ProcessConfig()) - { - FreeConfig(); - ReadConfigFile(Port); - } - else - Consoleprintf("Failed to reread config file - leaving config unchanged"); - - _beginthread(OpenSockets, 0, PORT); - - ResolveDelay = 2; - InvalidateRect(hWnd,NULL,TRUE); - - return 0; - } - - if (wmId == BPQADDARP) - { - if (PORT->ConfigWnd == 0) - { - PORT->ConfigWnd=CreateDialog(hInstance, ConfigClassName, 0, NULL); - - if (!PORT->ConfigWnd) - { - return (FALSE); - } - ShowWindow(PORT->ConfigWnd, SW_SHOW); - UpdateWindow(PORT->ConfigWnd); - } - - SetForegroundWindow(PORT->ConfigWnd); - - return(0); - } - 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_RESTORE: - - PORT->ResMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - - break; - - case SC_MINIMIZE: - - PORT->ResMinimized = TRUE; - - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - - case WM_VSCROLL: - - nScrollCode = (int) LOWORD(wParam); // scroll bar value - nPos = (short int) HIWORD(wParam); // scroll box position - - //hwndScrollBar = (HWND) lParam; // handle of scroll bar - - if (nScrollCode == SB_LINEUP || nScrollCode == SB_PAGEUP) - { - PORT->baseline--; - if (PORT->baseline <0) - PORT->baseline=0; - } - - if (nScrollCode == SB_LINEDOWN || nScrollCode == SB_PAGEDOWN) - { - PORT->baseline++; - if (PORT->baseline > PORT->arp_table_len) - PORT->baseline = PORT->arp_table_len; - } - - if (nScrollCode == SB_THUMBTRACK) - { - PORT->baseline=nPos; - } - - SetScrollPos(hWnd,SB_VERT,PORT->baseline,TRUE); - - InvalidateRect(hWnd,NULL,TRUE); - break; - - - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - - hOldFont = SelectObject( hdc, hFont) ; - - index = PORT->baseline; - displayline=0; - - while (index < PORT->arp_table_len) - { - arp = &PORT->arp_table[index]; - - Flags[0] = 0; - - if (arp->BCFlag) - strcat(Flags, "B "); - - if (arp->TCPState == TCPConnected) - strcat(Flags, "C "); - - if (arp->AutoAdded) - strcat(Flags, "A"); - - if (arp->ResolveFlag && arp->error != 0) - { - // resolver error - Display Error Code - sprintf(PORT->hostaddr,"Error %d",arp->error); - } - else - { - if (arp->IPv6) - Format_Addr((unsigned char *)&arp->destaddr6.sin6_addr, PORT->hostaddr, TRUE); - else - Format_Addr((unsigned char *)&arp->destaddr.sin_addr, PORT->hostaddr, FALSE); - } - - CONVFROMAX25(arp->callsign,outcall); - - if (arp->port == arp->SourcePort) - i=sprintf(line,"%.10s = %.64s %d = %-.30s %s ", - outcall, - arp->hostname, - arp->port, - PORT->hostaddr, - Flags); - else - i=sprintf(line,"%.10s = %.64s %d<%d = %-.30s %s ", - outcall, - arp->hostname, - arp->port, - arp->SourcePort, - PORT->hostaddr, - Flags); - - TextOut(hdc, 0, (displayline++)*14+2, line, i); - - index++; - } - - SelectObject( hdc, hOldFont ) ; - EndPaint (hWnd, &ps); - - break; - - case WM_DESTROY: - -// PostQuitMessage(0); - - break; - - - default: - return DefMDIChildProc(hWnd, message, wParam, lParam); - - } - return DefMDIChildProc(hWnd, message, wParam, lParam); - -} - -LRESULT FAR PASCAL ConfigWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) -{ - int cmd,id,i; - HWND hwndChild; - BOOL OK1,OK2,OK3; - - char call[10], host[65]; - int Interval; - int calllen; - int port; - char axcall[7]; - BOOL UDPFlag, BCFlag; - struct AXIPPORTINFO * PORT; - int useSourcePort = 0; - - for (i=1; i <= MAXBPQPORTS; i++) - { - PORT = Portlist[i]; - if (PORT == NULL) - continue; - - if (PORT->ConfigWnd == hWnd) - break; - } - - switch (message) - { - case WM_CTLCOLORDLG: - - return (LRESULT)bgBrush; - - case WM_COMMAND: - - id = LOWORD(wParam); - hwndChild = (HWND)(UINT)lParam; - cmd = HIWORD(wParam); - - switch (id) - { - case ID_SAVE: - - OK1=GetDlgItemText(PORT->ConfigWnd,1001,(LPSTR)call,10); - OK2=GetDlgItemText(PORT->ConfigWnd,1002,(LPSTR)host,64); - OK3=1; - - for (i=0;i<7;i++) - call[i] = toupper(call[i]); - - UDPFlag=IsDlgButtonChecked(PORT->ConfigWnd,1004); - BCFlag=IsDlgButtonChecked(PORT->ConfigWnd,1005); - - if (UDPFlag) - port=GetDlgItemInt(PORT->ConfigWnd,1003,&OK3,FALSE); - else - port=0; - - Interval=0; - - if (OK1 && OK2 && OK3==1) - { - if (convtoax25(call,axcall,&calllen)) - { - add_arp_entry(PORT, axcall,0,calllen,port,host,Interval, BCFlag, FALSE, 0, port, FALSE, 0, useSourcePort); - ResolveDelay = 2; - return(DestroyWindow(hWnd)); - } - } - - // Validation failed - - if (!OK1) SetDlgItemText(PORT->ConfigWnd,1001,"????"); - if (!OK2) SetDlgItemText(PORT->ConfigWnd,1002,"????"); - if (!OK3) SetDlgItemText(PORT->ConfigWnd,1003,"????"); - - break; - - case ID_CANCEL: - - return(DestroyWindow(hWnd)); - } - break; - -// case WM_CLOSE: - -// return(DestroyWindow(hWnd)); - - case WM_DESTROY: - - PORT->ConfigWnd=0; - - return(0); - - } - - return (DefWindowProc(hWnd, message, wParam, lParam)); - -} -#endif - -static void CreateResolverWindow(struct AXIPPORTINFO * PORT) -{ -#ifndef LINBPQ - - int WindowParam; - WNDCLASS wc; - char WindowTitle[100]; - int retCode, Type, Vallen; - HKEY hKey=0; - char Size[80]; - - HWND hResWnd; - char Key[80]; - RECT Rect = {0, 0, 300, 300}; - int Top, Left, Width, Height; - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", PORT->Port); - - retCode = RegOpenKeyEx (REGTREE, Key, 0, KEY_QUERY_VALUE, &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"ResSize",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, &PORT->ResMinimized); - - if (Rect.top < - 500 || Rect.left < - 500) - { - Rect.left = 0; - Rect.top = 0; - Rect.right = 600; - Rect.bottom = 400; - } - - if (Rect.top < OffsetH) // Make sure not off top of MDI frame - { - int Error = OffsetH - Rect.top; - Rect.top += Error; - Rect.bottom += Error; - } - - RegCloseKey(hKey); - } - - Top = Rect.top; - Left = Rect.left; - Width = Rect.right - Left; - Height = Rect.bottom - Top; - - // Register the window classes - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)AXResWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = NULL ; - wc.lpszClassName = "AXAppName"; - - RegisterClass(&wc); - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.lpfnWndProc = ConfigWndProc; - wc.lpszClassName = ConfigClassName; - RegisterClass(&wc); - - WindowParam = WS_OVERLAPPEDWINDOW | WS_VSCROLL; - - sprintf(WindowTitle,"AXIP Port %d Resolver", PORT->Port); - - PORT->hResWnd = hResWnd = CreateMDIWindow("AXAppName", WindowTitle, WindowParam, - Left - (OffsetW /2), Top - OffsetH + 4, Width, Height, ClientWnd, hInstance, 1234); - - - PORT->hResMenu = CreatePopupMenu(); - AppendMenu(PORT->hResMenu, MF_STRING, BPQREREAD, "ReRead Config"); - AppendMenu(PORT->hResMenu, MF_STRING, BPQADDARP, "Add Entry"); - - SetScrollRange(hResWnd,SB_VERT, 0, PORT->arp_table_len, TRUE); - - if (PORT->ResMinimized) - ShowWindow(hResWnd, SW_SHOWMINIMIZED); - else - ShowWindow(hResWnd, SW_RESTORE); -#endif -} -extern HWND hWndPopup; - - -static void ResolveNames(struct AXIPPORTINFO * PORT) -{ - int count = 0; - - PORT->ResolveNamesThreadId = GetCurrentThreadId(); // Detect if another started - - while(TRUE) - { - count++; // So we can trap first few loops - - ResolveDelay = 15 * 60; - - for (PORT->ResolveIndex=0; PORT->ResolveIndex < PORT->arp_table_len; PORT->ResolveIndex++) - { - struct arp_table_entry * arp = &PORT->arp_table[PORT->ResolveIndex]; - - if (arp->ResolveFlag) - { - struct addrinfo hints, *res = 0; - int n; - BOOL UseV6 = FALSE; - BOOL ForceV4 = FALSE; - - if (_memicmp(arp->hostname, "ipv6:", 5) == 0) - UseV6 = TRUE; - else if (_memicmp(arp->hostname, "ipv4:", 5) == 0) - ForceV4 = TRUE; - - memset(&hints, 0, sizeof hints); - hints.ai_socktype = SOCK_DGRAM; - - if (UseV6) - { - hints.ai_family = AF_INET6; // use IPv6 - n = getaddrinfo(&arp->hostname[5], NULL, &hints, &res); - } - else if (ForceV4) - { - hints.ai_family = AF_INET; // use IPv4 - n = getaddrinfo(&arp->hostname[5], NULL, &hints, &res); - } - else if (PORT->PortIPv6) // Can use IPv6 - { - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - n = getaddrinfo(arp->hostname, NULL, &hints, &res); - } - else - { - hints.ai_family = AF_INET; // use IPv4 only - n = getaddrinfo(arp->hostname, NULL, &hints, &res); - } - if (res) - { - arp->error = 0; - if (res->ai_family == AF_INET) - { - memcpy(&arp->destaddr.sin_addr.s_addr, &res->ai_addr->sa_data[2], 4); - arp->IPv6 = FALSE; - arp->destaddr.sin_family = AF_INET; -// Debugprintf("AXIP %s = %d.%d.%d.%d", arp->hostname, (UCHAR)res->ai_addr->sa_data[2], -// (UCHAR)res->ai_addr->sa_data[3], (UCHAR)res->ai_addr->sa_data[4], (UCHAR)res->ai_addr->sa_data[5]); - - } - else - { - struct sockaddr_in6 * sa6 = (struct sockaddr_in6 *)res->ai_addr; - - memcpy(&arp->destaddr6.sin6_addr, &sa6->sin6_addr, 16); - arp->IPv6 = TRUE; - arp->destaddr.sin_family = AF_INET6; - } - arp->destaddr.sin_port = htons(arp->port); - freeaddrinfo(res); - } - else - { - PORT->arp_table[PORT->ResolveIndex].error = WSAGetLastError(); - - if (count < 4) - ResolveDelay = 30; // if errors try again soon - } - } - } - - SaveAXIPCache(PORT); - -#ifndef LINBPQ - InvalidateRect(PORT->hResWnd,NULL,TRUE); -#endif - while(ResolveDelay-- > 0) - { - if (pthread_equal(PORT->ResolveNamesThreadId, GetCurrentThreadId()) == FALSE) - { - Debugprintf("AXIP Resolve thread %x redundant - closing", GetCurrentThreadId()); - return; - } - Sleep(1000); - } - } - Debugprintf("AXIP Resolve thread exitied"); -} - -#ifndef LINBPQ - -LRESULT CALLBACK MHWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - PAINTSTRUCT ps; - HDC hdc; - HFONT hOldFont ; - char line[100]; - char outcall[10]; - HGLOBAL hMem; - struct AXIPPORTINFO * PORT; - int index,displayline; - MINMAXINFO * mmi; - int nScrollCode,nPos; - - - int i; - - for (i=1; i <= MAXBPQPORTS; i++) - { - PORT = Portlist[i]; - if (PORT == NULL) - continue; - - if (PORT->hMHWnd == hWnd) - break; - } - - if (PORT == NULL) - return DefMDIChildProc(hWnd, message, wParam, lParam); - - switch (message) - { - case WM_GETMINMAXINFO: - - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = 600; - mmi->ptMaxSize.y = PORT->MaxMHWindowlength; - mmi->ptMaxTrackSize.x = 600; - mmi->ptMaxTrackSize.y = PORT->MaxMHWindowlength; - 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)PORT->hMHMenu, "Edit"); - 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_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) { - - case BPQCLEAR: - memset(PORT->MHTable, 0, sizeof(PORT->MHTable)); - InvalidateRect(hWnd,NULL,TRUE); - return 0; - - case BPQCOPY: - - hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, MaxMHEntries * 100); - - if (hMem != 0) - { - if (OpenClipboard(hWnd)) - { - CopyScreentoBuffer(GlobalLock(hMem), PORT); - GlobalUnlock(hMem); - EmptyClipboard(); - SetClipboardData(CF_TEXT,hMem); - CloseClipboard(); - } - else - { - GlobalFree(hMem); - } - } - return 0; - - default: - - 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_RESTORE: - - PORT->MHMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - break; - - case SC_MINIMIZE: - - PORT->MHMinimized = TRUE; - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_VSCROLL: - - nScrollCode = (int) LOWORD(wParam); // scroll bar value - nPos = (short int) HIWORD(wParam); // scroll box position - - //hwndScrollBar = (HWND) lParam; // handle of scroll bar - - if (nScrollCode == SB_LINEUP || nScrollCode == SB_PAGEUP) - { - PORT->mhbaseline--; - if (PORT->mhbaseline <0) - PORT->mhbaseline=0; - } - - if (nScrollCode == SB_LINEDOWN || nScrollCode == SB_PAGEDOWN) - { - PORT->mhbaseline++; - if (PORT->mhbaseline > PORT->CurrentMHEntries) - PORT->mhbaseline = PORT->CurrentMHEntries; - } - - if (nScrollCode == SB_THUMBTRACK) - { - PORT->mhbaseline=nPos; - } - - SetScrollPos(hWnd,SB_VERT,PORT->mhbaseline,TRUE); - - InvalidateRect(hWnd,NULL,TRUE); - break; - - - - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - hOldFont = SelectObject( hdc, hFont) ; - - index = PORT->mhbaseline; - displayline=0; - - PORT->CurrentMHEntries = 0; - - while (index < MaxMHEntries) - { - if (PORT->MHTable[index].proto != 0) - { - char Addr[80]; - - Format_Addr((unsigned char *)&PORT->MHTable[index].ipaddr6, Addr, PORT->MHTable[index].IPv6); - - CONVFROMAX25(PORT->MHTable[index].callsign,outcall); - - i=sprintf(line,"%-10s%-15s %c %-6d %-25s%c",outcall, - Addr, - PORT->MHTable[index].proto, - PORT->MHTable[index].port, - asctime(gmtime( &PORT->MHTable[index].LastHeard )), - (PORT->MHTable[index].Keepalive == 0) ? ' ' : 'K'); - - line[i-2]= ' '; // Clear CR returned by asctime - - TextOut(hdc,0,(displayline++)*14+2,line,i); - PORT->CurrentMHEntries ++; - } - index++; - } - - if (PORT->MaxMHWindowlength < PORT->CurrentMHEntries * 14 + 40) - PORT->MaxMHWindowlength = PORT->CurrentMHEntries * 14 + 40; - - SelectObject( hdc, hOldFont ) ; - EndPaint (hWnd, &ps); - - break; - - case WM_DESTROY: - - PORT->MHEnabled=FALSE; - - break; - - default: - return DefMDIChildProc(hWnd, message, wParam, lParam); - - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); -} - -#endif - -BOOL CopyScreentoBuffer(char * buff, struct AXIPPORTINFO * PORT) -{ - int index; - char outcall[10]; - - index = 0; - - while (index < MaxMHEntries) - { - if (PORT->MHTable[index].proto != 0) - { - CONVFROMAX25(PORT->MHTable[index].callsign,outcall); - - buff+=sprintf(buff,"%-10s%-15s %c %-6d %-26s",outcall, - inet_ntoa(PORT->MHTable[index].ipaddr), - PORT->MHTable[index].proto, - PORT->MHTable[index].port, - asctime(gmtime( &PORT->MHTable[index].LastHeard ))); - } - *(buff-2)=13; - *(buff-1)=10; - index++; - - } - *(buff)=0; - - return 0; -} - -void CreateMHWindow(struct AXIPPORTINFO * PORT) -{ -#ifndef LINBPQ - - WNDCLASS wc; - char WindowTitle[100]; - int retCode, Type, Vallen; - HKEY hKey=0; - char Size[80]; - HWND hMHWnd; - char Key[80]; - RECT Rect = {0, 0, 300, 300}; - int Top, Left, Width, Height; - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", PORT->Port); - - retCode = RegOpenKeyEx (REGTREE, Key, 0, KEY_QUERY_VALUE, &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"MHSize",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, &PORT->MHMinimized); - - if (Rect.top < - 500 || Rect.left < - 500) - { - Rect.left = 0; - Rect.top = 0; - Rect.right = 600; - Rect.bottom = 400; - } - - if (Rect.top < OffsetH) // Make sure not off top of MDI frame - { - int Error = OffsetH - Rect.top; - Rect.top += Error; - Rect.bottom += Error; - } - - - RegCloseKey(hKey); - } - - Top = Rect.top; - Left = Rect.left; - Width = Rect.right - Left; - Height = Rect.bottom - Top; - - PORT->MaxMHWindowlength = Height; - - wc.style = CS_HREDRAW | CS_VREDRAW ;//| CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)MHWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = NULL ; - wc.lpszClassName = "MHAppName"; - - RegisterClass(&wc); - - sprintf(WindowTitle,"AXIP Port %d MHEARD", PORT->Port); - - PORT->hMHWnd = hMHWnd = CreateMDIWindow("MHAppName", WindowTitle, - WS_OVERLAPPEDWINDOW | WS_VSCROLL, - Left - (OffsetW /2), Top - OffsetH, Width, Height, ClientWnd, hInstance, 1234); - - PORT->hMHMenu = CreatePopupMenu(); - AppendMenu(PORT->hMHMenu, MF_STRING, BPQCOPY, "Copy"); - AppendMenu(PORT->hMHMenu, MF_STRING, BPQCLEAR, "Clear"); - - if (PORT->MHMinimized) - ShowWindow(hMHWnd, SW_SHOWMINIMIZED); - else - ShowWindow(hMHWnd, SW_RESTORE); -#endif -} - -unsigned short int compute_crc(unsigned char *buf,int len) -{ - unsigned short fcs = 0xffff; - int i; - - for(i = 0; i < len; i++) - fcs = (fcs >>8 ) ^ CRCTAB[(fcs ^ buf[i]) & 0xff]; - - return fcs; -} - -/* - -static const unsigned short ccittTab[] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}; - -unsigned short int compute_crc_ccitt(unsigned char *buf, int len) -{ - int i; - unsigned short fcs = 0; - - for(i = 0; i < len; i++) - fcs = (fcs >>8 ) ^ ccittTab[(fcs ^ buf[i]) & 0xff]; - - return fcs; -} - - - union { - unsigned short m_crc16; - unsigned char m_crc8[2U]; - } fcs; - - -unsigned short CCCITTChecksum(unsigned char* data, unsigned int length) -{ - int i; - - fcs.m_crc16 = 0; - - for (i = 0U; i < length; i++) - fcs.m_crc16 = (fcs.m_crc8[0U] << 8) ^ ccittTab[fcs.m_crc8[1U] ^ data[i]]; - - return fcs.m_crc16; -} - -*/ - -static BOOL ReadConfigFile(int Port) -{ - -/* Linux Format - -broadcast QST-0 NODES-0 -# -# ax.25 route definition, define as many as you need. -# format is route (call/wildcard) (ip host at destination) -# ssid of 0 routes all ssid's -# -# route [flags] -# -# Valid flags are: -# b - allow broadcasts to be transmitted via this route -# d - this route is the default route -# -#route vk2sut-0 44.136.8.68 b -#route vk5xxx 44.136.188.221 b -#route vk2abc 44.1.1.1 -# -*/ - -//UDP 9999 # Port we listen on -//MAP G8BPQ-7 10.2.77.1 # IP 93 for compatibility -//MAP BPQ7 10.2.77.1 UDP 2222 # UDP port to send to -//MAP BPQ8 10.2.77.2 UDP 3333 # UDP port to send to - - char buf[256],errbuf[256]; - HKEY hKey=0; - char * Config; - struct AXIPPORTINFO * PORT; - - Config = PortConfig[Port]; - - if (Portlist[Port]) // Already defined, so must be re-read - { - PORT = Portlist[Port]; - - PORT->NumberofBroadcastAddreses = 0; - PORT->needip = FALSE; - PORT->NeedTCP = FALSE; - PORT->MHAvailable = FALSE; - PORT->MHEnabled = FALSE; - PORT->NumberofUDPPorts = 0; - PORT->NeedResolver = FALSE; - PORT->arp_table_len = 0; - memset(PORT->arp_table, 0, sizeof(struct arp_table_entry) * MAX_ENTRIES); - PORT->AutoAddARP = FALSE; - PORT->AutoAddBC = FALSE; - } - else - { - Portlist[Port] = PORT = zalloc(sizeof (struct AXIPPORTINFO)); - } - - PORT->Checkifcanreply = TRUE; - - if (Config) - { - char * ptr1 = Config, * ptr2; - - // Using config from bpq32.cfg - - 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 (!ProcessLine(buf, PORT)) - { - WritetoConsole("BPQAXIP - Bad config record"); - WritetoConsole(errbuf); - WritetoConsole("\n"); - } - } - - if (PORT->NumberofUDPPorts > MAXUDPPORTS) - { - n=sprintf(buf,"BPQAXIP - Too many UDP= lines - max is %d\n", MAXUDPPORTS); - WritetoConsole(buf); - } - return TRUE; - } - - WritetoConsole("No Configuration info in bpq32.cfg"); - - return FALSE; -} - -static int ProcessLine(char * buf, struct AXIPPORTINFO * PORT) -{ - char * ptr; - char * p_call; - char * p_ipad; - char * p_UDP; - char * p_udpport; - char * p_Interval; - - int calllen; - int port, SourcePort; - int bcflag; - char axcall[7]; - int Interval; - int noUpdate=FALSE; - int TCPMode; - int useSourcePort = 0; - - ptr = strtok(buf, " \t\n\r"); - - if(ptr == NULL) return (TRUE); - - if(*ptr =='#') return (TRUE); // comment - - if(*ptr ==';') return (TRUE); // comment - - if(_stricmp(ptr,"UDP") == 0) - { - if (PORT->NumberofUDPPorts > MAXUDPPORTS) PORT->NumberofUDPPorts--; - - p_udpport = strtok(NULL, " ,\t\n\r"); - - if (p_udpport == NULL) return (FALSE); - - PORT->udpport[PORT->NumberofUDPPorts] = atoi(p_udpport); - - if (PORT->udpport[PORT->NumberofUDPPorts] == 0) return (FALSE); - - ptr = strtok(NULL, " \t\n\r"); - - if (ptr && _stricmp(ptr, "ipv6") == 0) - { - PORT->PortIPv6 = TRUE; - PORT->IPv6[PORT->NumberofUDPPorts] = TRUE; - } - - PORT->NumberofUDPPorts++; - - return (TRUE); - } - - if(_stricmp(ptr,"MHEARD") == 0) - { - PORT->MHEnabled = TRUE; - PORT->MHAvailable = TRUE; - - return (TRUE); - } - - if(_stricmp(ptr,"DONTCHECKSOURCECALL") == 0) - { - PORT->Checkifcanreply = FALSE; - return (TRUE); - } - - if(_stricmp(ptr,"AUTOADDMAP") == 0) - { - PORT->AutoAddARP = TRUE; - PORT->AutoAddBC = TRUE; - return (TRUE); - } - - if(_stricmp(ptr,"AUTOADDQUIET") == 0) - { - PORT->AutoAddARP = TRUE; - PORT->AutoAddBC = FALSE; - return (TRUE); - } - - if(_stricmp(ptr,"MAP") == 0) - { - p_call = strtok(NULL, " \t\n\r"); - - if (p_call == NULL) return (FALSE); - - _strupr(p_call); - - if (_stricmp(p_call, "DUMMY") == 0) - { - Consoleprintf("MAP DUMMY is no longer needed - statement ignored"); - return TRUE; - } - - p_ipad = strtok(NULL, " \t\n\r"); - - if (p_ipad == NULL) return (FALSE); - - p_UDP = strtok(NULL, " \t\n\r"); - - Interval=0; - port=0; // Raw IP - bcflag=0; - TCPMode=0; - SourcePort = 0; - useSourcePort = 0; - -// -// Look for (optional) KEEPALIVE, DYNAMIC, UDP or BROADCAST params -// - while (p_UDP != NULL) - { - if (_stricmp(p_UDP,"NOUPDATE") == 0) - { - noUpdate = TRUE; - p_UDP = strtok(NULL, " \t\n\r"); - continue; - } - - if (_stricmp(p_UDP,"KEEPALIVE") == 0) - { - p_Interval = strtok(NULL, " \t\n\r"); - - if (p_Interval == NULL) return (FALSE); - - Interval = atoi(p_Interval); - p_UDP = strtok(NULL, " \t\n\r"); - continue; - } - - if (_stricmp(p_UDP,"UDP") == 0) - { - p_udpport = strtok(NULL, " \t\n\r"); - - if (p_udpport == NULL) return (FALSE); - - if (_stricmp(p_udpport,"FROMPORT") == 0) - { - useSourcePort = TRUE; - port = 0; - } - else - port = atoi(p_udpport); - - p_UDP = strtok(NULL, " \t\n\r"); - continue; - } - - if (_stricmp(p_UDP,"SOURCEPORT") == 0) - { - p_udpport = strtok(NULL, " \t\n\r"); - - if (p_udpport == NULL) return (FALSE); - - SourcePort = atoi(p_udpport); - p_UDP = strtok(NULL, " \t\n\r"); - continue; - } - - if (_stricmp(p_UDP,"TCP-Master") == 0) - { - p_udpport = strtok(NULL, " \t\n\r"); - - if (p_udpport == NULL) return (FALSE); - - port = atoi(p_udpport); - p_UDP = strtok(NULL, " \t\n\r"); - - TCPMode=TCPMaster; - - continue; - } - - if (_stricmp(p_UDP,"TCP-Slave") == 0) - { - p_udpport = strtok(NULL, " \t\n\r"); - - if (p_udpport == NULL) return (FALSE); - - port = atoi(p_udpport); - p_UDP = strtok(NULL, " \t\n\r"); - - TCPMode = TCPSlave; - continue; - - } - - - if (_stricmp(p_UDP,"B") == 0) - { - bcflag =TRUE; - p_UDP = strtok(NULL, " \t\n\r"); - continue; - } - - if ((*p_UDP == ';') || (*p_UDP == '#')) break; // Comment on end - - return FALSE; - - } - - if (convtoax25(p_call,axcall,&calllen)) - { - if (SourcePort == 0) - SourcePort = port; - - add_arp_entry(PORT, axcall, 0, calllen, port, p_ipad, Interval, bcflag, FALSE, TCPMode, SourcePort, FALSE, noUpdate, useSourcePort); - return (TRUE); - } - } // End of Process MAP - - if(_stricmp(ptr,"BROADCAST") == 0) - { - p_call = strtok(NULL, " \t\n\r"); - - if (p_call == NULL) return (FALSE); - - if (convtoax25(p_call,axcall,&calllen)) - { - add_bc_entry(PORT, axcall,calllen); - return (TRUE); - } - - - return (FALSE); // Failed convtoax25 - } - - // - // Bad line - // - return (FALSE); -} - -int CONVFROMAX25(char * incall, char * outcall) -{ - int in,out=0; - unsigned char chr; -// -// CONVERT AX25 FORMAT CALL IN incall TO NORMAL FORMAT IN out -// RETURNS LENGTH -// - memset(outcall,0x20,9); - outcall[9]=0; - - for (in=0;in<6;in++) - { - chr=incall[in]; - if (chr == 0x40) - break; - chr >>= 1; - outcall[out++]=chr; - } - - chr=incall[6]; // ssid - chr >>= 1; - chr &= 15; - - if (chr > 0) - { - outcall[out++]='-'; - if (chr > 9) - { - chr-=10; - outcall[out++]='1'; - } - chr+=48; - outcall[out++]=chr; - } - return (out); -} - - -BOOL convtoax25(unsigned char * callsign, unsigned char * ax25call,int * calllen) -{ - 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; - *calllen = 7; // include ssid in test - return (TRUE); - } - return (FALSE); - } - - if (callsign[i] == 0 || callsign[i] == ' ') - { - // - // End of call - no ssid - // - *calllen = 6; // wildcard ssid - return (TRUE); - } - - ax25call[i] = callsign[i] << 1; - } - - // - // Too many chars - // - - return (FALSE); -} - -BOOL add_arp_entry(struct AXIPPORTINFO * PORT, UCHAR * call, UCHAR * ip, int len, int port, - UCHAR * name, int keepalive, BOOL BCFlag, BOOL AutoAdded, int TCPFlag, int SourcePort, BOOL IPv6, int noUpdate, int useSourcePort) -{ - struct arp_table_entry * arp; - - if (PORT->arp_table_len == MAX_ENTRIES) - // - // Table full - // - return (FALSE); - - arp = &PORT->arp_table[PORT->arp_table_len]; - - if (SourcePort) - arp->SourcePort = SourcePort; - else - arp->SourcePort = port; - - arp->PORT = PORT; - - if (port == 0 && arp->replytoSourcePort == 0) - PORT->needip = 1; // Enable Raw IP Mode - - arp->ResolveFlag=TRUE; - PORT->NeedResolver=TRUE; - - memcpy (&arp->callsign,call,7); - strncpy((char *)&arp->hostname,name,64); - arp->len = len; - arp->port = port; - keepalive+=9; - keepalive/=10; - - arp->keepalive = keepalive; - arp->keepaliveinit = keepalive; - arp->BCFlag = BCFlag; - arp->AutoAdded = AutoAdded; - arp->TCPMode = TCPFlag; - arp->noUpdate = noUpdate; - PORT->arp_table_len++; - arp->replytoSourcePort = useSourcePort; - - if (PORT->MaxResWindowlength < (PORT->arp_table_len * 14) + 70) - PORT->MaxResWindowlength = (PORT->arp_table_len * 14) + 70; - - PORT->NeedResolver |= TCPFlag; // Need Resolver window to handle tcp socket messages - PORT->NeedTCP |= TCPFlag; - - if (ip) - { - // Only have an IP address if dynamically added - so update destaddr - - if (IPv6) - { - memcpy(&arp->destaddr6.sin6_addr, ip, 16); - arp->IPv6 = TRUE; - arp->destaddr.sin_family = AF_INET6; - } - else - { - memcpy(&arp->destaddr.sin_addr.s_addr, ip, 4); - arp->IPv6 = FALSE; - arp->destaddr.sin_family = AF_INET; - } - arp->destaddr.sin_port = htons(arp->port); -#ifndef LINBPQ - - SetScrollRange(PORT->hResWnd,SB_VERT, 0, PORT->arp_table_len, TRUE); - InvalidateRect(PORT->hResWnd, NULL, TRUE); -#endif - } - - return (TRUE); -} - -BOOL add_bc_entry(struct AXIPPORTINFO * PORT, unsigned char * call, int len) -{ - if (PORT->NumberofBroadcastAddreses == MAX_BROADCASTS) - // - // Table full - // - return (FALSE); - - memcpy (PORT->BroadcastAddresses[PORT->NumberofBroadcastAddreses].callsign,call,7); - PORT->BroadcastAddresses[PORT->NumberofBroadcastAddreses].len = len; - PORT->NumberofBroadcastAddreses++; - - return (TRUE); -} - - -int CheckKeepalives(struct AXIPPORTINFO * PORT) -{ - int index=0; - SOCKET txsock; - struct arp_table_entry * arp; - - if (PORT->arp_table_len >= MAX_ENTRIES) - { - Debugprintf("arp_table_len corrupt - %d", PORT->arp_table_len); - PORT->arp_table_len = MAX_ENTRIES - 1; - } - - while (index < PORT->arp_table_len) - { - if (PORT->arp_table[index].keepalive != 0) - { - arp = &PORT->arp_table[index]; - arp->keepalive--; - - if (arp->keepalive == 0) - { - // - // Send Keepalive Packet - // - arp->keepalive=arp->keepaliveinit; - - if (arp->error == 0) - { - if (arp->port == 0) txsock = PORT->sock; else txsock = PORT->udpsock[0]; - - sendto(txsock,"Keepalive",9,0,(struct sockaddr *)&arp->destaddr,sizeof(arp->destaddr)); - } - } - } - - index++; - - } - - // Decrement MH Keepalive flags - - for (index = 0; index < MaxMHEntries; index++) - { - if (PORT->MHTable[index].Keepalive != 0) - PORT->MHTable[index].Keepalive--; - } - - return (0); -} - -BOOL CheckSourceisResolvable(struct AXIPPORTINFO * PORT, char * call, int FromPort, VOID * rxaddr, int ToPort) -{ - // Makes sure we can reply to call before accepting message - - int index = 0; - struct arp_table_entry * arp; - - while (index < PORT->arp_table_len) - { - arp = &PORT->arp_table[index]; - - if (memcmp(arp->callsign, call, arp->len) == 0) - { - // Call is present - if AutoAdded, refresh IP address and Port - - // Why not refreesh resolved addresses - if dynamic addr has changed - // this will give quicker response - - if (arp->noUpdate == 0) - { - if (arp->IPv6) - { - struct sockaddr_in6 * SA6 = rxaddr; - memcpy(&arp->destaddr6.sin6_addr, &SA6->sin6_addr, 16); - } - else - { - struct sockaddr_in * SA = rxaddr; - memcpy(&arp->destaddr.sin_addr.s_addr, &SA->sin_addr, 4); - } - // Dont think I should update port unless using source port for dest - - if (arp->replytoSourcePort) - { - arp->port = FromPort; - if (arp->SourcePort == 0) - arp->SourcePort = ToPort; - } - } - arp->LastHeard = time(NULL); - return 1; // Ok to process - } - index++; - } - - return (0); // Not in list -} - -int Update_MH_List(struct AXIPPORTINFO * PORT, UCHAR * ipad, char * call, char proto, short port, BOOL IPv6) -{ - int index; - char callsign[7]; - int SaveKeepalive=0; - struct MHTableEntry * MH; - - memcpy(callsign,call,7); - callsign[6] &= 0x3e; // Mask non-ssid bits - - for (index = 0; index < MaxMHEntries; index++) - { - MH = &PORT->MHTable[index]; - - if (MH->callsign[0] == 0) - { - // empty entry, so call not present. Move all down, and add to front - -#ifdef WIN32 - SetScrollRange(PORT->hMHWnd, SB_VERT, 0, index + 1, TRUE); -#endif - goto MoveEntries; - } - - if (memcmp(MH->callsign,callsign,7) == 0 && - memcmp(&MH->ipaddr, ipad, (MH->IPv6) ? 16 : 4) == 0 && - MH->proto == proto && - MH->port == port) - { - // Entry found, move preceeding entries down and put on front - - SaveKeepalive = MH->Keepalive; - goto MoveEntries; - } - } - - // Table full move MaxMHEntries-1 entries down, and add on front - - index=MaxMHEntries-1; - -MoveEntries: - - // - // Move all preceeding entries down one, and put on front - // - - if (index > 0) - memmove(&PORT->MHTable[1],&PORT->MHTable[0],index*sizeof(struct MHTableEntry)); - - MH = &PORT->MHTable[0]; - - memcpy(MH->callsign,callsign,7); - memcpy(&MH->ipaddr6, ipad, (IPv6) ? 16 : 4); - MH->proto = proto; - - MH->port = port; - time(&MH->LastHeard); - MH->Keepalive = SaveKeepalive; - MH->IPv6 = IPv6; -#ifndef LINBPQ - InvalidateRect(PORT->hMHWnd,NULL,TRUE); -#endif - return 0; - -} - -int Update_MH_KeepAlive(struct AXIPPORTINFO * PORT, struct in_addr ipad, char proto, short port) -{ - int index; - - for (index = 0; index < MaxMHEntries; index++) - { - if (PORT->MHTable[index].callsign[0] == 0) - - // empty entry, so call not present. - - return 0; - - if (memcmp(&PORT->MHTable[index].ipaddr,&ipad,4) == 0 && - PORT->MHTable[index].proto == proto && - PORT->MHTable[index].port == port) - { - PORT->MHTable[index].Keepalive = 30; // 5 Minutes at 10 sec ticks - return 0; - } - } - - return 0; - -} - - -int DumpFrameInHex(unsigned char * msg, int len) -{ - char errmsg[100]; - int i=0; - - for (i=0;iarp_table_len) - { - sockptr = &PORT->arp_table[index++]; - - if (sockptr->TCPMode) - { - if (sockptr->TCPState == TCPListening) - { - int addrlen; - SOCKET sock; - BOOL bOptVal = TRUE; - struct sockaddr sin; - - addrlen = sizeof(struct sockaddr); - - sock = accept(sockptr->TCPListenSock, &sin, &addrlen); - - if (sock == INVALID_SOCKET) - { - int err = WSAGetLastError(); - - if (err == 10035 || err == 11) - continue; - - if (err == 10038 || err == 9) - { - // Not a socket - - closesocket(sockptr->TCPListenSock); - OpenListeningSocket(PORT, sockptr); - - continue; - } - - - Debugprintf("AXIP accept() failed Error %d", err); - continue; - } - - Debugprintf("AXIP Connect accepted - Socket %d Port %d", sock, sockptr->port); - - if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&bOptVal, 4) != SOCKET_ERROR) - Debugprintf("Set SO_KEEPALIVE: ON"); - - sockptr->TCPSock = sock; - sockptr->TCPState = TCPConnected; - } - - if (sockptr->TCPState == TCPConnected) - { - int InputLen; - - // Poll TCP Connection for data - - // May have several messages per packet, or message split over packets - - if (sockptr->InputLen > 3000) // Shouldnt have lines longer than this in text mode - { - sockptr->InputLen = 0; - } - - ioctl(sockptr->TCPSock, FIONBIO, ¶m); - - InputLen = recv(sockptr->TCPSock, &sockptr->TCPBuffer[sockptr->InputLen], 1000, 0); - - if (InputLen == 0) - { - Debugprintf("TCP Close received for socket %d", sockptr->TCPSock); - - if (sockptr->TCPMode == TCPSlave) - sockptr->TCPState = TCPListening; - else - sockptr->TCPState = 0; - closesocket(sockptr->TCPSock); - continue; - } - - if (InputLen < 0) - { - int err = WSAGetLastError(); - - if (err == 10035 || err == 11) - InputLen = 0; - else - { - if (sockptr->TCPMode == TCPSlave) - sockptr->TCPState = TCPListening; - else - sockptr->TCPState = 0; - - closesocket(sockptr->TCPSock); - continue; - } - } - - sockptr->InputLen += InputLen; - - if (sockptr->InputLen == 0) - { - sockptr->TCPOK++; - - if (sockptr->TCPOK > 36000) // 60 MINS - { - if (sockptr->TCPSock) - { - Debugprintf("No Data for 60 Mins on Data Sock %d State %d", - sockptr->TCPListenSock, sockptr->TCPSock, sockptr->TCPState); - - sockptr->TCPState = 0; - closesocket(sockptr->TCPSock); - sockptr->TCPSock = 0; - } - - closesocket(sockptr->TCPListenSock); - OpenListeningSocket(PORT, sockptr); - - sockptr->TCPOK = 0; - } - continue; - } - } - - ptr = memchr(sockptr->TCPBuffer, FEND, sockptr->InputLen); - - if (ptr) // FEND in buffer - { - ptr2 = &sockptr->TCPBuffer[sockptr->InputLen]; - ptr++; - - if (ptr == ptr2) - { - // Usual Case - single meg in buffer - - MsgLen = sockptr->InputLen; - sockptr->InputLen = 0; - - if (MsgLen > 1) - { - memcpy(Buffer, sockptr->TCPBuffer, MsgLen); - - if (PORT->MHEnabled) - Update_MH_List(PORT, (UCHAR *)&sockptr->destaddr.sin_addr.s_addr, &Buffer[7],'T', sockptr->port, 0); - - sockptr->TCPOK = 0; - - return MsgLen; - } - } - else - { - // buffer contains more that 1 message - - MsgLen = sockptr->InputLen - (int)((ptr2-ptr)); - memcpy(Buffer, sockptr->TCPBuffer, MsgLen); - - memmove(sockptr->TCPBuffer, ptr, sockptr->InputLen-MsgLen); - - sockptr->InputLen -= MsgLen; - - if (MsgLen > 1) - { - if (PORT->MHEnabled) - Update_MH_List(PORT, (UCHAR *)&sockptr->destaddr.sin_addr.s_addr, &Buffer[7],'T', sockptr->port, 0); - - sockptr->TCPOK = 0; - - return MsgLen; - } - } - } - } - } - return 0; - -} - -int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len) -{ - int i,txptr=0; - UCHAR c; - - outbuff[0]=FEND; - txptr=1; - - for (i=0;iTCPMode == TCPMaster) - { - if (arp->TCPState == 0) - { - arp->TCPSock=socket(AF_INET,SOCK_STREAM,0); - - if (arp->TCPSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for AX/TCP socket - error code = %d\n", WSAGetLastError()); - WritetoConsole(Msg); - goto wait; - } - - setsockopt (arp->TCPSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(arp->TCPSock, SOL_SOCKET, SO_KEEPALIVE, (char*)&bcopt, 4); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - if (bind(arp->TCPSock, (struct sockaddr *) &sinx, addrlen) != 0 ) - { - // - // Bind Failed - // - - i=sprintf(Msg, "Bind Failed for AX/TCP socket - error code = %d\n", WSAGetLastError()); - WritetoConsole(Msg); - - goto wait; - } - - arp->TCPState = TCPConnecting; - - if (connect(arp->TCPSock,(struct sockaddr *) &arp->destaddr, sizeof(arp->destaddr)) == 0) - { - // - // Connected successful - // - - arp->TCPState = TCPConnected; - OutputDebugString("AXTCP Connected\r\n"); - ioctl (arp->TCPSock, FIONBIO, ¶m); - Alerted = 0; - } - else - { - err=WSAGetLastError(); - - // Connect failed - // - - if (Alerted == 0) - { - i = sprintf(Msg, "Connect Failed for AX/TCP port %d - error code = %d\n", htons(arp->destaddr.sin_port), err); - WritetoConsole(Msg); - OutputDebugString(Msg); - Alerted = 1; - } - closesocket(arp->TCPSock); - arp->TCPSock = 0; - arp->TCPState = 0; - } - } -wait: - Sleep (115000); // 2 Mins - } - - Debugprintf("AX/TCP Connect Thread %x Closing", arp->TCPThreadID); - - arp->TCPThreadID = 0; - - return; // Not Used - -} - -VOID Format_Addr(unsigned char * Addr, char * Output, BOOL IPV6) -{ - unsigned char * src; - char zeros[12] = ""; - char * ptr; - struct - { - int base, len; - } best, cur; - unsigned int words[8]; - int i; - - if (IPV6 == FALSE) - { - sprintf((char *)Output, "%d.%d.%d.%d", Addr[0], Addr[1], Addr[2], Addr[3]); - return; - } - - src = Addr; - - // See if Encapsulated IPV4 addr - - if (src[12] != 0) - { - if (memcmp(src, zeros, 12) == 0) // 12 zeros, followed by non-zero - { - sprintf((char *)Output, "::%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 = Output; - - 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'; -} - - -#define LIBCONFIG_STATIC -#include "libconfig.h" - - - -VOID SaveAXIPCache(struct AXIPPORTINFO * PORT) -{ - config_setting_t *root, *group; - config_t cfg; - char ConfigName[256]; - int index=0; - struct arp_table_entry * arp; - unsigned char hostaddr[64]; - char Key[128]; - - if (BPQDirectory[0] == 0) - { - sprintf(ConfigName,"axipcache%d.cfg", PORT->Port); - } - else - { - sprintf(ConfigName,"%s/axipcache%d.cfg", BPQDirectory, PORT->Port); - } - - // Get rid of old config before saving - - config_init(&cfg); - - root = config_root_setting(&cfg); - - group = config_setting_add(root, "main", CONFIG_TYPE_GROUP); - - if (PORT->arp_table_len >= MAX_ENTRIES) - { - Debugprintf("arp_table_len corrupt - %d", PORT->arp_table_len); - PORT->arp_table_len = MAX_ENTRIES - 1; - } - - while (index < PORT->arp_table_len) - { - char * ptr = Key; - - arp = &PORT->arp_table[index++]; - - if (arp->IPv6) - Format_Addr((unsigned char *)&arp->destaddr6.sin6_addr, hostaddr, TRUE); - else - Format_Addr((unsigned char *)&arp->destaddr.sin_addr, hostaddr, FALSE); - - sprintf(Key, "*%s", arp->hostname); - - // libconfig keys can't contain . so replace with * - - while (*ptr) - { - if (*ptr == '.') *ptr = '*'; - ptr++; - } - - SaveStringValue(group, Key, hostaddr); - } - - if(!config_write_file(&cfg, ConfigName)) - { - fprintf(stderr, "Error while writing file.\n"); - config_destroy(&cfg); - return; - } - - config_destroy(&cfg); -} - -#ifndef LINBPQ - -static 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; - } - return FALSE; -} - -#endif - -VOID GetAXIPCache(struct AXIPPORTINFO * PORT) -{ - config_setting_t *group; - config_t cfg; - char ConfigName[256]; - int index=0; - struct arp_table_entry * arp; - unsigned char hostaddr[64]; - char Key[128]; - struct stat STAT; - - if (BPQDirectory[0] == 0) - { - sprintf(ConfigName,"axipcache%d.cfg", PORT->Port); - } - else - { - sprintf(ConfigName,"%s/axipcache%d.cfg", BPQDirectory, PORT->Port); - } - - memset((void *)&cfg, 0, sizeof(config_t)); - - config_init(&cfg); - - if (stat(ConfigName, &STAT) == -1) - return; - - if(!config_read_file(&cfg, ConfigName)) - { - fprintf(stderr, "AXIP Cache read error line %d - %s\n", config_error_line(&cfg), config_error_text(&cfg)); - config_destroy(&cfg); - return; - } - - group = config_lookup(&cfg, "main"); - - if (group == NULL) - { - config_destroy(&cfg); - return; - } - - while (index < PORT->arp_table_len) - { - char * ptr = Key; - - arp = &PORT->arp_table[index++]; - - sprintf(Key, "*%s", arp->hostname); - - // libconfig keys can't contain . so replace with * - - while (*ptr) - { - if (*ptr == '.') *ptr = '*'; - ptr++; - } - - if (GetStringValue(group, Key, hostaddr, 64)) - { - arp->destaddr.sin_addr.s_addr = inet_addr(hostaddr); - } - } - - config_destroy(&cfg); -} - diff --git a/.svn/pristine/04/04f5a5d5a7082c3a1451a77d1359fa064d327499.svn-base b/.svn/pristine/04/04f5a5d5a7082c3a1451a77d1359fa064d327499.svn-base deleted file mode 100644 index 940a7fc..0000000 --- a/.svn/pristine/04/04f5a5d5a7082c3a1451a77d1359fa064d327499.svn-base +++ /dev/null @@ -1,3903 +0,0 @@ -/* pngvcrd.c - mixed C/assembler version of utilities to read a PNG file - * - * For Intel x86 CPU and Microsoft Visual C++ compiler - * - * libpng version 1.2.8 - December 3, 2004 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2004 Glenn Randers-Pehrson - * Copyright (c) 1998, Intel Corporation - * - * Contributed by Nirav Chhatrapati, Intel Corporation, 1998 - * Interface to libpng contributed by Gilles Vollant, 1999 - * - * - * In png_do_read_interlace() in libpng versions 1.0.3a through 1.0.4d, - * a sign error in the post-MMX cleanup code for each pixel_depth resulted - * in bad pixels at the beginning of some rows of some images, and also - * (due to out-of-range memory reads and writes) caused heap corruption - * when compiled with MSVC 6.0. The error was fixed in version 1.0.4e. - * - * [png_read_filter_row_mmx_avg() bpp == 2 bugfix, GRR 20000916] - * - * [runtime MMX configuration, GRR 20010102] - * - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD) - -static int mmx_supported=2; - - -int PNGAPI -png_mmx_support(void) -{ - int mmx_supported_local = 0; - _asm { - push ebx //CPUID will trash these - push ecx - push edx - - pushfd //Save Eflag to stack - pop eax //Get Eflag from stack into eax - mov ecx, eax //Make another copy of Eflag in ecx - xor eax, 0x200000 //Toggle ID bit in Eflag [i.e. bit(21)] - push eax //Save modified Eflag back to stack - - popfd //Restored modified value back to Eflag reg - pushfd //Save Eflag to stack - pop eax //Get Eflag from stack - push ecx // save original Eflag to stack - popfd // restore original Eflag - xor eax, ecx //Compare the new Eflag with the original Eflag - jz NOT_SUPPORTED //If the same, CPUID instruction is not supported, - //skip following instructions and jump to - //NOT_SUPPORTED label - - xor eax, eax //Set eax to zero - - _asm _emit 0x0f //CPUID instruction (two bytes opcode) - _asm _emit 0xa2 - - cmp eax, 1 //make sure eax return non-zero value - jl NOT_SUPPORTED //If eax is zero, mmx not supported - - xor eax, eax //set eax to zero - inc eax //Now increment eax to 1. This instruction is - //faster than the instruction "mov eax, 1" - - _asm _emit 0x0f //CPUID instruction - _asm _emit 0xa2 - - and edx, 0x00800000 //mask out all bits but mmx bit(24) - cmp edx, 0 // 0 = mmx not supported - jz NOT_SUPPORTED // non-zero = Yes, mmx IS supported - - mov mmx_supported_local, 1 //set return value to 1 - -NOT_SUPPORTED: - mov eax, mmx_supported_local //move return value to eax - pop edx //CPUID trashed these - pop ecx - pop ebx - } - - //mmx_supported_local=0; // test code for force don't support MMX - //printf("MMX : %u (1=MMX supported)\n",mmx_supported_local); - - mmx_supported = mmx_supported_local; - return mmx_supported_local; -} - -/* Combines the row recently read in with the previous row. - This routine takes care of alpha and transparency if requested. - This routine also handles the two methods of progressive display - of interlaced images, depending on the mask value. - The mask value describes which pixels are to be combined with - the row. The pattern always repeats every 8 pixels, so just 8 - bits are needed. A one indicates the pixel is to be combined; a - zero indicates the pixel is to be skipped. This is in addition - to any alpha or transparency value associated with the pixel. If - you want all pixels to be combined, pass 0xff (255) in mask. */ - -/* Use this routine for x86 platform - uses faster MMX routine if machine - supports MMX */ - -void /* PRIVATE */ -png_combine_row(png_structp png_ptr, png_bytep row, int mask) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; -#endif - - png_debug(1,"in png_combine_row_asm\n"); - - if (mmx_supported == 2) { -#if !defined(PNG_1_0_X) - /* this should have happened in png_init_mmx_flags() already */ - png_warning(png_ptr, "asm_flags may not have been initialized"); -#endif - png_mmx_support(); - } - - if (mask == 0xff) - { - png_memcpy(row, png_ptr->row_buf + 1, - (png_size_t)PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->width)); - } - /* GRR: add "else if (mask == 0)" case? - * or does png_combine_row() not even get called in that case? */ - else - { - switch (png_ptr->row_info.pixel_depth) - { - case 1: - { - png_bytep sp; - png_bytep dp; - int s_inc, s_start, s_end; - int m; - int shift; - png_uint_32 i; - - sp = png_ptr->row_buf + 1; - dp = row; - m = 0x80; -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 7; - s_inc = 1; - } - else -#endif - { - s_start = 7; - s_end = 0; - s_inc = -1; - } - - shift = s_start; - - for (i = 0; i < png_ptr->width; i++) - { - if (m & mask) - { - int value; - - value = (*sp >> shift) & 0x1; - *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } - - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - - case 2: - { - png_bytep sp; - png_bytep dp; - int s_start, s_end, s_inc; - int m; - int shift; - png_uint_32 i; - int value; - - sp = png_ptr->row_buf + 1; - dp = row; - m = 0x80; -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 6; - s_inc = 2; - } - else -#endif - { - s_start = 6; - s_end = 0; - s_inc = -2; - } - - shift = s_start; - - for (i = 0; i < png_ptr->width; i++) - { - if (m & mask) - { - value = (*sp >> shift) & 0x3; - *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } - - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - - case 4: - { - png_bytep sp; - png_bytep dp; - int s_start, s_end, s_inc; - int m; - int shift; - png_uint_32 i; - int value; - - sp = png_ptr->row_buf + 1; - dp = row; - m = 0x80; -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 4; - s_inc = 4; - } - else -#endif - { - s_start = 4; - s_end = 0; - s_inc = -4; - } - shift = s_start; - - for (i = 0; i < png_ptr->width; i++) - { - if (m & mask) - { - value = (*sp >> shift) & 0xf; - *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } - - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - - case 8: - { - png_bytep srcptr; - png_bytep dstptr; - png_uint_32 len; - int m; - int diff, unmask; - - __int64 mask0=0x0102040810204080; - -#if !defined(PNG_1_0_X) - if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW) - /* && mmx_supported */ ) -#else - if (mmx_supported) -#endif - { - srcptr = png_ptr->row_buf + 1; - dstptr = row; - m = 0x80; - unmask = ~mask; - len = png_ptr->width &~7; //reduce to multiple of 8 - diff = png_ptr->width & 7; //amount lost - - _asm - { - movd mm7, unmask //load bit pattern - psubb mm6,mm6 //zero mm6 - punpcklbw mm7,mm7 - punpcklwd mm7,mm7 - punpckldq mm7,mm7 //fill register with 8 masks - - movq mm0,mask0 - - pand mm0,mm7 //nonzero if keep byte - pcmpeqb mm0,mm6 //zeros->1s, v versa - - mov ecx,len //load length of line (pixels) - mov esi,srcptr //load source - mov ebx,dstptr //load dest - cmp ecx,0 //lcr - je mainloop8end - -mainloop8: - movq mm4,[esi] - pand mm4,mm0 - movq mm6,mm0 - pandn mm6,[ebx] - por mm4,mm6 - movq [ebx],mm4 - - add esi,8 //inc by 8 bytes processed - add ebx,8 - sub ecx,8 //dec by 8 pixels processed - - ja mainloop8 -mainloop8end: - - mov ecx,diff - cmp ecx,0 - jz end8 - - mov edx,mask - sal edx,24 //make low byte the high byte - -secondloop8: - sal edx,1 //move high bit to CF - jnc skip8 //if CF = 0 - mov al,[esi] - mov [ebx],al -skip8: - inc esi - inc ebx - - dec ecx - jnz secondloop8 -end8: - emms - } - } - else /* mmx not supported - use modified C routine */ - { - register unsigned int incr1, initial_val, final_val; - png_size_t pixel_bytes; - png_uint_32 i; - register int disp = png_pass_inc[png_ptr->pass]; - int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; - - pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); - srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* - pixel_bytes; - dstptr = row + offset_table[png_ptr->pass]*pixel_bytes; - initial_val = offset_table[png_ptr->pass]*pixel_bytes; - final_val = png_ptr->width*pixel_bytes; - incr1 = (disp)*pixel_bytes; - for (i = initial_val; i < final_val; i += incr1) - { - png_memcpy(dstptr, srcptr, pixel_bytes); - srcptr += incr1; - dstptr += incr1; - } - } /* end of else */ - - break; - } // end 8 bpp - - case 16: - { - png_bytep srcptr; - png_bytep dstptr; - png_uint_32 len; - int unmask, diff; - __int64 mask1=0x0101020204040808, - mask0=0x1010202040408080; - -#if !defined(PNG_1_0_X) - if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW) - /* && mmx_supported */ ) -#else - if (mmx_supported) -#endif - { - srcptr = png_ptr->row_buf + 1; - dstptr = row; - - unmask = ~mask; - len = (png_ptr->width)&~7; - diff = (png_ptr->width)&7; - _asm - { - movd mm7, unmask //load bit pattern - psubb mm6,mm6 //zero mm6 - punpcklbw mm7,mm7 - punpcklwd mm7,mm7 - punpckldq mm7,mm7 //fill register with 8 masks - - movq mm0,mask0 - movq mm1,mask1 - - pand mm0,mm7 - pand mm1,mm7 - - pcmpeqb mm0,mm6 - pcmpeqb mm1,mm6 - - mov ecx,len //load length of line - mov esi,srcptr //load source - mov ebx,dstptr //load dest - cmp ecx,0 //lcr - jz mainloop16end - -mainloop16: - movq mm4,[esi] - pand mm4,mm0 - movq mm6,mm0 - movq mm7,[ebx] - pandn mm6,mm7 - por mm4,mm6 - movq [ebx],mm4 - - movq mm5,[esi+8] - pand mm5,mm1 - movq mm7,mm1 - movq mm6,[ebx+8] - pandn mm7,mm6 - por mm5,mm7 - movq [ebx+8],mm5 - - add esi,16 //inc by 16 bytes processed - add ebx,16 - sub ecx,8 //dec by 8 pixels processed - - ja mainloop16 - -mainloop16end: - mov ecx,diff - cmp ecx,0 - jz end16 - - mov edx,mask - sal edx,24 //make low byte the high byte -secondloop16: - sal edx,1 //move high bit to CF - jnc skip16 //if CF = 0 - mov ax,[esi] - mov [ebx],ax -skip16: - add esi,2 - add ebx,2 - - dec ecx - jnz secondloop16 -end16: - emms - } - } - else /* mmx not supported - use modified C routine */ - { - register unsigned int incr1, initial_val, final_val; - png_size_t pixel_bytes; - png_uint_32 i; - register int disp = png_pass_inc[png_ptr->pass]; - int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; - - pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); - srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* - pixel_bytes; - dstptr = row + offset_table[png_ptr->pass]*pixel_bytes; - initial_val = offset_table[png_ptr->pass]*pixel_bytes; - final_val = png_ptr->width*pixel_bytes; - incr1 = (disp)*pixel_bytes; - for (i = initial_val; i < final_val; i += incr1) - { - png_memcpy(dstptr, srcptr, pixel_bytes); - srcptr += incr1; - dstptr += incr1; - } - } /* end of else */ - - break; - } // end 16 bpp - - case 24: - { - png_bytep srcptr; - png_bytep dstptr; - png_uint_32 len; - int unmask, diff; - - __int64 mask2=0x0101010202020404, //24bpp - mask1=0x0408080810101020, - mask0=0x2020404040808080; - - srcptr = png_ptr->row_buf + 1; - dstptr = row; - - unmask = ~mask; - len = (png_ptr->width)&~7; - diff = (png_ptr->width)&7; - -#if !defined(PNG_1_0_X) - if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW) - /* && mmx_supported */ ) -#else - if (mmx_supported) -#endif - { - _asm - { - movd mm7, unmask //load bit pattern - psubb mm6,mm6 //zero mm6 - punpcklbw mm7,mm7 - punpcklwd mm7,mm7 - punpckldq mm7,mm7 //fill register with 8 masks - - movq mm0,mask0 - movq mm1,mask1 - movq mm2,mask2 - - pand mm0,mm7 - pand mm1,mm7 - pand mm2,mm7 - - pcmpeqb mm0,mm6 - pcmpeqb mm1,mm6 - pcmpeqb mm2,mm6 - - mov ecx,len //load length of line - mov esi,srcptr //load source - mov ebx,dstptr //load dest - cmp ecx,0 - jz mainloop24end - -mainloop24: - movq mm4,[esi] - pand mm4,mm0 - movq mm6,mm0 - movq mm7,[ebx] - pandn mm6,mm7 - por mm4,mm6 - movq [ebx],mm4 - - - movq mm5,[esi+8] - pand mm5,mm1 - movq mm7,mm1 - movq mm6,[ebx+8] - pandn mm7,mm6 - por mm5,mm7 - movq [ebx+8],mm5 - - movq mm6,[esi+16] - pand mm6,mm2 - movq mm4,mm2 - movq mm7,[ebx+16] - pandn mm4,mm7 - por mm6,mm4 - movq [ebx+16],mm6 - - add esi,24 //inc by 24 bytes processed - add ebx,24 - sub ecx,8 //dec by 8 pixels processed - - ja mainloop24 - -mainloop24end: - mov ecx,diff - cmp ecx,0 - jz end24 - - mov edx,mask - sal edx,24 //make low byte the high byte -secondloop24: - sal edx,1 //move high bit to CF - jnc skip24 //if CF = 0 - mov ax,[esi] - mov [ebx],ax - xor eax,eax - mov al,[esi+2] - mov [ebx+2],al -skip24: - add esi,3 - add ebx,3 - - dec ecx - jnz secondloop24 - -end24: - emms - } - } - else /* mmx not supported - use modified C routine */ - { - register unsigned int incr1, initial_val, final_val; - png_size_t pixel_bytes; - png_uint_32 i; - register int disp = png_pass_inc[png_ptr->pass]; - int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; - - pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); - srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* - pixel_bytes; - dstptr = row + offset_table[png_ptr->pass]*pixel_bytes; - initial_val = offset_table[png_ptr->pass]*pixel_bytes; - final_val = png_ptr->width*pixel_bytes; - incr1 = (disp)*pixel_bytes; - for (i = initial_val; i < final_val; i += incr1) - { - png_memcpy(dstptr, srcptr, pixel_bytes); - srcptr += incr1; - dstptr += incr1; - } - } /* end of else */ - - break; - } // end 24 bpp - - case 32: - { - png_bytep srcptr; - png_bytep dstptr; - png_uint_32 len; - int unmask, diff; - - __int64 mask3=0x0101010102020202, //32bpp - mask2=0x0404040408080808, - mask1=0x1010101020202020, - mask0=0x4040404080808080; - - srcptr = png_ptr->row_buf + 1; - dstptr = row; - - unmask = ~mask; - len = (png_ptr->width)&~7; - diff = (png_ptr->width)&7; - -#if !defined(PNG_1_0_X) - if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW) - /* && mmx_supported */ ) -#else - if (mmx_supported) -#endif - { - _asm - { - movd mm7, unmask //load bit pattern - psubb mm6,mm6 //zero mm6 - punpcklbw mm7,mm7 - punpcklwd mm7,mm7 - punpckldq mm7,mm7 //fill register with 8 masks - - movq mm0,mask0 - movq mm1,mask1 - movq mm2,mask2 - movq mm3,mask3 - - pand mm0,mm7 - pand mm1,mm7 - pand mm2,mm7 - pand mm3,mm7 - - pcmpeqb mm0,mm6 - pcmpeqb mm1,mm6 - pcmpeqb mm2,mm6 - pcmpeqb mm3,mm6 - - mov ecx,len //load length of line - mov esi,srcptr //load source - mov ebx,dstptr //load dest - - cmp ecx,0 //lcr - jz mainloop32end - -mainloop32: - movq mm4,[esi] - pand mm4,mm0 - movq mm6,mm0 - movq mm7,[ebx] - pandn mm6,mm7 - por mm4,mm6 - movq [ebx],mm4 - - movq mm5,[esi+8] - pand mm5,mm1 - movq mm7,mm1 - movq mm6,[ebx+8] - pandn mm7,mm6 - por mm5,mm7 - movq [ebx+8],mm5 - - movq mm6,[esi+16] - pand mm6,mm2 - movq mm4,mm2 - movq mm7,[ebx+16] - pandn mm4,mm7 - por mm6,mm4 - movq [ebx+16],mm6 - - movq mm7,[esi+24] - pand mm7,mm3 - movq mm5,mm3 - movq mm4,[ebx+24] - pandn mm5,mm4 - por mm7,mm5 - movq [ebx+24],mm7 - - add esi,32 //inc by 32 bytes processed - add ebx,32 - sub ecx,8 //dec by 8 pixels processed - - ja mainloop32 - -mainloop32end: - mov ecx,diff - cmp ecx,0 - jz end32 - - mov edx,mask - sal edx,24 //make low byte the high byte -secondloop32: - sal edx,1 //move high bit to CF - jnc skip32 //if CF = 0 - mov eax,[esi] - mov [ebx],eax -skip32: - add esi,4 - add ebx,4 - - dec ecx - jnz secondloop32 - -end32: - emms - } - } - else /* mmx _not supported - Use modified C routine */ - { - register unsigned int incr1, initial_val, final_val; - png_size_t pixel_bytes; - png_uint_32 i; - register int disp = png_pass_inc[png_ptr->pass]; - int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; - - pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); - srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* - pixel_bytes; - dstptr = row + offset_table[png_ptr->pass]*pixel_bytes; - initial_val = offset_table[png_ptr->pass]*pixel_bytes; - final_val = png_ptr->width*pixel_bytes; - incr1 = (disp)*pixel_bytes; - for (i = initial_val; i < final_val; i += incr1) - { - png_memcpy(dstptr, srcptr, pixel_bytes); - srcptr += incr1; - dstptr += incr1; - } - } /* end of else */ - - break; - } // end 32 bpp - - case 48: - { - png_bytep srcptr; - png_bytep dstptr; - png_uint_32 len; - int unmask, diff; - - __int64 mask5=0x0101010101010202, - mask4=0x0202020204040404, - mask3=0x0404080808080808, - mask2=0x1010101010102020, - mask1=0x2020202040404040, - mask0=0x4040808080808080; - -#if !defined(PNG_1_0_X) - if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW) - /* && mmx_supported */ ) -#else - if (mmx_supported) -#endif - { - srcptr = png_ptr->row_buf + 1; - dstptr = row; - - unmask = ~mask; - len = (png_ptr->width)&~7; - diff = (png_ptr->width)&7; - _asm - { - movd mm7, unmask //load bit pattern - psubb mm6,mm6 //zero mm6 - punpcklbw mm7,mm7 - punpcklwd mm7,mm7 - punpckldq mm7,mm7 //fill register with 8 masks - - movq mm0,mask0 - movq mm1,mask1 - movq mm2,mask2 - movq mm3,mask3 - movq mm4,mask4 - movq mm5,mask5 - - pand mm0,mm7 - pand mm1,mm7 - pand mm2,mm7 - pand mm3,mm7 - pand mm4,mm7 - pand mm5,mm7 - - pcmpeqb mm0,mm6 - pcmpeqb mm1,mm6 - pcmpeqb mm2,mm6 - pcmpeqb mm3,mm6 - pcmpeqb mm4,mm6 - pcmpeqb mm5,mm6 - - mov ecx,len //load length of line - mov esi,srcptr //load source - mov ebx,dstptr //load dest - - cmp ecx,0 - jz mainloop48end - -mainloop48: - movq mm7,[esi] - pand mm7,mm0 - movq mm6,mm0 - pandn mm6,[ebx] - por mm7,mm6 - movq [ebx],mm7 - - movq mm6,[esi+8] - pand mm6,mm1 - movq mm7,mm1 - pandn mm7,[ebx+8] - por mm6,mm7 - movq [ebx+8],mm6 - - movq mm6,[esi+16] - pand mm6,mm2 - movq mm7,mm2 - pandn mm7,[ebx+16] - por mm6,mm7 - movq [ebx+16],mm6 - - movq mm7,[esi+24] - pand mm7,mm3 - movq mm6,mm3 - pandn mm6,[ebx+24] - por mm7,mm6 - movq [ebx+24],mm7 - - movq mm6,[esi+32] - pand mm6,mm4 - movq mm7,mm4 - pandn mm7,[ebx+32] - por mm6,mm7 - movq [ebx+32],mm6 - - movq mm7,[esi+40] - pand mm7,mm5 - movq mm6,mm5 - pandn mm6,[ebx+40] - por mm7,mm6 - movq [ebx+40],mm7 - - add esi,48 //inc by 32 bytes processed - add ebx,48 - sub ecx,8 //dec by 8 pixels processed - - ja mainloop48 -mainloop48end: - - mov ecx,diff - cmp ecx,0 - jz end48 - - mov edx,mask - sal edx,24 //make low byte the high byte - -secondloop48: - sal edx,1 //move high bit to CF - jnc skip48 //if CF = 0 - mov eax,[esi] - mov [ebx],eax -skip48: - add esi,4 - add ebx,4 - - dec ecx - jnz secondloop48 - -end48: - emms - } - } - else /* mmx _not supported - Use modified C routine */ - { - register unsigned int incr1, initial_val, final_val; - png_size_t pixel_bytes; - png_uint_32 i; - register int disp = png_pass_inc[png_ptr->pass]; - int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; - - pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); - srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* - pixel_bytes; - dstptr = row + offset_table[png_ptr->pass]*pixel_bytes; - initial_val = offset_table[png_ptr->pass]*pixel_bytes; - final_val = png_ptr->width*pixel_bytes; - incr1 = (disp)*pixel_bytes; - for (i = initial_val; i < final_val; i += incr1) - { - png_memcpy(dstptr, srcptr, pixel_bytes); - srcptr += incr1; - dstptr += incr1; - } - } /* end of else */ - - break; - } // end 48 bpp - - default: - { - png_bytep sptr; - png_bytep dp; - png_size_t pixel_bytes; - int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; - unsigned int i; - register int disp = png_pass_inc[png_ptr->pass]; // get the offset - register unsigned int incr1, initial_val, final_val; - - pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); - sptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* - pixel_bytes; - dp = row + offset_table[png_ptr->pass]*pixel_bytes; - initial_val = offset_table[png_ptr->pass]*pixel_bytes; - final_val = png_ptr->width*pixel_bytes; - incr1 = (disp)*pixel_bytes; - for (i = initial_val; i < final_val; i += incr1) - { - png_memcpy(dp, sptr, pixel_bytes); - sptr += incr1; - dp += incr1; - } - break; - } - } /* end switch (png_ptr->row_info.pixel_depth) */ - } /* end if (non-trivial mask) */ - -} /* end png_combine_row() */ - - -#if defined(PNG_READ_INTERLACING_SUPPORTED) - -void /* PRIVATE */ -png_do_read_interlace(png_structp png_ptr) -{ - png_row_infop row_info = &(png_ptr->row_info); - png_bytep row = png_ptr->row_buf + 1; - int pass = png_ptr->pass; - png_uint_32 transformations = png_ptr->transformations; -#ifdef PNG_USE_LOCAL_ARRAYS - const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; -#endif - - png_debug(1,"in png_do_read_interlace\n"); - - if (mmx_supported == 2) { -#if !defined(PNG_1_0_X) - /* this should have happened in png_init_mmx_flags() already */ - png_warning(png_ptr, "asm_flags may not have been initialized"); -#endif - png_mmx_support(); - } - - if (row != NULL && row_info != NULL) - { - png_uint_32 final_width; - - final_width = row_info->width * png_pass_inc[pass]; - - switch (row_info->pixel_depth) - { - case 1: - { - png_bytep sp, dp; - int sshift, dshift; - int s_start, s_end, s_inc; - png_byte v; - png_uint_32 i; - int j; - - sp = row + (png_size_t)((row_info->width - 1) >> 3); - dp = row + (png_size_t)((final_width - 1) >> 3); -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (int)((row_info->width + 7) & 7); - dshift = (int)((final_width + 7) & 7); - s_start = 7; - s_end = 0; - s_inc = -1; - } - else -#endif - { - sshift = 7 - (int)((row_info->width + 7) & 7); - dshift = 7 - (int)((final_width + 7) & 7); - s_start = 0; - s_end = 7; - s_inc = 1; - } - - for (i = row_info->width; i; i--) - { - v = (png_byte)((*sp >> sshift) & 0x1); - for (j = 0; j < png_pass_inc[pass]; j++) - { - *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - - case 2: - { - png_bytep sp, dp; - int sshift, dshift; - int s_start, s_end, s_inc; - png_uint_32 i; - - sp = row + (png_size_t)((row_info->width - 1) >> 2); - dp = row + (png_size_t)((final_width - 1) >> 2); -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (png_size_t)(((row_info->width + 3) & 3) << 1); - dshift = (png_size_t)(((final_width + 3) & 3) << 1); - s_start = 6; - s_end = 0; - s_inc = -2; - } - else -#endif - { - sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1); - dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1); - s_start = 0; - s_end = 6; - s_inc = 2; - } - - for (i = row_info->width; i; i--) - { - png_byte v; - int j; - - v = (png_byte)((*sp >> sshift) & 0x3); - for (j = 0; j < png_pass_inc[pass]; j++) - { - *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - - case 4: - { - png_bytep sp, dp; - int sshift, dshift; - int s_start, s_end, s_inc; - png_uint_32 i; - - sp = row + (png_size_t)((row_info->width - 1) >> 1); - dp = row + (png_size_t)((final_width - 1) >> 1); -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (png_size_t)(((row_info->width + 1) & 1) << 2); - dshift = (png_size_t)(((final_width + 1) & 1) << 2); - s_start = 4; - s_end = 0; - s_inc = -4; - } - else -#endif - { - sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2); - dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2); - s_start = 0; - s_end = 4; - s_inc = 4; - } - - for (i = row_info->width; i; i--) - { - png_byte v; - int j; - - v = (png_byte)((*sp >> sshift) & 0xf); - for (j = 0; j < png_pass_inc[pass]; j++) - { - *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - - default: // This is the place where the routine is modified - { - __int64 const4 = 0x0000000000FFFFFF; - // __int64 const5 = 0x000000FFFFFF0000; // unused... - __int64 const6 = 0x00000000000000FF; - png_bytep sptr, dp; - png_uint_32 i; - png_size_t pixel_bytes; - int width = row_info->width; - - pixel_bytes = (row_info->pixel_depth >> 3); - - sptr = row + (width - 1) * pixel_bytes; - dp = row + (final_width - 1) * pixel_bytes; - // New code by Nirav Chhatrapati - Intel Corporation - // sign fix by GRR - // NOTE: there is NO MMX code for 48-bit and 64-bit images - - // use MMX routine if machine supports it -#if !defined(PNG_1_0_X) - if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_INTERLACE) - /* && mmx_supported */ ) -#else - if (mmx_supported) -#endif - { - if (pixel_bytes == 3) - { - if (((pass == 0) || (pass == 1)) && width) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width - sub edi, 21 // (png_pass_inc[pass] - 1)*pixel_bytes -loop_pass0: - movd mm0, [esi] ; X X X X X v2 v1 v0 - pand mm0, const4 ; 0 0 0 0 0 v2 v1 v0 - movq mm1, mm0 ; 0 0 0 0 0 v2 v1 v0 - psllq mm0, 16 ; 0 0 0 v2 v1 v0 0 0 - movq mm2, mm0 ; 0 0 0 v2 v1 v0 0 0 - psllq mm0, 24 ; v2 v1 v0 0 0 0 0 0 - psrlq mm1, 8 ; 0 0 0 0 0 0 v2 v1 - por mm0, mm2 ; v2 v1 v0 v2 v1 v0 0 0 - por mm0, mm1 ; v2 v1 v0 v2 v1 v0 v2 v1 - movq mm3, mm0 ; v2 v1 v0 v2 v1 v0 v2 v1 - psllq mm0, 16 ; v0 v2 v1 v0 v2 v1 0 0 - movq mm4, mm3 ; v2 v1 v0 v2 v1 v0 v2 v1 - punpckhdq mm3, mm0 ; v0 v2 v1 v0 v2 v1 v0 v2 - movq [edi+16] , mm4 - psrlq mm0, 32 ; 0 0 0 0 v0 v2 v1 v0 - movq [edi+8] , mm3 - punpckldq mm0, mm4 ; v1 v0 v2 v1 v0 v2 v1 v0 - sub esi, 3 - movq [edi], mm0 - sub edi, 24 - //sub esi, 3 - dec ecx - jnz loop_pass0 - EMMS - } - } - else if (((pass == 2) || (pass == 3)) && width) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width - sub edi, 9 // (png_pass_inc[pass] - 1)*pixel_bytes -loop_pass2: - movd mm0, [esi] ; X X X X X v2 v1 v0 - pand mm0, const4 ; 0 0 0 0 0 v2 v1 v0 - movq mm1, mm0 ; 0 0 0 0 0 v2 v1 v0 - psllq mm0, 16 ; 0 0 0 v2 v1 v0 0 0 - movq mm2, mm0 ; 0 0 0 v2 v1 v0 0 0 - psllq mm0, 24 ; v2 v1 v0 0 0 0 0 0 - psrlq mm1, 8 ; 0 0 0 0 0 0 v2 v1 - por mm0, mm2 ; v2 v1 v0 v2 v1 v0 0 0 - por mm0, mm1 ; v2 v1 v0 v2 v1 v0 v2 v1 - movq [edi+4], mm0 ; move to memory - psrlq mm0, 16 ; 0 0 v2 v1 v0 v2 v1 v0 - movd [edi], mm0 ; move to memory - sub esi, 3 - sub edi, 12 - dec ecx - jnz loop_pass2 - EMMS - } - } - else if (width) /* && ((pass == 4) || (pass == 5)) */ - { - int width_mmx = ((width >> 1) << 1) - 8; - if (width_mmx < 0) - width_mmx = 0; - width -= width_mmx; // 8 or 9 pix, 24 or 27 bytes - if (width_mmx) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width_mmx - sub esi, 3 - sub edi, 9 -loop_pass4: - movq mm0, [esi] ; X X v2 v1 v0 v5 v4 v3 - movq mm7, mm0 ; X X v2 v1 v0 v5 v4 v3 - movq mm6, mm0 ; X X v2 v1 v0 v5 v4 v3 - psllq mm0, 24 ; v1 v0 v5 v4 v3 0 0 0 - pand mm7, const4 ; 0 0 0 0 0 v5 v4 v3 - psrlq mm6, 24 ; 0 0 0 X X v2 v1 v0 - por mm0, mm7 ; v1 v0 v5 v4 v3 v5 v4 v3 - movq mm5, mm6 ; 0 0 0 X X v2 v1 v0 - psllq mm6, 8 ; 0 0 X X v2 v1 v0 0 - movq [edi], mm0 ; move quad to memory - psrlq mm5, 16 ; 0 0 0 0 0 X X v2 - pand mm5, const6 ; 0 0 0 0 0 0 0 v2 - por mm6, mm5 ; 0 0 X X v2 v1 v0 v2 - movd [edi+8], mm6 ; move double to memory - sub esi, 6 - sub edi, 12 - sub ecx, 2 - jnz loop_pass4 - EMMS - } - } - - sptr -= width_mmx*3; - dp -= width_mmx*6; - for (i = width; i; i--) - { - png_byte v[8]; - int j; - - png_memcpy(v, sptr, 3); - for (j = 0; j < png_pass_inc[pass]; j++) - { - png_memcpy(dp, v, 3); - dp -= 3; - } - sptr -= 3; - } - } - } /* end of pixel_bytes == 3 */ - - else if (pixel_bytes == 1) - { - if (((pass == 0) || (pass == 1)) && width) - { - int width_mmx = ((width >> 2) << 2); - width -= width_mmx; - if (width_mmx) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width_mmx - sub edi, 31 - sub esi, 3 -loop1_pass0: - movd mm0, [esi] ; X X X X v0 v1 v2 v3 - movq mm1, mm0 ; X X X X v0 v1 v2 v3 - punpcklbw mm0, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 - movq mm2, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 - punpcklwd mm0, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3 - movq mm3, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3 - punpckldq mm0, mm0 ; v3 v3 v3 v3 v3 v3 v3 v3 - punpckhdq mm3, mm3 ; v2 v2 v2 v2 v2 v2 v2 v2 - movq [edi], mm0 ; move to memory v3 - punpckhwd mm2, mm2 ; v0 v0 v0 v0 v1 v1 v1 v1 - movq [edi+8], mm3 ; move to memory v2 - movq mm4, mm2 ; v0 v0 v0 v0 v1 v1 v1 v1 - punpckldq mm2, mm2 ; v1 v1 v1 v1 v1 v1 v1 v1 - punpckhdq mm4, mm4 ; v0 v0 v0 v0 v0 v0 v0 v0 - movq [edi+16], mm2 ; move to memory v1 - movq [edi+24], mm4 ; move to memory v0 - sub esi, 4 - sub edi, 32 - sub ecx, 4 - jnz loop1_pass0 - EMMS - } - } - - sptr -= width_mmx; - dp -= width_mmx*8; - for (i = width; i; i--) - { - int j; - - /* I simplified this part in version 1.0.4e - * here and in several other instances where - * pixel_bytes == 1 -- GR-P - * - * Original code: - * - * png_byte v[8]; - * png_memcpy(v, sptr, pixel_bytes); - * for (j = 0; j < png_pass_inc[pass]; j++) - * { - * png_memcpy(dp, v, pixel_bytes); - * dp -= pixel_bytes; - * } - * sptr -= pixel_bytes; - * - * Replacement code is in the next three lines: - */ - - for (j = 0; j < png_pass_inc[pass]; j++) - *dp-- = *sptr; - sptr--; - } - } - else if (((pass == 2) || (pass == 3)) && width) - { - int width_mmx = ((width >> 2) << 2); - width -= width_mmx; - if (width_mmx) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width_mmx - sub edi, 15 - sub esi, 3 -loop1_pass2: - movd mm0, [esi] ; X X X X v0 v1 v2 v3 - punpcklbw mm0, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 - movq mm1, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 - punpcklwd mm0, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3 - punpckhwd mm1, mm1 ; v0 v0 v0 v0 v1 v1 v1 v1 - movq [edi], mm0 ; move to memory v2 and v3 - sub esi, 4 - movq [edi+8], mm1 ; move to memory v1 and v0 - sub edi, 16 - sub ecx, 4 - jnz loop1_pass2 - EMMS - } - } - - sptr -= width_mmx; - dp -= width_mmx*4; - for (i = width; i; i--) - { - int j; - - for (j = 0; j < png_pass_inc[pass]; j++) - { - *dp-- = *sptr; - } - sptr --; - } - } - else if (width) /* && ((pass == 4) || (pass == 5))) */ - { - int width_mmx = ((width >> 3) << 3); - width -= width_mmx; - if (width_mmx) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width_mmx - sub edi, 15 - sub esi, 7 -loop1_pass4: - movq mm0, [esi] ; v0 v1 v2 v3 v4 v5 v6 v7 - movq mm1, mm0 ; v0 v1 v2 v3 v4 v5 v6 v7 - punpcklbw mm0, mm0 ; v4 v4 v5 v5 v6 v6 v7 v7 - //movq mm1, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 - punpckhbw mm1, mm1 ;v0 v0 v1 v1 v2 v2 v3 v3 - movq [edi+8], mm1 ; move to memory v0 v1 v2 and v3 - sub esi, 8 - movq [edi], mm0 ; move to memory v4 v5 v6 and v7 - //sub esi, 4 - sub edi, 16 - sub ecx, 8 - jnz loop1_pass4 - EMMS - } - } - - sptr -= width_mmx; - dp -= width_mmx*2; - for (i = width; i; i--) - { - int j; - - for (j = 0; j < png_pass_inc[pass]; j++) - { - *dp-- = *sptr; - } - sptr --; - } - } - } /* end of pixel_bytes == 1 */ - - else if (pixel_bytes == 2) - { - if (((pass == 0) || (pass == 1)) && width) - { - int width_mmx = ((width >> 1) << 1); - width -= width_mmx; - if (width_mmx) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width_mmx - sub esi, 2 - sub edi, 30 -loop2_pass0: - movd mm0, [esi] ; X X X X v1 v0 v3 v2 - punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2 - movq mm1, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2 - punpckldq mm0, mm0 ; v3 v2 v3 v2 v3 v2 v3 v2 - punpckhdq mm1, mm1 ; v1 v0 v1 v0 v1 v0 v1 v0 - movq [edi], mm0 - movq [edi + 8], mm0 - movq [edi + 16], mm1 - movq [edi + 24], mm1 - sub esi, 4 - sub edi, 32 - sub ecx, 2 - jnz loop2_pass0 - EMMS - } - } - - sptr -= (width_mmx*2 - 2); // sign fixed - dp -= (width_mmx*16 - 2); // sign fixed - for (i = width; i; i--) - { - png_byte v[8]; - int j; - sptr -= 2; - png_memcpy(v, sptr, 2); - for (j = 0; j < png_pass_inc[pass]; j++) - { - dp -= 2; - png_memcpy(dp, v, 2); - } - } - } - else if (((pass == 2) || (pass == 3)) && width) - { - int width_mmx = ((width >> 1) << 1) ; - width -= width_mmx; - if (width_mmx) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width_mmx - sub esi, 2 - sub edi, 14 -loop2_pass2: - movd mm0, [esi] ; X X X X v1 v0 v3 v2 - punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2 - movq mm1, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2 - punpckldq mm0, mm0 ; v3 v2 v3 v2 v3 v2 v3 v2 - punpckhdq mm1, mm1 ; v1 v0 v1 v0 v1 v0 v1 v0 - movq [edi], mm0 - sub esi, 4 - movq [edi + 8], mm1 - //sub esi, 4 - sub edi, 16 - sub ecx, 2 - jnz loop2_pass2 - EMMS - } - } - - sptr -= (width_mmx*2 - 2); // sign fixed - dp -= (width_mmx*8 - 2); // sign fixed - for (i = width; i; i--) - { - png_byte v[8]; - int j; - sptr -= 2; - png_memcpy(v, sptr, 2); - for (j = 0; j < png_pass_inc[pass]; j++) - { - dp -= 2; - png_memcpy(dp, v, 2); - } - } - } - else if (width) // pass == 4 or 5 - { - int width_mmx = ((width >> 1) << 1) ; - width -= width_mmx; - if (width_mmx) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width_mmx - sub esi, 2 - sub edi, 6 -loop2_pass4: - movd mm0, [esi] ; X X X X v1 v0 v3 v2 - punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2 - sub esi, 4 - movq [edi], mm0 - sub edi, 8 - sub ecx, 2 - jnz loop2_pass4 - EMMS - } - } - - sptr -= (width_mmx*2 - 2); // sign fixed - dp -= (width_mmx*4 - 2); // sign fixed - for (i = width; i; i--) - { - png_byte v[8]; - int j; - sptr -= 2; - png_memcpy(v, sptr, 2); - for (j = 0; j < png_pass_inc[pass]; j++) - { - dp -= 2; - png_memcpy(dp, v, 2); - } - } - } - } /* end of pixel_bytes == 2 */ - - else if (pixel_bytes == 4) - { - if (((pass == 0) || (pass == 1)) && width) - { - int width_mmx = ((width >> 1) << 1) ; - width -= width_mmx; - if (width_mmx) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width_mmx - sub esi, 4 - sub edi, 60 -loop4_pass0: - movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4 - movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4 - punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4 - punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0 - movq [edi], mm0 - movq [edi + 8], mm0 - movq [edi + 16], mm0 - movq [edi + 24], mm0 - movq [edi+32], mm1 - movq [edi + 40], mm1 - movq [edi+ 48], mm1 - sub esi, 8 - movq [edi + 56], mm1 - sub edi, 64 - sub ecx, 2 - jnz loop4_pass0 - EMMS - } - } - - sptr -= (width_mmx*4 - 4); // sign fixed - dp -= (width_mmx*32 - 4); // sign fixed - for (i = width; i; i--) - { - png_byte v[8]; - int j; - sptr -= 4; - png_memcpy(v, sptr, 4); - for (j = 0; j < png_pass_inc[pass]; j++) - { - dp -= 4; - png_memcpy(dp, v, 4); - } - } - } - else if (((pass == 2) || (pass == 3)) && width) - { - int width_mmx = ((width >> 1) << 1) ; - width -= width_mmx; - if (width_mmx) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width_mmx - sub esi, 4 - sub edi, 28 -loop4_pass2: - movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4 - movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4 - punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4 - punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0 - movq [edi], mm0 - movq [edi + 8], mm0 - movq [edi+16], mm1 - movq [edi + 24], mm1 - sub esi, 8 - sub edi, 32 - sub ecx, 2 - jnz loop4_pass2 - EMMS - } - } - - sptr -= (width_mmx*4 - 4); // sign fixed - dp -= (width_mmx*16 - 4); // sign fixed - for (i = width; i; i--) - { - png_byte v[8]; - int j; - sptr -= 4; - png_memcpy(v, sptr, 4); - for (j = 0; j < png_pass_inc[pass]; j++) - { - dp -= 4; - png_memcpy(dp, v, 4); - } - } - } - else if (width) // pass == 4 or 5 - { - int width_mmx = ((width >> 1) << 1) ; - width -= width_mmx; - if (width_mmx) - { - _asm - { - mov esi, sptr - mov edi, dp - mov ecx, width_mmx - sub esi, 4 - sub edi, 12 -loop4_pass4: - movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4 - movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4 - punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4 - punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0 - movq [edi], mm0 - sub esi, 8 - movq [edi + 8], mm1 - sub edi, 16 - sub ecx, 2 - jnz loop4_pass4 - EMMS - } - } - - sptr -= (width_mmx*4 - 4); // sign fixed - dp -= (width_mmx*8 - 4); // sign fixed - for (i = width; i; i--) - { - png_byte v[8]; - int j; - sptr -= 4; - png_memcpy(v, sptr, 4); - for (j = 0; j < png_pass_inc[pass]; j++) - { - dp -= 4; - png_memcpy(dp, v, 4); - } - } - } - - } /* end of pixel_bytes == 4 */ - - else if (pixel_bytes == 6) - { - for (i = width; i; i--) - { - png_byte v[8]; - int j; - png_memcpy(v, sptr, 6); - for (j = 0; j < png_pass_inc[pass]; j++) - { - png_memcpy(dp, v, 6); - dp -= 6; - } - sptr -= 6; - } - } /* end of pixel_bytes == 6 */ - - else - { - for (i = width; i; i--) - { - png_byte v[8]; - int j; - png_memcpy(v, sptr, pixel_bytes); - for (j = 0; j < png_pass_inc[pass]; j++) - { - png_memcpy(dp, v, pixel_bytes); - dp -= pixel_bytes; - } - sptr-= pixel_bytes; - } - } - } /* end of mmx_supported */ - - else /* MMX not supported: use modified C code - takes advantage - * of inlining of memcpy for a constant */ - { - if (pixel_bytes == 1) - { - for (i = width; i; i--) - { - int j; - for (j = 0; j < png_pass_inc[pass]; j++) - *dp-- = *sptr; - sptr--; - } - } - else if (pixel_bytes == 3) - { - for (i = width; i; i--) - { - png_byte v[8]; - int j; - png_memcpy(v, sptr, pixel_bytes); - for (j = 0; j < png_pass_inc[pass]; j++) - { - png_memcpy(dp, v, pixel_bytes); - dp -= pixel_bytes; - } - sptr -= pixel_bytes; - } - } - else if (pixel_bytes == 2) - { - for (i = width; i; i--) - { - png_byte v[8]; - int j; - png_memcpy(v, sptr, pixel_bytes); - for (j = 0; j < png_pass_inc[pass]; j++) - { - png_memcpy(dp, v, pixel_bytes); - dp -= pixel_bytes; - } - sptr -= pixel_bytes; - } - } - else if (pixel_bytes == 4) - { - for (i = width; i; i--) - { - png_byte v[8]; - int j; - png_memcpy(v, sptr, pixel_bytes); - for (j = 0; j < png_pass_inc[pass]; j++) - { - png_memcpy(dp, v, pixel_bytes); - dp -= pixel_bytes; - } - sptr -= pixel_bytes; - } - } - else if (pixel_bytes == 6) - { - for (i = width; i; i--) - { - png_byte v[8]; - int j; - png_memcpy(v, sptr, pixel_bytes); - for (j = 0; j < png_pass_inc[pass]; j++) - { - png_memcpy(dp, v, pixel_bytes); - dp -= pixel_bytes; - } - sptr -= pixel_bytes; - } - } - else - { - for (i = width; i; i--) - { - png_byte v[8]; - int j; - png_memcpy(v, sptr, pixel_bytes); - for (j = 0; j < png_pass_inc[pass]; j++) - { - png_memcpy(dp, v, pixel_bytes); - dp -= pixel_bytes; - } - sptr -= pixel_bytes; - } - } - - } /* end of MMX not supported */ - break; - } - } /* end switch (row_info->pixel_depth) */ - - row_info->width = final_width; - - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width); - } - -} - -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - - -// These variables are utilized in the functions below. They are declared -// globally here to ensure alignment on 8-byte boundaries. - -union uAll { - __int64 use; - double align; -} LBCarryMask = {0x0101010101010101}, - HBClearMask = {0x7f7f7f7f7f7f7f7f}, - ActiveMask, ActiveMask2, ActiveMaskEnd, ShiftBpp, ShiftRem; - - -// Optimized code for PNG Average filter decoder -void /* PRIVATE */ -png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row - , png_bytep prev_row) -{ - int bpp; - png_uint_32 FullLength; - png_uint_32 MMXLength; - //png_uint_32 len; - int diff; - - bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel - FullLength = row_info->rowbytes; // # of bytes to filter - _asm { - // Init address pointers and offset - mov edi, row // edi ==> Avg(x) - xor ebx, ebx // ebx ==> x - mov edx, edi - mov esi, prev_row // esi ==> Prior(x) - sub edx, bpp // edx ==> Raw(x-bpp) - - xor eax, eax - // Compute the Raw value for the first bpp bytes - // Raw(x) = Avg(x) + (Prior(x)/2) -davgrlp: - mov al, [esi + ebx] // Load al with Prior(x) - inc ebx - shr al, 1 // divide by 2 - add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx - cmp ebx, bpp - mov [edi+ebx-1], al // Write back Raw(x); - // mov does not affect flags; -1 to offset inc ebx - jb davgrlp - // get # of bytes to alignment - mov diff, edi // take start of row - add diff, ebx // add bpp - add diff, 0xf // add 7 + 8 to incr past alignment boundary - and diff, 0xfffffff8 // mask to alignment boundary - sub diff, edi // subtract from start ==> value ebx at alignment - jz davggo - // fix alignment - // Compute the Raw value for the bytes upto the alignment boundary - // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) - xor ecx, ecx -davglp1: - xor eax, eax - mov cl, [esi + ebx] // load cl with Prior(x) - mov al, [edx + ebx] // load al with Raw(x-bpp) - add ax, cx - inc ebx - shr ax, 1 // divide by 2 - add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx - cmp ebx, diff // Check if at alignment boundary - mov [edi+ebx-1], al // Write back Raw(x); - // mov does not affect flags; -1 to offset inc ebx - jb davglp1 // Repeat until at alignment boundary -davggo: - mov eax, FullLength - mov ecx, eax - sub eax, ebx // subtract alignment fix - and eax, 0x00000007 // calc bytes over mult of 8 - sub ecx, eax // drop over bytes from original length - mov MMXLength, ecx - } // end _asm block - // Now do the math for the rest of the row - switch ( bpp ) - { - case 3: - { - ActiveMask.use = 0x0000000000ffffff; - ShiftBpp.use = 24; // == 3 * 8 - ShiftRem.use = 40; // == 64 - 24 - _asm { - // Re-init address pointers and offset - movq mm7, ActiveMask - mov ebx, diff // ebx ==> x = offset to alignment boundary - movq mm5, LBCarryMask - mov edi, row // edi ==> Avg(x) - movq mm4, HBClearMask - mov esi, prev_row // esi ==> Prior(x) - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes - // (we correct position in loop below) -davg3lp: - movq mm0, [edi + ebx] // Load mm0 with Avg(x) - // Add (Prev_row/2) to Average - movq mm3, mm5 - psrlq mm2, ShiftRem // Correct position Raw(x-bpp) data - movq mm1, [esi + ebx] // Load mm1 with Prior(x) - movq mm6, mm7 - pand mm3, mm1 // get lsb for each prev_row byte - psrlq mm1, 1 // divide prev_row bytes by 2 - pand mm1, mm4 // clear invalid bit 7 of each byte - paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte - // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry - movq mm1, mm3 // now use mm1 for getting LBCarrys - pand mm1, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 (Only valid for active group) - psrlq mm2, 1 // divide raw bytes by 2 - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte - pand mm2, mm6 // Leave only Active Group 1 bytes to add to Avg - paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active - // byte - // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry - psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 3-5 - movq mm2, mm0 // mov updated Raws to mm2 - psllq mm2, ShiftBpp // shift data to position correctly - movq mm1, mm3 // now use mm1 for getting LBCarrys - pand mm1, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 (Only valid for active group) - psrlq mm2, 1 // divide raw bytes by 2 - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte - pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg - paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active - // byte - - // Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry - psllq mm6, ShiftBpp // shift the mm6 mask to cover the last two - // bytes - movq mm2, mm0 // mov updated Raws to mm2 - psllq mm2, ShiftBpp // shift data to position correctly - // Data only needs to be shifted once here to - // get the correct x-bpp offset. - movq mm1, mm3 // now use mm1 for getting LBCarrys - pand mm1, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 (Only valid for active group) - psrlq mm2, 1 // divide raw bytes by 2 - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte - pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg - add ebx, 8 - paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active - // byte - - // Now ready to write back to memory - movq [edi + ebx - 8], mm0 - // Move updated Raw(x) to use as Raw(x-bpp) for next loop - cmp ebx, MMXLength - movq mm2, mm0 // mov updated Raw(x) to mm2 - jb davg3lp - } // end _asm block - } - break; - - case 6: - case 4: - case 7: - case 5: - { - ActiveMask.use = 0xffffffffffffffff; // use shift below to clear - // appropriate inactive bytes - ShiftBpp.use = bpp << 3; - ShiftRem.use = 64 - ShiftBpp.use; - _asm { - movq mm4, HBClearMask - // Re-init address pointers and offset - mov ebx, diff // ebx ==> x = offset to alignment boundary - // Load ActiveMask and clear all bytes except for 1st active group - movq mm7, ActiveMask - mov edi, row // edi ==> Avg(x) - psrlq mm7, ShiftRem - mov esi, prev_row // esi ==> Prior(x) - movq mm6, mm7 - movq mm5, LBCarryMask - psllq mm6, ShiftBpp // Create mask for 2nd active group - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes - // (we correct position in loop below) -davg4lp: - movq mm0, [edi + ebx] - psrlq mm2, ShiftRem // shift data to position correctly - movq mm1, [esi + ebx] - // Add (Prev_row/2) to Average - movq mm3, mm5 - pand mm3, mm1 // get lsb for each prev_row byte - psrlq mm1, 1 // divide prev_row bytes by 2 - pand mm1, mm4 // clear invalid bit 7 of each byte - paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte - // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry - movq mm1, mm3 // now use mm1 for getting LBCarrys - pand mm1, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 (Only valid for active group) - psrlq mm2, 1 // divide raw bytes by 2 - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte - pand mm2, mm7 // Leave only Active Group 1 bytes to add to Avg - paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active - // byte - // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry - movq mm2, mm0 // mov updated Raws to mm2 - psllq mm2, ShiftBpp // shift data to position correctly - add ebx, 8 - movq mm1, mm3 // now use mm1 for getting LBCarrys - pand mm1, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 (Only valid for active group) - psrlq mm2, 1 // divide raw bytes by 2 - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte - pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg - paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active - // byte - cmp ebx, MMXLength - // Now ready to write back to memory - movq [edi + ebx - 8], mm0 - // Prep Raw(x-bpp) for next loop - movq mm2, mm0 // mov updated Raws to mm2 - jb davg4lp - } // end _asm block - } - break; - case 2: - { - ActiveMask.use = 0x000000000000ffff; - ShiftBpp.use = 16; // == 2 * 8 [BUGFIX] - ShiftRem.use = 48; // == 64 - 16 [BUGFIX] - _asm { - // Load ActiveMask - movq mm7, ActiveMask - // Re-init address pointers and offset - mov ebx, diff // ebx ==> x = offset to alignment boundary - movq mm5, LBCarryMask - mov edi, row // edi ==> Avg(x) - movq mm4, HBClearMask - mov esi, prev_row // esi ==> Prior(x) - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes - // (we correct position in loop below) -davg2lp: - movq mm0, [edi + ebx] - psrlq mm2, ShiftRem // shift data to position correctly [BUGFIX] - movq mm1, [esi + ebx] - // Add (Prev_row/2) to Average - movq mm3, mm5 - pand mm3, mm1 // get lsb for each prev_row byte - psrlq mm1, 1 // divide prev_row bytes by 2 - pand mm1, mm4 // clear invalid bit 7 of each byte - movq mm6, mm7 - paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte - // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry - movq mm1, mm3 // now use mm1 for getting LBCarrys - pand mm1, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 (Only valid for active group) - psrlq mm2, 1 // divide raw bytes by 2 - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte - pand mm2, mm6 // Leave only Active Group 1 bytes to add to Avg - paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte - // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry - psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 2 & 3 - movq mm2, mm0 // mov updated Raws to mm2 - psllq mm2, ShiftBpp // shift data to position correctly - movq mm1, mm3 // now use mm1 for getting LBCarrys - pand mm1, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 (Only valid for active group) - psrlq mm2, 1 // divide raw bytes by 2 - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte - pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg - paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte - - // Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry - psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 4 & 5 - movq mm2, mm0 // mov updated Raws to mm2 - psllq mm2, ShiftBpp // shift data to position correctly - // Data only needs to be shifted once here to - // get the correct x-bpp offset. - movq mm1, mm3 // now use mm1 for getting LBCarrys - pand mm1, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 (Only valid for active group) - psrlq mm2, 1 // divide raw bytes by 2 - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte - pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg - paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte - - // Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry - psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 6 & 7 - movq mm2, mm0 // mov updated Raws to mm2 - psllq mm2, ShiftBpp // shift data to position correctly - // Data only needs to be shifted once here to - // get the correct x-bpp offset. - add ebx, 8 - movq mm1, mm3 // now use mm1 for getting LBCarrys - pand mm1, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 (Only valid for active group) - psrlq mm2, 1 // divide raw bytes by 2 - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte - pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg - paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte - - cmp ebx, MMXLength - // Now ready to write back to memory - movq [edi + ebx - 8], mm0 - // Prep Raw(x-bpp) for next loop - movq mm2, mm0 // mov updated Raws to mm2 - jb davg2lp - } // end _asm block - } - break; - - case 1: // bpp == 1 - { - _asm { - // Re-init address pointers and offset - mov ebx, diff // ebx ==> x = offset to alignment boundary - mov edi, row // edi ==> Avg(x) - cmp ebx, FullLength // Test if offset at end of array - jnb davg1end - // Do Paeth decode for remaining bytes - mov esi, prev_row // esi ==> Prior(x) - mov edx, edi - xor ecx, ecx // zero ecx before using cl & cx in loop below - sub edx, bpp // edx ==> Raw(x-bpp) -davg1lp: - // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) - xor eax, eax - mov cl, [esi + ebx] // load cl with Prior(x) - mov al, [edx + ebx] // load al with Raw(x-bpp) - add ax, cx - inc ebx - shr ax, 1 // divide by 2 - add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx - cmp ebx, FullLength // Check if at end of array - mov [edi+ebx-1], al // Write back Raw(x); - // mov does not affect flags; -1 to offset inc ebx - jb davg1lp -davg1end: - } // end _asm block - } - return; - - case 8: // bpp == 8 - { - _asm { - // Re-init address pointers and offset - mov ebx, diff // ebx ==> x = offset to alignment boundary - movq mm5, LBCarryMask - mov edi, row // edi ==> Avg(x) - movq mm4, HBClearMask - mov esi, prev_row // esi ==> Prior(x) - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes - // (NO NEED to correct position in loop below) -davg8lp: - movq mm0, [edi + ebx] - movq mm3, mm5 - movq mm1, [esi + ebx] - add ebx, 8 - pand mm3, mm1 // get lsb for each prev_row byte - psrlq mm1, 1 // divide prev_row bytes by 2 - pand mm3, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 - psrlq mm2, 1 // divide raw bytes by 2 - pand mm1, mm4 // clear invalid bit 7 of each byte - paddb mm0, mm3 // add LBCarrys to Avg for each byte - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte - paddb mm0, mm2 // add (Raw/2) to Avg for each byte - cmp ebx, MMXLength - movq [edi + ebx - 8], mm0 - movq mm2, mm0 // reuse as Raw(x-bpp) - jb davg8lp - } // end _asm block - } - break; - default: // bpp greater than 8 - { - _asm { - movq mm5, LBCarryMask - // Re-init address pointers and offset - mov ebx, diff // ebx ==> x = offset to alignment boundary - mov edi, row // edi ==> Avg(x) - movq mm4, HBClearMask - mov edx, edi - mov esi, prev_row // esi ==> Prior(x) - sub edx, bpp // edx ==> Raw(x-bpp) -davgAlp: - movq mm0, [edi + ebx] - movq mm3, mm5 - movq mm1, [esi + ebx] - pand mm3, mm1 // get lsb for each prev_row byte - movq mm2, [edx + ebx] - psrlq mm1, 1 // divide prev_row bytes by 2 - pand mm3, mm2 // get LBCarrys for each byte where both - // lsb's were == 1 - psrlq mm2, 1 // divide raw bytes by 2 - pand mm1, mm4 // clear invalid bit 7 of each byte - paddb mm0, mm3 // add LBCarrys to Avg for each byte - pand mm2, mm4 // clear invalid bit 7 of each byte - paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte - add ebx, 8 - paddb mm0, mm2 // add (Raw/2) to Avg for each byte - cmp ebx, MMXLength - movq [edi + ebx - 8], mm0 - jb davgAlp - } // end _asm block - } - break; - } // end switch ( bpp ) - - _asm { - // MMX acceleration complete now do clean-up - // Check if any remaining bytes left to decode - mov ebx, MMXLength // ebx ==> x = offset bytes remaining after MMX - mov edi, row // edi ==> Avg(x) - cmp ebx, FullLength // Test if offset at end of array - jnb davgend - // Do Paeth decode for remaining bytes - mov esi, prev_row // esi ==> Prior(x) - mov edx, edi - xor ecx, ecx // zero ecx before using cl & cx in loop below - sub edx, bpp // edx ==> Raw(x-bpp) -davglp2: - // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) - xor eax, eax - mov cl, [esi + ebx] // load cl with Prior(x) - mov al, [edx + ebx] // load al with Raw(x-bpp) - add ax, cx - inc ebx - shr ax, 1 // divide by 2 - add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx - cmp ebx, FullLength // Check if at end of array - mov [edi+ebx-1], al // Write back Raw(x); - // mov does not affect flags; -1 to offset inc ebx - jb davglp2 -davgend: - emms // End MMX instructions; prep for possible FP instrs. - } // end _asm block -} - -// Optimized code for PNG Paeth filter decoder -void /* PRIVATE */ -png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row, - png_bytep prev_row) -{ - png_uint_32 FullLength; - png_uint_32 MMXLength; - //png_uint_32 len; - int bpp; - int diff; - //int ptemp; - int patemp, pbtemp, pctemp; - - bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel - FullLength = row_info->rowbytes; // # of bytes to filter - _asm - { - xor ebx, ebx // ebx ==> x offset - mov edi, row - xor edx, edx // edx ==> x-bpp offset - mov esi, prev_row - xor eax, eax - - // Compute the Raw value for the first bpp bytes - // Note: the formula works out to be always - // Paeth(x) = Raw(x) + Prior(x) where x < bpp -dpthrlp: - mov al, [edi + ebx] - add al, [esi + ebx] - inc ebx - cmp ebx, bpp - mov [edi + ebx - 1], al - jb dpthrlp - // get # of bytes to alignment - mov diff, edi // take start of row - add diff, ebx // add bpp - xor ecx, ecx - add diff, 0xf // add 7 + 8 to incr past alignment boundary - and diff, 0xfffffff8 // mask to alignment boundary - sub diff, edi // subtract from start ==> value ebx at alignment - jz dpthgo - // fix alignment -dpthlp1: - xor eax, eax - // pav = p - a = (a + b - c) - a = b - c - mov al, [esi + ebx] // load Prior(x) into al - mov cl, [esi + edx] // load Prior(x-bpp) into cl - sub eax, ecx // subtract Prior(x-bpp) - mov patemp, eax // Save pav for later use - xor eax, eax - // pbv = p - b = (a + b - c) - b = a - c - mov al, [edi + edx] // load Raw(x-bpp) into al - sub eax, ecx // subtract Prior(x-bpp) - mov ecx, eax - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - add eax, patemp // pcv = pav + pbv - // pc = abs(pcv) - test eax, 0x80000000 - jz dpthpca - neg eax // reverse sign of neg values -dpthpca: - mov pctemp, eax // save pc for later use - // pb = abs(pbv) - test ecx, 0x80000000 - jz dpthpba - neg ecx // reverse sign of neg values -dpthpba: - mov pbtemp, ecx // save pb for later use - // pa = abs(pav) - mov eax, patemp - test eax, 0x80000000 - jz dpthpaa - neg eax // reverse sign of neg values -dpthpaa: - mov patemp, eax // save pa for later use - // test if pa <= pb - cmp eax, ecx - jna dpthabb - // pa > pb; now test if pb <= pc - cmp ecx, pctemp - jna dpthbbc - // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) - mov cl, [esi + edx] // load Prior(x-bpp) into cl - jmp dpthpaeth -dpthbbc: - // pb <= pc; Raw(x) = Paeth(x) + Prior(x) - mov cl, [esi + ebx] // load Prior(x) into cl - jmp dpthpaeth -dpthabb: - // pa <= pb; now test if pa <= pc - cmp eax, pctemp - jna dpthabc - // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) - mov cl, [esi + edx] // load Prior(x-bpp) into cl - jmp dpthpaeth -dpthabc: - // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) - mov cl, [edi + edx] // load Raw(x-bpp) into cl -dpthpaeth: - inc ebx - inc edx - // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 - add [edi + ebx - 1], cl - cmp ebx, diff - jb dpthlp1 -dpthgo: - mov ecx, FullLength - mov eax, ecx - sub eax, ebx // subtract alignment fix - and eax, 0x00000007 // calc bytes over mult of 8 - sub ecx, eax // drop over bytes from original length - mov MMXLength, ecx - } // end _asm block - // Now do the math for the rest of the row - switch ( bpp ) - { - case 3: - { - ActiveMask.use = 0x0000000000ffffff; - ActiveMaskEnd.use = 0xffff000000000000; - ShiftBpp.use = 24; // == bpp(3) * 8 - ShiftRem.use = 40; // == 64 - 24 - _asm - { - mov ebx, diff - mov edi, row - mov esi, prev_row - pxor mm0, mm0 - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm1, [edi+ebx-8] -dpth3lp: - psrlq mm1, ShiftRem // shift last 3 bytes to 1st 3 bytes - movq mm2, [esi + ebx] // load b=Prior(x) - punpcklbw mm1, mm0 // Unpack High bytes of a - movq mm3, [esi+ebx-8] // Prep c=Prior(x-bpp) bytes - punpcklbw mm2, mm0 // Unpack High bytes of b - psrlq mm3, ShiftRem // shift last 3 bytes to 1st 3 bytes - // pav = p - a = (a + b - c) - a = b - c - movq mm4, mm2 - punpcklbw mm3, mm0 // Unpack High bytes of c - // pbv = p - b = (a + b - c) - b = a - c - movq mm5, mm1 - psubw mm4, mm3 - pxor mm7, mm7 - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - movq mm6, mm4 - psubw mm5, mm3 - - // pa = abs(p-a) = abs(pav) - // pb = abs(p-b) = abs(pbv) - // pc = abs(p-c) = abs(pcv) - pcmpgtw mm0, mm4 // Create mask pav bytes < 0 - paddw mm6, mm5 - pand mm0, mm4 // Only pav bytes < 0 in mm7 - pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 - psubw mm4, mm0 - pand mm7, mm5 // Only pbv bytes < 0 in mm0 - psubw mm4, mm0 - psubw mm5, mm7 - pxor mm0, mm0 - pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 - pand mm0, mm6 // Only pav bytes < 0 in mm7 - psubw mm5, mm7 - psubw mm6, mm0 - // test pa <= pb - movq mm7, mm4 - psubw mm6, mm0 - pcmpgtw mm7, mm5 // pa > pb? - movq mm0, mm7 - // use mm7 mask to merge pa & pb - pand mm5, mm7 - // use mm0 mask copy to merge a & b - pand mm2, mm0 - pandn mm7, mm4 - pandn mm0, mm1 - paddw mm7, mm5 - paddw mm0, mm2 - // test ((pa <= pb)? pa:pb) <= pc - pcmpgtw mm7, mm6 // pab > pc? - pxor mm1, mm1 - pand mm3, mm7 - pandn mm7, mm0 - paddw mm7, mm3 - pxor mm0, mm0 - packuswb mm7, mm1 - movq mm3, [esi + ebx] // load c=Prior(x-bpp) - pand mm7, ActiveMask - movq mm2, mm3 // load b=Prior(x) step 1 - paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x) - punpcklbw mm3, mm0 // Unpack High bytes of c - movq [edi + ebx], mm7 // write back updated value - movq mm1, mm7 // Now mm1 will be used as Raw(x-bpp) - // Now do Paeth for 2nd set of bytes (3-5) - psrlq mm2, ShiftBpp // load b=Prior(x) step 2 - punpcklbw mm1, mm0 // Unpack High bytes of a - pxor mm7, mm7 - punpcklbw mm2, mm0 // Unpack High bytes of b - // pbv = p - b = (a + b - c) - b = a - c - movq mm5, mm1 - // pav = p - a = (a + b - c) - a = b - c - movq mm4, mm2 - psubw mm5, mm3 - psubw mm4, mm3 - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = - // pav + pbv = pbv + pav - movq mm6, mm5 - paddw mm6, mm4 - - // pa = abs(p-a) = abs(pav) - // pb = abs(p-b) = abs(pbv) - // pc = abs(p-c) = abs(pcv) - pcmpgtw mm0, mm5 // Create mask pbv bytes < 0 - pcmpgtw mm7, mm4 // Create mask pav bytes < 0 - pand mm0, mm5 // Only pbv bytes < 0 in mm0 - pand mm7, mm4 // Only pav bytes < 0 in mm7 - psubw mm5, mm0 - psubw mm4, mm7 - psubw mm5, mm0 - psubw mm4, mm7 - pxor mm0, mm0 - pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 - pand mm0, mm6 // Only pav bytes < 0 in mm7 - psubw mm6, mm0 - // test pa <= pb - movq mm7, mm4 - psubw mm6, mm0 - pcmpgtw mm7, mm5 // pa > pb? - movq mm0, mm7 - // use mm7 mask to merge pa & pb - pand mm5, mm7 - // use mm0 mask copy to merge a & b - pand mm2, mm0 - pandn mm7, mm4 - pandn mm0, mm1 - paddw mm7, mm5 - paddw mm0, mm2 - // test ((pa <= pb)? pa:pb) <= pc - pcmpgtw mm7, mm6 // pab > pc? - movq mm2, [esi + ebx] // load b=Prior(x) - pand mm3, mm7 - pandn mm7, mm0 - pxor mm1, mm1 - paddw mm7, mm3 - pxor mm0, mm0 - packuswb mm7, mm1 - movq mm3, mm2 // load c=Prior(x-bpp) step 1 - pand mm7, ActiveMask - punpckhbw mm2, mm0 // Unpack High bytes of b - psllq mm7, ShiftBpp // Shift bytes to 2nd group of 3 bytes - // pav = p - a = (a + b - c) - a = b - c - movq mm4, mm2 - paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x) - psllq mm3, ShiftBpp // load c=Prior(x-bpp) step 2 - movq [edi + ebx], mm7 // write back updated value - movq mm1, mm7 - punpckhbw mm3, mm0 // Unpack High bytes of c - psllq mm1, ShiftBpp // Shift bytes - // Now mm1 will be used as Raw(x-bpp) - // Now do Paeth for 3rd, and final, set of bytes (6-7) - pxor mm7, mm7 - punpckhbw mm1, mm0 // Unpack High bytes of a - psubw mm4, mm3 - // pbv = p - b = (a + b - c) - b = a - c - movq mm5, mm1 - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - movq mm6, mm4 - psubw mm5, mm3 - pxor mm0, mm0 - paddw mm6, mm5 - - // pa = abs(p-a) = abs(pav) - // pb = abs(p-b) = abs(pbv) - // pc = abs(p-c) = abs(pcv) - pcmpgtw mm0, mm4 // Create mask pav bytes < 0 - pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 - pand mm0, mm4 // Only pav bytes < 0 in mm7 - pand mm7, mm5 // Only pbv bytes < 0 in mm0 - psubw mm4, mm0 - psubw mm5, mm7 - psubw mm4, mm0 - psubw mm5, mm7 - pxor mm0, mm0 - pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 - pand mm0, mm6 // Only pav bytes < 0 in mm7 - psubw mm6, mm0 - // test pa <= pb - movq mm7, mm4 - psubw mm6, mm0 - pcmpgtw mm7, mm5 // pa > pb? - movq mm0, mm7 - // use mm0 mask copy to merge a & b - pand mm2, mm0 - // use mm7 mask to merge pa & pb - pand mm5, mm7 - pandn mm0, mm1 - pandn mm7, mm4 - paddw mm0, mm2 - paddw mm7, mm5 - // test ((pa <= pb)? pa:pb) <= pc - pcmpgtw mm7, mm6 // pab > pc? - pand mm3, mm7 - pandn mm7, mm0 - paddw mm7, mm3 - pxor mm1, mm1 - packuswb mm1, mm7 - // Step ebx to next set of 8 bytes and repeat loop til done - add ebx, 8 - pand mm1, ActiveMaskEnd - paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x) - - cmp ebx, MMXLength - pxor mm0, mm0 // pxor does not affect flags - movq [edi + ebx - 8], mm1 // write back updated value - // mm1 will be used as Raw(x-bpp) next loop - // mm3 ready to be used as Prior(x-bpp) next loop - jb dpth3lp - } // end _asm block - } - break; - - case 6: - case 7: - case 5: - { - ActiveMask.use = 0x00000000ffffffff; - ActiveMask2.use = 0xffffffff00000000; - ShiftBpp.use = bpp << 3; // == bpp * 8 - ShiftRem.use = 64 - ShiftBpp.use; - _asm - { - mov ebx, diff - mov edi, row - mov esi, prev_row - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm1, [edi+ebx-8] - pxor mm0, mm0 -dpth6lp: - // Must shift to position Raw(x-bpp) data - psrlq mm1, ShiftRem - // Do first set of 4 bytes - movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes - punpcklbw mm1, mm0 // Unpack Low bytes of a - movq mm2, [esi + ebx] // load b=Prior(x) - punpcklbw mm2, mm0 // Unpack Low bytes of b - // Must shift to position Prior(x-bpp) data - psrlq mm3, ShiftRem - // pav = p - a = (a + b - c) - a = b - c - movq mm4, mm2 - punpcklbw mm3, mm0 // Unpack Low bytes of c - // pbv = p - b = (a + b - c) - b = a - c - movq mm5, mm1 - psubw mm4, mm3 - pxor mm7, mm7 - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - movq mm6, mm4 - psubw mm5, mm3 - // pa = abs(p-a) = abs(pav) - // pb = abs(p-b) = abs(pbv) - // pc = abs(p-c) = abs(pcv) - pcmpgtw mm0, mm4 // Create mask pav bytes < 0 - paddw mm6, mm5 - pand mm0, mm4 // Only pav bytes < 0 in mm7 - pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 - psubw mm4, mm0 - pand mm7, mm5 // Only pbv bytes < 0 in mm0 - psubw mm4, mm0 - psubw mm5, mm7 - pxor mm0, mm0 - pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 - pand mm0, mm6 // Only pav bytes < 0 in mm7 - psubw mm5, mm7 - psubw mm6, mm0 - // test pa <= pb - movq mm7, mm4 - psubw mm6, mm0 - pcmpgtw mm7, mm5 // pa > pb? - movq mm0, mm7 - // use mm7 mask to merge pa & pb - pand mm5, mm7 - // use mm0 mask copy to merge a & b - pand mm2, mm0 - pandn mm7, mm4 - pandn mm0, mm1 - paddw mm7, mm5 - paddw mm0, mm2 - // test ((pa <= pb)? pa:pb) <= pc - pcmpgtw mm7, mm6 // pab > pc? - pxor mm1, mm1 - pand mm3, mm7 - pandn mm7, mm0 - paddw mm7, mm3 - pxor mm0, mm0 - packuswb mm7, mm1 - movq mm3, [esi + ebx - 8] // load c=Prior(x-bpp) - pand mm7, ActiveMask - psrlq mm3, ShiftRem - movq mm2, [esi + ebx] // load b=Prior(x) step 1 - paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x) - movq mm6, mm2 - movq [edi + ebx], mm7 // write back updated value - movq mm1, [edi+ebx-8] - psllq mm6, ShiftBpp - movq mm5, mm7 - psrlq mm1, ShiftRem - por mm3, mm6 - psllq mm5, ShiftBpp - punpckhbw mm3, mm0 // Unpack High bytes of c - por mm1, mm5 - // Do second set of 4 bytes - punpckhbw mm2, mm0 // Unpack High bytes of b - punpckhbw mm1, mm0 // Unpack High bytes of a - // pav = p - a = (a + b - c) - a = b - c - movq mm4, mm2 - // pbv = p - b = (a + b - c) - b = a - c - movq mm5, mm1 - psubw mm4, mm3 - pxor mm7, mm7 - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - movq mm6, mm4 - psubw mm5, mm3 - // pa = abs(p-a) = abs(pav) - // pb = abs(p-b) = abs(pbv) - // pc = abs(p-c) = abs(pcv) - pcmpgtw mm0, mm4 // Create mask pav bytes < 0 - paddw mm6, mm5 - pand mm0, mm4 // Only pav bytes < 0 in mm7 - pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 - psubw mm4, mm0 - pand mm7, mm5 // Only pbv bytes < 0 in mm0 - psubw mm4, mm0 - psubw mm5, mm7 - pxor mm0, mm0 - pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 - pand mm0, mm6 // Only pav bytes < 0 in mm7 - psubw mm5, mm7 - psubw mm6, mm0 - // test pa <= pb - movq mm7, mm4 - psubw mm6, mm0 - pcmpgtw mm7, mm5 // pa > pb? - movq mm0, mm7 - // use mm7 mask to merge pa & pb - pand mm5, mm7 - // use mm0 mask copy to merge a & b - pand mm2, mm0 - pandn mm7, mm4 - pandn mm0, mm1 - paddw mm7, mm5 - paddw mm0, mm2 - // test ((pa <= pb)? pa:pb) <= pc - pcmpgtw mm7, mm6 // pab > pc? - pxor mm1, mm1 - pand mm3, mm7 - pandn mm7, mm0 - pxor mm1, mm1 - paddw mm7, mm3 - pxor mm0, mm0 - // Step ex to next set of 8 bytes and repeat loop til done - add ebx, 8 - packuswb mm1, mm7 - paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x) - cmp ebx, MMXLength - movq [edi + ebx - 8], mm1 // write back updated value - // mm1 will be used as Raw(x-bpp) next loop - jb dpth6lp - } // end _asm block - } - break; - - case 4: - { - ActiveMask.use = 0x00000000ffffffff; - _asm { - mov ebx, diff - mov edi, row - mov esi, prev_row - pxor mm0, mm0 - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm1, [edi+ebx-8] // Only time should need to read - // a=Raw(x-bpp) bytes -dpth4lp: - // Do first set of 4 bytes - movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes - punpckhbw mm1, mm0 // Unpack Low bytes of a - movq mm2, [esi + ebx] // load b=Prior(x) - punpcklbw mm2, mm0 // Unpack High bytes of b - // pav = p - a = (a + b - c) - a = b - c - movq mm4, mm2 - punpckhbw mm3, mm0 // Unpack High bytes of c - // pbv = p - b = (a + b - c) - b = a - c - movq mm5, mm1 - psubw mm4, mm3 - pxor mm7, mm7 - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - movq mm6, mm4 - psubw mm5, mm3 - // pa = abs(p-a) = abs(pav) - // pb = abs(p-b) = abs(pbv) - // pc = abs(p-c) = abs(pcv) - pcmpgtw mm0, mm4 // Create mask pav bytes < 0 - paddw mm6, mm5 - pand mm0, mm4 // Only pav bytes < 0 in mm7 - pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 - psubw mm4, mm0 - pand mm7, mm5 // Only pbv bytes < 0 in mm0 - psubw mm4, mm0 - psubw mm5, mm7 - pxor mm0, mm0 - pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 - pand mm0, mm6 // Only pav bytes < 0 in mm7 - psubw mm5, mm7 - psubw mm6, mm0 - // test pa <= pb - movq mm7, mm4 - psubw mm6, mm0 - pcmpgtw mm7, mm5 // pa > pb? - movq mm0, mm7 - // use mm7 mask to merge pa & pb - pand mm5, mm7 - // use mm0 mask copy to merge a & b - pand mm2, mm0 - pandn mm7, mm4 - pandn mm0, mm1 - paddw mm7, mm5 - paddw mm0, mm2 - // test ((pa <= pb)? pa:pb) <= pc - pcmpgtw mm7, mm6 // pab > pc? - pxor mm1, mm1 - pand mm3, mm7 - pandn mm7, mm0 - paddw mm7, mm3 - pxor mm0, mm0 - packuswb mm7, mm1 - movq mm3, [esi + ebx] // load c=Prior(x-bpp) - pand mm7, ActiveMask - movq mm2, mm3 // load b=Prior(x) step 1 - paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x) - punpcklbw mm3, mm0 // Unpack High bytes of c - movq [edi + ebx], mm7 // write back updated value - movq mm1, mm7 // Now mm1 will be used as Raw(x-bpp) - // Do second set of 4 bytes - punpckhbw mm2, mm0 // Unpack Low bytes of b - punpcklbw mm1, mm0 // Unpack Low bytes of a - // pav = p - a = (a + b - c) - a = b - c - movq mm4, mm2 - // pbv = p - b = (a + b - c) - b = a - c - movq mm5, mm1 - psubw mm4, mm3 - pxor mm7, mm7 - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - movq mm6, mm4 - psubw mm5, mm3 - // pa = abs(p-a) = abs(pav) - // pb = abs(p-b) = abs(pbv) - // pc = abs(p-c) = abs(pcv) - pcmpgtw mm0, mm4 // Create mask pav bytes < 0 - paddw mm6, mm5 - pand mm0, mm4 // Only pav bytes < 0 in mm7 - pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 - psubw mm4, mm0 - pand mm7, mm5 // Only pbv bytes < 0 in mm0 - psubw mm4, mm0 - psubw mm5, mm7 - pxor mm0, mm0 - pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 - pand mm0, mm6 // Only pav bytes < 0 in mm7 - psubw mm5, mm7 - psubw mm6, mm0 - // test pa <= pb - movq mm7, mm4 - psubw mm6, mm0 - pcmpgtw mm7, mm5 // pa > pb? - movq mm0, mm7 - // use mm7 mask to merge pa & pb - pand mm5, mm7 - // use mm0 mask copy to merge a & b - pand mm2, mm0 - pandn mm7, mm4 - pandn mm0, mm1 - paddw mm7, mm5 - paddw mm0, mm2 - // test ((pa <= pb)? pa:pb) <= pc - pcmpgtw mm7, mm6 // pab > pc? - pxor mm1, mm1 - pand mm3, mm7 - pandn mm7, mm0 - pxor mm1, mm1 - paddw mm7, mm3 - pxor mm0, mm0 - // Step ex to next set of 8 bytes and repeat loop til done - add ebx, 8 - packuswb mm1, mm7 - paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x) - cmp ebx, MMXLength - movq [edi + ebx - 8], mm1 // write back updated value - // mm1 will be used as Raw(x-bpp) next loop - jb dpth4lp - } // end _asm block - } - break; - case 8: // bpp == 8 - { - ActiveMask.use = 0x00000000ffffffff; - _asm { - mov ebx, diff - mov edi, row - mov esi, prev_row - pxor mm0, mm0 - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm1, [edi+ebx-8] // Only time should need to read - // a=Raw(x-bpp) bytes -dpth8lp: - // Do first set of 4 bytes - movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes - punpcklbw mm1, mm0 // Unpack Low bytes of a - movq mm2, [esi + ebx] // load b=Prior(x) - punpcklbw mm2, mm0 // Unpack Low bytes of b - // pav = p - a = (a + b - c) - a = b - c - movq mm4, mm2 - punpcklbw mm3, mm0 // Unpack Low bytes of c - // pbv = p - b = (a + b - c) - b = a - c - movq mm5, mm1 - psubw mm4, mm3 - pxor mm7, mm7 - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - movq mm6, mm4 - psubw mm5, mm3 - // pa = abs(p-a) = abs(pav) - // pb = abs(p-b) = abs(pbv) - // pc = abs(p-c) = abs(pcv) - pcmpgtw mm0, mm4 // Create mask pav bytes < 0 - paddw mm6, mm5 - pand mm0, mm4 // Only pav bytes < 0 in mm7 - pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 - psubw mm4, mm0 - pand mm7, mm5 // Only pbv bytes < 0 in mm0 - psubw mm4, mm0 - psubw mm5, mm7 - pxor mm0, mm0 - pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 - pand mm0, mm6 // Only pav bytes < 0 in mm7 - psubw mm5, mm7 - psubw mm6, mm0 - // test pa <= pb - movq mm7, mm4 - psubw mm6, mm0 - pcmpgtw mm7, mm5 // pa > pb? - movq mm0, mm7 - // use mm7 mask to merge pa & pb - pand mm5, mm7 - // use mm0 mask copy to merge a & b - pand mm2, mm0 - pandn mm7, mm4 - pandn mm0, mm1 - paddw mm7, mm5 - paddw mm0, mm2 - // test ((pa <= pb)? pa:pb) <= pc - pcmpgtw mm7, mm6 // pab > pc? - pxor mm1, mm1 - pand mm3, mm7 - pandn mm7, mm0 - paddw mm7, mm3 - pxor mm0, mm0 - packuswb mm7, mm1 - movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes - pand mm7, ActiveMask - movq mm2, [esi + ebx] // load b=Prior(x) - paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x) - punpckhbw mm3, mm0 // Unpack High bytes of c - movq [edi + ebx], mm7 // write back updated value - movq mm1, [edi+ebx-8] // read a=Raw(x-bpp) bytes - - // Do second set of 4 bytes - punpckhbw mm2, mm0 // Unpack High bytes of b - punpckhbw mm1, mm0 // Unpack High bytes of a - // pav = p - a = (a + b - c) - a = b - c - movq mm4, mm2 - // pbv = p - b = (a + b - c) - b = a - c - movq mm5, mm1 - psubw mm4, mm3 - pxor mm7, mm7 - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - movq mm6, mm4 - psubw mm5, mm3 - // pa = abs(p-a) = abs(pav) - // pb = abs(p-b) = abs(pbv) - // pc = abs(p-c) = abs(pcv) - pcmpgtw mm0, mm4 // Create mask pav bytes < 0 - paddw mm6, mm5 - pand mm0, mm4 // Only pav bytes < 0 in mm7 - pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 - psubw mm4, mm0 - pand mm7, mm5 // Only pbv bytes < 0 in mm0 - psubw mm4, mm0 - psubw mm5, mm7 - pxor mm0, mm0 - pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 - pand mm0, mm6 // Only pav bytes < 0 in mm7 - psubw mm5, mm7 - psubw mm6, mm0 - // test pa <= pb - movq mm7, mm4 - psubw mm6, mm0 - pcmpgtw mm7, mm5 // pa > pb? - movq mm0, mm7 - // use mm7 mask to merge pa & pb - pand mm5, mm7 - // use mm0 mask copy to merge a & b - pand mm2, mm0 - pandn mm7, mm4 - pandn mm0, mm1 - paddw mm7, mm5 - paddw mm0, mm2 - // test ((pa <= pb)? pa:pb) <= pc - pcmpgtw mm7, mm6 // pab > pc? - pxor mm1, mm1 - pand mm3, mm7 - pandn mm7, mm0 - pxor mm1, mm1 - paddw mm7, mm3 - pxor mm0, mm0 - // Step ex to next set of 8 bytes and repeat loop til done - add ebx, 8 - packuswb mm1, mm7 - paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x) - cmp ebx, MMXLength - movq [edi + ebx - 8], mm1 // write back updated value - // mm1 will be used as Raw(x-bpp) next loop - jb dpth8lp - } // end _asm block - } - break; - - case 1: // bpp = 1 - case 2: // bpp = 2 - default: // bpp > 8 - { - _asm { - mov ebx, diff - cmp ebx, FullLength - jnb dpthdend - mov edi, row - mov esi, prev_row - // Do Paeth decode for remaining bytes - mov edx, ebx - xor ecx, ecx // zero ecx before using cl & cx in loop below - sub edx, bpp // Set edx = ebx - bpp -dpthdlp: - xor eax, eax - // pav = p - a = (a + b - c) - a = b - c - mov al, [esi + ebx] // load Prior(x) into al - mov cl, [esi + edx] // load Prior(x-bpp) into cl - sub eax, ecx // subtract Prior(x-bpp) - mov patemp, eax // Save pav for later use - xor eax, eax - // pbv = p - b = (a + b - c) - b = a - c - mov al, [edi + edx] // load Raw(x-bpp) into al - sub eax, ecx // subtract Prior(x-bpp) - mov ecx, eax - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - add eax, patemp // pcv = pav + pbv - // pc = abs(pcv) - test eax, 0x80000000 - jz dpthdpca - neg eax // reverse sign of neg values -dpthdpca: - mov pctemp, eax // save pc for later use - // pb = abs(pbv) - test ecx, 0x80000000 - jz dpthdpba - neg ecx // reverse sign of neg values -dpthdpba: - mov pbtemp, ecx // save pb for later use - // pa = abs(pav) - mov eax, patemp - test eax, 0x80000000 - jz dpthdpaa - neg eax // reverse sign of neg values -dpthdpaa: - mov patemp, eax // save pa for later use - // test if pa <= pb - cmp eax, ecx - jna dpthdabb - // pa > pb; now test if pb <= pc - cmp ecx, pctemp - jna dpthdbbc - // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) - mov cl, [esi + edx] // load Prior(x-bpp) into cl - jmp dpthdpaeth -dpthdbbc: - // pb <= pc; Raw(x) = Paeth(x) + Prior(x) - mov cl, [esi + ebx] // load Prior(x) into cl - jmp dpthdpaeth -dpthdabb: - // pa <= pb; now test if pa <= pc - cmp eax, pctemp - jna dpthdabc - // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) - mov cl, [esi + edx] // load Prior(x-bpp) into cl - jmp dpthdpaeth -dpthdabc: - // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) - mov cl, [edi + edx] // load Raw(x-bpp) into cl -dpthdpaeth: - inc ebx - inc edx - // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 - add [edi + ebx - 1], cl - cmp ebx, FullLength - jb dpthdlp -dpthdend: - } // end _asm block - } - return; // No need to go further with this one - } // end switch ( bpp ) - _asm - { - // MMX acceleration complete now do clean-up - // Check if any remaining bytes left to decode - mov ebx, MMXLength - cmp ebx, FullLength - jnb dpthend - mov edi, row - mov esi, prev_row - // Do Paeth decode for remaining bytes - mov edx, ebx - xor ecx, ecx // zero ecx before using cl & cx in loop below - sub edx, bpp // Set edx = ebx - bpp -dpthlp2: - xor eax, eax - // pav = p - a = (a + b - c) - a = b - c - mov al, [esi + ebx] // load Prior(x) into al - mov cl, [esi + edx] // load Prior(x-bpp) into cl - sub eax, ecx // subtract Prior(x-bpp) - mov patemp, eax // Save pav for later use - xor eax, eax - // pbv = p - b = (a + b - c) - b = a - c - mov al, [edi + edx] // load Raw(x-bpp) into al - sub eax, ecx // subtract Prior(x-bpp) - mov ecx, eax - // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv - add eax, patemp // pcv = pav + pbv - // pc = abs(pcv) - test eax, 0x80000000 - jz dpthpca2 - neg eax // reverse sign of neg values -dpthpca2: - mov pctemp, eax // save pc for later use - // pb = abs(pbv) - test ecx, 0x80000000 - jz dpthpba2 - neg ecx // reverse sign of neg values -dpthpba2: - mov pbtemp, ecx // save pb for later use - // pa = abs(pav) - mov eax, patemp - test eax, 0x80000000 - jz dpthpaa2 - neg eax // reverse sign of neg values -dpthpaa2: - mov patemp, eax // save pa for later use - // test if pa <= pb - cmp eax, ecx - jna dpthabb2 - // pa > pb; now test if pb <= pc - cmp ecx, pctemp - jna dpthbbc2 - // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) - mov cl, [esi + edx] // load Prior(x-bpp) into cl - jmp dpthpaeth2 -dpthbbc2: - // pb <= pc; Raw(x) = Paeth(x) + Prior(x) - mov cl, [esi + ebx] // load Prior(x) into cl - jmp dpthpaeth2 -dpthabb2: - // pa <= pb; now test if pa <= pc - cmp eax, pctemp - jna dpthabc2 - // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) - mov cl, [esi + edx] // load Prior(x-bpp) into cl - jmp dpthpaeth2 -dpthabc2: - // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) - mov cl, [edi + edx] // load Raw(x-bpp) into cl -dpthpaeth2: - inc ebx - inc edx - // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 - add [edi + ebx - 1], cl - cmp ebx, FullLength - jb dpthlp2 -dpthend: - emms // End MMX instructions; prep for possible FP instrs. - } // end _asm block -} - -// Optimized code for PNG Sub filter decoder -void /* PRIVATE */ -png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row) -{ - //int test; - int bpp; - png_uint_32 FullLength; - png_uint_32 MMXLength; - int diff; - - bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel - FullLength = row_info->rowbytes - bpp; // # of bytes to filter - _asm { - mov edi, row - mov esi, edi // lp = row - add edi, bpp // rp = row + bpp - xor eax, eax - // get # of bytes to alignment - mov diff, edi // take start of row - add diff, 0xf // add 7 + 8 to incr past - // alignment boundary - xor ebx, ebx - and diff, 0xfffffff8 // mask to alignment boundary - sub diff, edi // subtract from start ==> value - // ebx at alignment - jz dsubgo - // fix alignment -dsublp1: - mov al, [esi+ebx] - add [edi+ebx], al - inc ebx - cmp ebx, diff - jb dsublp1 -dsubgo: - mov ecx, FullLength - mov edx, ecx - sub edx, ebx // subtract alignment fix - and edx, 0x00000007 // calc bytes over mult of 8 - sub ecx, edx // drop over bytes from length - mov MMXLength, ecx - } // end _asm block - - // Now do the math for the rest of the row - switch ( bpp ) - { - case 3: - { - ActiveMask.use = 0x0000ffffff000000; - ShiftBpp.use = 24; // == 3 * 8 - ShiftRem.use = 40; // == 64 - 24 - _asm { - mov edi, row - movq mm7, ActiveMask // Load ActiveMask for 2nd active byte group - mov esi, edi // lp = row - add edi, bpp // rp = row + bpp - movq mm6, mm7 - mov ebx, diff - psllq mm6, ShiftBpp // Move mask in mm6 to cover 3rd active - // byte group - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm1, [edi+ebx-8] -dsub3lp: - psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes - // no need for mask; shift clears inactive bytes - // Add 1st active group - movq mm0, [edi+ebx] - paddb mm0, mm1 - // Add 2nd active group - movq mm1, mm0 // mov updated Raws to mm1 - psllq mm1, ShiftBpp // shift data to position correctly - pand mm1, mm7 // mask to use only 2nd active group - paddb mm0, mm1 - // Add 3rd active group - movq mm1, mm0 // mov updated Raws to mm1 - psllq mm1, ShiftBpp // shift data to position correctly - pand mm1, mm6 // mask to use only 3rd active group - add ebx, 8 - paddb mm0, mm1 - cmp ebx, MMXLength - movq [edi+ebx-8], mm0 // Write updated Raws back to array - // Prep for doing 1st add at top of loop - movq mm1, mm0 - jb dsub3lp - } // end _asm block - } - break; - - case 1: - { - // Placed here just in case this is a duplicate of the - // non-MMX code for the SUB filter in png_read_filter_row below - // - // png_bytep rp; - // png_bytep lp; - // png_uint_32 i; - // bpp = (row_info->pixel_depth + 7) >> 3; - // for (i = (png_uint_32)bpp, rp = row + bpp, lp = row; - // i < row_info->rowbytes; i++, rp++, lp++) - // { - // *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff); - // } - _asm { - mov ebx, diff - mov edi, row - cmp ebx, FullLength - jnb dsub1end - mov esi, edi // lp = row - xor eax, eax - add edi, bpp // rp = row + bpp -dsub1lp: - mov al, [esi+ebx] - add [edi+ebx], al - inc ebx - cmp ebx, FullLength - jb dsub1lp -dsub1end: - } // end _asm block - } - return; - - case 6: - case 7: - case 4: - case 5: - { - ShiftBpp.use = bpp << 3; - ShiftRem.use = 64 - ShiftBpp.use; - _asm { - mov edi, row - mov ebx, diff - mov esi, edi // lp = row - add edi, bpp // rp = row + bpp - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm1, [edi+ebx-8] -dsub4lp: - psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes - // no need for mask; shift clears inactive bytes - movq mm0, [edi+ebx] - paddb mm0, mm1 - // Add 2nd active group - movq mm1, mm0 // mov updated Raws to mm1 - psllq mm1, ShiftBpp // shift data to position correctly - // there is no need for any mask - // since shift clears inactive bits/bytes - add ebx, 8 - paddb mm0, mm1 - cmp ebx, MMXLength - movq [edi+ebx-8], mm0 - movq mm1, mm0 // Prep for doing 1st add at top of loop - jb dsub4lp - } // end _asm block - } - break; - - case 2: - { - ActiveMask.use = 0x00000000ffff0000; - ShiftBpp.use = 16; // == 2 * 8 - ShiftRem.use = 48; // == 64 - 16 - _asm { - movq mm7, ActiveMask // Load ActiveMask for 2nd active byte group - mov ebx, diff - movq mm6, mm7 - mov edi, row - psllq mm6, ShiftBpp // Move mask in mm6 to cover 3rd active - // byte group - mov esi, edi // lp = row - movq mm5, mm6 - add edi, bpp // rp = row + bpp - psllq mm5, ShiftBpp // Move mask in mm5 to cover 4th active - // byte group - // PRIME the pump (load the first Raw(x-bpp) data set - movq mm1, [edi+ebx-8] -dsub2lp: - // Add 1st active group - psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes - // no need for mask; shift clears inactive - // bytes - movq mm0, [edi+ebx] - paddb mm0, mm1 - // Add 2nd active group - movq mm1, mm0 // mov updated Raws to mm1 - psllq mm1, ShiftBpp // shift data to position correctly - pand mm1, mm7 // mask to use only 2nd active group - paddb mm0, mm1 - // Add 3rd active group - movq mm1, mm0 // mov updated Raws to mm1 - psllq mm1, ShiftBpp // shift data to position correctly - pand mm1, mm6 // mask to use only 3rd active group - paddb mm0, mm1 - // Add 4th active group - movq mm1, mm0 // mov updated Raws to mm1 - psllq mm1, ShiftBpp // shift data to position correctly - pand mm1, mm5 // mask to use only 4th active group - add ebx, 8 - paddb mm0, mm1 - cmp ebx, MMXLength - movq [edi+ebx-8], mm0 // Write updated Raws back to array - movq mm1, mm0 // Prep for doing 1st add at top of loop - jb dsub2lp - } // end _asm block - } - break; - case 8: - { - _asm { - mov edi, row - mov ebx, diff - mov esi, edi // lp = row - add edi, bpp // rp = row + bpp - mov ecx, MMXLength - movq mm7, [edi+ebx-8] // PRIME the pump (load the first - // Raw(x-bpp) data set - and ecx, 0x0000003f // calc bytes over mult of 64 -dsub8lp: - movq mm0, [edi+ebx] // Load Sub(x) for 1st 8 bytes - paddb mm0, mm7 - movq mm1, [edi+ebx+8] // Load Sub(x) for 2nd 8 bytes - movq [edi+ebx], mm0 // Write Raw(x) for 1st 8 bytes - // Now mm0 will be used as Raw(x-bpp) for - // the 2nd group of 8 bytes. This will be - // repeated for each group of 8 bytes with - // the 8th group being used as the Raw(x-bpp) - // for the 1st group of the next loop. - paddb mm1, mm0 - movq mm2, [edi+ebx+16] // Load Sub(x) for 3rd 8 bytes - movq [edi+ebx+8], mm1 // Write Raw(x) for 2nd 8 bytes - paddb mm2, mm1 - movq mm3, [edi+ebx+24] // Load Sub(x) for 4th 8 bytes - movq [edi+ebx+16], mm2 // Write Raw(x) for 3rd 8 bytes - paddb mm3, mm2 - movq mm4, [edi+ebx+32] // Load Sub(x) for 5th 8 bytes - movq [edi+ebx+24], mm3 // Write Raw(x) for 4th 8 bytes - paddb mm4, mm3 - movq mm5, [edi+ebx+40] // Load Sub(x) for 6th 8 bytes - movq [edi+ebx+32], mm4 // Write Raw(x) for 5th 8 bytes - paddb mm5, mm4 - movq mm6, [edi+ebx+48] // Load Sub(x) for 7th 8 bytes - movq [edi+ebx+40], mm5 // Write Raw(x) for 6th 8 bytes - paddb mm6, mm5 - movq mm7, [edi+ebx+56] // Load Sub(x) for 8th 8 bytes - movq [edi+ebx+48], mm6 // Write Raw(x) for 7th 8 bytes - add ebx, 64 - paddb mm7, mm6 - cmp ebx, ecx - movq [edi+ebx-8], mm7 // Write Raw(x) for 8th 8 bytes - jb dsub8lp - cmp ebx, MMXLength - jnb dsub8lt8 -dsub8lpA: - movq mm0, [edi+ebx] - add ebx, 8 - paddb mm0, mm7 - cmp ebx, MMXLength - movq [edi+ebx-8], mm0 // use -8 to offset early add to ebx - movq mm7, mm0 // Move calculated Raw(x) data to mm1 to - // be the new Raw(x-bpp) for the next loop - jb dsub8lpA -dsub8lt8: - } // end _asm block - } - break; - - default: // bpp greater than 8 bytes - { - _asm { - mov ebx, diff - mov edi, row - mov esi, edi // lp = row - add edi, bpp // rp = row + bpp -dsubAlp: - movq mm0, [edi+ebx] - movq mm1, [esi+ebx] - add ebx, 8 - paddb mm0, mm1 - cmp ebx, MMXLength - movq [edi+ebx-8], mm0 // mov does not affect flags; -8 to offset - // add ebx - jb dsubAlp - } // end _asm block - } - break; - - } // end switch ( bpp ) - - _asm { - mov ebx, MMXLength - mov edi, row - cmp ebx, FullLength - jnb dsubend - mov esi, edi // lp = row - xor eax, eax - add edi, bpp // rp = row + bpp -dsublp2: - mov al, [esi+ebx] - add [edi+ebx], al - inc ebx - cmp ebx, FullLength - jb dsublp2 -dsubend: - emms // End MMX instructions; prep for possible FP instrs. - } // end _asm block -} - -// Optimized code for PNG Up filter decoder -void /* PRIVATE */ -png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row, - png_bytep prev_row) -{ - png_uint_32 len; - len = row_info->rowbytes; // # of bytes to filter - _asm { - mov edi, row - // get # of bytes to alignment - mov ecx, edi - xor ebx, ebx - add ecx, 0x7 - xor eax, eax - and ecx, 0xfffffff8 - mov esi, prev_row - sub ecx, edi - jz dupgo - // fix alignment -duplp1: - mov al, [edi+ebx] - add al, [esi+ebx] - inc ebx - cmp ebx, ecx - mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx - jb duplp1 -dupgo: - mov ecx, len - mov edx, ecx - sub edx, ebx // subtract alignment fix - and edx, 0x0000003f // calc bytes over mult of 64 - sub ecx, edx // drop over bytes from length - // Unrolled loop - use all MMX registers and interleave to reduce - // number of branch instructions (loops) and reduce partial stalls -duploop: - movq mm1, [esi+ebx] - movq mm0, [edi+ebx] - movq mm3, [esi+ebx+8] - paddb mm0, mm1 - movq mm2, [edi+ebx+8] - movq [edi+ebx], mm0 - paddb mm2, mm3 - movq mm5, [esi+ebx+16] - movq [edi+ebx+8], mm2 - movq mm4, [edi+ebx+16] - movq mm7, [esi+ebx+24] - paddb mm4, mm5 - movq mm6, [edi+ebx+24] - movq [edi+ebx+16], mm4 - paddb mm6, mm7 - movq mm1, [esi+ebx+32] - movq [edi+ebx+24], mm6 - movq mm0, [edi+ebx+32] - movq mm3, [esi+ebx+40] - paddb mm0, mm1 - movq mm2, [edi+ebx+40] - movq [edi+ebx+32], mm0 - paddb mm2, mm3 - movq mm5, [esi+ebx+48] - movq [edi+ebx+40], mm2 - movq mm4, [edi+ebx+48] - movq mm7, [esi+ebx+56] - paddb mm4, mm5 - movq mm6, [edi+ebx+56] - movq [edi+ebx+48], mm4 - add ebx, 64 - paddb mm6, mm7 - cmp ebx, ecx - movq [edi+ebx-8], mm6 // (+56)movq does not affect flags; - // -8 to offset add ebx - jb duploop - - cmp edx, 0 // Test for bytes over mult of 64 - jz dupend - - - // 2 lines added by lcreeve at netins.net - // (mail 11 Jul 98 in png-implement list) - cmp edx, 8 //test for less than 8 bytes - jb duplt8 - - - add ecx, edx - and edx, 0x00000007 // calc bytes over mult of 8 - sub ecx, edx // drop over bytes from length - jz duplt8 - // Loop using MMX registers mm0 & mm1 to update 8 bytes simultaneously -duplpA: - movq mm1, [esi+ebx] - movq mm0, [edi+ebx] - add ebx, 8 - paddb mm0, mm1 - cmp ebx, ecx - movq [edi+ebx-8], mm0 // movq does not affect flags; -8 to offset add ebx - jb duplpA - cmp edx, 0 // Test for bytes over mult of 8 - jz dupend -duplt8: - xor eax, eax - add ecx, edx // move over byte count into counter - // Loop using x86 registers to update remaining bytes -duplp2: - mov al, [edi + ebx] - add al, [esi + ebx] - inc ebx - cmp ebx, ecx - mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx - jb duplp2 -dupend: - // Conversion of filtered row completed - emms // End MMX instructions; prep for possible FP instrs. - } // end _asm block -} - - -// Optimized png_read_filter_row routines -void /* PRIVATE */ -png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep - row, png_bytep prev_row, int filter) -{ -#ifdef PNG_DEBUG - char filnm[10]; -#endif - - if (mmx_supported == 2) { -#if !defined(PNG_1_0_X) - /* this should have happened in png_init_mmx_flags() already */ - png_warning(png_ptr, "asm_flags may not have been initialized"); -#endif - png_mmx_support(); - } - -#ifdef PNG_DEBUG - png_debug(1, "in png_read_filter_row\n"); - switch (filter) - { - case 0: sprintf(filnm, "none"); - break; -#if !defined(PNG_1_0_X) - case 1: sprintf(filnm, "sub-%s", - (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "MMX" : "x86"); - break; - case 2: sprintf(filnm, "up-%s", - (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "MMX" : "x86"); - break; - case 3: sprintf(filnm, "avg-%s", - (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "MMX" : "x86"); - break; - case 4: sprintf(filnm, "Paeth-%s", - (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "MMX":"x86"); - break; -#else - case 1: sprintf(filnm, "sub"); - break; - case 2: sprintf(filnm, "up"); - break; - case 3: sprintf(filnm, "avg"); - break; - case 4: sprintf(filnm, "Paeth"); - break; -#endif - default: sprintf(filnm, "unknw"); - break; - } - png_debug2(0,"row=%5d, %s, ", png_ptr->row_number, filnm); - png_debug2(0, "pd=%2d, b=%d, ", (int)row_info->pixel_depth, - (int)((row_info->pixel_depth + 7) >> 3)); - png_debug1(0,"len=%8d, ", row_info->rowbytes); -#endif /* PNG_DEBUG */ - - switch (filter) - { - case PNG_FILTER_VALUE_NONE: - break; - - case PNG_FILTER_VALUE_SUB: - { -#if !defined(PNG_1_0_X) - if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB) && - (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) && - (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold)) -#else - if (mmx_supported) -#endif - { - png_read_filter_row_mmx_sub(row_info, row); - } - else - { - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp = row + bpp; - png_bytep lp = row; - - for (i = bpp; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); - rp++; - } - } - break; - } - - case PNG_FILTER_VALUE_UP: - { -#if !defined(PNG_1_0_X) - if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP) && - (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) && - (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold)) -#else - if (mmx_supported) -#endif - { - png_read_filter_row_mmx_up(row_info, row, prev_row); - } - else - { - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_bytep rp = row; - png_bytep pp = prev_row; - - for (i = 0; i < istop; ++i) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } - } - break; - } - - case PNG_FILTER_VALUE_AVG: - { -#if !defined(PNG_1_0_X) - if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG) && - (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) && - (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold)) -#else - if (mmx_supported) -#endif - { - png_read_filter_row_mmx_avg(row_info, row, prev_row); - } - else - { - png_uint_32 i; - png_bytep rp = row; - png_bytep pp = prev_row; - png_bytep lp = row; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_uint_32 istop = row_info->rowbytes - bpp; - - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + - ((int)(*pp++) >> 1)) & 0xff); - rp++; - } - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + - ((int)(*pp++ + *lp++) >> 1)) & 0xff); - rp++; - } - } - break; - } - - case PNG_FILTER_VALUE_PAETH: - { -#if !defined(PNG_1_0_X) - if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH) && - (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) && - (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold)) -#else - if (mmx_supported) -#endif - { - png_read_filter_row_mmx_paeth(row_info, row, prev_row); - } - else - { - png_uint_32 i; - png_bytep rp = row; - png_bytep pp = prev_row; - png_bytep lp = row; - png_bytep cp = prev_row; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_uint_32 istop=row_info->rowbytes - bpp; - - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } - - for (i = 0; i < istop; i++) // use leftover rp,pp - { - int a, b, c, pa, pb, pc, p; - - a = *lp++; - b = *pp++; - c = *cp++; - - p = b - c; - pc = a - c; - -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - - /* - if (pa <= pb && pa <= pc) - p = a; - else if (pb <= pc) - p = b; - else - p = c; - */ - - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; - - *rp = (png_byte)(((int)(*rp) + p) & 0xff); - rp++; - } - } - break; - } - - default: - png_warning(png_ptr, "Ignoring bad row filter type"); - *row=0; - break; - } -} - -#endif /* PNG_ASSEMBLER_CODE_SUPPORTED && PNG_USE_PNGVCRD */ diff --git a/.svn/pristine/05/05307223de728f7306ffe553ec00689c462798f9.svn-base b/.svn/pristine/05/05307223de728f7306ffe553ec00689c462798f9.svn-base deleted file mode 100644 index f4bc715..0000000 --- a/.svn/pristine/05/05307223de728f7306ffe553ec00689c462798f9.svn-base +++ /dev/null @@ -1,1676 +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 -*/ - -// Mail and Chat Server for BPQ32 Packet Switch -// -// Support for FLAMP compatible Mulitcast - -#include "bpqmail.h" - -void decodeblock( unsigned char in[4], unsigned char out[3]); // Base64 Decode - -time_t MulticastMaxAge = 48 * 60 * 60; // 48 Hours in secs - -struct MSESSION * MSessions = NULL; - -#ifndef LINBPQ - -#include "AFXRES.h" - -HWND hMCMonitor = NULL; -HWND MCList; - -static HMENU hMCMenu; // handle of menu - -static char MCClassName[]="BPQMCWINDOW"; - -RECT MCMonitorRect; - -static int Height, Width, LastY; - -#define BGCOLOUR RGB(236,233,216) - -void MCMoveWindows() -{ - RECT rcClient; - int ClientWidth, ClientHeight; - - GetClientRect(hMCMonitor, &rcClient); - - if (rcClient.bottom == 0) // Minimised - return; - - ClientHeight = rcClient.bottom; - ClientWidth = rcClient.right; - - MoveWindow(MCList, 0, 0, rcClient.right, rcClient.bottom, TRUE); -} - -void CopyMCToClipboard(HWND hWnd); - -LRESULT CALLBACK MCWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - LPRECT lprc; - struct MSESSION * Sess = MSessions; - struct MSESSION * Temp; - - switch (message) - { - - case WM_ACTIVATE: - - break; - - case WM_CLOSE: - if (wParam) // Used by Close All Programs. - return 0; - - return (DefWindowProc(hWnd, message, wParam, lParam)); - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - - case ID_EDIT_COPY: - - CopyMCToClipboard(hMCMonitor); - return 0;; - - case ID_EDIT_CLEAR: - - while (Sess) - { - ListView_DeleteItem(MCList, Sess->Index); - - if (Sess->FileName) - free(Sess->FileName); - - if (Sess->OrigTimeStamp) - free(Sess->OrigTimeStamp); - - if (Sess->Message) - free(Sess->Message); - - if (Sess->BlockList) - free(Sess->BlockList); - - if (Sess->ID) - free(Sess->ID); - - Temp = Sess; - Sess = Sess->Next; - } - - MSessions = NULL; - return 0; - - default: - return 0; - } - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) { - - case SC_MINIMIZE: - - if (cfgMinToTray) - return ShowWindow(hWnd, SW_HIDE); - - default: - - return (DefWindowProc(hWnd, message, wParam, lParam)); - } - - case WM_SIZING: - - lprc = (LPRECT) lParam; - - Height = lprc->bottom-lprc->top; - Width = lprc->right-lprc->left; - - MCMoveWindows(); - - return TRUE; - - - case WM_DESTROY: - - // Remove the subclass from the edit control. - - GetWindowRect(hWnd, &MonitorRect); // For save soutine - - if (cfgMinToTray) - DeleteTrayMenuItem(hWnd); - - - hMCMonitor = NULL; - - break; - - default: - return (DefWindowProc(hWnd, message, wParam, lParam)); - - } - return (0); -} - - -static void MoveMCWindows() -{ - RECT rcMain, rcClient; - int ClientHeight, ClientWidth; - - GetWindowRect(hMCMonitor, &rcMain); - GetClientRect(hMCMonitor, &rcClient); - - ClientHeight = rcClient.bottom; - ClientWidth = rcClient.right; - -// MoveWindow(hwndMon,2, 0, ClientWidth-4, SplitPos, TRUE); -// MoveWindow(hwndOutput,2, 2, ClientWidth-4, ClientHeight-4, TRUE); -// MoveWindow(hwndSplit,0, SplitPos, ClientWidth, SplitBarHeight, TRUE); -} - - - - -HWND CreateMCListView (HWND hwndParent) -{ - INITCOMMONCONTROLSEX icex; // Structure for control initialization. - HWND hList; - LV_COLUMN Column; - LOGFONT lf; - HFONT hFont; - int n = 0; - - memset(&lf, 0, sizeof(LOGFONT)); - - lf.lfHeight = 12; - lf.lfWidth = 8; - lf.lfPitchAndFamily = FIXED_PITCH; - strcpy (lf.lfFaceName, "FIXEDSYS"); - - hFont = CreateFontIndirect(&lf); - - icex.dwICC = ICC_LISTVIEW_CLASSES; - InitCommonControlsEx(&icex); - - // Create the list-view window in report view with label editing enabled. - - hList = CreateWindow(WC_LISTVIEW, - "Messages", - WS_CHILD | LVS_REPORT | LVS_EDITLABELS, - 0, 0, 100, 100, - hwndParent, - (HMENU)NULL, - hInst, - NULL); - - SendMessage(hList, WM_SETFONT,(WPARAM) hFont, 0); - - - ListView_SetExtendedListViewStyle(hList,LVS_EX_FULLROWSELECT); - - Column.cx=45; - Column.mask=LVCF_WIDTH | LVCF_TEXT; - Column.pszText="ID"; - - SendMessage(hList, LVM_INSERTCOLUMN, n++, (LPARAM)&Column); - Column.cx=95; - Column.mask=LVCF_WIDTH | LVCF_TEXT; - Column.pszText="From"; - - SendMessage(hList, LVM_INSERTCOLUMN, n++, (LPARAM)&Column); - - Column.cx=140; - Column.mask=LVCF_WIDTH | LVCF_TEXT; - Column.pszText="FileName"; - - SendMessage(hList, LVM_INSERTCOLUMN, n++, (LPARAM)&Column); - - Column.cx=50; - Column.mask=LVCF_WIDTH | LVCF_TEXT; - Column.pszText="Size"; - - SendMessage(hList, LVM_INSERTCOLUMN, n++, (LPARAM)&Column); - - Column.cx=40; - Column.mask=LVCF_WIDTH | LVCF_TEXT; - Column.pszText="%"; - SendMessage(hList, LVM_INSERTCOLUMN, n++, (LPARAM)&Column); - - Column.cx=55; - Column.mask=LVCF_WIDTH | LVCF_TEXT; - Column.pszText="Time"; - SendMessage(hList, LVM_INSERTCOLUMN, n++, (LPARAM)&Column); - - Column.cx=55; - Column.mask=LVCF_WIDTH | LVCF_TEXT; - Column.pszText="Age"; - SendMessage(hList, LVM_INSERTCOLUMN, n++, (LPARAM)&Column); - - Column.cx=20; - Column.mask=LVCF_WIDTH | LVCF_TEXT; - Column.pszText="C"; - - SendMessage(hList, LVM_INSERTCOLUMN, n++, (LPARAM)&Column); - - Column.cx=430; - Column.mask=LVCF_WIDTH | LVCF_TEXT; - Column.pszText="BlockList"; - SendMessage(hList, LVM_INSERTCOLUMN, n++, (LPARAM) &Column); - - ShowWindow(hList, SW_SHOWNORMAL); - UpdateWindow(hList); - - return (hList); -} - -#define OurSetItemText(hwndLV, i, iSubItem_, pszText_) \ -{ LV_ITEM _ms_lvi;\ - _ms_lvi.iSubItem = iSubItem_;\ - _ms_lvi.pszText = pszText_;\ - SNDMSG((hwndLV), LVM_SETITEMTEXT, (WPARAM)i, (LPARAM)(LV_ITEM FAR *)&_ms_lvi);\ -} - -void RefreshMCLine(struct MSESSION * MSession) -{ - LV_ITEM Item; - LVFINDINFO Finfo; - int ret, n, pcent; - char Time[80]; - char Agestring[80]; - char Size[16] = "??"; - char Percent[16] = "??"; - char Key[16]; - - char BlockList[101] = ""; - struct tm * TM; - time_t Age; - - if (MCList == 0) - return; - - sprintf(Key, "%04X", MSession->Key); - - Age = time(NULL) - MSession->LastUpdated; - -// if (LocalTime) -// TM = localtime(&MSession->LastUpdated); -// else - TM = gmtime(&Age); - - sprintf(Agestring, "%.2d:%.2d", - TM->tm_hour, TM->tm_min); - - TM = gmtime(&MSession->Created); - - sprintf(Time, "%.2d:%.2d", - TM->tm_hour, TM->tm_min); - - - Finfo.flags = LVFI_STRING; - Finfo.psz = Key; - Finfo.vkDirection = VK_DOWN; - ret = SendMessage(MCList, LVM_FINDITEM, (WPARAM)-1, (LPARAM) &Finfo); - - if (ret == -1) - { - n = ListView_GetItemCount(MCList); - MSession->Index = n; - } - else - MSession->Index = ret; - - Item.mask=LVIF_TEXT; - Item.iItem = MSession->Index; - Item.iSubItem = 0; - Item.pszText = Key; - - ret = SendMessage(MCList, LVM_SETITEMTEXT, (WPARAM)MSession->Index, (LPARAM) &Item); - - if (ret == 0) - MSession->Index = ListView_InsertItem(MCList, &Item); - - sprintf(Size, "%d", MSession->MessageLen); - - if (MSession->MessageLen) - { - int i; - - pcent = (MSession->BlocksReceived * 100) / MSession->BlockCount; - sprintf(Percent, "%d", pcent); - - // Flag received blocks. Normalise to 50 wide - - memset(BlockList, '.', 50); - - for (i = 0; i < 50; i++) - { - int posn = (i * MSession->BlockCount) / 50; - if (MSession->BlockList[posn] == 1) - BlockList[i] = 'Y'; - } - } - - n = 0; - - OurSetItemText(MCList, MSession->Index, n++, Key); - if (MSession->ID) - OurSetItemText(MCList, MSession->Index, n++, MSession->ID) - else - OurSetItemText(MCList, MSession->Index, n++, " "); - - OurSetItemText(MCList, MSession->Index, n++, MSession->FileName); - OurSetItemText(MCList, MSession->Index, n++, Size); - OurSetItemText(MCList, MSession->Index, n++, Percent); - OurSetItemText(MCList, MSession->Index, n++, Time); - OurSetItemText(MCList, MSession->Index, n++, Agestring); - - if (MSession->Completed) - OurSetItemText(MCList, MSession->Index, n++, "Y") - else - OurSetItemText(MCList, MSession->Index, n++, " "); - - OurSetItemText(MCList, MSession->Index, n++, BlockList); -} - - -BOOL CreateMulticastConsole() -{ - WNDCLASS wc; - HBRUSH bgBrush; - RECT rcClient; - - if (hMCMonitor) - { - ShowWindow(hMCMonitor, SW_SHOWNORMAL); - SetForegroundWindow(hMCMonitor); - return FALSE; // Already open - } - - bgBrush = CreateSolidBrush(BGCOLOUR); - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = MCWndProc; - - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInst; - wc.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(BPQICON) ); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = bgBrush; - - wc.lpszMenuName = NULL; - wc.lpszClassName = MCClassName; - - RegisterClass(&wc); - - hMCMonitor=CreateDialog(hInst, MCClassName, 0, NULL); - - if (!hMCMonitor) - return (FALSE); - - hMCMenu=GetMenu(hMCMonitor); - -// CheckMenuItem(hMenu,MONBBS, MonBBS ? MF_CHECKED : MF_UNCHECKED); -// CheckMenuItem(hMenu,MONCHAT, MonCHAT ? MF_CHECKED : MF_UNCHECKED); -// CheckMenuItem(hMenu,MONTCP, MonTCP ? MF_CHECKED : MF_UNCHECKED); - - DrawMenuBar(hMCMonitor); - - // Create List View - - GetClientRect (hMCMonitor, &rcClient); - - MCList = CreateMCListView(hMCMonitor); - - MoveWindow(MCList, 0, 0, rcClient.right, rcClient.bottom, TRUE); - - if (cfgMinToTray) - AddTrayMenuItem(hMCMonitor, "Mail Multicast Monitor"); - - ShowWindow(hMCMonitor, SW_SHOWNORMAL); - - if (MCMonitorRect.right < 100 || MCMonitorRect.bottom < 100) - { - GetWindowRect(hMCMonitor, &MCMonitorRect); - } - - MoveWindow(hMCMonitor, MCMonitorRect.left, MCMonitorRect.top, - MCMonitorRect.right-MCMonitorRect.left, MCMonitorRect.bottom-MCMonitorRect.top, TRUE); - - MoveMCWindows(); - - return TRUE; - -} -void CopyMCToClipboard(HWND hWnd) -{ - int i,n, len=0; - char * Buffer; - HGLOBAL hMem; - char * ptr; - - char Time[80]; - char Agestring[80]; - char From[16]; - char Size[16]; - char Percent[16]; - char FileName[128]; - char Key[16]; - char Complete[2]; - - char BlockList[128]; - - n = ListView_GetItemCount(MCList); - - Buffer = malloc((n + 1) * 200); - - len = sprintf(Buffer, "ID From FileName Size %% Time Age Blocklist\r\n"); - - for (i=0; i> 1) ^ 0xA001; - else - crcval = (crcval >> 1); - } -} - -static unsigned int CalcCRC(UCHAR * ptr, int Len) -{ - int i; - - crcval = 0xFFFF; - for (i = 0; i < Len; i++) - { - update(*ptr++); - } - return crcval; -} - -struct MSESSION * FindMSession(unsigned int Key) -{ - struct MSESSION * Sess = MSessions; - struct MSESSION * LastSess = NULL; - - while (Sess) - { - if (Sess->Key == Key) - return Sess; - - LastSess = Sess; - Sess = Sess->Next; - } - - // Not found - - Sess = zalloc(sizeof(struct MSESSION)); - - if (Sess == NULL) - return NULL; - - Sess->Key = Key; - - Sess->Created = time(NULL); - - if (LastSess) - LastSess->Next = Sess; - else - MSessions = Sess; - - return Sess; -} - -#include "LzmaLib.h" - -#define LZMA_STR "\1LZMA" - -UCHAR * LZUncompress(UCHAR * Decoded, size_t Len, size_t * NewLen) -{ - unsigned char * buf; - unsigned char inprops[LZMA_PROPS_SIZE]; - size_t inlen; - int r; - - size_t rlen = 0; - size_t outlen; - - memcpy(&rlen, &Decoded[5], 4); - - outlen = ntohl(rlen); - *NewLen = outlen; - - buf = malloc(outlen); - - if (outlen > 1 << 25) - { - Debugprintf("Refusing to decompress data (> 32 MiB)"); - return NULL; - } - - - memcpy(inprops, Decoded + strlen(LZMA_STR) + sizeof(int), LZMA_PROPS_SIZE); - - inlen = Len - strlen(LZMA_STR) - sizeof(int) - LZMA_PROPS_SIZE; - - if ((r = LzmaUncompress(buf, &outlen, (const unsigned char*)Decoded + Len - inlen, &inlen, - inprops, LZMA_PROPS_SIZE)) != SZ_OK) - { - Debugprintf("Lzma Uncompress failed: %s", LZMA_ERRORS[r]); - return NULL; - } - else - { - return buf; - } -} - -void decodeblock128(unsigned char in[8], unsigned char out[7] ) -{ - out[0] = (unsigned char) (in[0] << 1 | in[1] >> 6); - out[1] = (unsigned char) (in[1] << 2 | in[2] >> 5); - out[2] = (unsigned char) (in[2] << 3 | in[3] >> 4); - out[3] = (unsigned char) (in[3] << 4 | in[4] >> 3); - out[4] = (unsigned char) in[4] << 5 | in[5] >> 2; - out[5] = (unsigned char) in[5] << 6 | in[6] >> 1; - out[6] = (unsigned char) in[6] << 7 | in[7]; -} - - -void SaveMulticastMessage(struct MSESSION * MSession) -{ - UCHAR * Decoded = NULL; // Output from Basexxx decode - UCHAR * Uncompressed = NULL; - size_t DecodedLen; // Length of decoded message - size_t UncompressedLen; // Length of decompressed message - int ExpectedLen; // From front of Base128 or Base256 message - int HddrLen; // Length of Expected Len Header - - if (MSession->FileName == NULL) - return; // Need Name - - MSession->Completed = TRUE; // So we don't get it again - - // If compresses and encoded, decode and decompress - - if (memcmp(MSession->Message, "[b64:start]", 11) == 0) - { - UCHAR * ptr1 = &MSession->Message[11]; - UCHAR * ptr2 = malloc(MSession->MessageLen); // Must get smaller - - int Len = MSession->MessageLen - 21; // Header and Trailer - - Decoded = ptr2; - - // Decode Base64 encoding - - while (Len > 0) - { - decodeblock(ptr1, ptr2); - ptr1 += 4; - ptr2 += 3; - Len -= 4; - } - - DecodedLen = (int)(ptr2 - Decoded); - Uncompressed = LZUncompress(Decoded, DecodedLen, &UncompressedLen); - } - else if (memcmp(MSession->Message, "[b128:start]", 12) == 0) - { - UCHAR * ptr1 = &MSession->Message[12]; - UCHAR * ptr2 = malloc(MSession->MessageLen); // Must get smaller - UCHAR ch; - UCHAR * Intermed; - - int Len = MSession->MessageLen - 23; // Header and Trailer - - Intermed = ptr2; - - // Decode Base128 encoding - - // First remove transparency (as in base256) - - - // Extract decoded msg len - - ExpectedLen = atoi(ptr1); - - ptr1 = strchr(ptr1, 10); - ptr1++; - - HddrLen = (int)(ptr1 - &MSession->Message[12]); - - if (ExpectedLen == 0 || ExpectedLen > Len || ptr1 == (UCHAR *)1) - { - Debugprintf("MCAST Missing Length Field"); - return; - } - - Len -= HddrLen;; - - while (Len > 0) - { - ch = *(ptr1++); - Len --; - - if (ch == ':') - { - ch = *(ptr1++); - Len--; - - switch (ch) - { - case ':' : *(ptr2++) = ':'; break; - case '0' : *(ptr2++) = 0x00; break; - case '1' : *(ptr2++) = 0x01; break; - case '2' : *(ptr2++) = 0x02; break; - case '3' : *(ptr2++) = 0x03; break; - case '4' : *(ptr2++) = 0x04; break; - case '5' : *(ptr2++) = 0x05; break; - case '6' : *(ptr2++) = 0x06; break; - case '7' : *(ptr2++) = 0x07; break; - case '8' : *(ptr2++) = 0x08; break; - case '9' : *(ptr2++) = 0x09; break; - case 'A' : *(ptr2++) = '\n'; break; - case 'B' : *(ptr2++) = '\r'; break; - case 'C' : *(ptr2++) = '^'; break; - case 'D' : *(ptr2++) = 0x7F; break; - case 'E' : *(ptr2++) = 0xFF; break; - } - } - else - *(ptr2++) = ch; - } - - - Len = ptr2 - Intermed; - - ptr1 = Intermed; - ptr2 = malloc(MSession->MessageLen); // Must get smaller - Decoded = ptr2; - - while (Len > 0) - { - decodeblock128(ptr1, ptr2); - ptr1 += 8; - ptr2 += 7; - Len -= 8; - } - - DecodedLen = ptr2 - Decoded; - Uncompressed = LZUncompress(Decoded, DecodedLen, &UncompressedLen); - } - else if (memcmp(MSession->Message, "[b256:start]", 12) == 0) - { - UCHAR * ptr1 = &MSession->Message[12]; - UCHAR * ptr2 = malloc(MSession->MessageLen); // Must get smaller - UCHAR ch; - - int Len = MSession->MessageLen - 23; // Header and Trailer - - Decoded = ptr2; - - // Decode Base256 encoding - - // Extract decoded msg len - - ExpectedLen = atoi(ptr1); - - ptr1 = strchr(ptr1, 10); - ptr1++; - - HddrLen = ptr1 - &MSession->Message[12]; - - if (ExpectedLen == 0 || ExpectedLen > Len || ptr1 == (UCHAR *)1) - { - Debugprintf("MCAST Missing Length Field"); - return; - } - - Len -= HddrLen;; - - while (Len > 0) - { - ch = *(ptr1++); - Len --; - - if (ch == ':') - { - ch = *(ptr1++); - Len--; - - switch (ch) - { - case ':' : *(ptr2++) = ':'; break; - case '0' : *(ptr2++) = 0x00; break; - case '1' : *(ptr2++) = 0x01; break; - case '2' : *(ptr2++) = 0x02; break; - case '3' : *(ptr2++) = 0x03; break; - case '4' : *(ptr2++) = 0x04; break; - case '5' : *(ptr2++) = 0x05; break; - case '6' : *(ptr2++) = 0x06; break; - case '7' : *(ptr2++) = 0x07; break; - case '8' : *(ptr2++) = 0x08; break; - case '9' : *(ptr2++) = 0x09; break; - case 'A' : *(ptr2++) = '\n'; break; - case 'B' : *(ptr2++) = '\r'; break; - case 'C' : *(ptr2++) = '^'; break; - case 'D' : *(ptr2++) = 0x7F; break; - case 'E' : *(ptr2++) = 0xFF; break; - } - } - else - *(ptr2++) = ch; - } - - DecodedLen = ptr2 - Decoded; - Uncompressed = LZUncompress(Decoded, DecodedLen, &UncompressedLen); - } - else - { - // Plain Text - - UncompressedLen = MSession->MessageLen; - Uncompressed = MSession->Message; - - MSession->Message = NULL; // So we dont try to free again - } - - if (Decoded) - free(Decoded); - - if (Uncompressed) - { - // Write it away and free it - - char MsgFile[MAX_PATH]; - FILE * hFile; - int WriteLen=0; - UCHAR * ptr1 = Uncompressed; - - // Make Sure MCAST directory exists - - sprintf_s(MsgFile, sizeof(MsgFile), "%s/MCAST", MailDir); - -#ifdef WIN32 - CreateDirectory(MsgFile, NULL); // Just in case -#else - mkdir(MsgFile, S_IRWXU | S_IRWXG | S_IRWXO); - chmod(MsgFile, S_IRWXU | S_IRWXG | S_IRWXO); -#endif - - sprintf_s(MsgFile, sizeof(MsgFile), "%s/MCAST/%s", MailDir, MSession->FileName); - - hFile = fopen(MsgFile, "wb"); - - if (hFile) - { - WriteLen = (int)fwrite(Uncompressed, 1, UncompressedLen, hFile); - fclose(hFile); - } - - - // if it looks like an export file (Starts SP SB or ST) and ends /ex - // import and delete it. - - if (*(ptr1) == 'S' && ptr1[2] == ' ') - if (_memicmp(&ptr1[UncompressedLen - 5], "/EX", 3) == 0) - ImportMessages(NULL, MsgFile, TRUE); - - free (Uncompressed); - } -} - -VOID ProcessMCASTLine(ConnectionInfo * conn, struct UserInfo * user, char * Buffer, int MsgLen) -{ - char Opcode[80]; - unsigned int checksum, len = 0; - char * data; - int headerlen = 0; - unsigned int crcval; - int n; - unsigned int Key; - struct MSESSION * MSession; - - if (MsgLen == 1 && Buffer[0] == 13) - return; - - MsgLen --; // Remove the CR we added - - Buffer[MsgLen] = 0; - - if (MsgLen == 1 && Buffer[0] == 13) - return; - -// return; - - n = sscanf(&Buffer[1], "%s %04d %04X", Opcode, &len, &checksum); - - if (n != 3) - return; - - data = strchr(Buffer, '>'); - - if (data) - headerlen = (int)(++data - Buffer); - - if (headerlen + len != MsgLen) - return; - - crcval = CalcCRC(data, len); - - if (checksum != crcval) - return; - - // Extract Session Key - - sscanf(&data[1], "%04X", &Key); - - MSession = FindMSession(Key); - - if (MSession == 0) - return; // ?? couldn't allocate - - MSession->LastUpdated = time(NULL); - - if (MSession->Completed) - return; // We already have it all - - if (strcmp(Opcode, "ID") == 0) - { - strlop(&data[6], ' '); - MSession->ID = _strdup(&data[6]); - - return; - } - - if (strcmp(Opcode, "PROG") == 0) - { - // Ignore for now - return; - } - - if (strcmp(Opcode, "FILE") == 0) - { - // {80BC}20141108142542:debug_log.txt - - char * FN = strchr(&data[6], ':'); - - if (FN) - { - *(FN++) = 0; - - MSession->FileName = _strdup(FN); - MSession->OrigTimeStamp = _strdup(&data[6]); - } - - // We could get whole message without getting the Name, - // so check - - if (MSession->BlockCount && MSession->BlocksReceived == MSession->BlockCount) - { - // We have the whole message. Decode and Save - - if (MSession->MessageLen) // Also need length - SaveMulticastMessage(MSession); - } - - RefreshMCLine(MSession); - return; - } - - if (strcmp(Opcode, "SIZE") == 0) - { - // SIZE 14 2995>{80BC}465 8 64 - - int a, b, c, n = sscanf(&data[6], "%d %d %d", &a, &b, &c); - - if (n == 3) - { - // We may already have some (or even all) the message if we - // missed the SIZE block first time round - - if (MSession->Message) - { - // Already have at least part of it - - if (MSession->BlockSize != c) - { - // We based blocksize on last packet, so need to sort out mess - - // Find where we put the block, and move it - - UCHAR * OldLoc; - - MSession->Message = realloc(MSession->Message, a); - MSession->BlockList = realloc(MSession->BlockList, b); - - OldLoc = &MSession->Message[(MSession->BlockCount - 1) * MSession->BlockSize]; - - memmove(&MSession->Message[(MSession->BlockCount - 1) * c], OldLoc, MSession->BlockSize); - - MSession->BlockSize = c; - } - - if (MSession->BlockCount < b) - { - // Dont have it all, so need to extend ; - - MSession->Message = realloc(MSession->Message, a); - MSession->BlockList = realloc(MSession->BlockList, b); - } - } - - MSession->MessageLen = a; - MSession->BlockCount = b; - MSession->BlockSize = c; - - if (MSession->Message == NULL) - { - MSession->Message = zalloc(b * c); - MSession->BlockList = zalloc(b); - } - - // We might have it all now - - if (MSession->BlocksReceived == MSession->BlockCount) - { - // We have the whole message. Decode and Save - - SaveMulticastMessage(MSession); - } - } - - RefreshMCLine(MSession); - return; - } - - if (strcmp(Opcode, "DATA") == 0) - { - // {80BC:1}[b256:start]401 - - int Blockno = atoi(&data[6]); - char * dataptr = strchr(&data[6], '}'); - - if (dataptr == 0) - return; - - dataptr++; - - // What should we do if we don't have Filename or Size?? - - // If we assume this isn't the last block, then we can get - // the block size from this message. This is pretty save, but - // I guess as we will only get one last block, if we subsequently - // get an earlier one that is bigger, we can recalculate the position - // of this block and move it. - - if (MSession->MessageLen == 0) - { - // Haven't received SIZE Message yet. Guess the blocksize - - int blocksize = MsgLen - (int)(dataptr - Buffer); - - if (MSession->BlockSize == 0) - { - MSession->BlockSize = blocksize; - } - else - { - if (MSession->BlockSize < blocksize) - { - // We based blocksize on last packet, so need to sort out mess - - // Find where we put the block, and move it - - UCHAR * OldLoc = &MSession->Message[(MSession->BlockCount - 1) * MSession->BlockSize]; - memmove(&MSession->Message[(MSession->BlockCount - 1) * blocksize], OldLoc, MSession->BlockSize); - - MSession->BlockSize = blocksize; - } - } - - // We need to realloc Message and Blocklist if this is a later block - - if (MSession->BlockCount < Blockno) - { - MSession->Message = realloc(MSession->Message, Blockno * MSession->BlockSize); - MSession->BlockList = realloc(MSession->BlockList, Blockno); - - memset(&MSession->BlockList[MSession->BlockCount], 0, Blockno - MSession->BlockCount); - MSession->BlockCount = Blockno; - - } - - } - if (Blockno == 0 || Blockno > MSession->BlockCount) - return; - - Blockno--; - - if (MSession->BlockList[Blockno] == 1) - { - // Already have this block - - return; - } - - - memcpy(&MSession->Message[Blockno * MSession->BlockSize], dataptr, MSession->BlockSize); - MSession->BlockList[Blockno] = 1; - - MSession->BlocksReceived++; - - if (MSession->BlocksReceived == MSession->BlockCount && MSession->MessageLen) - { - // We have the whole message. Decode and Save - - SaveMulticastMessage(MSession); - } - - RefreshMCLine(MSession); - - return; - } - - MsgLen++; - -/* - -QST DE GM8BPQ - -{80BC}FLAMP 2.2.03 -{80BC}20141108142542:debug_log.txt -{80BC}GM8BPQ Skigersta -{80BC}465 8 64 -{80BC:1}[b256:start]401 -:1LZMA:0:0:6-]:0:0:0:4:0$--:7m?8-v\-E-Y-[--- -{80BC:2}rS-)N{j--o--ZMPX-,-l-yD------E--;-o:6-|;--f---q----0<---%-- -{80BC:3}*N-?N--*:Cf{:9--z-J:9-HMd:8-------Q--D---_-a----:C$;A-j---(: -{80BC:4}DWb--K---Qq-uj-_--;i------T-\>-{:6---~-ij~-,-(-O--2--+ --:8 -{80BC:5}p---:7Gf:E-5o->x---4--K--:3-\:E---gouuH-3'----:A!.:7 ---N:0S -{80BC:6}.---/-~#.-:D:7zg~--m--:8-'---Y%-?--ze\-ho:5-}-:C:A:1u-1-O- -- -{80BC:7}9p-42-w--G:2G:3--g--O---n----c-#----DF-!~--:D-A--|-e------- -{80BC:8}B{--:0 -[b256:end] -{80BC:EOF} -{80BC:EOT} - -DE GM8BPQ K - -*/ - - return; -/* - if (strcmp(Buffer, "ARQ::ETX\r") == 0) - { - // Decode it. - - UCHAR * ptr1, * ptr2, * ptr3; - int len, linelen; - struct MsgInfo * Msg = conn->TempMsg; - time_t Date; - char FullTo[100]; - char FullFrom[100]; - char ** RecpTo = NULL; // May be several Recipients - char ** HddrTo = NULL; // May be several Recipients - char ** Via = NULL; // May be several Recipients - int LocalMsg[1000] ; // Set if Recipient is a local wl2k address - - int B2To; // Offset to To: fields in B2 header - int Recipients = 0; - int RMSMsgs = 0, BBSMsgs = 0; - -// Msg->B2Flags |= B2Msg; - - - ptr1 = conn->MailBuffer; - len = Msg->length; - ptr1[len] = 0; - - if (strstr(ptr1, "ARQ:ENCODING::")) - { - // a file, not a message. If is called "BBSPOLL" do a reverse forward else Ignore for now - - _strupr(conn->MailBuffer); - if (strstr(conn->MailBuffer, "BBSPOLL")) - { - SendARQMail(conn); - } - - free(conn->MailBuffer); - conn->MailBuffer = NULL; - conn->MailBufferSize = 0; - - return; - } - Loop: - ptr2 = strchr(ptr1, '\r'); - - linelen = ptr2 - ptr1; - - if (_memicmp(ptr1, "From:", 5) == 0 && linelen > 6) // Can have empty From: - { - char SaveFrom[100]; - char * FromHA; - - memcpy(FullFrom, ptr1, linelen); - FullFrom[linelen] = 0; - - // B2 From may now contain an @BBS - - strcpy(SaveFrom, FullFrom); - - FromHA = strlop(SaveFrom, '@'); - - if (strlen(SaveFrom) > 12) SaveFrom[12] = 0; - - strcpy(Msg->from, &SaveFrom[6]); - - if (FromHA) - { - if (strlen(FromHA) > 39) FromHA[39] = 0; - Msg->emailfrom[0] = '@'; - strcpy(&Msg->emailfrom[1], _strupr(FromHA)); - } - - // Remove any SSID - - ptr3 = strchr(Msg->from, '-'); - if (ptr3) *ptr3 = 0; - - } - else if (_memicmp(ptr1, "To:", 3) == 0 || _memicmp(ptr1, "cc:", 3) == 0) - { - HddrTo=realloc(HddrTo, (Recipients+1) * sizeof(void *)); - HddrTo[Recipients] = zalloc(100); - - memset(FullTo, 0, 99); - memcpy(FullTo, &ptr1[4], linelen-4); - memcpy(HddrTo[Recipients], ptr1, linelen+2); - LocalMsg[Recipients] = FALSE; - - _strupr(FullTo); - - B2To = ptr1 - conn->MailBuffer; - - if (_memicmp(FullTo, "RMS:", 4) == 0) - { - // remove RMS and add @winlink.org - - strcpy(FullTo, "RMS"); - strcpy(Msg->via, &FullTo[4]); - } - else - { - ptr3 = strchr(FullTo, '@'); - - if (ptr3) - { - *ptr3++ = 0; - strcpy(Msg->via, ptr3); - } - else - Msg->via[0] = 0; - } - - if (_memicmp(&ptr1[4], "SMTP:", 5) == 0) - { - // Airmail Sends MARS messages as SMTP - - if (CheckifPacket(Msg->via)) - { - // Packet Message - - memmove(FullTo, &FullTo[5], strlen(FullTo) - 4); - _strupr(FullTo); - _strupr(Msg->via); - - // Update the saved to: line (remove the smtp:) - - strcpy(&HddrTo[Recipients][4], &HddrTo[Recipients][9]); - BBSMsgs++; - goto BBSMsg; - } - - // If a winlink.org address we need to convert to call - - if (_stricmp(Msg->via, "winlink.org") == 0) - { - memmove(FullTo, &FullTo[5], strlen(FullTo) - 4); - _strupr(FullTo); - LocalMsg[Recipients] = CheckifLocalRMSUser(FullTo); - } - else - { - memcpy(Msg->via, &ptr1[9], linelen); - Msg->via[linelen - 9] = 0; - strcpy(FullTo,"RMS"); - } -// FullTo[0] = 0; - - BBSMsg: - _strupr(FullTo); - _strupr(Msg->via); - } - - if (memcmp(FullTo, "RMS:", 4) == 0) - { - // remove RMS and add @winlink.org - - memmove(FullTo, &FullTo[4], strlen(FullTo) - 3); - strcpy(Msg->via, "winlink.org"); - sprintf(HddrTo[Recipients], "To: %s\r\n", FullTo); - } - - if (strcmp(Msg->via, "RMS") == 0) - { - // replace RMS with @winlink.org - - strcpy(Msg->via, "winlink.org"); - sprintf(HddrTo[Recipients], "To: %s@winlink.org\r\n", FullTo); - } - - if (strlen(FullTo) > 6) - FullTo[6] = 0; - - strlop(FullTo, '-'); - - strcpy(Msg->to, FullTo); - - if (SendBBStoSYSOPCall) - if (_stricmp(FullTo, BBSName) == 0) - strcpy(Msg->to, SYSOPCall); - - if ((Msg->via[0] == 0 || strcmp(Msg->via, "BPQ") == 0 || strcmp(Msg->via, "BBS") == 0)) - { - // No routing - check @BBS and WP - - struct UserInfo * ToUser = LookupCall(FullTo); - - Msg->via[0] = 0; // In case BPQ and not found - - if (ToUser) - { - // Local User. If Home BBS is specified, use it - - if (ToUser->HomeBBS[0]) - { - strcpy(Msg->via, ToUser->HomeBBS); - } - } - else - { - WPRecP WP = LookupWP(FullTo); - - if (WP) - { - strcpy(Msg->via, WP->first_homebbs); - - } - } - - // Fix To: address in B2 Header - - if (Msg->via[0]) - sprintf(HddrTo[Recipients], "To: %s@%s\r\n", FullTo, Msg->via); - else - sprintf(HddrTo[Recipients], "To: %s\r\n", FullTo); - - } - - RecpTo=realloc(RecpTo, (Recipients+1) * sizeof(void *)); - RecpTo[Recipients] = zalloc(10); - - Via=realloc(Via, (Recipients+1) * sizeof(void *)); - Via[Recipients] = zalloc(50); - - strcpy(Via[Recipients], Msg->via); - strcpy(RecpTo[Recipients++], FullTo); - - // Remove the To: Line from the buffer - - } - else if (_memicmp(ptr1, "Type:", 4) == 0) - { - if (ptr1[6] == 'N') - Msg->type = 'T'; // NTS - else - Msg->type = ptr1[6]; - } - else if (_memicmp(ptr1, "Subject:", 8) == 0) - { - int Subjlen = ptr2 - &ptr1[9]; - if (Subjlen > 60) Subjlen = 60; - memcpy(Msg->title, &ptr1[9], Subjlen); - - goto ProcessBody; - } -// else if (_memicmp(ptr1, "Body:", 4) == 0) -// { -// MsgLen = atoi(&ptr1[5]); -// StartofMsg = ptr1; -// } - else if (_memicmp(ptr1, "File:", 5) == 0) - { - Msg->B2Flags |= Attachments; - } - else if (_memicmp(ptr1, "Date:", 5) == 0) - { - struct tm rtime; - char seps[] = " ,\t\r"; - - memset(&rtime, 0, sizeof(struct tm)); - - // Date: 2009/07/25 10:08 - - sscanf(&ptr1[5], "%04d/%02d/%02d %02d:%02d:%02d", - &rtime.tm_year, &rtime.tm_mon, &rtime.tm_mday, &rtime.tm_hour, &rtime.tm_min, &rtime.tm_sec); - - sscanf(&ptr1[5], "%02d/%02d/%04d %02d:%02d:%02d", - &rtime.tm_mday, &rtime.tm_mon, &rtime.tm_year, &rtime.tm_hour, &rtime.tm_min, &rtime.tm_sec); - - rtime.tm_year -= 1900; - - Date = mktime(&rtime) - (time_t)_MYTIMEZONE; - - if (Date == (time_t)-1) - Date = time(NULL); - - Msg->datecreated = Date; - - } - - if (linelen) // Not Null line - { - ptr1 = ptr2 + 2; // Skip cr - goto Loop; - } - - - // Processed all headers -ProcessBody: - - ptr2 +=2; // skip crlf - - Msg->length = &conn->MailBuffer[Msg->length] - ptr2; - - memmove(conn->MailBuffer, ptr2, Msg->length); - - CreateMessageFromBuffer(conn); - - conn->BBSFlags = 0; // Clear ARQ Mode - return; - } - - // File away the data - - Buffer[MsgLen++] = 0x0a; // BBS Msgs stored with crlf - - if ((conn->TempMsg->length + MsgLen) > conn->MailBufferSize) - { - conn->MailBufferSize += 10000; - conn->MailBuffer = realloc(conn->MailBuffer, conn->MailBufferSize); - - if (conn->MailBuffer == NULL) - { - BBSputs(conn, "*** Failed to extend Message Buffer\r"); - conn->CloseAfterFlush = 20; // 2 Secs - - return; - } - } - - memcpy(&conn->MailBuffer[conn->TempMsg->length], Buffer, MsgLen); - - conn->TempMsg->length += MsgLen; - - return; - - // Not sure what to do yet with files, but will process emails (using text style forwarding -*/ -/* -ARQ:FILE::flarqmail-1.eml -ARQ:EMAIL:: -ARQ:SIZE::96 -ARQ::STX -//FLARQ COMPOSER -Date: 16/01/2014 22:26:06 -To: g8bpq -From: -Subject: test message - -Hello -Hello - -ARQ::ETX -*/ - - return; -} - -VOID MCastConTimer(ConnectionInfo * conn) -{ - conn->MCastListenTime--; - - if (conn->MCastListenTime == 0) - Disconnect(conn->BPQStream); -} - -VOID MCastTimer() -{ - struct MSESSION * Sess = MSessions; - struct MSESSION * Prev = NULL; - - time_t Now = time(NULL); - - while (Sess) - { - if (Sess->Completed == FALSE) - RefreshMCLine(Sess); - - if (Now - Sess->LastUpdated > MulticastMaxAge) - { - // remove from list - -#ifndef LINBPQ - ListView_DeleteItem(MCList, Sess->Index); -#endif - if (Prev) - Prev->Next = Sess->Next; - else - MSessions = Sess->Next; - - if (Sess->FileName) - free(Sess->FileName); - - if (Sess->OrigTimeStamp) - free(Sess->OrigTimeStamp); - - if (Sess->Message) - free(Sess->Message); - - if (Sess->BlockList) - free(Sess->BlockList); - - if (Sess->ID) - free(Sess->ID); - - free(Sess); - - return; // Saves messing with chain - - } - Prev = Sess; - Sess = Sess->Next; - } -} - -int MulticastStatusHTML(char * Reply) -{ - char StatusPage [] = - "
ID    From      FileName        Size  %%  Time   Age   Blocklist"
-		"                                                   "
-		"\r\n

"; - int Len = 0; - char Unknown[] = "???"; - - struct MSESSION * Sess = MSessions; - - if (Sess ==NULL) - return 0; - - Len = sprintf(Reply, "%s", StatusPage); - - while (Sess) - { - char Percent[16] = "???"; - char BlockList[51] = ""; - int i; - char Time[80]; - char Agestring[80]; - struct tm * TM; - time_t Age; - char * ID = Unknown; - char * FileName = Unknown; - - Age = time(NULL) - Sess->LastUpdated; - - TM = gmtime(&Age); - - sprintf(Agestring, "%.2d:%.2d", TM->tm_hour, TM->tm_min); - - TM = gmtime(&Sess->Created); - - sprintf(Time, "%.2d:%.2d", TM->tm_hour, TM->tm_min); - - if (Sess->MessageLen && Sess->BlockCount) - { - int pcent; - - pcent = (Sess->BlocksReceived * 100) / Sess->BlockCount; - sprintf(Percent, "%d", pcent); - } - - // Flag received blocks. Normalise to 50 wide - - memset(BlockList, '.', 50); - - if (Sess->BlockList) - { - for (i = 0; i < 50; i++) - { - int posn = (i * Sess->BlockCount) / 50; - if (Sess->BlockList[posn] == 1) - BlockList[i] = 'Y'; - } - } - if (Sess->FileName) - FileName = Sess->FileName; - - if (Sess->ID) - ID = Sess->ID; - - Len += sprintf(&Reply[Len], "%04X %-10s%-15s%5d %-3s %s %s %s\r\n", - Sess->Key, ID, FileName, - Sess->MessageLen, Percent, Time, Agestring, BlockList); - - Sess = Sess->Next; - } - - Len += sprintf(&Reply[Len], "%s", StatusTail); - - return Len; -} diff --git a/.svn/pristine/05/05be6263d55be8cd16e65e2edc8dcf1aab6277a1.svn-base b/.svn/pristine/05/05be6263d55be8cd16e65e2edc8dcf1aab6277a1.svn-base deleted file mode 100644 index 84df6b3..0000000 --- a/.svn/pristine/05/05be6263d55be8cd16e65e2edc8dcf1aab6277a1.svn-base +++ /dev/null @@ -1,3143 +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 -*/ - - -// July 2010 - -// BPQ32 now reads bpqcfg.txt. This module converts it to the original binary format. - -// Based on the standalonw bpqcfg.c - -/************************************************************************/ -/* CONFIG.C Jonathan Naylor G4KLX, 19th November 1988 */ -/* */ -/* Program to produce configuration file for G8BPQ Network Switch */ -/* based on the original written in BASIC by G8BPQ. */ -/* */ -/* Subsequently extended by G8BPQ */ -/* */ -/************************************************************************/ -// -// 22/11/95 - Add second port alias for digipeating (for APRS) -// - Add PORTMAXDIGIS param - -// 1999 - Win32 Version (but should also compile in 16 bit - -// 5/12/99 - Add DLLNAME Param for ext driver - -// 26/11/02 - Added AUTOSAVE - -// Jan 2006 - -// Add params for input and output names -// Wait before exiting if error detected - -// March 2006 - -// Accept # as comment delimiter -// Display input and output filenames -// Wait before exit, even if ok - -// March 2006 - -// Add L4APPL param - -// Jan 2007 - -// Remove UNPROTO -// Add BTEXT -// Add BCALL - -// Nov 2007 - -// Convert calls and APPLICATIONS string to upper case - -// Jan 2008 - -// Remove trailing space from UNPROTO -// Don't warn BBSCALL etc missing if APPL1CALL etc present - -// August 2008 - -// Add IPGATEWAY Parameter -// Add Port DIGIMASK Parameter - -// December 2008 - -// Add C_IS_CHAT Parameter - -// March 2009 - -// Add C style COmments (/* */ at start of line) - -// August 2009 - -// Add INP3 flag to locked routes - -// November 2009 - -// Add PROTOCOL=PACTOR or WINMOR option - -// December 2009 - -// Add INP3 MAXRTT and MAXHOPS Commands - -// March 2010 - -// Add SIMPLE mode - -// March 2010 - -// Change SIMPLE mode default of Full_CTEXT to 1 - -// April 2010 - -// Add NoKeepAlive ROUTE option - -// Converted to intenal bpq32 process - -// Spetember 2010 - -// Add option of embedded port configuration - - - -#define _CRT_SECURE_NO_DEPRECATE - -#include "cheaders.h" - -#include -#include -#include -#include -#include - -#include "configstructs.h" - -// KISS Options Equates - -#define CHECKSUM 1 -#define POLLINGKISS 2 // KISSFLAGS BITS -#define ACKMODE 4 // CAN USE ACK REQURED FRAMES -#define POLLEDKISS 8 // OTHER END IS POLLING US -#define D700 16 // D700 Mode (Escape "C" chars -#define TNCX 32 // TNC-X Mode (Checksum of ACKMODE frames includes ACK bytes -#define PITNC 64 // PITNC Mode - can reset TNC with FEND 15 2 -#define NOPARAMS 128 // Don't send SETPARAMS frame -#define FLDIGI 256 // Support FLDIGI COmmand Frames -#define TRACKER 512 // SCS Tracker. Need to set KISS Mode -#define FASTI2C 1024 // Use BLocked I2C Reads (like ARDOP) -#define DRATS 2048 - - - -struct WL2KInfo * DecodeWL2KReportLine(char * buf); - -// Dummy file routines - write to buffer instead - -char * PortConfig[70]; -char * RadioConfigMsg[70]; -char * WL2KReportLine[70]; - -int nextRadioPort = 0; -int nextDummyInterlock = 233; - -BOOL PortDefined[70]; - -extern BOOL IncludesMail; -extern BOOL IncludesChat; -extern int needAIS; -extern int needADSB; - -extern int AGWPort; -extern int AGWSessions; -extern int AGWMask; - -extern BOOL LoopMonFlag; -extern BOOL Loopflag; - -extern char NodeMapServer[80]; -extern char ChatMapServer[80]; - -double LatFromLOC; -double LonFromLOC; - - - -VOID * zalloc(int len); - -int WritetoConsoleLocal(char * buff); -char * stristr (char *ch1, char *ch2); -int FromLOC(char * Locator, double * pLat, double * pLon); - -VOID Consoleprintf(const char * format, ...) -{ - char Mess[512]; - va_list(arglist); - - va_start(arglist, format); - vsprintf(Mess, format, arglist); - strcat(Mess, "\n"); - WritetoConsoleLocal(Mess); - - return; -} - - -#pragma pack() - -int tnctypes(int i, char value[],char rec[]); -int do_kiss (char value[],char rec[]); - -struct TNCDATA * TNCCONFIGTABLE = NULL; // malloc'ed -int NUMBEROFTNCPORTS = 0; - -struct UPNP * UPNPConfig = NULL; - -struct TNCDATA * TNC2ENTRY; - -extern char PWTEXT[]; -extern char HFCTEXT[]; -extern int HFCTEXTLEN; -extern char LOCATOR[]; -extern char MAPCOMMENT[]; -extern char LOC[]; -extern int RFOnly; - -int decode_rec(char *rec); -int applcallsign(int i,char *value,char *rec); -int appl_qual(int i,char *value,char *rec); -int callsign(char * val, char *value, char *rec); -int int_value(short * val, char *value, char *rec); -int hex_value(int * val, char *value, char *rec); -int bin_switch(char * val, char *value, char *rec); -int dec_switch(char * val, char *value, char *rec); -int applstrings(int i,char *value, char *rec); -int dotext(char * val, char *key_word, int max); -int dolinked(int i, char * value, char * rec); -int routes(int i); -int ports(int i); -int tncports(int i); -int dedports(int i); -int xindex(char *s,char *t); -int verify(char *s,char c); -int GetNextLine(char * rec); -int call_check(char *callsign, char * val); -int call_check_internal(char * callsign); -int callstring(int i,char *value,char *rec); -int decode_port_rec(char *rec); -int doid(int i,char *value,char *rec); -int dodll(int i,char *value,char *rec); -int doDriver(int i,char *value,char *rec); -int hwtypes(int i,char *value,char *rec); -int protocols(int i,char *value,char *rec); -int bbsflag(int i,char *value,char *rec); -int channel(int i,char *value,char *rec); -int validcalls(int i,char *value,char *rec); -int kissoptions(int i,char *value,char *rec); -int decode_tnc_rec(char *rec); -int tnctypes(int i,char *value,char *rec); -int do_kiss(char *value,char *rec); -int decode_ded_rec(char *rec); -int simple(int i); -int64_t int64_value(int64_t * val, char value[], char rec[]); - - -int C_Q_ADD_NP(VOID *PQ, VOID *PBUFF); -int doSerialPortName(int i, char * value, char * rec); -int doPermittedAppls(int i, char * value, char * rec); -int doKissCommand(int i, char * value, char * rec); - -BOOL ProcessAPPLDef(char * rec); -BOOL ToLOC(double Lat, double Lon , char * Locator); - -//int i; -//char value[]; -//char rec[]; - -int FIRSTAPPL=1; -BOOL Comment = FALSE; -int CommentLine = 0; - -#define MAXLINE 512 -#define FILEVERSION 22 - -extern UCHAR BPQDirectory[]; - -struct CONFIGTABLE xxcfg; -struct PORTCONFIG xxp; - -char inputname[250]="bpqcfg.txt"; -char option[250]; - -/************************************************************************/ -/* STATIC VARIABLES */ -/************************************************************************/ - -static char *keywords[] = -{ -"OBSINIT", "OBSMIN", "NODESINTERVAL", "L3TIMETOLIVE", "L4RETRIES", "L4TIMEOUT", -"BUFFERS", "PACLEN", "TRANSDELAY", "T3", "IDLETIME", "BBS", -"NODE", "NODEALIAS", "BBSALIAS", "NODECALL", "BBSCALL", -"TNCPORT", "IDMSG:", "INFOMSG:", "ROUTES:", "PORT", "MAXLINKS", -"MAXNODES", "MAXROUTES", "MAXCIRCUITS", "IDINTERVAL", "MINQUAL", -"HIDENODES", "L4DELAY", "L4WINDOW", "BTINTERVAL", "UNPROTO", "BBSQUAL", -"APPLICATIONS", "EMS", "CTEXT:", "DESQVIEW", "HOSTINTERRUPT", "ENABLE_LINKED", -"XXDEDHOST", "FULL_CTEXT", "SIMPLE", "AUTOSAVE" , "L4APPL", -"APPL1CALL", "APPL2CALL", "APPL3CALL", "APPL4CALL", -"APPL5CALL", "APPL6CALL", "APPL7CALL", "APPL8CALL", -"APPL1ALIAS", "APPL2ALIAS", "APPL3ALIAS", "APPL4ALIAS", -"APPL5ALIAS", "APPL6ALIAS", "APPL7ALIAS", "APPL8ALIAS", -"APPL1QUAL", "APPL2QUAL", "APPL3QUAL", "APPL4QUAL", -"APPL5QUAL", "APPL6QUAL", "APPL7QUAL", "APPL8QUAL", -"BTEXT:", "NETROMCALL", "C_IS_CHAT", "MAXRTT", "MAXHOPS", // IPGATEWAY= no longer allowed -"LogL4Connects", "LogAllConnects", "SAVEMH", "ENABLEADIFLOG", "ENABLEEVENTS", "SAVEAPRSMSGS", -"EnableM0LTEMap", "MQTT", "MQTT_HOST", "MQTT_PORT", "MQTT_USER", "MQTT_PASS", -"L4Compress", "L4CompMaxframe", "L4CompPaclen", "L2Compress", "L2CompMaxframe", "L2CompPaclen" -}; /* parameter keywords */ - -static void * offset[] = -{ -&xxcfg.C_OBSINIT, &xxcfg.C_OBSMIN, &xxcfg.C_NODESINTERVAL, &xxcfg.C_L3TIMETOLIVE, &xxcfg.C_L4RETRIES, &xxcfg.C_L4TIMEOUT, -&xxcfg.C_BUFFERS, &xxcfg.C_PACLEN, &xxcfg.C_TRANSDELAY, &xxcfg.C_T3, &xxcfg.C_IDLETIME, &xxcfg.C_BBS, -&xxcfg.C_NODE, &xxcfg.C_NODEALIAS, &xxcfg.C_BBSALIAS, &xxcfg.C_NODECALL, &xxcfg.C_BBSCALL, -0, &xxcfg.C_IDMSG, &xxcfg.C_INFOMSG, &xxcfg.C_ROUTE, &xxcfg.C_PORT, &xxcfg.C_MAXLINKS, -&xxcfg.C_MAXDESTS, &xxcfg.C_MAXNEIGHBOURS, &xxcfg.C_MAXCIRCUITS, &xxcfg.C_IDINTERVAL, &xxcfg.C_MINQUAL, -&xxcfg.C_HIDENODES, &xxcfg.C_L4DELAY, &xxcfg.C_L4WINDOW, &xxcfg.C_BTINTERVAL, &xxcfg.C_WASUNPROTO, &xxcfg.C_BBSQUAL, -&xxcfg.C_APPL, &xxcfg.C_EMSFLAG, &xxcfg.C_CTEXT , &xxcfg.C_DESQVIEW, &xxcfg.C_HOSTINTERRUPT, &xxcfg.C_LINKEDFLAG, -0, &xxcfg.C_FULLCTEXT, 0, &xxcfg.C_AUTOSAVE, &xxcfg.C_L4APPL, -&xxcfg.C_APPL[0].ApplCall, &xxcfg.C_APPL[1].ApplCall, &xxcfg.C_APPL[2].ApplCall, &xxcfg.C_APPL[3].ApplCall, -&xxcfg.C_APPL[4].ApplCall, &xxcfg.C_APPL[5].ApplCall, &xxcfg.C_APPL[6].ApplCall, &xxcfg.C_APPL[7].ApplCall, -&xxcfg.C_APPL[0].ApplAlias, &xxcfg.C_APPL[1].ApplAlias, &xxcfg.C_APPL[2].ApplAlias, &xxcfg.C_APPL[3].ApplAlias, -&xxcfg.C_APPL[4].ApplAlias, &xxcfg.C_APPL[5].ApplAlias, &xxcfg.C_APPL[6].ApplAlias, &xxcfg.C_APPL[7].ApplAlias, -&xxcfg.C_APPL[0].ApplQual, &xxcfg.C_APPL[1].ApplQual, &xxcfg.C_APPL[2].ApplQual, &xxcfg.C_APPL[3].ApplQual, -&xxcfg.C_APPL[4].ApplQual, &xxcfg.C_APPL[5].ApplQual, &xxcfg.C_APPL[6].ApplQual, &xxcfg.C_APPL[7].ApplQual, -&xxcfg.C_BTEXT, &xxcfg.C_NETROMCALL, &xxcfg.C_C, &xxcfg.C_MAXRTT, &xxcfg.C_MAXHOPS, // IPGATEWAY= no longer allowed -&xxcfg.C_LogL4Connects, &xxcfg.C_LogAllConnects, &xxcfg.C_SaveMH, &xxcfg.C_ADIF, &xxcfg.C_EVENTS, &xxcfg.C_SaveAPRSMsgs, -&xxcfg.C_M0LTEMap, &xxcfg.C_MQTT, &xxcfg.C_MQTT_HOST, &xxcfg.C_MQTT_PORT, &xxcfg.C_MQTT_USER, &xxcfg.C_MQTT_PASS, -&xxcfg.C_L4Compress, &xxcfg.C_L4CompMaxframe, &xxcfg.C_L4CompPaclen, &xxcfg.C_L2Compress, &xxcfg.C_L2CompMaxframe, &xxcfg.C_L2CompPaclen}; /* offset for corresponding data in config file */ - -static int routine[] = -{ -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 2, -2, 0, 0, 0, 0, -3, 4, 20, 5, 6, 1, -1, 1, 1, 1, 1, -2, 1, 1, 1, 7, 1, -8, 2, 4, 2, 9, 10, -11, 1, 12, 2 , 1, -13, 13, 13, 13, -13, 13 ,13, 13, -13, 13, 13, 13, -13, 13 ,13, 13, -14, 14, 14, 14, -14, 14 ,14, 14, -15, 0, 2, 9, 9, -2, 2, 1, 2, 2, 2, -2, 2, 0, 1, 20, 20, -1, 1, 1, 1, 1, 1} ; // Routine to process param - -int PARAMLIM = sizeof(routine)/sizeof(int); -//int NUMBEROFKEYWORDS = sizeof(routine)/sizeof(int); - -//#define PARAMLIM 74 - - -static char eof_message[] = "Unexpected end of file on input\n"; - -static char *pkeywords[] = -{ -"ID", "TYPE", "PROTOCOL", "IOADDR", "INTLEVEL", "SPEED", "CHANNEL", -"BBSFLAG", "QUALITY", "MAXFRAME", "TXDELAY", "SLOTTIME", "PERSIST", -"FULLDUP", "SOFTDCD", "FRACK", "RESPTIME", "RETRIES", -"PACLEN", "CWID", "PORTCALL", "PORTALIAS", "ENDPORT", "VALIDCALLS", -"QUALADJUST", "DIGIFLAG", "DIGIPORT", "USERS" ,"UNPROTO", "PORTNUM", -"TXTAIL", "ALIAS_IS_BBS", "L3ONLY", "KISSOPTIONS", "INTERLOCK", "NODESPACLEN", -"TXPORT", "MHEARD", "CWIDTYPE", "MINQUAL", "MAXDIGIS", "PORTALIAS2", "DLLNAME", -"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"}; /* parameter keywords */ - -static void * poffset[] = -{ -&xxp.ID, &xxp.TYPE, &xxp.PROTOCOL, &xxp.IOADDR, &xxp.INTLEVEL, &xxp.SPEED, &xxp.CHANNEL, -&xxp.BBSFLAG, &xxp.QUALITY, &xxp.MAXFRAME, &xxp.TXDELAY, &xxp.SLOTTIME, &xxp.PERSIST, -&xxp.FULLDUP, &xxp.SOFTDCD, &xxp.FRACK, &xxp.RESPTIME, &xxp.RETRIES, -&xxp.PACLEN, &xxp.CWID, &xxp.PORTCALL, &xxp.PORTALIAS, 0, &xxp.VALIDCALLS, -&xxp.QUALADJUST, &xxp.DIGIFLAG, &xxp.DIGIPORT, &xxp.USERS, &xxp.UNPROTO, &xxp.PORTNUM, -&xxp.TXTAIL, &xxp.ALIAS_IS_BBS, &xxp.L3ONLY, &xxp.KISSOPTIONS, &xxp.INTERLOCK, &xxp.NODESPACLEN, -&xxp.TXPORT, &xxp.MHEARD, &xxp.CWIDTYPE, &xxp.MINQUAL, &xxp.MAXDIGIS, &xxp.PORTALIAS2, &xxp.DLLNAME, -&xxp.BCALL, &xxp.DIGIMASK, &xxp.DefaultNoKeepAlives, &xxp.IOADDR, &xxp.DLLNAME, &xxp.WL2K, &xxp.UIONLY, -&xxp.IOADDR, &xxp.IPADDR, &xxp.INTLEVEL, &xxp.IOADDR, &xxp.IOADDR, &xxp.ListenPort, &xxp.NoNormalize, -&xxp.IGNOREUNLOCKED, &xxp.INP3ONLY, &xxp.TCPPORT, &xxp.RIGPORT, &xxp.PERMITTEDAPPLS, &xxp.Hide, -&xxp.SmartID, &xxp.KissParams, &xxp.SendtoM0LTEMap, &xxp.PortFreq, &xxp.M0LTEMapInfo, &xxp.QtSMPort}; /* offset for corresponding data in config file */ - -static int proutine[] = -{ -4, 5, 8, 3, 1, 1, 7, -6, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 0, 0, 0, 9, 10, -1, 13, 13, 1, 11, 1, -1, 2, 2, 12, 1, 1, -1, 7, 7, 13, 13, 0, 14, -0, 1, 2, 18, 15, 16, 2, -1, 17, 1, 1, 1, 1, 2, -2, 2, 1, 1, 19, 2, -1, 20, 1, 21, 22, 1}; /* routine to process parameter */ - -int PPARAMLIM = sizeof(proutine)/sizeof(int); - -static int endport = 0; -static int portnum = 1; -static int portindex = 0; -static int porterror = 0; -static int tncporterror = 0; -static int dedporterror = 0; -static int kissflags = 0; -static int NextAppl = 0; -static int routeindex = 0; - - -/************************************************************************/ -/* Global variables */ -/************************************************************************/ - -int paramok[100] = {0}; /* PARAMETER OK FLAG */ - -FILE *fp1; /* TEXT INPUT FILE */ - -static char s1[80]; -static char s2[80]; -static char s3[80]; -static char s4[80]; -static char s5[80]; -static char s6[80]; -static char s7[80]; -static char s8[80]; - -char commas[]=",,,,,,,,,,,,,,,,"; - -char bbscall[11]; -char bbsalias[11]; -int bbsqual; - - -extern UCHAR ConfigDirectory[260]; - -BOOL LocSpecified = FALSE; - -/************************************************************************/ -/* MAIN PROGRAM */ -/************************************************************************/ - -VOID WarnThread(); - -int LineNo = 0; - -int heading = 0; - - -BOOL ProcessConfig() -{ - int i; - char rec[MAXLINE]; - int Cfglen = sizeof(xxcfg); - struct APPLCONFIG * App; - - memset(&xxcfg, 0, sizeof(xxcfg)); - memset(&xxp, 0, sizeof(xxp)); - - heading = 0; - portnum = 1; - NextAppl = 0; - LOCATOR[0] = 0; - MAPCOMMENT[0] = 0; - routeindex = 0; - portindex = 0; - - for (i = 0; i < 70; i++) - { - if (PortConfig[i]) - { - free(PortConfig[i]); - PortConfig[i] = NULL; - } - PortDefined[i] = FALSE; - - if (RadioConfigMsg[i]) - { - free(RadioConfigMsg[i]); - RadioConfigMsg[i] = NULL; - } - } - - nextRadioPort = 0; - - TNCCONFIGTABLE = NULL; - NUMBEROFTNCPORTS = 0; - - AGWMask = 0; - - UPNPConfig = NULL; - - Consoleprintf("Configuration file Preprocessor."); - - if (ConfigDirectory[0] == 0) - { - strcpy(inputname, "bpq32.cfg"); - } - else - { - strcpy(inputname,ConfigDirectory); - strcat(inputname,"/"); - strcat(inputname, "bpq32.cfg"); - } - - if ((fp1 = fopen(inputname,"r")) == NULL) - { - Consoleprintf("Could not open file %s Error code %d", inputname, errno); - return FALSE; - } - - Consoleprintf("Using Configuration file %s",inputname); - - memset(&xxcfg, 0, sizeof(xxcfg)); - - App = (struct APPLCONFIG *)&xxcfg.C_APPL[0]; - - for (i=0; i < NumberofAppls; i++) - { - memset(App->Command, ' ', 12); - memset(App->CommandAlias, ' ', 48); - memset(App->ApplCall, ' ', 10); - memset(App->ApplAlias, ' ', 10); - - App++; - } - -// xxcfg.SaveMH = TRUE; // Default to save - - GetNextLine(rec); - - while (rec[0]) - { - decode_rec(rec); - GetNextLine(rec); - } - - if (xxcfg.C_NODECALL[0] == ' ') - { - Consoleprintf("Missing NODECALL"); - heading = 1; - } - - - paramok[6]=1; /* dont need BUFFERS */ - paramok[8]=1; /* dont need TRANSDELAY */ - paramok[13]=1; // NodeAlias - paramok[17]=1; /* dont need TNCPORTS */ - paramok[20]=1; // Or ROUTES - - paramok[32]=1; /* dont need UNPROTO */ - - paramok[35]=1; /* dont need EMS */ - paramok[37]=1; /* dont need DESQVIEW */ - paramok[38]=1; /* dont need HOSTINTERRUPT */ - - paramok[40]=1; /* or DEDHOST */ - - paramok[42]=1; /* or SIMPLE */ - - paramok[43]=1; /* or AUTOSAVE */ - - paramok[44]=1; /* or L4APPL */ - - - paramok[16]=1; // BBSCALL - paramok[14]=1; // BBSALIAS - paramok[33]=1; // BBSQUAL - paramok[34]=1; // APPLICATIONS - - if (paramok[45]==1) - { - paramok[16]=1; // APPL1CALL overrides BBSCALL - memcpy(xxcfg.C_BBSCALL, xxcfg.C_APPL[0].ApplCall, 10); - } - - if (paramok[53]==1) - { - paramok[14]=1; // APPL1ALIAS overrides BBSALIAS - memcpy(xxcfg.C_BBSALIAS, xxcfg.C_APPL[0].ApplAlias, 10); - } - - if (paramok[61]==1) - { - paramok[33]=1; // APPL1QUAL overrides BBSQUAL - xxcfg.C_BBSQUAL = xxcfg.C_APPL[0].ApplQual; - } - - - for (i=0;i<24;i++) - - paramok[45+i]=1; /* or APPLCALLS, APPLALIASS APPLQUAL */ - - paramok[69]=1; // BText optional - paramok[70]=1; // IPGateway optional - paramok[71]=1; // C_IS_CHAT optional - - paramok[72]=1; // MAXRTT optional - paramok[73]=1; // MAXHOPS optional - paramok[74]=1; // LogL4Connects optional - paramok[75]=1; // LogAllConnects optional - paramok[76]=1; // SAVEMH optional - paramok[77]=1; // ENABLEADIFLOG optional - paramok[78]=1; // EnableEvents optional - paramok[79]=1; // SaveAPRSMsgs optional - paramok[79]=1; // SaveAPRSMsgs optional - paramok[80]=1; // EnableM0LTEMap optional - paramok[81]=1; // MQTT Params - paramok[82]=1; // MQTT Params - 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 - paramok[89]=1; // L2Compress - paramok[90]=1; // L2Compress Maxframe - paramok[91]=1; // L2Compress Paclen - - - for (i=0; i < PARAMLIM; i++) - { - if (paramok[i] == 0) - { - if (heading == 0) - { - Consoleprintf(" "); - Consoleprintf("The following parameters were not correctly specified"); - heading = 1; - } - Consoleprintf(keywords[i]); - } - } - - if (portnum == 1) - { - Consoleprintf("No valid radio ports defined"); - heading = 1; - } - - if (Comment) - { - Consoleprintf("Unterminated Comment (Missing */) at line %d", CommentLine); - heading = 1; - } - - fclose(fp1); - - if (LOCATOR[0] == 0 && LocSpecified == 0 && RFOnly == 0) - { - Consoleprintf(""); - 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(""); - -// _beginthread(WarnThread, 0, 0); - } - - if (heading == 0) - { - Consoleprintf("Conversion (probably) successful"); - Consoleprintf(""); - } - else - { - Consoleprintf("Conversion failed"); - return FALSE; - } - -/* - // Dump to file for debugging - - sprintf_s(inputname, sizeof(inputname), "CFG%d", time(NULL)); - - fp1 = fopen(inputname, "wb"); - - if (fp1) - { - fwrite(ConfigBuffer, 1, 100000, fp1); - fclose(fp1); - } -*/ - return TRUE; -} - -/************************************************************************/ -/* Decode PARAM= */ -/************************************************************************/ - -int decode_rec(char * rec) -{ - int i; - int cn = 1; /* RETURN CODE FROM ROUTINES */ - - char key_word[300] = ""; - char value[300] = ""; - - if (_memicmp(rec, "NODEMAPSERVER=", 14) == 0) - { - // Map reporting override - - strcpy(NodeMapServer, &rec[14]); - strlop(NodeMapServer, ' '); - - return 1; - } - - if (_memicmp(rec, "CloseOnError=", 13) == 0) - { - // Close BPQ on trapped program error - - CloseOnError = atoi(&rec[13]); - return 1; - } - - if (_memicmp(rec, "CHATMAPSERVER=", 14) == 0) - { - // Map reporting override - - strcpy(ChatMapServer, &rec[14]); - strlop(ChatMapServer, ' '); - - return 1; - } - - if (_memicmp(rec, "IPGATEWAY", 9) == 0 && rec[9] != '=') // IPGATEWAY, not IPGATEWAY= - { - // Create Embedded IPGateway Config - - // Copy all subsequent lines up to **** to a memory buffer - - char * ptr; - - PortConfig[IPConfigSlot] = ptr = malloc(50000); - - *ptr = 0; - - GetNextLine(rec); - - while (!feof(fp1)) - { - if (_memicmp(rec, "****", 3) == 0) - { - PortConfig[IPConfigSlot] = realloc(PortConfig[IPConfigSlot], (strlen(ptr) + 1)); - xxcfg.C_IP = 1; - return 0; - } - - strcat(ptr, rec); - strcat(ptr, "\r\n"); - GetNextLine(rec); - } - - Consoleprintf("Missing **** for IPGateway Config"); - heading = 1; - - return 0; - } - - if (_memicmp(rec, "PORTMAPPER", 10) == 0) - { - // Create Embedded portmapper Config - - // Copy all subsequent lines up to **** to a memory buffer - - char * ptr; - - PortConfig[PortMapConfigSlot] = ptr = malloc(50000); - - *ptr = 0; - - GetNextLine(rec); - - while (!feof(fp1)) - { - if (_memicmp(rec, "****", 3) == 0) - { - PortConfig[PortMapConfigSlot] = realloc(PortConfig[PortMapConfigSlot], (strlen(ptr) + 1)); - xxcfg.C_PM = 1; - return 0; - } - - strcat(ptr, rec); - strcat(ptr, "\r\n"); - GetNextLine(rec); - } - - Consoleprintf("Missing **** for Portmapper Config"); - heading = 1; - - return 0; - } - - if (_memicmp(rec, "APRSDIGI", 8) == 0) - { - // Create Embedded APRS Config - - // Copy all subsequent lines up to **** to a memory buffer - - char * ptr; - - PortConfig[APRSConfigSlot] = ptr = malloc(50000); - - *ptr = 0; - - // Don't use GetNextLine - we need to keep ; in messages - - fgets(rec,MAXLINE,fp1); - LineNo++; - - while (!feof(fp1)) - { - if (_memicmp(rec, "****", 3) == 0) - { - PortConfig[APRSConfigSlot] = realloc(PortConfig[APRSConfigSlot], (strlen(ptr) + 1)); - return 0; - } - if (strlen(rec) > 1) - { - if (memcmp(rec, "/*", 2) == 0) - { - Comment = TRUE; - CommentLine = LineNo; - goto NextAPRS; - } - else if (memcmp(rec, "*/", 2) == 0) - { - Comment = FALSE; - goto NextAPRS; - } - } - - if (Comment) - goto NextAPRS; - - strcat(ptr, rec); - strcat(ptr, "\r\n"); -NextAPRS: - fgets(rec,MAXLINE,fp1); - LineNo++; - } - - if (_memicmp(rec, "****", 3) == 0) - return 0; // No Newline after *** - - Consoleprintf("Missing **** for APRS Config"); - heading = 1; - - return 0; - } - - if (_memicmp(rec, "PASSWORD", 8) == 0) - { - // SYSOP Password - - if (strlen(rec) > 88) rec[88] = 0; - - _strupr(rec); - - strcpy(PWTEXT, &rec[9]); - return 0; - } - -#ifdef LINBPQ - - if (_memicmp(rec, "LINMAIL", 7) == 0) - { - // Enable Mail on Linux Verdion - - IncludesMail = TRUE; - - return 0; - } - - if (_memicmp(rec, "LINCHAT", 7) == 0) - { - // Enable Chat on Linux Verdion - - IncludesChat = TRUE; - - return 0; - } -#endif - - if (_memicmp(rec, "ENABLEAIS", 9) == 0) - { - needAIS = TRUE; - return 0; - } - - if (_memicmp(rec, "ENABLEADSB", 9) == 0) - { - needADSB = TRUE; - return 0; - } - - if (_memicmp(rec, "HFCTEXT", 7) == 0) - { - // HF only CTEXT (normlly short to reduce traffic) - - if (strlen(rec) > 87) rec[87] = 0; - strcpy(HFCTEXT, &rec[8]); - HFCTEXTLEN = (int)(strlen(HFCTEXT)); - HFCTEXT[HFCTEXTLEN - 1] = '\r'; - return 0; - } - - if (_memicmp(rec, "LOCATOR", 7) == 0) - { - // Station Maidenhead Locator or Lat/Long - - char * Context; - char * ptr1 = strtok_s(&rec[7], " ,=\t\n\r:", &Context); - char * ptr2 = strtok_s(NULL, " ,=\t\n\r:", &Context); - - LocSpecified = TRUE; - - if (_memicmp(&rec[8], "NONE", 4) == 0) - return 0; - - if (_memicmp(&rec[8], "XXnnXX", 6) == 0) - return 0; - - if (ptr1) - { - strcpy(LOCATOR, ptr1); - if (ptr2) - { - strcat(LOCATOR, ":"); - strcat(LOCATOR, ptr2); - ToLOC(atof(ptr1), atof(ptr2), LOC); - LatFromLOC = atof(ptr1); - LonFromLOC = atof(ptr2); - - } - else - { - if (strlen(ptr1) == 6) - { - strcpy(LOC, ptr1); - FromLOC(LOC, &LatFromLOC, &LonFromLOC); - // Randomise in square - LatFromLOC += ((rand() / 24.0) / RAND_MAX); - LonFromLOC += ((rand() / 12.0) / RAND_MAX); - - } - } - } - return 0; - } - - if (_memicmp(rec, "MAPCOMMENT", 10) == 0) - { - // Additional Info for Node Map - - char * ptr1 = &rec[11]; - char * ptr2 = MAPCOMMENT; - - while (*ptr1) - { - if (*ptr1 == ',') - { - *ptr2++ = '&'; - *ptr2++ = '#'; - *ptr2++ = '4'; - *ptr2++ = '4'; - *ptr2++ = ';'; - } - else - *(ptr2++) = *ptr1; - - ptr1++; - - if ((ptr2 - MAPCOMMENT) > 248) - break; - } - - *ptr2 = 0; - - return 0; - } - - // Process BRIDGE statement - - if (_memicmp(rec, "BRIDGE", 6) == 0) - { - int DigiTo; - int Port; - char * Context; - char * p_value; - char * ptr; - - p_value = strtok_s(&rec[7], ",=\t\n\r", &Context); - - Port = atoi(p_value); - - if (Port > MaxBPQPortNo) - return FALSE; - - if (Context == NULL) - return FALSE; - - ptr = strtok_s(NULL, ",\t\n\r", &Context); - - while (ptr) - { - DigiTo = atoi(ptr); - - if (DigiTo > MaxBPQPortNo) - return 0; - - if (Port != DigiTo) // Not to our port! - xxcfg.CfgBridgeMap[Port][DigiTo] = TRUE; - - ptr = strtok_s(NULL, " ,\t\n\r", &Context); - } - - return 0; - } - - - // AGW Emulator Params - - if (_memicmp(rec, "AGWPORT", 7) == 0) - { - AGWPort = atoi(&rec[8]); - return 0; - } - - if (_memicmp(rec, "AGWSESSIONS", 11) == 0) - { - AGWSessions = atoi(&rec[12]); - return 0; - } - - if (_memicmp(rec, "AGWMASK", 7) == 0) - { - AGWMask = strtol(&rec[8], 0, 0); - return 0; - } - - if (_memicmp(rec, "AGWAPPL", 7) == 0) - { - AGWMask |= 1 << (strtol(&rec[8], 0, 0) - 1); - return 0; - } - - if (_memicmp(rec, "AGWLOOPMON", 10) == 0) - { - LoopMonFlag = strtol(&rec[11], 0, 0); - return 0; - } - if (_memicmp(rec, "AGWLOOPTX", 9) == 0) - { - Loopflag = strtol(&rec[10], 0, 0); - return 0; - } - - if (_memicmp(rec, "APPLICATION ", 12) == 0 || _memicmp(rec, "APPLICATION=", 12) == 0) - { - // New Style APPLICATION Definition - - char save[300]; - - strcpy(save, rec); // Save in case error - - if (!ProcessAPPLDef(&rec[12])) - { - Consoleprintf("Invalid Record %s", save); - heading = 1; - } - else - paramok[34]=1; // Got APPLICATIONS - - return 0; - } - - if (_memicmp(rec, "EXCLUDE=", 8) == 0) - { - char * ptr2 = &rec[8]; - UCHAR * ptr3 = xxcfg.C_EXCLUDE; - - _strupr(ptr2); - while (*(ptr2) > 32) - { - ConvToAX25(ptr2, ptr3); - ptr3 += 7; - - if (strchr(ptr2, ',')) - { - ptr2 = strchr(ptr2, ','); - ptr2++; - } - else - break; - - if (ptr3 > &xxcfg.C_EXCLUDE[63]) - { - Consoleprintf("Too Many Excluded Calls"); - heading = 1; - break; - } - } - - return 0; - } - if (_memicmp(rec, "RADIO", 5) == 0) - { - if (strlen(rec) > 11) - { - RadioConfigMsg[nextRadioPort++] = _strdup(rec); - return 0; - } - else - { - // Multiline config, ending in **** - - char * rptr; - - RadioConfigMsg[nextRadioPort] = rptr = zalloc(50000); - - strcpy(rptr, rec); - - GetNextLine(rec); - - while(!feof(fp1)) - { - if (memcmp(rec, "***", 3) == 0) - { - RadioConfigMsg[nextRadioPort] = realloc(RadioConfigMsg[nextRadioPort], (strlen(rptr) + 1)); - nextRadioPort++; - return 0; - } - strcat(rptr, rec); - GetNextLine(rec); - } - } - } - - if (_memicmp(rec, "UPNP ", 5) == 0) - { - struct UPNP * Entry = (struct UPNP *)zalloc(sizeof(struct UPNP)); - char * ptr, * context; - char copy[256]; - - strcpy(copy, rec); - - ptr = strtok_s(&rec[5], ", ", &context); - - if (ptr) - Entry->Protocol = _strdup(ptr); - - ptr = strtok_s(NULL, ", ", &context); - - if (ptr) - Entry->LANport = Entry->WANPort = _strdup(ptr);; - - ptr = strtok_s(NULL, ", ", &context); - - if (ptr) - Entry->WANPort = _strdup(ptr);; - - if (Entry->LANport) - { - Entry->Next = UPNPConfig; - UPNPConfig = Entry; - return 1; - } - - Consoleprintf("Bad UPNP Line %s", copy); - heading = 1; - - return 0; - } - - - if (_memicmp("MQTT_HOST=", rec, 10) == 0) - { - strcpy(xxcfg.C_MQTT_HOST, &rec[10]); - xxcfg.C_MQTT_HOST[strlen(xxcfg.C_MQTT_HOST)-1] = '\0'; - return 0; - } - if (_memicmp("MQTT_USER=", rec, 10) == 0) - { - strcpy(xxcfg.C_MQTT_USER, &rec[10]); - xxcfg.C_MQTT_USER[strlen(xxcfg.C_MQTT_USER)-1] = '\0'; - return 0; - } - if (_memicmp("MQTT_PASS=", rec, 10) == 0) - { - strcpy(xxcfg.C_MQTT_PASS, &rec[10]); - xxcfg.C_MQTT_PASS[strlen(xxcfg.C_MQTT_PASS)-1] = '\0'; - return 0; -} - - - if (xindex(rec,"=") >= 0) - sscanf(rec,"%[^=]=%s",key_word,value); - else - sscanf(rec,"%s",key_word); - -/************************************************************************/ -/* SEARCH FOR KEYWORD IN TABLE */ -/************************************************************************/ - - for (i=0; i < PARAMLIM && _stricmp(keywords[i],key_word) != 0 ; i++) - ; - - if (i == PARAMLIM) - Consoleprintf("bpq32.cfg line no %d not recognised - Ignored: %s" ,LineNo, rec); - else - { - - switch (routine[i]) - { - case 0: - cn = callsign((char *)offset[i], value, rec); /* CALLSIGNS */ - break; - - case 1: - cn = int_value((short *)offset[i], value, rec); /* INTEGER VALUES */ - break; - - case 2: - cn = bin_switch((char *)offset[i], value, rec); /* 0/1 SWITCHES */ - break; - - case 3: - cn = tncports(i); /* VIRTUAL COMBIOS PORTS */ - break; - - case 4: - cn = dotext((char *)offset[i], key_word, 510); /* TEXT PARMS */ - break; - - case 20: - cn = dotext((char *)offset[i], key_word, 2000); /* INFO TEXT PARM */ - break; - - case 5: - cn = routes(i); /* ROUTES TO LOCK IN */ - break; - - case 6: - cn = ports(i); /* PORTS DEFINITION */ - break; - - case 7: - Consoleprintf("Obsolete Record %s ignored",rec); - Consoleprintf("UNPROTO address should now be specified in PORT definition"); - - break; - - case 8: - cn = applstrings(i,value,rec); /* APPLICATIONS LIST */ - break; - - case 9: - cn = dec_switch((char *)offset[i],value,rec); /* 0/9 SWITCHES */ - break; - - case 10: - cn = dolinked(i,value,rec); /* SINGLE CHAR */ - break; - - case 11: - Consoleprintf("Obsolete Record %s ignored", rec); - break; - - case 12: - cn = simple(i); /* Set up basic L2 system*/ - break; - - case 13: - cn = applcallsign(i,value,rec); /* CALLSIGNS */ - break; - - case 14: - cn = appl_qual(i,value,rec); /* INTEGER VALUES */ - break; - - case 15: - cn = dotext((char *)offset[i], key_word, 120); /* BTEXT */ - break; - } - - paramok[i] = cn; - } - - return 0; -} - -/************************************************************************/ -/* CALLSIGNS */ -/************************************************************************/ -int applcallsign(int i, char * value, char * rec) -{ - char * val = (char *)offset[i]; - - if (call_check_internal(value)) - { - // Invalid - - return 0; - } - - memcpy(val, value, 10); - - if (i==45) - strcpy(bbscall,value); - if (i==53) - strcpy(bbsalias,value); - - return 1; -} - -int appl_qual(int i, char * value, char * rec) -{ - int j, k; - int * val = (int *)offset[i]; - - k = sscanf(value," %d",&j); - - if (k != 1) - { - Consoleprintf("Invalid numerical value "); - Consoleprintf("%s\r\n",rec); - return(0); - } - - if (i==61) bbsqual=j; - - *val = j; - return(1); -} - - -int callsign(char * ptr, char * value, char * rec) -{ - if (call_check(value, ptr) == 1) - { - Consoleprintf("%s",rec); - return(0); - } - - return(1); -} - - -/************************************************************************/ -/* VALIDATE INT VALUES */ -/************************************************************************/ - -int int_value(short * val, char value[], char rec[]) -{ - int j,k; - - k = sscanf(value," %d",&j); - - if (k != 1) - { - Consoleprintf("Invalid numerical value "); - Consoleprintf("%s\r\n",rec); - return(0); - } - - val[0] = j; - return(1); -} - -int64_t int64_value(int64_t * val, char value[], char rec[]) -{ - *val = strtoll(value, NULL, 10); - return(1); -} - -/************************************************************************/ -/* VALIDATE HEX INT VALUES */ -/************************************************************************/ - -int hex_value(int * val, char value[], char rec[]) -{ - int j = -1, k = 0; - - k = sscanf(value, " %xH", &j); - - if (j < 0) - { - Consoleprintf("Bad Hex Value"); - Consoleprintf("%s\r\n", rec); - return(0); - } - - val[0] = j; - return(1); -} -; - -/************************************************************************/ -/* VALIDATE BINARY SWITCH DATA AND WRITE TO FILE */ -/************************************************************************/ - -int bin_switch(char * val, char * value, char * rec) -{ - int value_int; - - value_int = atoi(value); - - if (value_int == 0 || value_int == 1) - { - val[0] = value_int; - return 1; - } - else - { - Consoleprintf("Invalid switch value, must be either 0 or 1"); - Consoleprintf("%s\r\n",rec); - return(0); - } -} -/* -; single byte decimal -*/ -int dec_switch (char * val, char * value, char * rec) -{ - int value_int; - - value_int = atoi(value); - - if (value_int < 256) - { - val[0] = value_int; - return 1; - } - else - { - Consoleprintf("Invalid value, must be between 0 and 255"); - Consoleprintf("%s\r\n",rec); - return(0); - } -} - - -int applstrings(int i, char * value, char * rec) -{ - char appl[250]; // In case trailing spaces - char * ptr1; - char * ptr2; - struct APPLCONFIG * App; - int j; - - // strcat(rec,commas); // Ensure 16 commas - - ptr1 = &rec[13]; // skip APPLICATIONS= - - App = &xxcfg.C_APPL[0]; - - while (NextAppl++ < NumberofAppls) - { - memset(appl, ' ', 249); - appl[249] = 0; - - ptr2=appl; - - j = *ptr1++; - - while (j != ',' && j) - { - *(ptr2++) = toupper(j); - j = *ptr1++; - } - - ptr2 = strchr(appl, '/'); - - if (ptr2) - { - // Command has an Alias - - *ptr2++ = 0; - memcpy(App->CommandAlias, ptr2, 48); - strcat(appl, " "); - } - - memcpy(App->Command, appl, 12); - xxcfg.C_BBS = 1; - - if (*(ptr1 - 1) == 0) - return 1; - - App++; - } - return(1); -} - - -/************************************************************************/ -/* USE FOR FREE FORM TEXT IN MESSAGES */ -/************************************************************************/ - -int dotext(char * val, char * key_word, int max) -{ - int len = 0; - char * ptr; - - char rec[MAXLINE]; - - GetNextLine(rec); - - if (xindex(rec,"***") == 0) - *val = '\r'; - - while (xindex(rec,"***") != 0 && !feof(fp1)) - { - ptr = strchr(rec, 10); - if (ptr) *ptr = 0; - ptr = strchr(rec, 13); - if (ptr) *ptr = 0; - - strcat(rec, "\r"); - - len += (int)strlen(rec); - - if (len <= max) - { - strcpy(val, rec); - val += (int)strlen(rec); - } - - fgets(rec,MAXLINE,fp1); - LineNo++; - } - - if (len > max) - { - Consoleprintf("Text too long: %s (max %d\r\n",key_word, max); - return(0); - } - - if (feof(fp1)) - return(0); - else - return(1); -} - - -/************************************************************************/ -/* CONVERT PRE-SET ROUTES PARAMETERS TO BINARY */ -/************************************************************************/ - -int routes(int i) -{ - struct ROUTECONFIG * Route; - - int err_flag = 0; - int main_err = 0; - - char rec[MAXLINE]; - - - GetNextLine(rec); - - while (xindex(rec,"***") != 0 && !feof(fp1)) - { - char Param[8][256]; - char * ptr1, * ptr2; - int n = 0, inp3 = 0; - - Route = &xxcfg.C_ROUTE[routeindex++]; - - // strtok and sscanf can't handle successive commas, so split up usig strchr - - memset(Param, 0, 2048); - strlop(rec, 13); - strlop(rec, ';'); - - ptr1 = rec; - - while (ptr1 && *ptr1 && n < 8) - { - ptr2 = strchr(ptr1, ','); - if (ptr2) *ptr2++ = 0; - - strcpy(&Param[n++][0], ptr1); - ptr1 = ptr2; - while(ptr1 && *ptr1 && *ptr1 == ' ') - ptr1++; - } - - strcpy(Route->call, &Param[0][0]); - - Route->quality = atoi(Param[1]); - Route->port = atoi(Param[2]); - Route->pwind = atoi(Param[3]); - Route->pfrack = atoi(Param[4]); - Route->ppacl = atoi(Param[5]); - inp3 = atoi(Param[6]); - Route->farQual = atoi(Param[7]); - - if (Route->farQual < 0 || Route->farQual > 255) - { - Consoleprintf("Remote Quality must be between 0 and 255"); - Consoleprintf("%s\r\n",rec); - - err_flag = 1; - } - - if (Route->quality < 0 || Route->quality > 255) - { - Consoleprintf("Quality must be between 0 and 255"); - Consoleprintf("%s\r\n",rec); - - err_flag = 1; - } - - if (Route->port < 1 || Route->port > MaxBPQPortNo) - { - Consoleprintf("Port number must be between 1 and 64"); - Consoleprintf("%s\r\n",rec); - err_flag = 1; - } - - // Use top bit of window as INP3 Flag, next as NoKeepAlive - - if (inp3 & 1) - Route->pwind |= 0x80; - - if (inp3 & 2) - Route->pwind |= 0x40; - - if (err_flag == 1) - { - Consoleprintf("%s\r\n",rec); - main_err = 1; - err_flag = 0; - } - GetNextLine(rec); - } - - if (routeindex > MaxLockedRoutes) - { - routeindex--; - Consoleprintf("Route information too long "); - main_err = 1; - } - - if (feof(fp1)) - { - Consoleprintf(eof_message); - return(0); - } - - if (main_err == 1) - return(0); - else - return(1); -} - - -/************************************************************************/ -/* CONVERT PORT DEFINITIONS TO BINARY */ -/************************************************************************/ -int hw; // Hardware type -int LogicalPortNum; // As set by PORTNUM - -int ports(int i) -{ - char rec[MAXLINE]; - endport=0; - porterror=0; - kissflags=0; - - xxp.PORTNUM = portnum; - - LogicalPortNum = portnum; - - if (LogicalPortNum > MaxBPQPortNo) - { - Consoleprintf("Port Number must be between 1 and %d", MaxBPQPortNo); - heading = 1; - } - - xxp.SendtoM0LTEMap = 1; // Default to enabled - - while (endport == 0 && !feof(fp1)) - { - GetNextLine(rec); - decode_port_rec(rec); - } - if (porterror != 0) - { - Consoleprintf("Error in port definition"); - return(0); - } - - if (PortDefined[LogicalPortNum]) // Already defined? - { - Consoleprintf("Port %d already defined", LogicalPortNum); - heading = 1; - } - - PortDefined[LogicalPortNum] = TRUE; - - xxp.KISSOPTIONS = kissflags; - - // copy Port Config to main config - - memcpy(&xxcfg.C_PORT[portindex++], &xxp, sizeof(xxp)); - memset(&xxp, 0, sizeof(xxp)); - - portnum++; - - return(1); - -} - - -int tncports(int i) -{ - char rec[MAXLINE]; - endport=0; - tncporterror=0; - - TNC2ENTRY = zalloc(sizeof(struct TNCDATA)); - - TNC2ENTRY->APPLFLAGS = 6; - TNC2ENTRY->PollDelay = 1; - - while (endport == 0 && !feof(fp1)) - { - GetNextLine(rec); - decode_tnc_rec(rec); - } - if (tncporterror != 0) - { - Consoleprintf("Error in TNC PORT definition"); - free (TNC2ENTRY); - return(0); - } - - C_Q_ADD_NP(&TNCCONFIGTABLE, TNC2ENTRY); // Add to chain - - NUMBEROFTNCPORTS++; - - return(1); - - -} - - -/************************************************************************/ -/* MISC FUNCTIONS */ -/************************************************************************/ - -/************************************************************************/ -/* FIND OCCURENCE OF ONE STRING WITHIN ANOTHER */ -/************************************************************************/ - -int xindex(char s[], char t[]) -{ - int i, j ,k; - - for (i=0; s[i] != '\0'; i++) - { - for (j=i, k=0; t[k] != '\0' && s[i] == t[k]; j++, k++) - ; - if (t[k] == '\0') - return(i); - } - return(-1); -} - - -/************************************************************************/ -/* FIND FIRST OCCURENCE OF A CHARACTER THAT IS NOT c */ -/************************************************************************/ - -int verify(char s[], char c) -{ - int i; - - for (i = 0; s[i] != '\0'; i++) - if (s[i] != c) - return(i); - - return(-1); -} - -/************************************************************************/ -/* GET NEXT LINE THAT ISN'T BLANK OR IS A COMMENT LINE */ -/************************************************************************/ - -// Returns an empty string to indicate end of config - -// Modified Aril 2020 to allow #include of file fragments - -FILE * savefp = NULL; -int saveLineNo; -char includefilename[250]; - -int GetNextLine(char *rec) -{ - int i, j; - char * ret; - char * ptr, *context; - - while (TRUE) - { - ret = fgets(rec,MAXLINE,fp1); - LineNo++; - - if (ret == NULL) - { - if (savefp) - { - // we have reached eof on an include file - switch back - - fclose(fp1); - fp1 = savefp; - savefp = NULL; - LineNo = saveLineNo; - continue; - } - - rec[0] = 0; - return 0; // return end of config - } - - for (i=0; rec[i] != '\0'; i++) - if (rec[i] == '\t' || rec[i] == '\n' || rec[i] == '\r') - rec[i] = ' '; - - - - j = verify(rec,' '); - - if (j > 0) - { - // Remove Leading Spaces - - for (i=0; rec[j] != '\0'; i++, j++) - rec[i] = rec[j]; - - rec[i] = '\0'; - } - - if (stristr(rec,"WebTermCSS") == 0 && stristr(rec,"HybridCoLocatedRMS") == 0 && stristr(rec,"HybridFrequencies") == 0) // Needs ; in string - strlop(rec, ';'); - else - j = j; - - if (strlen(rec) > 1) - if (memcmp(rec, "/*",2) == 0) - { - Comment = TRUE; - CommentLine = LineNo; - } - else - if (memcmp(rec, "*/",2) == 0) - { - rec[0] = 32; - rec[1] = 0; - Comment = FALSE; - } - - if (Comment) - { - rec[0] = 32; - rec[1] = 0; - continue; - } - - // remove trailing spaces - - while(strlen(rec) && rec[strlen(rec) - 1] == ' ') - rec[strlen(rec) - 1] = 0; - - strcat(rec, " "); - - ptr = strtok_s(rec, " ", &context); - - // Put one back - - if (ptr) - { - if (context) - { - ptr[strlen(ptr)] = ' '; - } - rec = ptr; - - // look for #include - - if (_memicmp(rec, "#include ", 9) == 0) - { - savefp = fp1; - - if (BPQDirectory[0] == 0) - { - strcpy(includefilename, &rec[9]); - } - else - { - strcpy(includefilename,BPQDirectory); - strcat(includefilename,"/"); - strcat(includefilename, &rec[9]); - } - - if ((fp1 = fopen(includefilename,"r")) == NULL) - { - Consoleprintf("Could not open #include file %s Error code %d", includefilename, errno); - fp1 = savefp; - savefp = NULL; - } - else - { - saveLineNo = LineNo; - LineNo = 0; - } - continue; // get next line - } - return 0; - } - } - - // Should never reach this - - return 0; -} - - -/************************************************************************/ -/* TEST VALIDITY OF CALLSIGN */ -/************************************************************************/ - -int call_check_internal(char * callsign) -{ - char call[20]; - int ssid; - int err_flag = 0; - int i; - - if (xindex(callsign,"-") > 0) /* There is an SSID field */ - { - sscanf(callsign,"%[^-]-%d",call,&ssid); - if (strlen(call) > 6) - { - Consoleprintf("Callsign too long, 6 characters before SSID"); - Consoleprintf("%s\r\n",callsign); - err_flag = 1; - } - if (ssid < 0 || ssid > 15) - { - Consoleprintf("SSID out of range, must be between 0 and 15"); - Consoleprintf("%s\r\n",callsign); - err_flag = 1; - } - } - else /* No SSID field */ - { - if (strlen(callsign) > 6) - { - Consoleprintf("Callsign too long, 6 characters maximum"); - Consoleprintf("%s\r\n",callsign); - err_flag = 1; - } - } - - strcat(callsign," "); - callsign[10] = '\0'; - for (i=0; i< 10; i++) - callsign[i]=toupper(callsign[i]); - - return(err_flag); -} - -int call_check(char * callsign, char * loc) -{ - int err = call_check_internal(callsign); - memcpy(loc, callsign, 10); - return err; -} - - -/* Process UNPROTO string allowing VIA */ - -char workstring[80]; - -int callstring(int i, char * value, char * rec) -{ - char * val = (char *)poffset[i]; - size_t j = (int)strlen(value); - - memcpy(val, value, j); - return 1; -} - -/* - RADIO PORT PROCESSING -*/ - - -int decode_port_rec(char * rec) -{ - int i; - int cn = 1; /* RETURN CODE FROM ROUTINES */ - uint32_t IPADDR; -#ifdef WIN32 - WSADATA WsaData; // receives data from WSAStartupproblem -#endif - char key_word[30]=""; - char value[300]=""; - - if (_memicmp(rec, "CONFIG", 6) == 0) - { - // Create Embedded PORT Config - - // Copy all subseuent lines up to ENDPORT to a memory buffer - - char * ptr; - int i; - - if (LogicalPortNum > 64) - { - Consoleprintf("Portnum %d is invalid", LogicalPortNum); - LogicalPortNum = 0; - } - - PortConfig[LogicalPortNum] = ptr = malloc(50000); - *ptr = 0; - - GetNextLine(rec); - - while (!feof(fp1)) - { - if (_memicmp(rec, "ENDPORT", 7) == 0) - { - PortConfig[LogicalPortNum] = realloc(PortConfig[LogicalPortNum], (strlen(ptr) + 1)); - endport = 1; - return 0; - } - - i = (int)strlen(rec); - i--; - - while(i > 1) - { - if (rec[i] == ' ') - rec[i] = 0; // Remove trailing spaces - else - break; - - i--; - } - - // Pick out RIGCONFIG Records - - if (_memicmp(rec, "RIGCONTROL", 10) == 0) - { - // RIGCONTROL COM60 19200 ICOM IC706 5e 4 14.103/U1w 14.112/u1 18.1/U1n 10.12/l1 - - // Convert to new format (RADIO Interlockno); - - int Interlock = xxp.INTERLOCK; - char radio[16]; - - if (Interlock == 0) // Replace with dummy - { - Interlock = xxp.INTERLOCK = nextDummyInterlock; - nextDummyInterlock++; - } - - sprintf(radio, "RADIO %d ", Interlock); - memcpy(rec, radio, 10); - - if (strlen(rec) > 15) - { - RadioConfigMsg[nextRadioPort++] = _strdup(rec); - } - else - { - // Multiline config, ending in **** - - char * rptr; - - RadioConfigMsg[nextRadioPort] = rptr = zalloc(50000); - - strcpy(rptr, radio); - - GetNextLine(rec); - - while(!feof(fp1)) - { - if (memcmp(rec, "***", 3) == 0) - { - RadioConfigMsg[nextRadioPort] = realloc(RadioConfigMsg[nextRadioPort], (strlen(rptr) + 1)); - nextRadioPort++; - break; - } - strcat(rptr, rec); - GetNextLine(rec); - } - } - } - else - { - strcat(ptr, rec); - strcat(ptr, "\r\n"); - } - GetNextLine(rec); - } - - Consoleprintf("Missing ENDPORT for Port %d", portnum); - heading = 1; - - return 0; - } - - if (xindex(rec,"=") >= 0) - sscanf(rec,"%[^=]=%s",key_word,value); - else - sscanf(rec,"%s",key_word); - - if (_stricmp(key_word, "portnum") == 0) - { - // Save as LogicalPortNum - - LogicalPortNum = atoi(value); - } - - if (_stricmp(key_word, "XDIGI") == 0) - { - // Cross Port Digi definition - - // XDIGI=CALL,PORT,UI - - struct XDIGI * Digi = zalloc(sizeof(struct XDIGI)); // Chain - char * call, * pport, * Context; - - call = strtok_s(value, ",", &Context); - pport = strtok_s(NULL, ",", &Context); - - if (call && pport && ConvToAX25(call, Digi->Call)) - { - Digi->Port = atoi(pport); - if (Digi->Port) - { - if (Context) - { - _strupr(Context); - if (strstr(Context, "UI")) - Digi->UIOnly = TRUE; - } - - // Add to chain - - if (xxp.XDIGIS) - Digi->Next = xxp.XDIGIS; - - xxp.XDIGIS = Digi; - return 0; - } - } - Consoleprintf("Invalid XDIGI Statement %s", rec); - porterror = 1; - return 0; - } - - -/************************************************************************/ -/* SEARCH FOR KEYWORD IN TABLE */ -/************************************************************************/ - - for (i=0; i < PPARAMLIM && _stricmp(pkeywords[i],key_word) != 0 ; i++) - ; - - if (i == PPARAMLIM) - Consoleprintf("Source record not recognised - Ignored:%s\r\n",rec); - else - { - - switch (proutine[i]) - { - - case 0: - cn = callsign((char *)poffset[i], value, rec); /* CALLSIGNS */ - break; - - case 1: - cn = int_value((short *)poffset[i], value, rec); /* INTEGER VALUES */ - break; - - case 2: - cn = bin_switch((char *)poffset[i], value, rec); /* 0/1 SWITCHES */ - break; - - case 3: - cn = hex_value((int *)poffset[i], value, rec); /* HEX NUMBERS */ - break; - - case 4: - cn = doid(i,value,rec); /* ID PARMS */ - break; - - case 5: - cn = hwtypes(i,value,rec); /* HARDWARE TYPES */ - break; - - case 6: - cn = bbsflag(i,value,rec); - break; - - case 7: - cn = channel(i,value,rec); - break; - - case 8: - cn = protocols(i,value,rec); - break; - - case 10: - cn = validcalls(i,value,rec); - break; - - case 11: - cn = callstring(i,value,rec); - break; - - case 12: - cn = kissoptions(i,value,rec); - break; - - case 13: - cn = dec_switch((char *)poffset[i], value, rec); /* 0/9 SWITCHES */ - break; - - case 14: - cn = dodll(i,value,rec); /* DLL PARMS */ - break; - - case 15: - cn = doDriver(i,value,rec); /* DLL PARMS */ - break; - - case 16: - - xxp.WL2K = DecodeWL2KReportLine(rec); - break; - - case 17: - - // IP Address for KISS over UDP - -#ifdef WIN32 - WSAStartup(MAKEWORD(2, 0), &WsaData); -#endif - IPADDR = inet_addr(&rec[7]); - memcpy(&xxp.IPADDR, &IPADDR, 4); -#ifdef WIN32 - WSACleanup(); -#endif - break; - - case 18: - cn = doSerialPortName(i,value,rec); // COMPORT - break; - - case 19: - cn = doPermittedAppls(i,value,rec); // Permitted Apps - break; - - case 20: - cn = doKissCommand(i, value, rec); // Permitted Apps - break; - - case 21: - cn = int64_value(poffset[i], value, rec); /* INTEGER VALUES */ - break; - - case 22: - xxp.M0LTEMapInfo = _strdup(value); - cn = 1; - break; - - case 9: - - cn = 1; - endport=1; - - break; - } - } - if (cn == 0) porterror=1; - - return 0; -} - - -int doid(int i, char value[], char rec[]) -{ - unsigned int j; - for (j = 3;( j < (unsigned int)strlen(rec)+1); j++) - - workstring[j-3] = rec[j]; - - // Remove trailing spaces before checking length - - i = (int)strlen(workstring); - i--; - - while(i > 1) - { - if (workstring[i] == ' ') - workstring[i] = 0; // Remove trailing spaces - else - break; - - i--; - } - - if (i > 29) - { - Consoleprintf("Port description too long - Truncated"); - Consoleprintf("%s\r\n",rec); - } - strcat(workstring," "); - workstring[30] = '\0'; - - memcpy(xxp.ID, workstring, 30); - return(1); -} - -int dodll(int i, char value[], char rec[]) -{ - unsigned int j; - - strlop(rec, ' '); - for (j = 8;( j < (unsigned int)strlen(rec)+1); j++) - workstring[j-8] = rec[j]; - - if (j > 24) - { - Consoleprintf("DLL name too long - Truncated"); - Consoleprintf("%s\r\n",rec); - - } - - _strupr(workstring); - strcat(workstring," "); - - memcpy(xxp.DLLNAME, workstring, 16); - xxp.TYPE = 16; // External - - if (strstr(xxp.DLLNAME, "TELNET") || strstr(xxp.DLLNAME, "AXIP")) - RFOnly = FALSE; - - return(1); -} - -int doDriver(int i, char * value, char * rec) -{ - unsigned int j; - for (j = 7;( j < (unsigned int)strlen(rec)+1); j++) - workstring[j-7] = rec[j]; - - if (j > 23) - { - Consoleprintf("Driver name too long - Truncated"); - Consoleprintf("%s\r\n",rec); - } - - _strupr(workstring); - strcat(workstring," "); - - memcpy(xxp.DLLNAME, workstring, 16); - xxp.TYPE = 16; // External - - // Set some defaults in case HFKISS - - xxp.CHANNEL = 'A'; - xxp.FRACK = 7000; - xxp.RESPTIME = 1000; - xxp.MAXFRAME = 4; - xxp.RETRIES = 6; - - if (strstr(xxp.DLLNAME, "TELNET") || strstr(xxp.DLLNAME, "AXIP")) - RFOnly = FALSE; - - return 1; -} -int IsNumeric(char *str) -{ - while(*str) - { - if(!isdigit(*str)) - return 0; - str++; - } - - return 1; -} - - -int doSerialPortName(int i, char * value, char * rec) -{ - rec += 8; - - if (strlen(rec) > 250) - { - Consoleprintf("Serial Port Name too long - Truncated"); - Consoleprintf("%s\r\n",rec); - rec[250] = 0; - } - - strlop(rec, ' '); - - if (IsNumeric(rec)) - xxp.IOADDR = atoi(rec); - else - xxp.SerialPortName = _strdup(rec); - - return 1; -} - -int doPermittedAppls(int i, char * value, char * rec) -{ - unsigned int Mask = 0; - char * Context; - char * ptr1 = strtok_s(value, " ,=\t\n\r", &Context); - - // Param is a comma separated list of Appl Numbers allowed to connect on this port - - while (ptr1 && ptr1[0]) - { - Mask |= 1 << (atoi(ptr1) - 1); - ptr1 = strtok_s(NULL, " ,=\t\n\r", &Context); - } - - xxp.HavePermittedAppls = 1; // indicate used - xxp.PERMITTEDAPPLS = Mask; - - return 1; -} -int doKissCommand(int i, char * value, char * rec) -{ - // Param is kiss command and any operands as decimal bytes - - xxp.KissParams = _strdup(strlop(rec, '=')); - return 1; -} - - -int hwtypes(int i, char value[], char rec[]) -{ - hw = 255; - if (_stricmp(value,"ASYNC") == 0) - { - // Set some defaults - - xxp.CHANNEL = 'A'; - xxp.FRACK = 7000; - xxp.RESPTIME = 1000; - xxp.MAXFRAME = 4; - xxp.RETRIES = 6; - hw = 0; - } - - if (_stricmp(value,"PC120") == 0) - hw = 2; - if (_stricmp(value,"DRSI") == 0) - hw = 4; - if (_stricmp(value,"DE56") == 0) - hw = 4; - if (_stricmp(value,"TOSH") == 0) - hw = 6; - if (_stricmp(value,"QUAD") == 0) - hw = 8; - if (_stricmp(value,"RLC100") == 0) - hw = 10; - if (_stricmp(value,"RLC400") == 0) - hw = 12; - if (_stricmp(value,"INTERNAL") == 0 || _stricmp(value,"LOOPBACK") == 0) - { - // Set Sensible defaults - - memset(xxp.ID, ' ', 30); - memcpy(xxp.ID, "Loopback", 8); - xxp.CHANNEL = 'A'; - xxp.FRACK = 5000; - xxp.RESPTIME = 1000; - xxp.MAXFRAME = 4; - xxp.RETRIES = 5; - xxp.DIGIFLAG = 1; - hw = 14; - } - if (_stricmp(value,"EXTERNAL") == 0) - { - hw = 16; - - // Set some defaults in case KISSHF - - xxp.CHANNEL = 'A'; - xxp.FRACK = 7000; - xxp.RESPTIME = 1000; - xxp.MAXFRAME = 4; - xxp.RETRIES = 6; - } - - if (_stricmp(value,"BAYCOM") == 0) - hw = 18; - if (_stricmp(value,"PA0HZP") == 0) - hw = 20; - if (_stricmp(value,"I2C") == 0) - { - // Set some defaults - - xxp.CHANNEL = 'A'; - xxp.FRACK = 7000; - xxp.RESPTIME = 1000; - xxp.MAXFRAME = 4; - xxp.RETRIES = 6; - hw = 22; - } - - if (hw == 255) - { - Consoleprintf("Invalid Hardware Type (not DRSI PC120 INTERNAL EXTERNAL BAYCOM PA0HZP ASYNC QUAD)"); - Consoleprintf("%s\r\n", rec); - return (0); - } - else - xxp.TYPE = hw; - - return(1); -} -int protocols(int i, char value[], char rec[]) -{ - int hw; - - hw = 255; - if (_stricmp(value,"KISS") == 0) - hw = 0; - if (_stricmp(value,"NETROM") == 0) - hw = 2; - if (_stricmp(value,"BPQKISS") == 0) - hw = 4; - if (_stricmp(value,"HDLC") == 0) - hw = 6; - if (_stricmp(value,"L2") == 0) - hw = 8; - if (_stricmp(value,"PACTOR") == 0) - hw = 10; - if (_stricmp(value,"WINMOR") == 0) - hw = 10; - if (_stricmp(value,"ARQ") == 0) - hw = 12; - - if (hw == 255) - { - Consoleprintf("Invalid Protocol (not KISS NETROM PACTOR WINMOR ARQ HDLC )"); - Consoleprintf("%s\r\n", rec); - return (0); - } - else - xxp.PROTOCOL = hw; - return(1); -} - - -int bbsflag(int i, char value[],char rec[]) -{ - int hw=255; - - if (_stricmp(value,"NOBBS") == 0) - hw = 1; - if (_stricmp(value,"BBSOK") == 0) - hw = 0; - if (_stricmp(value,"") == 0) - hw = 0; - - if (hw==255) - { - Consoleprintf("BBS Flag must be NOBBS, BBSOK, or null"); - Consoleprintf("%s\r\n",rec); - return(0); - } - - xxp.BBSFLAG = hw; - - return(1); -} - -int channel(int i, char * value, char * rec) -{ - char * val = (char *)poffset[i]; - val[0] = value[0]; - return 1; -} - -int dolinked(int i, char * value, char * rec) -{ - char * val = (char *)offset[i]; - val[0] = value[0]; - return 1; -} - -int validcalls(int i, char * value, char * rec) -{ - if ((strlen(value) + (int)strlen(xxp.VALIDCALLS)) > 255) - { - Consoleprintf("Too Many VALIDCALLS"); - Consoleprintf("%s\r\n", rec); - return(0); - } - - strcat(xxp.VALIDCALLS, value); - return(1); -} - - -int kissoptions(int i, char value[], char rec[]) -{ - int err=255; - - char opt1[12] = ""; - char opt2[12] = ""; - char opt3[12] = ""; - char opt4[12] = ""; - char opt5[12] = ""; - char opt6[12] = ""; - char opt7[12] = ""; - char opt8[12] = ""; - - - - sscanf(value,"%[^,+],%[^,+],%[^,+],%[^,+],%[^,+],%[^,+],%[^,+],%[^,+]", - opt1,opt2,opt3,opt4,opt5,opt6,opt6,opt8); - - if (opt1[0] != '\0') {do_kiss(opt1,rec);} - if (opt2[0] != '\0') {do_kiss(opt2,rec);} - if (opt3[0] != '\0') {do_kiss(opt3,rec);} - if (opt4[0] != '\0') {do_kiss(opt4,rec);} - if (opt5[0] != '\0') {do_kiss(opt5,rec);} - if (opt6[0] != '\0') {do_kiss(opt6,rec);} - if (opt7[0] != '\0') {do_kiss(opt7,rec);} - if (opt8[0] != '\0') {do_kiss(opt8,rec);} - - return(1); -} - - - -/* - TNC PORT PROCESSING -*/ -static char *tkeywords[] = -{ -"COM", "TYPE", "APPLMASK", "KISSMASK", "APPLFLAGS", "ENDPORT" -}; /* parameter keywords */ - -static int toffset[] = -{ -0, 1, 2, 3, 5, 8 -}; /* offset for corresponding data in config file */ - -static int troutine[] = -{ -1, 5, 1, 3, 1, 9 -}; /* routine to process parameter */ - -#define TPARAMLIM 6 - - -typedef struct _TCMDX -{ - char String[12]; // COMMAND STRING - UCHAR CMDLEN; // SIGNIFICANT LENGTH - VOID (* CMDPROC)(struct TNCDATA * TNC, char * Tail, struct _TCMDX * CMD);// COMMAND PROCESSOR - size_t CMDFLAG; // FLAG/VALUE Offset - -} TCMDX; - - - -extern TCMDX TNCCOMMANDLIST[]; -extern int NUMBEROFTNCCOMMANDS; - -int decode_tnc_rec(char * rec) -{ - char key_word[20]; - char value[300]; - - if (xindex(rec,"=") >= 0) - sscanf(rec,"%[^=]=%s",key_word,value); - else - sscanf(rec,"%s",key_word); - - if (_stricmp(key_word, "ENDPORT") == 0) - { - endport=1; - return 0; - } - else if (_stricmp(key_word, "TYPE") == 0) - { - if (_stricmp(value, "TNC2") == 0) - { - TNC2ENTRY->Mode = TNC2; - - // Set Defaults - - TNC2ENTRY->SENDPAC = 13; - TNC2ENTRY->CRFLAG = 1; - TNC2ENTRY->MTX = 1; - TNC2ENTRY->MCOM = 1; - TNC2ENTRY->MMASK = -1; // MONITOR MASK FOR PORTS - - TNC2ENTRY->COMCHAR = 3; - TNC2ENTRY->CMDTIME = 10; // SYSTEM TIMER = 100MS - TNC2ENTRY->PASSCHAR = 0x16; // CTRL-V - TNC2ENTRY->StreamSW = 0x7C; // | - TNC2ENTRY->LCStream = 1; - } - else if (_stricmp(value, "DED") == 0) - TNC2ENTRY->Mode = DED; - else if (_stricmp(value, "KANT") == 0) - TNC2ENTRY->Mode = KANTRONICS; - else if (_stricmp(value, "SCS") == 0) - TNC2ENTRY->Mode = SCS; - else - { - Consoleprintf("Invalid TNC Type"); - Consoleprintf("%s\r\n",rec); - } - } - else if (_stricmp(key_word, "COMPORT") == 0) - strcpy(TNC2ENTRY->PORTNAME, value); - else if (_stricmp(key_word, "APPLMASK") == 0) - TNC2ENTRY->APPLICATION = strtol(value, 0, 0); - else if (_stricmp(key_word, "APPLNUM") == 0) - TNC2ENTRY->APPLICATION = 1 << (strtol(value, 0, 0) - 1); - else if (_stricmp(key_word, "APPLFLAGS") == 0) - TNC2ENTRY->APPLFLAGS = strtol(value, 0, 0); - else if (_stricmp(key_word, "CHANNELS") == 0) - TNC2ENTRY->HOSTSTREAMS = strtol(value, 0, 0); - else if (_stricmp(key_word, "STREAMS") == 0) - TNC2ENTRY->HOSTSTREAMS = strtol(value, 0, 0); - else if (_stricmp(key_word, "POLLDELAY") == 0) - TNC2ENTRY->PollDelay = strtol(value, 0, 0); - else if (_stricmp(key_word, "CONOK") == 0) - TNC2ENTRY->CONOK = strtol(value, 0, 0); - else if (_stricmp(key_word, "AUTOLF") == 0) - TNC2ENTRY->AUTOLF = strtol(value, 0, 0); - else if (_stricmp(key_word, "ECHO") == 0) - TNC2ENTRY->ECHOFLAG = (char)strtol(value, 0, 0); - else - { - if (TNC2ENTRY->Mode == TNC2) - { - // Try process as TNC2 Command - - int n = 0; - TCMDX * CMD = &TNCCOMMANDLIST[0]; - char * ptr1 = key_word; - UCHAR * valueptr; - - strcat(key_word, " "); - - _strupr(key_word); - - for (n = 0; n < NUMBEROFTNCCOMMANDS; n++) - { - int CL = CMD->CMDLEN; - - // ptr1 is input command - - ptr1 = key_word; - - if (memcmp(CMD->String, ptr1, CL) == 0) - { - // Found match so far - check rest - - char * ptr2 = &CMD->String[CL]; - - ptr1 += CL; - - if (*(ptr1) != ' ') - { - while(*(ptr1) == *ptr2 && *(ptr1) != ' ') - { - ptr1++; - ptr2++; - } - } - - if (*(ptr1) == ' ') - { - valueptr = (UCHAR *)TNC2ENTRY + CMD->CMDFLAG; - *valueptr = (UCHAR)strtol(value, 0, 0); - return 0; - } - } - CMD++; - } - } - - Consoleprintf("Source record not recognised - Ignored:%s\r\n",rec); - } - return 0; -} - - -int do_kiss (char * value,char * rec) -{ - int err=255; - - if (_stricmp(value,"POLLED") == 0) - { - err=0; - kissflags=kissflags | POLLINGKISS; - } - else if (_stricmp(value,"CHECKSUM") == 0) - { - err=0; - kissflags=kissflags | CHECKSUM; - } - else if (_stricmp(value,"D700") == 0) - { - err=0; - kissflags=kissflags | D700; - } - else if (_stricmp(value,"TNCX") == 0) - { - err=0; - kissflags=kissflags | TNCX; - } - else if (_stricmp(value,"PITNC") == 0) - { - err=0; - kissflags=kissflags | PITNC; - } - else if (_stricmp(value,"TRACKER") == 0) - { - err=0; - kissflags |= TRACKER; - } - else if (_stricmp(value,"NOPARAMS") == 0) - { - err=0; - kissflags=kissflags | NOPARAMS; - } - else if (_stricmp(value,"ACKMODE") == 0) - { - err=0; - kissflags=kissflags | ACKMODE; - } - else if (_stricmp(value,"SLAVE") == 0) - { - err=0; - kissflags=kissflags | POLLEDKISS; - } - else if (_stricmp(value,"FLDIGI") == 0) - { - err=0; - kissflags |= FLDIGI; - } - else if (_stricmp(value,"FASTI2C") == 0) - { - err=0; - kissflags |= FASTI2C; - } - - else if (_stricmp(value,"DRATS") == 0) - { - err=0; - kissflags |= DRATS; - } - - if (err == 255) - { - Consoleprintf("Invalid KISS Options (not POLLED ACKMODE CHECKSUM D700 SLAVE TNCX PITNC NOPARAMS FASTI2C DRATS)"); - Consoleprintf("%s\r\n",rec); - } - return (err); -} - - -int simple(int i) -{ - // Set up the basic config header - - xxcfg.C_AUTOSAVE = 1; - xxcfg.C_SaveMH = 1; - xxcfg.C_BBS = 1; - xxcfg.C_BTINTERVAL = 60; - xxcfg.C_BUFFERS = 999; - xxcfg.C_C = 1; - xxcfg.C_DESQVIEW = 0; - xxcfg.C_EMSFLAG = 0; - xxcfg.C_FULLCTEXT = 1; - xxcfg.C_HIDENODES = 0; - xxcfg.C_HOSTINTERRUPT = 127; - xxcfg.C_IDINTERVAL = 10; - xxcfg.C_IDLETIME = 900; - xxcfg.C_IP = 0; - xxcfg.C_PM = 0; - xxcfg.C_L3TIMETOLIVE = 25; - xxcfg.C_L4DELAY = 10; - xxcfg.C_L4RETRIES = 3; - xxcfg.C_L4TIMEOUT = 60; - xxcfg.C_L4WINDOW = 4; - xxcfg.C_LINKEDFLAG = 'A'; - xxcfg.C_MAXCIRCUITS = 128; - xxcfg.C_MAXDESTS = 250; - xxcfg.C_MAXHOPS = 4; - xxcfg.C_MAXLINKS = 64; - xxcfg.C_MAXNEIGHBOURS = 64; - xxcfg.C_MAXRTT = 90; - xxcfg.C_MINQUAL = 150; - xxcfg.C_NODE = 1; - xxcfg.C_NODESINTERVAL = 30; - xxcfg.C_OBSINIT = 6; - xxcfg.C_OBSMIN = 5; - xxcfg.C_PACLEN = 236; - xxcfg.C_T3 = 180; - xxcfg.C_TRANSDELAY = 1; - - /* Set PARAMOK flags on all values that are defaulted */ - - for (i=0; i < PARAMLIM; i++) - paramok[i]=1; - - paramok[15] = 0; // Must have callsign - paramok[45] = 0; // Dont Have Appl1Call - paramok[53] = 0; // or APPL1ALIAS - - return(1); -} - -VOID FreeConfig() -{ -} - -BOOL ProcessAPPLDef(char * buf) -{ - // New Style APPL definition - - // APPL n,COMMAND,CMDALIAS,APPLCALL,APPLALIAS,APPLQUAL,L2ALIAS - - char * ptr1, * ptr2; - int Appl, n = 0; - char Param[8][256]; - struct APPLCONFIG * App; - - memset(Param, 0, 2048); - - ptr1 = buf; - - while (ptr1 && *ptr1 && n < 8) - { - ptr2 = strchr(ptr1, ','); - if (ptr2) *ptr2++ = 0; - - strcpy(&Param[n++][0], ptr1); - ptr1 = ptr2; - } - - if (_stricmp(Param[1], Param[2]) == 0) - { - // Alias = Application - will loop. - - return FALSE; - } - - _strupr(Param[0]); - _strupr(Param[1]); - - // Leave Alias in original case - - _strupr(Param[3]); - _strupr(Param[4]); - _strupr(Param[5]); - _strupr(Param[6]); - _strupr(Param[7]); - - - Appl = atoi(Param[0]); - - if (Appl < 1 || Appl > NumberofAppls) return FALSE; - - App = &xxcfg.C_APPL[Appl - 1]; // Recs from zero - - if (Param[1][0] == 0) // No Application - return FALSE; - - if (strlen(Param[1]) > 12) return FALSE; - - memcpy(App->Command, Param[1], (int)strlen(Param[1])); - - xxcfg.C_BBS = 1; - - if (strlen(Param[2]) > 48) return FALSE; - - memcpy(App->CommandAlias, Param[2], (int)strlen(Param[2])); - - if (strlen(Param[3]) > 10) return FALSE; - - memcpy(App->ApplCall, Param[3], (int)strlen(Param[3])); - - if (strlen(Param[4]) > 10) return FALSE; - - memcpy(App->ApplAlias, Param[4], (int)strlen(Param[4])); - - App->ApplQual = atoi(Param[5]); - - if (strlen(Param[6]) > 10) return FALSE; - - memcpy(App->L2Alias, Param[6], (int)strlen(Param[6])); - - return TRUE; -} - -double xfmod(double p1, double p2) -{ - int temp; - - temp = (int)(p1/p2); - p1 = p1 -(p2 * temp); - return p1; -} - - BOOL ToLOC(double Lat, double Lon , char * Locator) - { - int i; - double S1, S2; - - Lon = Lon + 180; - Lat = Lat + 90; - - S1 = xfmod(Lon, 20); - - #pragma warning(push) - #pragma warning(disable : 4244) - - i = Lon / 20; - Locator[0] = 65 + i; - - S2 = xfmod(S1, 2); - - i = S1 / 2; - Locator[2] = 48 + i; - - i = S2 * 12; - Locator[4] = 65 + i; - - S1 = xfmod(Lat,10); - - i = Lat / 10; - Locator[1] = 65 + i; - - S2 = xfmod(S1,1); - - i = S1; - Locator[3] = 48 + i; - - i = S2 * 24; - Locator[5] = 65 + i; - - #pragma warning(pop) - - return TRUE; -} - -int FromLOC(char * Locator, double * pLat, double * pLon) -{ - double i; - double Lat, Lon; - - _strupr(Locator); - - *pLon = 0; - *pLat = 0; // in case invalid - - - // Basic validation for APRS positions - - // The first pair (a field) encodes with base 18 and the letters "A" to "R". - // The second pair (square) encodes with base 10 and the digits "0" to "9". - // The third pair (subsquare) encodes with base 24 and the letters "a" to "x". - - i = Locator[0]; - - if (i < 'A' || i > 'R') - return 0; - - Lon = (i - 65) * 20; - - i = Locator[2]; - if (i < '0' || i > '9') - return 0; - - Lon = Lon + (i - 48) * 2; - - i = Locator[4]; - if (i < 'A' || i > 'X') - return 0; - - Lon = Lon + (i - 65) / 12; - - i = Locator[1]; - if (i < 'A' || i > 'R') - return 0; - - Lat = (i - 65) * 10; - - i = Locator[3]; - if (i < '0' || i > '9') - return 0; - - Lat = Lat + (i - 48); - - i = Locator[5]; - if (i < 'A' || i > 'X') - return 0; - - Lat = Lat + (i - 65) / 24; - - if (Lon < 0 || Lon > 360) - Lon = 180; - if (Lat < 0 || Lat > 180) - Lat = 90; - - *pLon = Lon - 180; - *pLat = Lat - 90; - - return 1; -} diff --git a/.svn/pristine/05/05cb3c09ff4898bc77bda06f9cff0f0a53df0c80.svn-base b/.svn/pristine/05/05cb3c09ff4898bc77bda06f9cff0f0a53df0c80.svn-base deleted file mode 100644 index 20f185d..0000000 --- a/.svn/pristine/05/05cb3c09ff4898bc77bda06f9cff0f0a53df0c80.svn-base +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.svn/pristine/06/06e4dc036e31dfb016e7d2147ca5564a44fa2e59.svn-base b/.svn/pristine/06/06e4dc036e31dfb016e7d2147ca5564a44fa2e59.svn-base deleted file mode 100644 index da78480..0000000 --- a/.svn/pristine/06/06e4dc036e31dfb016e7d2147ca5564a44fa2e59.svn-base +++ /dev/null @@ -1,223 +0,0 @@ -/* LzmaDec.h -- LZMA Decoder - 2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __LZMADEC_H -#define __LZMADEC_H - -#include "types.h" - -/* #define _LZMA_PROB32 */ -/* _LZMA_PROB32 can increase the speed on some CPUs, - but memory usage for CLzmaDec::probs will be doubled in that case */ - -#ifdef _LZMA_PROB32 -#define CLzmaProb LZ_UInt32 -#else -#define CLzmaProb UInt16 -#endif - - -/* ---------- LZMA Properties ---------- */ - -#define LZMA_PROPS_SIZE 5 - -typedef struct _CLzmaProps -{ - unsigned lc, lp, pb; - LZ_UInt32 dicSize; -} CLzmaProps; - -/* LzmaProps_Decode - decodes properties - Returns: - SZ_OK - SZ_ERROR_UNSUPPORTED - Unsupported properties - */ - -SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); - - -/* ---------- LZMA Decoder state ---------- */ - -/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. - Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ - -#define LZMA_REQUIRED_INPUT_MAX 20 - -typedef struct -{ - CLzmaProps prop; - CLzmaProb *probs; - Byte *dic; - const Byte *buf; - LZ_UInt32 range, code; - SizeT dicPos; - SizeT dicBufSize; - LZ_UInt32 processedPos; - LZ_UInt32 checkDicSize; - unsigned state; - LZ_UInt32 reps[4]; - unsigned remainLen; - int needFlush; - int needInitState; - LZ_UInt32 numProbs; - unsigned tempBufSize; - Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; -} CLzmaDec; - -#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } - -void LzmaDec_Init(CLzmaDec *p); - -/* There are two types of LZMA streams: - 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. - 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ - -typedef enum -{ - LZMA_FINISH_ANY, /* finish at any point */ - LZMA_FINISH_END /* block must be finished at the end */ -} ELzmaFinishMode; - -/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! - - You must use LZMA_FINISH_END, when you know that current output buffer - covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. - - If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, - and output value of destLen will be less than output buffer size limit. - You can check status result also. - - You can use multiple checks to test data integrity after full decompression: - 1) Check Result and "status" variable. - 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. - 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. - You must use correct finish mode in that case. */ - -typedef enum -{ - LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ - LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ - LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ - LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ -} ELzmaStatus; - -/* ELzmaStatus is used only as output value for function call */ - - -/* ---------- Interfaces ---------- */ - -/* There are 3 levels of interfaces: - 1) Dictionary Interface - 2) Buffer Interface - 3) One Call Interface - You can select any of these interfaces, but don't mix functions from different - groups for same object. */ - - -/* There are two variants to allocate state for Dictionary Interface: - 1) LzmaDec_Allocate / LzmaDec_Free - 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs - You can use variant 2, if you set dictionary buffer manually. - For Buffer Interface you must always use variant 1. - - LzmaDec_Allocate* can return: - SZ_OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties - */ - -SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); -void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); - -SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); -void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); - -/* ---------- Dictionary Interface ---------- */ - -/* You can use it, if you want to eliminate the overhead for data copying from - dictionary to some other external buffer. - You must work with CLzmaDec variables directly in this interface. - - STEPS: - LzmaDec_Constr() - LzmaDec_Allocate() - for (each new stream) - { - LzmaDec_Init() - while (it needs more decompression) - { - LzmaDec_DecodeToDic() - use data from CLzmaDec::dic and update CLzmaDec::dicPos - } - } - LzmaDec_Free() - */ - -/* LzmaDec_DecodeToDic - - The decoding to internal dictionary buffer (CLzmaDec::dic). - You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! - - finishMode: - It has meaning only if the decoding reaches output limit (dicLimit). - LZMA_FINISH_ANY - Decode just dicLimit bytes. - LZMA_FINISH_END - Stream must be finished after dicLimit. - - Returns: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_NEEDS_MORE_INPUT - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error - */ - -SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); - - -/* ---------- Buffer Interface ---------- */ - -/* It's zlib-like interface. - See LzmaDec_DecodeToDic description for information about STEPS and return results, - but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need - to work with CLzmaDec variables manually. - - finishMode: - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). - */ - -SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); - - -/* ---------- One Call Interface ---------- */ - -/* LzmaDecode - - finishMode: - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). - - Returns: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). - */ - -SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc); - -#endif diff --git a/.svn/pristine/08/0811f3c6b3e6a6eafccc305825e33cd8c8621f75.svn-base b/.svn/pristine/08/0811f3c6b3e6a6eafccc305825e33cd8c8621f75.svn-base deleted file mode 100644 index 8ce98e6..0000000 --- a/.svn/pristine/08/0811f3c6b3e6a6eafccc305825e33cd8c8621f75.svn-base +++ /dev/null @@ -1,4583 +0,0 @@ -/* -Copyright 2001-2015 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 -*/ - -// Version 0.0.3.1 July 2016 -// Switch to Thunderforest tile server - -// Version 0.0.4.1 January 2019 -// Add option to set IS filter to map view automatically - -// Version 1.1.14.5 March 2020 -// Add option to run two instances of Linbpq and APRS - -// Version 1.1.14.6 Sept 2021 -// Use my Tile Servers - - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. -#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#define LINBPQ - -#include "compatbits.h" - -#include "BPQAPRS.h" - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#define XK_MISCELLANY -#include - -#include -#include - -#include -#include - -#define LIBCONFIG_STATIC -#include "libconfig.h" - -#include -#include -#include - -#define PNG_SKIP_SETJMP_CHECK - -#include - -#define VOID void -#define UCHAR unsigned char -#define BOOL int -#define BYTE unsigned char -#define UINT unsigned int -#define TRUE 1 -#define FALSE 0 - - -#undef PNG_NO_STDIO - -int multiple = 0; - - -GtkWidget *dialog; -GtkWidget *window; -GtkWidget *dialog; -GtkWidget *window; -GtkWidget *box1; -GtkWidget *box2; -GtkWidget *box3; -GtkWidget *hbox; -GtkWidget *button; -GtkWidget *button2; -GtkWidget *checklabel; -GtkWidget *check1; -GtkWidget *check2; -GtkWidget *check3; -GtkWidget *check4; -GtkWidget *checkhbox; -GtkWidget *separator; -GtkWidget *table; -GtkWidget *vscrollbar; -GtkWidget *vscrollbar2; -GtkTextBuffer *text; -GtkTextBuffer *text2; -GtkWidget *entry; -GtkWidget *vpaned; -GtkWidget *frame1; -GtkWidget *frame2; -GtkWidget *view; -GtkWidget* scrolledwin; -GtkWidget *view2; -GtkWidget* scrolledwin2; -GtkWidget *box10; -GtkWidget *menubar; -GtkWidget *combo; -GtkWidget *label1, *label2; -GtkListStore *receiveditems; -GtkListStore *sentitems; - -GtkTreeModel *model; - -char MyFont[50] = "Monospace 10"; - -gchar *fontname; - -char RX_SOCK_PATH[] = "BPQAPRSrxsock"; -char TX_SOCK_PATH[] = "BPQAPRStxsock"; - -int sfd; -struct sockaddr_un my_addr, peer_addr; -socklen_t peer_addr_size; -int maxfd; - -struct SharedMem * SMEM; - -UCHAR * Shared; // Start of Shared Mememy -UCHAR * StnRecordBase; // Start of Station Records - -int AutoFilterTimer = 0; - -#define AUTOFILTERDELAY 20 // 20 secs - -VOID SecTimer(); -void plotLine(int x0, int y0, int x1, int y1, COLORREF rgb); -void SelectTXMsg (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data); -int LoadImageFile (void * hwnd, char * pstrPathName, - png_byte **ppbImage, int *pxImgSize, int *pyImgSize, - int *piChannels, png_color *pBkgColor); -BOOL PngLoadImage (char * pstrFileName, png_byte **ppbImageData, - png_uint_32 *piWidth, png_uint_32 *piHeight, int *piChannels, png_color *pBkgColor); - -BOOL RGBToJpegFile(char * fileName, BYTE *dataBuf, UINT widthPix, UINT height, BOOL color, int quality); -int XDestroyImage(XImage *ximage); - -int XLookupString(XKeyEvent *event_struct, char *buffer_return, int bytes_buffer, KeySym *keysym_return, void *status_in_out); - -void RefreshTXList(); - -static png_color bkgColor = {127, 127, 127}; - -struct SEM -{ - UINT Flag; - int Clashes; - int Gets; - int Rels; -}; - - -struct SEM Semaphore = {0, 0, 0, 0}; - -void GetSemaphore(struct SEM * Semaphore) -{ - // - // Wait for it to be free - // - - if (Semaphore->Flag != 0) - { - Semaphore->Clashes++; - } - -loop1: - - while (Semaphore->Flag != 0) - { - Sleep(10); - } - - // try to get semaphore - - if (__sync_lock_test_and_set(&Semaphore->Flag, 1) != 0) - - // Failed to get it - goto loop1; // try again; - - //Ok. got it - - Semaphore->Gets++; - - return; -} - -void FreeSemaphore(struct SEM * Semaphore) -{ - if (Semaphore->Flag == 0) - printf("Free Semaphore Called when Sem not held\n"); - - Semaphore->Rels++; - Semaphore->Flag = 0; - - return; -} - -char * strlop(char * buf, char delim) -{ - // Terminate buf at delim, and return rest of string - - char * ptr = strchr(buf, delim); - - if (ptr == NULL) return NULL; - - *(ptr)++=0; - - return ptr; -} - -unsigned long _beginthread(void(*start_address)(), unsigned stack_size, VOID * arglist) -{ - pthread_t thread; - - if (pthread_create(&thread, NULL, (void * (*)(void *))start_address, (void*) arglist) != 0) - perror("New Thread"); - else - pthread_detach(thread); - - return thread; -} - -int Sleep(int ms) -{ - usleep(ms * 1000); - return 0; -} - -struct OSMQUEUE OSMQueue = {NULL,0,0,0}; - -int OSMQueueCount = 0; - -static int cxWinSize = 788, cyWinSize = 788; -static int cxImgSize = 768, cyImgSize = 768; -static int topBorder = 30, bottomBorder = 0; -static int leftBorder = 2, rightBorder = 2; - -static int cImgChannels = 3; -static int ImgChannels; - -int Bytesperpixel = 4; - -int ExpireTime = 120; -int TrackExpireTime = 1440; -BOOL SuppressNullPosn = FALSE; -BOOL DefaultNoTracks = FALSE; -BOOL LocalTime = TRUE; -BOOL KM = FALSE; -BOOL AddViewToFilter = FALSE; - -char ISFilter[1000] = "m/50 u/APBPQ*"; - -int SlowTimer = 0; - -BOOL CreateJPEG = TRUE; -int JPEGInterval = 300; -int JPEGCounter = 0; -char JPEGFileName[MAX_PATH] = "BPQAPRS/HTML/APRSImage.jpg"; - -char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - - -Display * display; -Window root, win; -GC gc; -XImage * image, * popupimage; - -int SetBaseX = 0; // Lowest Tiles in currently loaded set -int SetBaseY = 0; - -int TileX = 0; -int TileY = 0; - -int Zoom = 2; - -int MaxZoom = 16; - -int MapCentreX = 256; -int MapCentreY = 256; - -int MouseX, MouseY; -int PopupX, PopupY; - -double MouseLat, MouseLon; - -BOOL NeedRefresh = FALSE; -int NeedRedraw = 0; - -int ScrollX = 128; -int ScrollY = 128; - -int WindowX = 100, WindowY = 100; // Position of window on screen -int WindowWidth = 788; -int WindowHeight = 788; - -BOOL popupActive = FALSE; -BOOL selActive = FALSE; - -char OSMDir[256] = "BPQAPRS/OSMTiles"; - -struct STATIONRECORD ** StationRecords = NULL; -struct STATIONRECORD * ControlRecord; - -int StationCount; - - -UCHAR NextSeq = 1; - -char APRSCall[10]; -char LoppedAPRSCall[10]; -char BaseCall[10]; - - -// Image chunks are 256 rows of 3 * 256 bytes - -// Read 8 * 8 files, and copy to a 2048 * 3 * 2048 array. The display scrolls over this area, and -// it is refreshed when window approaches the edge of the array. - -int WIDTH; -int HEIGHT; - -int WIDTHTILES = 4; -int HEIGHTTILES = 4; - -UCHAR * Image = NULL; -UCHAR * iconImage = NULL; -UCHAR * PopupImage = NULL; - -BOOL ImageChanged = 0; - -int RetryCount = 7; -int RetryIntervals[] = {0, 512, 256, 128, 64, 32, 16, 8}; - -// 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 -}; - -COLORREF Colours[256] = {0, RGB(0,0,255), RGB(0,128,0), RGB(0,128,192), - RGB(0,192,0), RGB(0,192,255), RGB(0,255,0), RGB(128,0,128), - RGB(128,64,0), RGB(128,128,128), RGB(192,0,0), RGB(192,0,255), - RGB(192,64,128), RGB(192,128,255), RGB(255,0,0), RGB(255,0,255), // 81 - RGB(255,64,0), RGB(255,64,128), RGB(255,64,192), RGB(255,128,0)}; - - - - -struct my_error_mgr { - struct jpeg_error_mgr pub; /* "public" fields */ - - jmp_buf setjmp_buffer; /* for return to caller */ -}; - -typedef struct my_error_mgr * my_error_ptr; - -void my_error_exit (j_common_ptr cinfo) -{ - /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ - my_error_ptr myerr = (my_error_ptr) cinfo->err; - - char buffer[JMSG_LENGTH_MAX]; - /* Create the message */ - (*cinfo->err->format_message) (cinfo, buffer); - - /* Always display the message. */ - printf("JPEG Fatal Error"); - - - /* Return control to the setjmp point */ - longjmp(myerr->setjmp_buffer, 1); -} - -int memicmp(unsigned char *a, unsigned char *b, int n) -{ - if (n) - { - while (n && toupper(*a) == toupper(*b)) - n--, a++, b++; - - if (n) - return toupper(*a) - toupper(*b); - } - return 0; -} -int stricmp(const unsigned char * pStr1, const unsigned char *pStr2) -{ - unsigned char c1, c2; - int v; - - if (pStr1 == NULL) - { - return 1; - } - - - do { - c1 = *pStr1++; - c2 = *pStr2++; - /* The casts are necessary when pStr1 is shorter & char is signed */ - v = tolower(c1) - tolower(c2); - } while ((v == 0) && (c1 != '\0') && (c2 != '\0') ); - - return v; -} - -char * strupr(char* s) -{ - char* p = s; - - if (s == 0) - return 0; - - while (*p = toupper( *p )) p++; - return s; -} - -// Return coorinates in tiles. - -double long2x(double lon, int z) -{ - return (lon + 180.0) / 360.0 * pow(2.0, z); -} - -double lat2y(double lat, int z) -{ - return (1.0 - log( tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, z); -} - -double tilex2long(double x, int z) -{ - return x / pow(2.0, z) * 360.0 - 180; -} - -double tiley2lat(double y, int z) -{ - double n = M_PI - 2.0 * M_PI * y / pow(2.0, z); - return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); -} - -void GetCornerLatLon(double * TLLat, double * TLLon, double * BRLat, double * BRLon) -{ - int X = ScrollX; - int Y = ScrollY; - - *TLLat = tiley2lat(SetBaseY + (Y / 256.0), Zoom); - *TLLon = tilex2long(SetBaseX + (X / 256.0), Zoom); - - X = ScrollX + cxWinSize; - Y = ScrollY + cyWinSize; - - *BRLat = tiley2lat(SetBaseY + (Y / 256.0), Zoom); - *BRLon = tilex2long(SetBaseX + (X / 256.0), Zoom); -} - - -void GetMouseLatLon(double * Lat, double * Lon) -{ - int X = ScrollX + MouseX; - int Y = ScrollY + MouseY; - - *Lat = tiley2lat(SetBaseY + (Y / 256.0), Zoom); - *Lon = tilex2long(SetBaseX + (X / 256.0), Zoom); -} - -BOOL GetLocPixels(double Lat, double Lon, int * X, int * Y) -{ - // Get the pixel offet of supplied location in current image. - - // If location is outside current image, return FAlSE - - int TileX; - int TileY; - int OffsetX, OffsetY; - double FX; - double FY; - - // if TileX or TileY are outside the window, return null - - FX = long2x(Lon, Zoom); - TileX = (int)floor(FX); - OffsetX = TileX - SetBaseX; - - if (OffsetX < 0 || OffsetX > 7) - return FALSE; - - FY = lat2y(Lat, Zoom); - TileY = (int)floor(FY); - OffsetY = TileY - SetBaseY; - - if (OffsetY < 0 || OffsetY > 7) - return FALSE; - - FX -= TileX; - FX = FX * 256.0; - - *X = (int)FX + 256 * OffsetX; - - FY -= TileY; - FY = FY * 256.0; - - *Y = (int)FY + 256 * OffsetY; - - return TRUE; -} - -int long2tilex(double lon, int z) -{ - return (int)(floor((lon + 180.0) / 360.0 * pow(2.0, z))); -} - -int lat2tiley(double lat, int z) -{ - return (int)(floor((1.0 - log( tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, z))); -} - - -BOOL CentrePositionToMouse(double Lat, double Lon) -{ - // Positions specified location at the mouse - - int X, Y; - - SetBaseX = long2tilex(Lon, Zoom) - 2; - SetBaseY = lat2tiley(Lat, Zoom) - 2; // Set Location at middle - - if (GetLocPixels(Lat, Lon, &X, &Y) == FALSE) - return FALSE; // Off map - - ScrollX = X - cxWinSize/2; - ScrollY = Y - cyWinSize/2; - - -// Map is now centered at loc cursor was at - -// Need to move by distance mouse is from centre - - // if ScrollX, Y are zero, the centre of the map corresponds to 1024, 1024 - -// ScrollX -= 1024 - X; // Posn to centre -// ScrollY -= 1024 - Y; - - ScrollX += cxWinSize/2 - MouseX; - ScrollY += cyWinSize/2 - MouseY; - - // May Need to move image - - while(ScrollX < 0) - { - SetBaseX--; - ScrollX += 256; - } - - while(ScrollY < 0) - { - SetBaseY--; - ScrollY += 256; - } - - while(ScrollX > 255) - { - SetBaseX++; - ScrollX -= 256; - } - - while(ScrollY > 255) - { - SetBaseY++; - ScrollY -= 256; - } - - AutoFilterTimer = AUTOFILTERDELAY; // Update filter if no change for 30 secs - - return TRUE; -} - -SOCKADDR_IN destaddr1 = {0}; -SOCKADDR_IN destaddr2 = {0}; - -unsigned int ipaddr = 0; - -//char Host[] = "tile.openstreetmap.org"; - -//char Host[] = "oatile1.mqcdn.com"; //SAT -//char Host[] = "otile1.mqcdn.com"; - -//char Host[] = "tile.thunderforest.com"; - -char Host[] = "server.g8bpq.net"; -char Host1[] = "server1.g8bpq.net"; -char Host2[] = "server2.g8bpq.net"; - -int Host1Down = 0; -int Host2Down = 0; - -char mapStyle[64] = "outdoors"; //"neighbourhood mobile-atlas - - -char HeaderTemplate[] = "Accept: */*\r\nHost: %s\r\nConnection: close\r\nContent-Length: 0\r\nUser-Agent: BPQ32(G8BPQ)\r\n\r\n"; - - -VOID ResolveThread() -{ - struct hostent * HostEnt; - int err; - -// while (TRUE) - { - // Resolve Name if needed - - HostEnt = gethostbyname(Host1); - - if (!HostEnt) - { - err = WSAGetLastError(); - printf("Resolve Failed for %s %d %x\n", Host1, err); - } - else - { - memcpy(&destaddr1.sin_addr.s_addr,HostEnt->h_addr,4); - } - - HostEnt = gethostbyname(Host2); - - if (!HostEnt) - { - err = WSAGetLastError(); - printf("Resolve Failed for %s %d %x\n", Host2, err); - } - else - { - memcpy(&destaddr2.sin_addr.s_addr,HostEnt->h_addr,4); - } -/// Sleep(60 * 15 * 1000); - } -} - - - -VOID OSMGet(int x, int y, int zoom) -{ - struct OSMQUEUE * OSMRec = malloc(sizeof(struct OSMQUEUE)); - - GetSemaphore(&Semaphore); - - OSMQueueCount++; - - OSMRec->Next = OSMQueue.Next; - OSMQueue.Next = OSMRec; - OSMRec->x = x; - OSMRec->y = y; - OSMRec->Zoom = zoom; - - FreeSemaphore(&Semaphore); -} - -VOID RefreshTile(char * FN, int TileZoom, int Tilex, int Tiley); - -VOID OSMThread() -{ - // Request a page from OSM - - char FN[256]; - char Tile[80]; - struct OSMQUEUE * OSMRec; - int Zoom, x, y; - - SOCKET sock; - SOCKADDR_IN sinx; - int addrlen=sizeof(sinx); - int err; - u_long param=1; - BOOL bcopt=TRUE; - char Request[100]; - char Header[256]; - UCHAR Buffer[200000]; - int Len, InputLen = 0; - UCHAR * ptr; - int inptr = 0; - struct stat STAT; - FILE * Handle; - - destaddr1.sin_family = AF_INET; - destaddr1.sin_port = htons(7381); - destaddr2.sin_family = AF_INET; - destaddr2.sin_port = htons(7381); - - while (TRUE) - { - while (OSMQueue.Next) - { - GetSemaphore(&Semaphore); - - OSMRec = OSMQueue.Next; - OSMQueue.Next = OSMRec->Next; - - OSMQueueCount--; - - FreeSemaphore(&Semaphore); - - x = OSMRec->x; - y = OSMRec->y; - Zoom = OSMRec->Zoom; - - free(OSMRec); - -// wsprintf(Tile, "/%02d/%d/%d.png", Zoom, x, y); -// wsprintf(Tile, "/tiles/1.0.0/sat/%02d/%d/%d.jpg", Zoom, x, y); -// sprintf(Tile, "/tiles/1.0.0/osm/%02d/%d/%d.jpg", Zoom, x, y); - -// sprintf(Tile, "/%s/%d/%d/%d.png?apikey=41ab899ed1fd4d09b11da7caf3a48e1f", mapStyle, Zoom, x, y); - - sprintf(Tile, "/styles/klokantech-basic/%d/%d/%d.png", Zoom, x, y); - - sprintf(FN, "%s/%02d/%d/%d.png", OSMDir, Zoom, x, y); - - if (stat(FN, &STAT) == 0) - { - printf(" File %s Exists - skipping\n", FN); - continue; - } - - printf("Getting %s\n", FN); - - Len = sprintf(Request, "GET %s HTTP/1.0\r\n", Tile); - - // Allocate a Socket entry - - sock=socket(AF_INET,SOCK_STREAM,0); - - if (sock == INVALID_SOCKET) - return; - - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); - - if (Host1Down == 0) - { - if (connect(sock,(LPSOCKADDR) &destaddr1, sizeof(destaddr1)) != 0) - { - printf("OSM GET Connect to %s Failed %d\n", Host1, errno); - Host1Down = 600; // Don't try again for 10 mins - } - else - goto ConnectOK; - } - if (Host2Down == 0) - { - if (connect(sock,(LPSOCKADDR) &destaddr2, sizeof(destaddr2)) != 0) - { - printf("OSM GET Connect to %s Failed %d\n", Host2, errno); - Host1Down = 600; // Don't try again for 10 mins - } - else - goto ConnectOK; - } - - // - // Neither available or connect failed to both - // - - // Reduce retry timers - - if (Host1Down > 60 && Host2Down > 60) - { - Host1Down = 60; - Host2Down = 60; - } - - break; - -ConnectOK: - -//GET /15/15810/9778.png HTTP/1.0 -//Accept: */* -//Host: tile.openstreetmap.org -//Connection: close -//Content-Length: 0 -//User-Agent: APRSIS32(G8BPQ) - - InputLen = 0; - inptr = 0; - - send(sock, Request, Len, 0); - sprintf(Header, HeaderTemplate, Host); - send(sock, Header, strlen(Header), 0); - - while (InputLen != -1) - { - InputLen = recv(sock, &Buffer[inptr], 200000 - inptr, 0); - - if (InputLen > 0) - inptr += InputLen; - else - { - // File Complete?? - - if (strstr(Buffer, " 200 OK")) - { - ptr = strstr(Buffer, "Content-Length:"); - - if (ptr) - { - int FileLen = atoi(ptr + 15); - ptr = strstr(Buffer, "\r\n\r\n"); - - if (ptr) - { - ptr += 4; - char Dir[256]; - - if (FileLen == inptr - (ptr - Buffer)) - { - // File is OK - - int cnt; - - Handle = fopen(FN, "wb"); - - if (Handle) - { - fwrite(ptr, 1, FileLen, Handle); - fclose(Handle); - printf("Tile %s Loaded\n", FN); - RefreshTile(FN, Zoom, x, y); - break; - } - - if (errno != 2) // Bad Path - { - printf("Create %s failed %d\n", FN, errno); - perror("fopen"); - break; - } - - sprintf(Dir, "%s/%02d/%d", OSMDir, Zoom, x); - - if (mkdir(Dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) - { - printf("Error Creating %s\n", FN); - perror("mkdir"); - break; - } - - // Retry Create - - Handle = fopen(FN, "wb"); - - if (Handle) - { - fwrite(ptr, 1, FileLen, Handle); - fclose(Handle); - - printf("Tile %s Loaded\n", FN); - RefreshTile(FN, Zoom, x, y); - break; - } - - printf("Create %s falled\n", FN); - perror("fopen"); - break; - } - } - } - } - printf("OSM GET Bad Response %s ", Buffer); - sprintf(FN, "%s/DummyTile.jpg", OSMDir); - RefreshTile(FN, Zoom, x, y); - - break; - } - } - close(sock); - } - - // Queue is empty - - sleep(1); -} -} - -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 = ControlRecord->Lat; - double loh = ControlRecord->Lon; - double dist; -/* - -'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); - - dist = 60*degrees(acos(sin(lah) * sin(laa) + cos(lah) * cos(laa) * cos(loa-loh))) * 1.15077945; - - if (KM) - dist *= 1.60934; - - return dist; -} - -double Bearing(double lat2, double lon2) -{ - double lat1 = ControlRecord->Lat; - double lon1 = ControlRecord->Lon; - 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; - -} - - - -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; -} - -struct STATIONRECORD * FindStation(char * Call, BOOL AddIfNotFount) -{ - int i = 0; - struct STATIONRECORD * find; - struct STATIONRECORD * ptr; - struct STATIONRECORD * last = NULL; - int sum = 0; - - if (StationRecords == 0) - return FALSE; - - if (strlen(Call) > 9) - Call[9] = 0; - - find = *StationRecords; - while(find) - { - if (strlen(find->Callsign) > 9) - 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->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; -} - -int PopupHeight; -int PopupWidth; -int PopupLeft; -int PopupTop; -struct STATIONRECORD * popupStn; -struct STATIONRECORD * List[1000] = {0}; - - -VOID CreateStationPopup(struct STATIONRECORD * ptr, int RelX, int RelY) -{ - char Msg[80]; - int Len = 130; - int Line = 12; - struct tm * TM; - int x, y; - - PopupLeft = RelX - 10; - PopupTop = RelY - 30; - - if (PopupLeft + 400 > cxWinSize) - PopupLeft = cxWinSize - 405; - - if (PopupTop + 150> cyWinSize) - PopupTop= cyWinSize - 165; - - popupActive = TRUE; - popupStn = ptr; - PopupHeight = 200; - PopupWidth = 350; - - XClearArea(display, win, PopupLeft, PopupTop, 350, 200, FALSE); - XDrawRectangle(display, win, gc, PopupLeft, PopupTop, 350, 200); - - x = PopupLeft; - y = PopupTop; - - if (LocalTime) - TM = localtime(&ptr->TimeLastUpdated); - else - TM = gmtime(&ptr->TimeLastUpdated); - - Len = sprintf(Msg, "Last Heard: %.2d:%.2d:%.2d on Port %d", - TM->tm_hour, TM->tm_min, TM->tm_sec, ptr->LastPort); - - XDrawImageString(display, win, gc, x + 2, y + Line, ptr->Callsign, strlen(ptr->Callsign)); - Line += 12; - - XDrawImageString(display, win, gc, x + 2, y + Line, ptr->Path, strlen(ptr->Path)); - Line += 12; - -// XDrawImageString(display, win, gc, x + 2, y + Line, ptr->Status, 40); -// Line += 12; - - XDrawImageString(display, win, gc, x + 2, y + Line, Msg, Len); - Line += 12; - - -// Item.pszText = ptr->LastPacket; - - Len = sprintf(Msg, "Distance %6.1f Bearing %3.0f Course %1.0f Speed %3.1f", - Distance(ptr->Lat, ptr->Lon), - Bearing(ptr->Lat, ptr->Lon), ptr->Course, ptr->Speed); - - XDrawImageString(display, win, gc, x + 2, y + Line, Msg, Len); - Line += 12; - - - if (ptr->LastWXPacket[0]) - { - //display wx info - - struct APRSConnectionInfo temp; - - memset(&temp, 0, sizeof(temp)); - - DecodeWXReport(&temp, ptr->LastWXPacket); - - Len = sprintf(Msg, "Wind Speed %d MPH", temp.WindSpeed); - XDrawImageString(display, win, gc, x + 2, y + Line, Msg, Len); - Line += 12; - - Len = sprintf(Msg, "Wind Gust %d MPH", temp.WindGust); - XDrawImageString(display, win, gc, x + 2, y + Line, Msg, Len); - Line += 12; - - Len = sprintf(Msg, "Wind Direction %d°", temp.WindDirn); - XDrawImageString(display, win, gc, x + 2, y + Line, Msg, Len); - Line += 12; - - Len = sprintf(Msg, "Temperature %d°F", temp.Temp); - XDrawImageString(display, win, gc, x + 2, y + Line, Msg, Len); - Line += 12; - - Len = sprintf(Msg, "Pressure %05.1f", temp.Pressure /10.0); - XDrawImageString(display, win, gc, x + 2, y + Line, Msg, Len); - Line += 12; - - Len = sprintf(Msg, "Humidity %d%%", temp.Humidity); - XDrawImageString(display, win, gc, x + 2, y + Line, Msg, Len); - Line += 12; - } - -/* -Rain last hour##RAIN_HOUR_IN##" -Rain today##RAIN_TODAY_IN##" -Rain last 24 hours##RAIN_24_IN##" - -*/ -} - -VOID GetStationFromList(int MouseX, int MouseY) -{ - int RelX = MouseX + leftBorder; - int RelY = MouseY + topBorder; - - int index = (RelY - PopupTop) /12; - - if (List[index]) - { - selActive = FALSE; - CreateStationPopup(List[index], RelX, RelY); - } -} - -VOID FindStationsByPixel(int MouseX, int MouseY) -{ - int j=0; - struct STATIONRECORD * ptr = *StationRecords; - int RelX = MouseX - ScrollX + leftBorder; - int RelY = MouseY - ScrollY + topBorder; - - if (popupActive || selActive) - { - // if mouse within popup, leave alone - - if (RelX > PopupLeft && RelX < (PopupLeft + PopupWidth) && - RelY > PopupTop && RelY < (PopupTop + PopupHeight)) - return; - } - - while(ptr && j < 999) - { - if (abs((ptr->DispX - MouseX)) < 4 && abs((ptr->DispY - MouseY)) < 4) - List[j++] = ptr; - - ptr = ptr->Next; - } - - if (j == 0) - { - if (popupActive) - { - XPutImage (display, win, gc, image, ScrollX, ScrollY, leftBorder, topBorder, cxImgSize, cyImgSize); - popupActive = 0; - } - - if (selActive) - { - XPutImage (display, win, gc, image, ScrollX, ScrollY, leftBorder, topBorder, cxImgSize, cyImgSize); - selActive = 0; - } - return; - } - - // If only one, display info popup, else display selection popup - - if (popupActive || selActive) - return; // Already on display - - if (j == 1) - { - CreateStationPopup(List[0], RelX, RelY); - } - else - { - char Msg[80]; - int Line = 12; - int i; - - PopupLeft = RelX - 10; - PopupTop = RelY - 30; - - if (j > 20) - j = 20; - - PopupHeight = j * 12 + 4; - PopupWidth = 80; - - if (PopupLeft + 80 > cxWinSize) - PopupLeft = cxWinSize - 85; - - if (PopupTop + PopupHeight > cyWinSize) - PopupTop = cyWinSize - PopupHeight; - - selActive = TRUE; - - XClearArea(display, win, PopupLeft, PopupTop, 80, PopupHeight, FALSE); - XDrawRectangle(display, win, gc, PopupLeft, PopupTop, 80, PopupHeight); - - for (i = 0; i < j; i++) - { - memset(Msg, ' ', 12); - memcpy(Msg, List[i]->Callsign, strlen(List[i]->Callsign)); - XDrawImageString(display, win, gc, PopupLeft + 2, PopupTop + Line, Msg, 11); - Line += 12; - } - } -} - -VOID DrawCharacter(int X, int Y, int j, unsigned char chr) -{ - // Font is 5 bits wide x 8 high. Each byte of font contains one column, so 5 bytes per char - - int Pointer, i, c, index, bit, mask; - - Pointer = ((Y - 5) * WIDTH * Bytesperpixel) + ((X + 11) * Bytesperpixel) + (j * 6 * Bytesperpixel); - - mask = 1; - - for (i = 0; i < 2; i++) - { - for (index = 0 ; index < 6 ; index++) - { - Image[Pointer++] = 255; // Blank lines above chars - Image[Pointer++] = 255; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 255; - Pointer++; - } - } - - Pointer += (WIDTH - 6) * Bytesperpixel; - } - - // Pointer = ((Y - 3) * 2048 * 3) + (X * 3) + 36 + (j * 18); - - for (i = 0; i < 7; i++) - { - Image[Pointer++] = 255; // Blank col between chars - Image[Pointer++] = 255; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 255; - Pointer++; - } - for (index = 0 ; index < 5 ; index++) - { - c = ASCII[chr - 0x20][index]; // Font data - bit = c & mask; - - if (bit) - { - Image[Pointer++] = 0; - Image[Pointer++] = 0; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 0; - Pointer++; - } - } - else - { - Image[Pointer++] = 255; - Image[Pointer++] = 255; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 255; - Pointer++; - } - } - } - mask <<= 1; - Pointer += (WIDTH - 6) * Bytesperpixel; - } - - // Pointer = ((Y - 3) * 2048 * 3) + (X * 3) + 36 + (j * 18); - - mask = 1; - - for (i = 0; i < 2; i++) - { - for (index = 0 ; index < 6 ; index++) - { - Image[Pointer++] = 255; // Blank lines below chars between chars - Image[Pointer++] = 255; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 255; - Pointer++; - } - } - Pointer += (WIDTH - 6) * Bytesperpixel; - } -} - -int DrawStation(struct STATIONRECORD * ptr, BOOL AllStations) -{ - int X, Y, Pointer, i, c, index, bit, mask, calllen, calllenpixels; - UINT j; - char Overlay; - char * nptr; - time_t AgeLimit = time(NULL ) - (TrackExpireTime * 60); - int SavePointer; - - if (ptr->Moved == 0 && AllStations == 0) - return 0; // No need to repaint - - if (SuppressNullPosn && ptr->Lat == 0.0) - return 0; - - if (ptr->ObjState == '_') // Killed Object - return 0; - - if (GetLocPixels(ptr->Lat, ptr->Lon, &X, &Y)) - { - if (X < 12 || Y < 12 || X > (WIDTH - 36) || Y > (HEIGHT - 36)) - return 0; // Too close to edges - - if (ptr->LatTrack[0] && ptr->NoTracks == FALSE) - { - // Draw Track - - int Index = ptr->Trackptr; - int i, n; - int X, Y; - int LastX = 0, LastY = 0; - - for (n = 0; n < TRACKPOINTS; n++) - { - if (ptr->LatTrack[Index] && ptr->TrackTime[Index] > AgeLimit) - { - if (GetLocPixels(ptr->LatTrack[Index], ptr->LonTrack[Index], &X, &Y)) - { - if (LastX) - { - if (abs(X - LastX) < 600 && abs(Y - LastY) < 600) - if (X > 0 && Y > 0 && X < (WIDTH - 5) && Y < (HEIGHT - 5)) - plotLine(LastX, LastY, X, Y, Colours[ptr->TrackColour]); - - } - - LastX = X; - LastY = Y; - } - } - Index++; - if (Index == TRACKPOINTS) - Index = 0; - - } - } - - ptr->Moved = 0; - - ptr->DispX = X; - ptr->DispY = Y; // Save for mouse over checks - - // X and Y are offsets into the pixel data in array Image. Actual Bytes are at Y * 2048 * 3 + (X * 3) - - // Draw Icon - - if (Y < 8) Y = 8; - if (X < 8) X = 8; - - nptr = &Image[(((Y - 8) * WIDTH) + X - 8) * Bytesperpixel]; // Center icon on station - - j = (ptr->iconRow * 21 * 337 * Bytesperpixel) - + (ptr->iconCol * 21 * Bytesperpixel) - + 3 * Bytesperpixel + (337 * 3 * Bytesperpixel); - - for (i = 0; i < 16; i++) - { - memcpy(nptr, &iconImage[j], 16 * Bytesperpixel); - nptr += WIDTH * Bytesperpixel; - j += 337 * Bytesperpixel; - } - - // If an overlay is specified, add it - - Overlay = ptr->IconOverlay; - - if (Overlay) - { - Pointer = (((Y - 4) * WIDTH) + (X - 3)) * Bytesperpixel; - mask = 1; - - for (index = 0 ; index < 7 ; index++) - { - Image[Pointer++] = 255; // Blank line above chars - Image[Pointer++] = 255; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 255; - Pointer++; - } - } - Pointer += (WIDTH - 7) * Bytesperpixel; - - for (i = 0; i < 7; i++) - { - Image[Pointer++] = 255; // Blank col - Image[Pointer++] = 255; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 255; - Pointer++; - } - - for (index = 0 ; index < 5 ; index++) - { - c = ASCII[Overlay - 0x20][index]; // Font data - bit = c & mask; - - - if (bit) - { - Image[Pointer++] = 0; - Image[Pointer++] = 0; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 0; - Pointer++; - } - } - else - { - Image[Pointer++] = 255; - Image[Pointer++] = 255; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 255; - Pointer++; - } - } - } - - Image[Pointer++] = 255; // Blank col - Image[Pointer++] = 255; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 255; - Pointer++; - } - - mask <<= 1; - Pointer += (WIDTH - 7) * Bytesperpixel; - } - for (index = 0 ; index < 7 ; index++) - { - Image[Pointer++] = 255; // Blank line below chars - Image[Pointer++] = 255; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 255; - Pointer++; - } - } - Pointer += (WIDTH - 6) * Bytesperpixel; - } - - calllen = strlen(ptr->Callsign); - - while (calllen && ptr->Callsign[calllen - 1] == ' ') // Remove trailing spaces - calllen--; - - calllenpixels = (calllen + 1) * 6; - - // Draw Callsign Box - - Pointer = ((Y - 7) * WIDTH * Bytesperpixel) + ((X + 9) * Bytesperpixel); - - // Draw | at each end - - for (j = 0; j < 13; j++) - { - Image[Pointer] = 0; - Image[Pointer++ + calllenpixels * Bytesperpixel] = 0; - Image[Pointer] = 0; - Image[Pointer++ + calllenpixels * Bytesperpixel] = 0; - if (Bytesperpixel == 4) - { - Image[Pointer] = 0; - Image[Pointer++ + calllenpixels * Bytesperpixel] = 0; - Pointer++; - } - Pointer += (WIDTH - 1) * Bytesperpixel; - } - - // Draw Top Line - - for (i = 0; i < calllenpixels; i++) - { - Image[Pointer++] = 0; - Image[Pointer++] = 0; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 0; - Pointer++; - } - } - - // Draw Bottom Line - - Pointer = ((Y - 7) * WIDTH * Bytesperpixel) + ((X + 9) * Bytesperpixel); - - for (i = 0; i < calllenpixels; i++) - { - Image[Pointer++] = 0; - Image[Pointer++] = 0; - if (Bytesperpixel == 4) - { - Image[Pointer++] = 0; - Pointer++; - } - } - - // Draw Callsign. - - for (j = 0; j < calllen; j++) - { - DrawCharacter(X, Y,j, ptr->Callsign[j]); - } - ImageChanged = TRUE; - return 1; - } - else - { - ptr->DispX = 0; - ptr->DispY = 0; // Off Screen - } - return 0; -} - - -int RefreshStationMap(BOOL AllStations) -{ - struct STATIONRECORD * ptr = *StationRecords; - int blackColor = BlackPixel(display, DefaultScreen(display)); - int whiteColor = WhitePixel(display, DefaultScreen(display)); - int Changed = 0; - char msg[80]; - int i = 0, len; - - while (ptr) - { - Changed += DrawStation(ptr, AllStations); - i++; - ptr = ptr->Next; - } - -// NeedRefresh = FALSE; -// LastRefresh = time(NULL); - -// if (RecsDeleted) -// RefreshStationList();] - - len = sprintf(msg, "%d Stations Zoom = %d", i, Zoom); - XDrawImageString(display, win, gc, 20, 20, msg, len); - - StationCount = i; - return Changed; -} - - - -void j_putRGBScanline(BYTE *jpegline, - int widthPix, - unsigned char *outBuf, - int row, int XOffset, int YOffset) -{ - // Offsets are in tiles, not pixels - - int offset = row * WIDTH * Bytesperpixel; //widthPix - int count; - unsigned int val; - - offset += XOffset * 256 * Bytesperpixel; - offset += YOffset * 256 * WIDTH * Bytesperpixel; - - for (count = 0; count < 256; count++) - { - if (Bytesperpixel == 2) - { - val = (*(jpegline + count * 3 + 2) >> 3); - val |= ((*(jpegline + count * 3 + 1) >> 2) << 5); - val |= ((*(jpegline + count * 3 + 0) >> 3) << 11); - *(outBuf + offset++) = (val & 0xff); - *(outBuf + offset++) = (unsigned char)(val >> 8); - } - else - { - *(outBuf + offset++) = *(jpegline + count * 3 + 2); // Blue - *(outBuf + offset++) = *(jpegline + count * 3 + 1); // Green - *(outBuf + offset++) = *(jpegline + count * 3 + 0); // Red - offset++; - } - } -} - -// -// stash a gray scanline -// - -void j_putGrayScanlineToRGB(BYTE *jpegline, - int widthPix, - BYTE *outBuf, - int row) -{ - int offset = row * widthPix * 3; - int count; - for (count=0;countalloc_sarray) - ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); - - /* Step 6: while (scan lines remain to be read) */ - /* jpeg_read_scanlines(...); */ - - /* Here we use the library's state variable cinfo.output_scanline as the - * loop counter, so that we don't have to keep track ourselves. - */ - while (cinfo.output_scanline < cinfo.output_height) { - /* jpeg_read_scanlines expects an array of pointers to scanlines. - * Here the array is only one element long, but you could ask for - * more than one scanline at a time if that's more convenient. - */ - (void) jpeg_read_scanlines(&cinfo, buffer, 1); - /* Assume put_scanline_someplace wants a pointer and sample count. */ - - // asuumer all 3-components are RGBs - if (cinfo.out_color_components==3) { - - j_putRGBScanline(buffer[0], - *width, - Image, - cinfo.output_scanline-1, XOffset, YOffset); - - } else if (cinfo.out_color_components==1) { - - // assume all single component images are grayscale - j_putGrayScanlineToRGB(buffer[0], - *width, - Image, - cinfo.output_scanline-1); - - } - - } - - /* Step 7: Finish decompression */ - - (void) jpeg_finish_decompress(&cinfo); - /* We can ignore the return value since suspension is not possible - * with the stdio data source. - */ - - /* Step 8: Release JPEG decompression object */ - - /* This is an important step since it will release a good deal of memory. */ - jpeg_destroy_decompress(&cinfo); - - /* After finish_decompress, we can close the input file. - * Here we postpone it until after no more JPEG errors are possible, - * so as to simplify the setjmp error logic above. (Actually, I don't - * think that jpeg_destroy can do an error exit, but why assume anything...) - */ - fclose(infile); - - /* At this point you may want to check to see whether any corrupt-data - * warnings occurred (test whether jerr.pub.num_warnings is nonzero). - */ - - return 0; -} -// store a scanline to our data buffer - -void j_putRGBScanline(BYTE *jpegline, - int widthPix, - BYTE *outBuf, - int row, int X, int Y); - -void j_putGrayScanlineToRGB(BYTE *jpegline, - int widthPix, - BYTE *outBuf, - int row); - -VOID LoadImageTile(int Zoom, int startx, int starty, int x, int y); - -VOID RefreshTile(char * FN, int TileZoom, int Tilex, int Tiley) -{ - // Called when a new tile has been diwnloaded from OSM - - int StartRow, StartCol; - UCHAR * pbImage = NULL; - int x, y, i, j; - int ImgChannels; - - if (TileZoom != Zoom) - return; // Zoom level has changed - - x = Tilex - SetBaseX; - y = Tiley - SetBaseY; - - if (x < 0 || x > WIDTHTILES -1 || y < 0 || y > HEIGHTTILES - 1) - return; // Tile isn't part of current image; - - LoadImageTile (Zoom, Tilex, Tiley, x, y); - NeedRedraw = 1; - -// XPutImage (display, win, gc, image, ScrollX, ScrollY, leftBorder, topBorder, cxImgSize, cyImgSize); -} - - -VOID LoadImageTile(int Zoom, int startx, int starty, int x, int y) -{ - char FN[100]; - int i, j; - int StartRow; - int StartCol; - char Tile[100]; - UCHAR * pbImage = NULL; - int ImgChannels; - BOOL JPG=FALSE; - struct stat STAT; - int cx, cy; - - int Limit = (int)pow(2, Zoom); -/* - printf("LoadImage %d %d %d\n", Limit, startx, startx); - - if (startx < 0) - startx = startx + WIDTHTILES; - else - if (startx > WIDTHTILES - 1) - startx = WIDTHTILES - startx; - - if (starty < 0) - starty = starty + HEIGHTTILES; - else - if (starty > HEIGHTTILES -1 ) - starty = HEIGHTTILES - starty; - - if (startx < 0 || startx > WIDTHTILES) - x = WIDTHTILES / 2; - - if (starty < 0 || y > HEIGHTTILES) - starty = HEIGHTTILES /2; - - printf("LoadImage %d %d %d\n", Limit, startx, starty); -*/ - if ((startx) >= Limit || (starty) >= Limit || startx< 0 || starty < 0) - { -// printf("Not Loading %d %d %d\n",Limit, startx, startx ); - return; //goto NoFile; - } - - // May be PNG or JPG - - sprintf(Tile, "/%02d/%d/%d.png", Zoom, startx, starty); - sprintf(FN, "%s%s", OSMDir, Tile); - - if (stat(FN, &STAT) == 0) - goto gotfile; - - sprintf(Tile, "/%02d/%d/%d.jpg", Zoom, startx, starty); - sprintf(FN, "%s%s", OSMDir, Tile); - - JPG = TRUE; - - if (stat(FN, &STAT) == 0) - goto gotfile; - - - OSMGet(startx, starty, Zoom); - return; - -gotfile: - - if (JPG) - { - JpegFileToRGB(FN, &cx, &cy, x, y); - ImgChannels = 3; - } - else - { - int offset; - int cxImgSize, cyImgSize; - UCHAR * ImageSave; - - LoadImageFile (NULL, FN, &pbImage, &cxImgSize, &cyImgSize, &ImgChannels, &bkgColor); - -// printf("%d %d %d\n", cxImgSize, cyImgSize, ImgChannels); -// ImgChannels = 4; - StartCol = x * Bytesperpixel * 256; - StartRow = y * 256; - -// printf("WIDTH %d Height %d Bytesperpixel = %d x = %d y = %d\n", WIDTH, HEIGHT, Bytesperpixel, x, y); - if (pbImage == NULL) - { - pbImage = malloc(256 * ImgChannels * 256); - memset(pbImage, 0x40, 256 * ImgChannels * 256); - } - - ImageSave = pbImage; - - offset = ((StartRow) * WIDTH * ImgChannels) + StartCol; - -// printf ("x %d y %d offset %d \n", x, y, offset); - - - for (i = 0; i < 256; i++) - { - int count, val; - - offset = ((StartRow + i) * WIDTH * Bytesperpixel) + StartCol; - - // this does one scan line - - for (count = 0; count < 256; count++) - { - if (Bytesperpixel == 2) - { - val = (*(pbImage + count * ImgChannels + 2) >> 3); - val |= ((*(pbImage + count * ImgChannels + 1) >> 2) << 5); - val |= ((*(pbImage + count * ImgChannels + 0) >> 3) << 11); - Image[offset++] = (val & 0xff); - Image[offset++] = (unsigned char)(val >> 8); - } - else - { - Image[offset++] = *(pbImage + count * ImgChannels + 2); // Blue - Image[offset++] = *(pbImage + count * ImgChannels + 1); // Green - Image[offset++] = *(pbImage + count * ImgChannels + 0); // Red - offset++; - } - } - pbImage += ImgChannels * 256; - } - - free(ImageSave); - } -} - - -VOID LoadImageSet(int Zoom, int TileX, int TileY) -{ - int x, y; - - if (SetBaseX != TileX || SetBaseY != TileY) - { - // Only Load if changed - - SetBaseX = TileX; // Lowest Tiles in currently loaded set - SetBaseY = TileY; - - memset(Image, 0, WIDTH * Bytesperpixel * HEIGHT); - XClearWindow(display, win); - - for (y = 0; y < HEIGHTTILES; y++) - { - for (x = 0; x < WIDTHTILES; x++) - { - LoadImageTile(Zoom, TileX + x, TileY + y, x, y); - } - } - RefreshStationMap(TRUE); - } - XPutImage (display, win, gc, image, ScrollX, ScrollY, leftBorder, topBorder, cxImgSize, cyImgSize); -} - -BYTE * ReadIcons(char * fileName, UINT *width, UINT *height) -{ - struct jpeg_decompress_struct cinfo; - struct my_error_mgr jmerr; - struct jpeg_error_mgr jerr; - FILE * infile=NULL; /* source file */ - - JSAMPARRAY buffer; /* Output row buffer */ - int row_stride; /* physical row width in output buffer */ - char buf[250]; - BYTE *dataBuf; - - *width=0; - *height=0; - - if ((infile = fopen(fileName, "rb")) == NULL) { - return NULL; - } - - cinfo.err = jpeg_std_error(&jerr); - - if (setjmp(jmerr.setjmp_buffer)) { - /* If we get here, the JPEG code has signaled an error. - * We need to clean up the JPEG object, close the input file, and return. - */ - - jpeg_destroy_decompress(&cinfo); - - if (infile!=NULL) - fclose(infile); - return NULL; - } - - - jpeg_create_decompress(&cinfo); - - jpeg_stdio_src(&cinfo, infile); - - (void) jpeg_read_header(&cinfo, TRUE); - - (void) jpeg_start_decompress(&cinfo); - - dataBuf = malloc(cinfo.output_width * 4 * cinfo.output_height); - memset(dataBuf, 0, cinfo.output_width * 4 * cinfo.output_height); - - if (dataBuf==NULL) - { - jpeg_destroy_decompress(&cinfo); - fclose(infile); - return NULL; - } - - // how big is this thing gonna be? - *width = cinfo.output_width; - *height = cinfo.output_height; - - /* JSAMPLEs per row in output buffer */ - row_stride = cinfo.output_width * cinfo.output_components; - - /* Make a one-row-high sample array that will go away when done with image */ - buffer = (*cinfo.mem->alloc_sarray) - ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); - - /* Step 6: while (scan lines remain to be read) */ - /* jpeg_read_scanlines(...); */ - - /* Here we use the library's state variable cinfo.output_scanline as the - * loop counter, so that we don't have to keep track ourselves. - */ - while (cinfo.output_scanline < cinfo.output_height) - { - int offset; - int count; - unsigned int val; - - (void) jpeg_read_scanlines(&cinfo, buffer, 1); - - offset = (cinfo.output_scanline-1) * cinfo.output_width * Bytesperpixel; - - for (count = 0; count < cinfo.output_width; count++) - { - if (Bytesperpixel == 2) - { - val = (*(buffer[0] + count * 3 + 2) >> 3); - val |= ((*(buffer[0] + count * 3 + 1) >> 2) << 5); - val |= ((*(buffer[0] + count * 3 + 0) >> 3) << 11); - *(dataBuf + offset++) = (val & 0xff); - *(dataBuf + offset++) = (unsigned char)(val >> 8); - } - else - { - *(dataBuf + offset++) = *(buffer[0] + count * 3 + 2); // Blue - *(dataBuf + offset++) = *(buffer[0] + count * 3 + 1); // Green - *(dataBuf + offset++) = *(buffer[0] + count * 3 + 0); // Red - offset++; - } - } - } - - (void) jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - fclose(infile); - return dataBuf; -} -// store a scanline to our data buffer - -void ZoomIn() -{ - if (Zoom < 16) - { - Zoom ++; - CentrePositionToMouse(MouseLat, MouseLon); - TileX = SetBaseX; - TileY = SetBaseY; - NeedRefresh = TRUE; - } -} -void ZoomOut() -{ - if (Zoom > 1) - { - Zoom --; - CentrePositionToMouse(MouseLat, MouseLon); - TileX = SetBaseX; - TileY = SetBaseY; - if (Zoom == 1) - ScrollX = ScrollY = 0; - - NeedRefresh = TRUE; - } -} - -config_t cfg; -config_setting_t *croot, *group; - -int GetIntValue(config_setting_t * group, char * name, int defaultval) -{ - config_setting_t *setting; - - setting = config_setting_get_member (group, name); - if (setting) - return config_setting_get_int (setting); - - return defaultval; -} - -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); -} - -BOOL GetStringValue(config_setting_t * group, char * name, char * value) -{ - const char * str; - config_setting_t *setting; - - setting = config_setting_get_member (group, name); - - if (setting) - { - str = config_setting_get_string (setting); - strcpy(value, str); - return TRUE; - } - return FALSE; -} - -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); - -} - - - -enum -{ - COL_FROM = 0, - COL_TO, - COL_SEQ, - COL_TIME, - COL_RECEIVED, - NUM_COLS -} ; - - -void CancelMessageSend (GtkWidget *menuitem, struct APRSMESSAGE * userdata) -{ -/* - userdata->Retries = 0; - userdata->RetryTimer = 0; - userdata->Cancelled = TRUE; - UpdateTXMessageLine(userdata); -*/ -} - - -void view_popup_menu_onDoNothing (GtkWidget *menuitem, gpointer userdata) -{ - GtkTreeView *treeview = GTK_TREE_VIEW(userdata); -} - -void view_popup_menu (GtkWidget *treeview, GdkEventButton *event, struct APRSMESSAGE * userdata) -{ - GtkWidget *menu, *menuitem1,*menuitem2 ; - char Msg[80]; - - sprintf(Msg,"Cancel Message Seq %s to %s?", userdata->Seq, userdata->ToCall); - - menu = gtk_menu_new(); - - menuitem1 = gtk_menu_item_new_with_label(Msg); - menuitem2 = gtk_menu_item_new_with_label("Return"); - - g_signal_connect(menuitem1, "activate", - (GCallback) CancelMessageSend, (gpointer)userdata); - g_signal_connect(menuitem2, "activate", - (GCallback) view_popup_menu_onDoNothing, treeview); - - if (userdata->Retries) // Not active so cant cancel - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem1); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem2); - - gtk_widget_show_all(menu); - - /* Note: event can be NULL here when called from view_onPopupMenu; - * gdk_event_get_time() accepts a NULL argument */ - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, - (event != NULL) ? event->button : 0, - gdk_event_get_time((GdkEvent*)event)); - } - - -gboolean view_onButtonPressed (GtkWidget *treeview, GdkEventButton *event, gpointer userdata) -{ - // Right click on TX Message window. If a message is selected, - // Pop up a Cancel Message Window - - if (event->type == GDK_BUTTON_PRESS && event->button == 3) - { - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; - struct APRSMESSAGE * ptr = SMEM->OutstandingMsgs; - - if (ptr == 0) - return TRUE; - - // Make sure the entry that was clicked is selected - - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); - - if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview), - (gint) event->x, (gint) event->y, &path, NULL, NULL, NULL)) - { - gtk_tree_selection_unselect_all(selection); - gtk_tree_selection_select_path(selection, path); - gtk_tree_path_free(path); - } - - - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); - - if (gtk_tree_selection_get_selected(selection, &model, &iter)) - { - gchar *Seq; - - gtk_tree_model_get (model, &iter, 1, &Seq, -1); - - // Find the message - - while (ptr) - { - if (strcmp(ptr->Seq, Seq) == 0) - { - view_popup_menu(treeview, event, ptr); - g_free(Seq); - return TRUE; - } - ptr = ptr->Next; - } - - g_free(Seq); - g_print ("Msg not found.\n"); - } - g_print ("no row selected.\n"); - } - - return FALSE; /* we did not handle this */ -} - -gboolean view_onPopupMenu (GtkWidget *treeview, gpointer userdata) -{ - view_popup_menu(treeview, NULL, userdata); - - return TRUE; /* we handled this */ -} - - -static GtkWidget *create_sent_window( void ) -{ - GtkCellRenderer *renderer; - GtkTreeModel *model; - GtkTreeIter iter; - - view = gtk_tree_view_new(); - - gtk_signal_connect (GTK_OBJECT (view), "row_activated", - GTK_SIGNAL_FUNC (SelectTXMsg), NULL); - - - g_signal_connect(view, "button-press-event", (GCallback) view_onButtonPressed, NULL); - g_signal_connect(view, "popup-menu", (GCallback) view_onPopupMenu, NULL); - - - - - renderer = gtk_cell_renderer_text_new(); - renderer->ypad = 0; - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (view), -1, "To", renderer, "text", 0, NULL); - - renderer = gtk_cell_renderer_text_new (); - renderer->ypad = 0; - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (view), -1, "Seq", renderer, "text", 1, NULL); - - renderer = gtk_cell_renderer_text_new (); - renderer->ypad = 0; - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (view), -1, "State", renderer, "text", 2, NULL); - - renderer = gtk_cell_renderer_text_new (); - renderer->ypad = 0; - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (view), -1, "Time", renderer, "text", 3, NULL); - - renderer = gtk_cell_renderer_text_new (); - renderer->ypad = 0; - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (view), -1, "Sent", renderer, "text", 4, NULL); - - sentitems = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); - - model = GTK_TREE_MODEL(sentitems); - - gtk_tree_view_set_model((GtkTreeView *)view, model); - - /* The tree view has acquired its own reference to the - * model, so we can drop ours. That way the model will - * be freed automatically when the tree view is destroyed */ - - g_object_unref (model); - -// gtk_container_add (GTK_CONTAINER (window), view2); - - scrolledwin = gtk_scrolled_window_new(NULL,NULL); - gtk_container_set_border_width(GTK_CONTAINER(scrolledwin), 1); -// gtk_widget_set_size_request(scrolledwin, 300, 80); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin), GTK_SHADOW_IN); -// gtk_container_add(GTK_CONTAINER(scrolledwin), view); - //tree_view = gtk_tree_view_new(); - gtk_container_add(GTK_CONTAINER (scrolledwin), view); - //gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (view)); - //gtk_widget_show(tree_view); -/* - gtk_table_attach (GTK_TABLE (table), scrolledwin,0, 1, 0, 1, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); -*/ - gtk_widget_show(scrolledwin); - return scrolledwin; - -} - -GdkPixbuf *create_pixbuf(const gchar * filename) -{ - GdkPixbuf *pixbuf; - GError *error = NULL; - pixbuf = gdk_pixbuf_new_from_file(filename, &error); - if(!pixbuf) { - fprintf(stderr, "%s\n", error->message); - g_error_free(error); - } - return pixbuf; -} - - -static GtkWidget *create_received_window(void) -{ - GtkCellRenderer *renderer; - - view2 = gtk_tree_view_new(); - -// gtk_tree_view_set_fixed_height_mode(view2, TRUE); - - renderer = gtk_cell_renderer_text_new(); - renderer->ypad = 0; - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view2), -1, "From", renderer, "text", COL_FROM, NULL); - - renderer = gtk_cell_renderer_text_new (); - renderer->ypad = 0; - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view2), -1, "To", renderer, "text", COL_TO, NULL); - - renderer = gtk_cell_renderer_text_new (); - renderer->ypad = 0; - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view2), -1, "Seq", renderer, "text", COL_SEQ, NULL); - - renderer = gtk_cell_renderer_text_new (); - renderer->ypad = 0; - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view2), -1, "Time", renderer, "text", COL_TIME, NULL); - - renderer = gtk_cell_renderer_text_new (); - renderer->ypad = 0; - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view2), -1, "Received", renderer, "text", COL_RECEIVED, NULL); - - receiveditems = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); - - gtk_tree_view_set_model((GtkTreeView *)view2, (GtkTreeModel *)receiveditems); - - /* The tree view has acquired its own reference to the - * model, so we can drop ours. That way the model will - * be freed automatically when the tree view is destroyed */ - - g_object_unref (receiveditems); - - scrolledwin2 = gtk_scrolled_window_new(NULL,NULL); - gtk_container_set_border_width(GTK_CONTAINER(scrolledwin2), 2); -// gtk_widget_set_size_request(scrolledwin2, 300, 80); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin2),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin2), GTK_SHADOW_IN); - gtk_container_add(GTK_CONTAINER(scrolledwin2), view2); - - gtk_widget_show(scrolledwin2); - - return scrolledwin2; - -} - -char ToCalls[1024] = ""; - -VOID SendAPRSMessage(const char * Text, char * ToCall); - -void enter_callback( GtkWidget *widget, - GtkWidget *entry ) -{ - const gchar *entry_text; - entry_text = gtk_entry_get_text (GTK_ENTRY (entry)); - gchar * tocall = strupr(gtk_combo_box_text_get_active_text((GtkComboBoxText *)combo)); - char Key[32]; - - if (strlen(tocall) > 9) - tocall[9] = 0; - - sprintf(Key, "|%s|", tocall); - - if (tocall) - { - SendAPRSMessage(entry_text, tocall); - - // if new call add to combo box - - if (strstr(ToCalls, Key) == 0) - { - if (strlen(ToCalls) < 1000) - strcat(ToCalls, Key); - - gtk_combo_box_text_prepend_text ((GtkComboBoxText *)combo, tocall); - } - - g_free(tocall); - gtk_entry_set_text (GTK_ENTRY (entry), ""); - } -} - - -void SelectTXMsg (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) -{ - GtkTreeIter iter; - GtkTreeModel *model; - struct APRSMESSAGE * ptr = SMEM->OutstandingMsgs; - - if (ptr == 0) - return; - - model = gtk_tree_view_get_model(tree_view); - - if (gtk_tree_model_get_iter(model, &iter, path)) - { - gchar *seq; - - gtk_tree_model_get(model, &iter, 1, &seq, -1); - - g_print ("Double-clicked row contains seq %s\n", seq); - g_free(seq); - } - - return; -} - - -VOID GTKThread() -{ - gtk_main(); -} - -int msgWinWidth = 300; -int msgWinHeight = 300; -int msgWinX = 100; -int msgWinY = 100; -int Split = 100; // Rx/Tx Window split - - -void frame_callback(GtkWindow *window, GdkEvent *event, gpointer data) -{ - int x, y; - char buf[10]; - - msgWinX = event->configure.x; - msgWinY = event->configure.y; - msgWinWidth = event->configure.width; - msgWinHeight = event->configure.height; - - // gtk_widget_set_size_request(entry, msgWinWidth - 210 , 20); //gtk_entry_new_with_buffer(text); - - // gtk_window_set_title(window, buf); - // gtk_window_set_title (GTK_WINDOW (window), "BPQAPRS Messaging"); -} - -BOOL OnlyMine = FALSE; -BOOL OnlySeq = FALSE; -BOOL ShowBulls = FALSE; -BOOL AllSSID = FALSE; - - -void check_callback(GtkButton *button, gpointer user_data) -{ - GtkTreeIter iter; - struct APRSMESSAGE * ptr = SMEM->Messages; - int n = 0; - - char BaseFrom[10]; - - OnlyMine = gtk_toggle_button_get_active((GtkToggleButton *)check1); - OnlySeq = gtk_toggle_button_get_active((GtkToggleButton *)check2); - ShowBulls = gtk_toggle_button_get_active((GtkToggleButton *)check3); - AllSSID = gtk_toggle_button_get_active((GtkToggleButton *)check4); - - // rewite the Message display with new filter - - if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(receiveditems), &iter, NULL, 0)) - { - while (gtk_list_store_remove(receiveditems, &iter)) - {} - } - while (ptr) - { - if (memcmp(ptr->ToCall, "BLN", 3)== 0) - if (ShowBulls == TRUE) - goto wantit; - - if (strcmp(ptr->ToCall, APRSCall) == 0) // to me? - goto wantit; - - if (AllSSID) - { - memcpy(BaseFrom, ptr->ToCall, 10); - strlop(BaseFrom, ' '); - 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: - - gtk_list_store_insert_with_values( - receiveditems, &iter, -1, - COL_FROM, ptr->FromCall, - COL_TO, ptr->ToCall, - COL_SEQ, ptr->Seq, - COL_TIME, ptr->Time, - COL_RECEIVED, ptr->Text, -1); - - ptr = ptr->Next; - n++; - } - - - if (n) - gtk_tree_view_scroll_to_cell((GtkTreeView *)view2, - gtk_tree_model_get_path (GTK_TREE_MODEL(receiveditems), &iter), NULL, FALSE, 0, 0); - - -} - - -void button_callback(GtkButton *button, gpointer user_data) -{ - SMEM->ClearRX = 1; -} - - -void button2_callback(GtkButton *button, gpointer user_data) -{ - // Clear Sent Messages - - SMEM->ClearTX = 1; -} - - -static gboolean delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) -{ - // Don't allow window to be closed - - return TRUE; -} - -void SaveConfig() -{ - memset((void *)&cfg, 0, sizeof(config_t)); - - config_init(&cfg); - - croot = config_root_setting(&cfg); - - gtk_window_get_size(GTK_WINDOW(window), &msgWinWidth, &msgWinHeight); - gtk_window_get_position(GTK_WINDOW(window), &msgWinX, &msgWinY); - Split = gtk_paned_get_position((GtkPaned *)vpaned); - - group = config_setting_add(croot, "APRS", CONFIG_TYPE_GROUP); - - SaveIntValue(group, "Zoom", Zoom); - SaveIntValue(group, "SetBaseX", SetBaseX); - SaveIntValue(group, "SetBaseY", SetBaseY); - SaveIntValue(group, "ScrollX", ScrollX); - SaveIntValue(group, "ScrollY", ScrollY); - SaveIntValue(group, "WindowX", WindowX); - SaveIntValue(group, "WindowY", WindowY); - SaveIntValue(group, "WindowWidth", WindowWidth); - SaveIntValue(group, "WindowHeight", WindowHeight); - SaveIntValue(group, "WIDTHTILES", WIDTHTILES); - SaveIntValue(group, "HEIGHTTILES", HEIGHTTILES); - SaveIntValue(group, "msgWinWidth", msgWinWidth); - SaveIntValue(group, "msgWinHeight", msgWinHeight); - SaveIntValue(group, "msgWinX", msgWinX); - SaveIntValue(group, "msgWinY", msgWinY); - SaveIntValue(group, "Split", Split); - - SaveIntValue(group, "OnlyMine", OnlyMine); - SaveIntValue(group, "OnlySeq", OnlySeq); - SaveIntValue(group, "ShowBulls", ShowBulls); - - SaveIntValue(group, "LocalTime", LocalTime); - SaveIntValue(group, "KM", KM); - SaveIntValue(group, "AddViewToFilter", AddViewToFilter); - SaveStringValue(group, "ISFilter", ISFilter); - - - SaveIntValue(group, "CreateJPEG", CreateJPEG); - SaveIntValue(group, "JPEGInterval", JPEGInterval); - SaveStringValue(group, "JPEGFileName", JPEGFileName); - - if(!config_write_file(&cfg, "BPQAPRS.cfg")) - printf("Error while writing config file.\n"); - else - printf("Config Saved\n"); - - config_destroy(&cfg); - - printf("%s\n", ToCalls); -} - -// Linux Signal Handlers - -BOOL Running = TRUE; - -static void sigterm_handler(int sig) -{ - printf("sigterm\n"); - Running = FALSE; -} - -static void sigint_handler(int sig) -{ - SaveConfig(); - Running = FALSE; - exit(0); -} - -int main(int argc, char *argv[]) -{ - UCHAR * pbImage = NULL; - char FN[256]; - int fd; - int x, y; - time_t TimeLoaded = time(NULL); - struct stat STAT; - char * Env; - char BPQDirectory[256]; - char SharedName[256]; - char * ptr1; - - int SharedSize; - - double vals[10]; - int screen_number, depth, bitmap_pad, status; - unsigned long white; - unsigned long black; - Visual * visual; - unsigned int i, j; - Pixmap pixmap, popuppixmap; - - int x11_fd; - fd_set in_fds; - - struct timeval tv; - XEvent event; - XConfigureEvent xce; - XKeyEvent xkeyev; - Time lastupevent; - - char text[256]; - long unsigned int key; - - int LastX, LastY; // Saved mouse position when button down - int MovedX, MovedY; - - double sx, sy; - UCHAR * APRSStationMemory; - Atom wmDeleteMessage; - PangoFontDescription *font_desc; - GtkTreeIter iter; - -#ifndef WIN32 - signal(SIGHUP, SIG_IGN); - signal(SIGINT, sigint_handler); - signal(SIGTERM, sigterm_handler); - signal(SIGPIPE, SIG_IGN); -#endif - - printf("G8BPQ APRS Client for Linux Version 1.1.14.7 \n"); - printf("Copyright(c) 2004-2021 John Wiseman G8BPQ\n"); - printf("APRS is a registered trademark of Bob Bruninga.\n"); - printf("This software is based in part on the work of the Independent JPEG Group.\n"); - printf("Mapping from OpenStreetMap (http://openstreetmap.org)\n"); - printf("Imagery (c) OpenMapTiles (https://openmaptiles.org)\n\n"); - - if (argc > 1 && argv[1] && stricmp(argv[1], "-v") == 0) - return 0; - - config_init(&cfg); - - if (argc > 1 && argv[1] && stricmp(argv[1], "multiple") == 0) - { - multiple = 1; - printf("Running in multiple instance mode\n\n"); - } - - /* Read the file. If there is an error, report it and exit. */ - - if(!config_read_file(&cfg, "BPQAPRS.cfg")) - { - fprintf(stderr, "%d - %s\n", - config_error_line(&cfg), config_error_text(&cfg)); - config_destroy(&cfg); - } - else - { - group = config_lookup (&cfg, "APRS"); - - if (group) - { - Zoom = GetIntValue(group, "Zoom", 2); - TileX = GetIntValue(group, "SetBaseX", 0); - TileY = GetIntValue(group, "SetBaseY", 0); - ScrollX = GetIntValue(group, "ScrollX", 0); - ScrollY = GetIntValue(group, "ScrollY", 0); - WindowX = GetIntValue(group, "WindowX", 100); - WindowY = GetIntValue(group, "WindowY", 100); - WindowWidth = GetIntValue(group, "WindowWidth", 788); - WindowHeight = GetIntValue(group, "WindowHeight", 788); - HEIGHTTILES = GetIntValue(group, "HEIGHTTILES", 4); - WIDTHTILES = GetIntValue(group, "WIDTHTILES", 4); - - msgWinWidth = GetIntValue(group, "msgWinWidth", 300); - msgWinHeight = GetIntValue(group, "msgWinHeight", 300); - msgWinX = GetIntValue(group, "msgWinX", 100); - msgWinY = GetIntValue(group, "msgWinY", 100); - Split = GetIntValue(group, "Split", 100); - - OnlyMine = GetIntValue(group, "OnlyMine", 0); - OnlySeq = GetIntValue(group, "OnlySeq", 1); - ShowBulls = GetIntValue(group, "ShowBulls", 0); - - LocalTime = GetIntValue(group, "LocalTime", 0); - KM = GetIntValue(group, "KM", 0); - - AddViewToFilter = GetIntValue(group, "AddViewToFilter", 0); - - CreateJPEG = GetIntValue(group, "CreateJPEG", 1); - JPEGInterval = GetIntValue(group, "JPEGInterval", 300); - GetStringValue(group, "JPEGFileName", JPEGFileName); - GetStringValue(group, "ISFilter", ISFilter); - } - } - - if (Zoom == 0) - Zoom = 2; - - HEIGHT = HEIGHTTILES * 256; - WIDTH = WIDTHTILES * 256; - - Env = getenv("DISPLAY"); - - if (Env == NULL) - { - printf("DISPLAY is not set - can't run without X\n", Env); - return 0; - } - - printf("DISPLAY is set to %s\n", Env); - - if (strstr(Env, "localhost:1")) - printf("!!! WARNING !!! X session seems to be tunneled over an SSH session\nThis program will run much faster if you set DISPLAY to the Host running your X Server\n"); - - // Get shared memory - - // Append last bit of current directory to shared name - - getcwd(BPQDirectory, 256); - 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); - - - fd = shm_open(SharedName, O_RDWR, S_IRUSR | S_IWUSR); - if (fd == -1) - { - printf("Open APRS Shared Memory %s Failed\n", SharedName); - return 0; - } - else - { - // Map shared memory object - - Shared = mmap((void *)APRSSHAREDMEMORYBASE, 8192 * 4096, - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0); - - if (Shared == MAP_FAILED) - { - printf("Map APRS Shared Memory Failed\n"); - APRSStationMemory = NULL; - return 0; - } - } - - if (Shared != (void *)APRSSHAREDMEMORYBASE) - { - printf("Map APRS Shared Memory Allocated at wrong address %x Should be 0x43000000\n", Shared); - return 0; - } - - printf("Map APRS Shared Memory Allocated at %x\n", Shared); - - - SMEM = (struct SharedMem *)Shared; - SharedSize = SMEM->SharedMemLen; - - printf("Shared Memory Size %d Max %d\n", SharedSize, 8192 * 4096); - - if (SharedSize > 8192 * 4096) - { - printf("MAXSTATIONS too high\n"); - return 0; - } - - StnRecordBase = Shared + 32; - StationRecords = (struct STATIONRECORD**)StnRecordBase; - - ControlRecord = (struct STATIONRECORD*)StnRecordBase; - - memset(APRSCall, 0x20, 9); - memcpy(APRSCall, ControlRecord->Callsign, strlen(ControlRecord->Callsign)); - - printf("LinBPQ Configured with MaxStations %d APRSCall %s\n", - ControlRecord->LastPort, APRSCall); - - memcpy(BaseCall, APRSCall, 10); // Get call less SSID - strlop(BaseCall, ' '); - strlop(BaseCall, '-'); - - // Remap with Server's view of MaxStations - -// munmap(APRSStationMemory, 4096 * 4096); - -// perror("munmap"); - -// Shared = mmap((void *)APRSSHAREDMEMORYBASE, SharedSize, -// PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - -// printf("Map APRS Shared Memory Allocated at %x\n", Shared); - - if (Shared == MAP_FAILED) - { - printf("Extend APRS Shared Memory Failed\n"); - APRSStationMemory = NULL; - return 0; - } - - SMEM->NeedRefresh = 1; // Initial Load of messages - - maxfd = sfd = socket(AF_UNIX, SOCK_DGRAM, 0); - - if (sfd == -1) - { - perror("Socket"); - } - else - { - memset(&my_addr, 0, sizeof(struct sockaddr_un)); - my_addr.sun_family = AF_UNIX; - strncpy(my_addr.sun_path, RX_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, TX_SOCK_PATH, sizeof(peer_addr.sun_path) - 1); - - unlink(RX_SOCK_PATH); - - if (bind(sfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr_un)) == -1) - perror("bind"); - } - - XInitThreads(); - - ResolveThread(); - _beginthread(OSMThread, 0, NULL); - - - display = XOpenDisplay(NULL); - - if (! display) - { - printf("Couldn't open X display\n"); - return 1; - } - - screen_number = DefaultScreen (display); - depth = DefaultDepth (display, screen_number); - visual = DefaultVisual (display, screen_number); - gc = DefaultGC (display, screen_number); - bitmap_pad = BitmapPad (display); - white = WhitePixel (display, screen_number); - black = BlackPixel (display, screen_number); - root = DefaultRootWindow (display); - - if (depth == 16) - Bytesperpixel = 2; - - Image = malloc(WIDTH * Bytesperpixel * HEIGHT + 100); // Seems past last byte gets corrupt - - if (mkdir(OSMDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) - { - if (errno != 17) // File exists - { - printf("Error Creating %s\n", OSMDir); - perror("mkdir"); - } - } - - for (i = 0; i < 20; i++) - { - sprintf(FN, "%s/%02d", OSMDir, i); - if (mkdir(FN, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) - { - if (errno != 17) // File exists - { - printf("Error Creating %s\n", FN); - perror("mkdir"); - } - } - } - - // Read Icons - - iconImage = ReadIcons("BPQAPRS/Symbols.jpg", &x, &y); - - if (x == 0) - printf("Couldn't load Icons\n"); - -// win = XCreateSimpleWindow (display, root, 50, 50, 800, 800, 0, black, white); - win = XCreateWindow (display, root, 50, 50, 788, 788, 0, depth, CopyFromParent, CopyFromParent, 0, 0); - XStoreName(display, win, "BPQAPRS Map"); - - wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False); - XSetWMProtocols(display, win, &wmDeleteMessage, 1); - -// XSelectInput(display, win, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask); - - XSelectInput(display, win, ExposureMask | KeyPressMask | PointerMotionMask | - ButtonPressMask | ButtonReleaseMask | StructureNotifyMask); - - XSetWindowBackground(display, win, 0xffffff); - XClearWindow(display, win); - XMapWindow (display, win); - - XMoveResizeWindow(display, win, WindowX, WindowY, WindowWidth, WindowHeight); - - image = XCreateImage (display, visual, depth, ZPixmap, 0, NULL, WIDTH, HEIGHT, bitmap_pad, 0); - - printf("depth : %d\nbitmap_pad : %d\nimage bpp : %d\n", depth, bitmap_pad, image->bits_per_pixel); - - image->data = Image; - - pixmap = XCreatePixmap (display, root, WIDTH, HEIGHT, depth); - - XSetLineAttributes(display, gc, 2, LineSolid, CapNotLast, JoinMiter); - - SetBaseX = -1; // force reload - SetBaseY = -1; - - LoadImageSet(Zoom, TileX, TileY); // Loads 1024 * 1024 Block - - x11_fd = ConnectionNumber(display); - - if (x11_fd > maxfd) - maxfd = x11_fd; - - gtk_init (&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size(GTK_WINDOW (window), msgWinWidth, msgWinHeight); - gtk_widget_set_uposition(GTK_WIDGET(window),msgWinX, msgWinY); - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - gtk_window_set_resizable(GTK_WINDOW (window), TRUE); -// g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (close_application), NULL); - gtk_window_set_title (GTK_WINDOW (window), "BPQAPRS Messaging"); - gtk_container_set_border_width(GTK_CONTAINER (window), 0); - - // Load bpqicon if present - - if (stat("bpqicon.png", &STAT) == 0) - gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf("bpqicon.png")); - - //gtk_window_get_frame_dimensions(GTK_WINDOW(window),&left,&top,&right,&bottom); - - - gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL); - -// g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(frame_callback), NULL); - - // Create a box for the menu - - box1 = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (window), box1); - - checklabel = gtk_label_new(" "); - - check1 = gtk_check_button_new_with_label ("Show only My Msgs "); - check4 = gtk_check_button_new_with_label ("All SSIDs "); - check2 = gtk_check_button_new_with_label ("Show only Sequenced Msgs "); - check3 = gtk_check_button_new_with_label ("Show Bulls "); - - button = gtk_button_new_with_label("Clear RX"); - button2 = gtk_button_new_with_label("Clear TX"); - - gtk_toggle_button_set_active((GtkToggleButton *)check1, OnlyMine); - gtk_toggle_button_set_active((GtkToggleButton *)check2, OnlySeq); - gtk_toggle_button_set_active((GtkToggleButton *)check3, ShowBulls); - gtk_toggle_button_set_active((GtkToggleButton *)check4, AllSSID); - - g_signal_connect(G_OBJECT(check1), "clicked", G_CALLBACK(check_callback), "1"); - g_signal_connect(G_OBJECT(check2), "clicked", G_CALLBACK(check_callback), "2"); - g_signal_connect(G_OBJECT(check3), "clicked", G_CALLBACK(check_callback), "3"); - g_signal_connect(G_OBJECT(check4), "clicked", G_CALLBACK(check_callback), "4"); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_callback), "1"); - g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(button2_callback), "1"); - - // hBox for Check boxes - - checkhbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (checkhbox), checklabel, FALSE, FALSE, 0); - gtk_container_add (GTK_CONTAINER (checkhbox), check1); - gtk_container_add (GTK_CONTAINER (checkhbox), check4); - gtk_container_add (GTK_CONTAINER (checkhbox), check2); - gtk_container_add (GTK_CONTAINER (checkhbox), check3); - gtk_container_add (GTK_CONTAINER (checkhbox), button); - gtk_container_add (GTK_CONTAINER (checkhbox), button2); - checklabel = gtk_label_new(" "); - gtk_container_add (GTK_CONTAINER (checkhbox), checklabel); - - gtk_box_pack_start (GTK_BOX (box1), checkhbox, FALSE, FALSE, 0); - - box10 = gtk_vbox_new (FALSE, 0); - -// menubar = get_menubar_menu (window); - -// gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 1); - gtk_container_add (GTK_CONTAINER (box1), box10); - gtk_widget_show (window); - - vpaned = gtk_vpaned_new (); - gtk_container_add (GTK_CONTAINER (box10), vpaned); - gtk_paned_set_position(GTK_PANED(vpaned), Split); - gtk_widget_show (vpaned); - - /* Now create the contents of the two halves of the window */ - - frame1 = create_received_window(); - gtk_paned_add1 (GTK_PANED (vpaned), frame1); - gtk_widget_show (frame1); - - frame2 = create_sent_window(); - gtk_paned_add2 (GTK_PANED (vpaned), frame2); - gtk_widget_show (frame2); - -// separator = gtk_hseparator_new (); -// gtk_box_pack_start(GTK_BOX (box1), separator, FALSE, TRUE, 0); - - box2 = gtk_hbox_new(FALSE, 10); - gtk_container_set_border_width(GTK_CONTAINER (box2), 1); - gtk_box_pack_start(GTK_BOX (box10), box2, FALSE, FALSE, 0); - - // set up the text entry line - - label1 = gtk_label_new(" To"); - label2 = gtk_label_new("Message"); - combo = gtk_combo_box_text_new_with_entry(); - gtk_widget_set_size_request(combo, 100, 10); - - entry = gtk_entry_new(); -// gtk_widget_set_size_request(entry, 100, 20); //gtk_entry_new_with_buffer(text); - gtk_entry_set_max_length(GTK_ENTRY(entry), 100); - gtk_entry_set_activates_default(GTK_ENTRY (entry), TRUE); - g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK(enter_callback), (gpointer)entry); - gtk_box_pack_start(GTK_BOX(box2), label1, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(box2), combo, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(box2), label2, FALSE, FALSE, 0); - gtk_container_add(GTK_CONTAINER(box2), entry); - gtk_widget_grab_focus(entry); - - - - - font_desc=pango_font_description_from_string(MyFont); - gtk_widget_modify_font (entry, font_desc); - gtk_widget_modify_font (combo, font_desc); - gtk_widget_modify_font (view, font_desc); - gtk_widget_modify_font (view2, font_desc); - - gtk_widget_show_all (window); - gtk_widget_show (window); - - // Main loop - - _beginthread(GTKThread, 0, NULL); - _beginthread(SecTimer, 0, NULL); - - AutoFilterTimer = AUTOFILTERDELAY; // Update filter if no change for 30 secs - - while(Running) - { - unsigned char Msg[256]; - int numBytes; - struct STATIONRECORD * Station; - - FD_ZERO(&in_fds); - FD_SET(x11_fd, &in_fds); - FD_SET(sfd, &in_fds); - - tv.tv_usec = 0; - tv.tv_sec = 1; - - // Wait for X Event, Message from LinBPQ or a Timer - - if (select(maxfd+1, &in_fds, 0, 0, &tv)) - { - if (FD_ISSET(sfd, &in_fds)) - { - numBytes = recvfrom(sfd, Msg, 256, 0, NULL, NULL); - } - - // may be X event, but pick up later - } - else - { - // Handle timer here - - if (SMEM->NeedRefresh) - { - SMEM->NeedRefresh = FALSE; - - // Use Checkbox event to rewrite display - - check_callback((GtkButton *)check1, "1"); - RefreshTXList(); - } - - // NeedRedraw += RefreshStationMap(FALSE); // Draw new or moved stations - - // Do a full redraw at least evey 2 mins if anything has changed - -// SlowTimer++; -// if (SlowTimer > 40) // 2 Mins -// if (NeedRedraw) -// NeedRefresh = TRUE; - } - - // Handle XEvents and flush the input - - while(Running && XPending(display)) - { - XNextEvent(display, &event); - - MouseX = event.xbutton.x - leftBorder; - MouseY = event.xbutton.y - topBorder; - - GetMouseLatLon(&MouseLat, &MouseLon); - - switch (event.type) - { - - case ClientMessage: - - if (event.xclient.data.l[0] == wmDeleteMessage) - Running = FALSE; - break; - - case KeyPress: - - xkeyev = event.xkey; - - XLookupString(&event.xkey, text, 255, &key, 0); - -// printf("Key %c Hex %x Code %d %x\n", text[0], text[0], key, key); - - switch(key) - { - case XK_Left: - - WindowX -= 8; - XMoveWindow(display, win, WindowX, WindowY); - break; - - case XK_Up: - - WindowY -= 8; - XMoveWindow(display, win, WindowX, WindowY); - break; - - case XK_Right: - - WindowX += 8; - XMoveWindow(display, win, WindowX, WindowY); - break; - - case XK_Down: - - WindowY += 8; - XMoveWindow(display, win, WindowX, WindowY); - break; - - case '-': - - ZoomOut(); - break; - - case '=': - case '+': - - ZoomIn(); - break; - } - - break; - - case Expose: - - XPutImage (display, win, gc, image, ScrollX, ScrollY, leftBorder, topBorder, cxImgSize, cyImgSize); - break; - - case ConfigureNotify: - - xce = event.xconfigure; - - // This event type is generated for a variety of - // happenings, so check whether the window has been - // resized. - - WindowX = xce.x; - WindowY = xce.y; - WindowWidth = xce.width; - WindowHeight = xce.height; - - if (xce.width != cxWinSize || xce.height != cyWinSize) - { - cxWinSize = xce.width; - cyWinSize = xce.height; - cxImgSize = cxWinSize - (leftBorder + rightBorder); - cyImgSize = cyWinSize - (topBorder + bottomBorder); - - XClearWindow(display, win); - XPutImage (display, win, gc, image, ScrollX, ScrollY, leftBorder, topBorder, cxImgSize, cyImgSize); - } - - break; - - case MotionNotify: - - FindStationsByPixel(MouseX + ScrollX, MouseY + ScrollY); - break; - - - case ButtonPress: - - switch (event.xbutton.button) - { - case 1: // Left Button - - LastX = MouseX; - LastY = MouseY; - break; - - case 4: // Scrollup - - ZoomIn(); - break; - - case 5: // Scrolldown - - ZoomOut(); - break; - } - - break; - - case ButtonRelease: - - if (popupActive && (event.xbutton.time - lastupevent) < 300) - { - // Double Click on Station - - char Key[32]; - char LoppedCall[10]; - int n = 8; - - memcpy(LoppedCall, popupStn->Callsign, 9); - - while (n && LoppedCall[n] == ' ') - { - n--; - } - - if (n) - LoppedCall[n + 1] = 0; - - sprintf(Key, "|%s|", LoppedCall); - - // if new call add to combo box - - if (strstr(ToCalls, Key) == 0) - { - if (strlen(ToCalls) < 1000) - strcat(ToCalls, Key); - - gtk_combo_box_text_prepend_text ((GtkComboBoxText *)combo, LoppedCall); - } - } - - lastupevent = event.xbutton.time; - - switch (event.xbutton.button) - { - case 1: // Left Button - - // if a Popup is on display, then select station, else scroll map - - if (selActive) - { - GetStationFromList(MouseX, MouseY); - break; - } - - MovedX = MouseX - LastX; - MovedY = MouseY - LastY; - - if (MovedX == 0 && MovedY == 0) - break; - - ScrollX -= (MovedX); - ScrollY -= (MovedY); - - while (ScrollX < 0) - { - TileX--; - ScrollX += 256; - } - - while (ScrollX > 255) - { - TileX++; - ScrollX -= 256; - } - - if (TileX < 0) - { - TileX = 0; - ScrollX = 0; - } - - while (ScrollY < 0) - { - TileY--; - ScrollY += 256; - } - - while (ScrollY > 255) - { - TileY++; - ScrollY -= 256; - } - - if (TileY < 0) - { - TileY = 0; - ScrollY = 0; - } - - NeedRefresh = TRUE; - AutoFilterTimer = AUTOFILTERDELAY; // Update filter if no change for 30 secs - - break; - } - break; - } - } // end of while xpending - - if (popupActive || selActive) - { - } - else - { - if (NeedRefresh) - { - SetBaseX = -1; - LoadImageSet(Zoom, TileX, TileY); - NeedRefresh = FALSE; - SlowTimer = 0; - } - if (NeedRedraw) - { - NeedRedraw = 0; - XPutImage (display, win, gc, image, ScrollX, ScrollY, leftBorder, topBorder, cxImgSize, cyImgSize); - } - } - } - - SaveConfig(); - - status = XDestroyImage (image); - return 0; -} - -void PutAPRSMessage(char * Frame, int Len) -{ - if (sendto(sfd, Frame, Len, 0, (struct sockaddr *) &peer_addr, sizeof(struct sockaddr_un)) != Len) - perror("sendto"); -} - -VOID SendFilterCommand(char * Filter) -{ - char Msg[2000]; - int n; - - strcpy(Msg, "SERVER"); - strcpy(&Msg[10], Filter); - - PutAPRSMessage(Msg, strlen(&Msg[10]) + 11); - - strcpy(&Msg[10], "filter?"); - PutAPRSMessage(Msg, strlen(&Msg[10]) + 11); -} - -void RefreshTXList() -{ - struct APRSMESSAGE * Message = SMEM->OutstandingMsgs; - int n = 0; - - GtkTreeIter iter; - gchar *seq; - char status[10]; - - // Clear old list - - if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(sentitems), &iter, NULL, 0)) - { - while (gtk_list_store_remove(sentitems, &iter)) - {} - } - while (Message) - { - if (Message->Acked) - strcpy(status, "A"); - else if (Message->Cancelled) - strcpy(status, "C"); - else if (Message->Retries == 0) - strcpy(status, "F"); - else - sprintf(status, "%d", Message->Retries); - - gtk_list_store_insert_with_values( - sentitems, &iter, -1, - 0, Message->ToCall, - 1, Message->Seq, - 2, status, - 3, Message->Time, - 4, Message->Text, -1); - n++; - - Message = Message->Next; - } - - if (n) - gtk_tree_view_scroll_to_cell ((GtkTreeView *)view, - gtk_tree_model_get_path (GTK_TREE_MODEL(sentitems), &iter), NULL, FALSE, 0, 0); -} - -VOID SendAPRSMessage(const char * Text, char * ToCall) -{ - char Msg[255]; - - strcpy(Msg, ToCall); - strcpy(&Msg[10], Text); - - PutAPRSMessage(Msg, strlen(&Msg[10]) + 11); - - return; -} - -VOID SecTimer() -{ - while (TRUE) - { - struct STATIONRECORD * sptr = *StationRecords; - int n = 0; - char Msg[20]; - - if (Host1Down) - Host1Down --; - - if (Host2Down) - Host2Down --; - - - // See if changed flag set on any stations - - NeedRedraw += RefreshStationMap(FALSE); // Draw new or moved stations - - // Do a full redraw at least evey 2 mins if anything has changed - - SlowTimer++; - if (SlowTimer > 120) // 2 Mins - if (NeedRedraw) - NeedRefresh = TRUE; - -/* - while (sptr) - { - if (sptr->Moved) - DrawStation(sptr, FALSE); - - sptr = sptr->Next; - } -*/ - JPEGCounter++; - - if (CreateJPEG) - { - if (JPEGCounter > JPEGInterval) - { - if (RGBToJpegFile(JPEGFileName, Image, cxImgSize, cyImgSize, TRUE, 50)) - JPEGCounter = 0; - } - } - -/* - if (SendWX) - SendWeatherBeacon(); - - // If any changes to image redraw it - - if (ImageChanged) - { - // We have drawn a new Icon. As we only redraw if it has moved, - // we need to reload image every now and again to get rid of ghost images - - time_t NOW = time(NULL); - - if ((NOW - LastRefresh) > 10) - { - LastRefresh = NOW; - ReloadMaps = TRUE; - } - - ImageChanged = FALSE; - InvalidateRect(hMapWnd, NULL, FALSE); - } - - wsprintf(Msg, "%d", StationCount); - SendMessage(hStatus, SB_SETTEXT, (WPARAM)(INT) 0 | 1, (LPARAM)Msg); - - wsprintf(Msg, "%d", OSMQueueCount); - SendMessage(hStatus, SB_SETTEXT, (WPARAM)(INT) 0 | 2, (LPARAM)Msg); - - wsprintf(Msg, "%d", Zoom); - SendMessage(hStatus, SB_SETTEXT, (WPARAM)(INT) 0 | 3, (LPARAM)Msg); -*/ - - if (AutoFilterTimer) - { - AutoFilterTimer--; - - if (AutoFilterTimer == 0 && AddViewToFilter) - { - // send filter to IS - - double TLLat, TLLon, BRLat, BRLon; - char Filter[256]; - - GetCornerLatLon(&TLLat, &TLLon, &BRLat, &BRLon); - sprintf(Filter, "%s a/%.3f/%.3f/%.3f/%.3f", ISFilter, TLLat, TLLon, BRLat, BRLon); - - SendFilterCommand(Filter); - } - } - - Sleep(1000); - } -} - -BOOL RGBToJpegFile(char * fileName, BYTE *dataBuf, UINT widthPix, UINT height, BOOL color, int quality) -{ - struct jpeg_compress_struct cinfo; - struct my_error_mgr jerr; - FILE * outfile=NULL; - unsigned char * RGBBuff = malloc(widthPix * 3); // no idea why - unsigned char * ptr1, * ptr2; - int n; - unsigned int val, r, g, b; - char Message[32]; - int X, Y, j, Len; - struct tm * TM; - time_t NOW = time(NULL); - - if (dataBuf==NULL) - return FALSE; - if (widthPix==0) - return FALSE; - if (height==0) - return FALSE; - - // Write a Date/Time stamp to top left - - if (LocalTime) - TM = localtime(&NOW); - else - TM = gmtime(&NOW); - - Len = sprintf(Message, "%02d:%02d:%02d %02d %s %04d", - TM->tm_hour, TM->tm_min, TM->tm_sec, - TM->tm_mday, month[TM->tm_mon], TM->tm_year + 1900); - - X = ScrollX; - Y = ScrollY + 8; - - for (j = 0; j < Len; j++) - { - DrawCharacter(X, Y, j, Message[j]); - } - - - - /* More stuff */ - /* Step 1: allocate and initialize JPEG compression object */ - - cinfo.err = jpeg_std_error(&jerr.pub); - jerr.pub.error_exit = my_error_exit; - - /* Establish the setjmp return context for my_error_exit to use. */ - - if (setjmp(jerr.setjmp_buffer)) - { - /* If we get here, the JPEG code has signaled an error. - * We need to clean up the JPEG object, close the input file, and return. - */ - - jpeg_destroy_compress(&cinfo); - - if (outfile!=NULL) - fclose(outfile); - - return FALSE; - } - - /* Now we can initialize the JPEG compression object. */ - - jpeg_create_compress(&cinfo); - - /* Step 2: specify data destination (eg, a file) */ - /* Note: steps 2 and 3 can be done in either order. */ - - if ((outfile = fopen(fileName, "wb")) == NULL) - { -// char buf[250]; -// sprintf(buf, "JpegFile :\nCan't open %s\n", fileName); -// MessageBox(NULL, buf, "", 0); - return FALSE; - } - - jpeg_stdio_dest(&cinfo, outfile); - - /* Step 3: set parameters for compression */ - - /* First we supply a description of the input image. - * Four fields of the cinfo struct must be filled in: - */ - cinfo.image_width = widthPix; /* image widthPix and height, in pixels */ - cinfo.image_height = height; - - cinfo.input_components = 3; /* # of color components per pixel */ - cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ - -/* Now use the library's routine to set default compression parameters. - * (You must set at least cinfo.in_color_space before calling this, - * since the defaults depend on the source color space.) - */ - - jpeg_set_defaults(&cinfo); - /* Now you can set any non-default parameters you wish to. - * Here we just illustrate the use of quality (quantization table) scaling: - */ - jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); - - /* Step 4: Start compressor */ - - /* TRUE ensures that we will write a complete interchange-JPEG file. - * Pass TRUE unless you are very sure of what you're doing. - */ - jpeg_start_compress(&cinfo, TRUE); - - /* Step 5: while (scan lines remain to be written) */ - /* jpeg_write_scanlines(...); */ - - /* Here we use the library's state variable cinfo.next_scanline as the - * loop counter, so that we don't have to keep track ourselves. - * To keep things simple, we pass one scanline per call; you can pass - * more if you wish, though. - */ - - while (cinfo.next_scanline < cinfo.image_height) - { - /* jpeg_write_scanlines expects an array of pointers to scanlines. - * Here the array is only one element long, but you could pass - * more than one scanline at a time if that's more convenient. - */ - - unsigned char * outRow; - - outRow = RGBBuff; - - // We have to convert from 2 or 4 bytes to pixel to 3 byte rgb - - ptr1 = dataBuf + ((ScrollY * WIDTH) + ScrollX + (cinfo.next_scanline * WIDTH)) * Bytesperpixel; - - ptr2 = RGBBuff; - - for (n = 0; n < widthPix; n++) - { - if (Bytesperpixel == 2) - { - val = (*(ptr1++)); - val |= (*(ptr1++)) << 8; - - b = val << 3; - g = (val >> 5) << 2; - r = (val >> 11) << 3; - - *(ptr2++) = r; - *(ptr2++) = g; - *(ptr2++) = b; - } - else - { - *(ptr2++) = *(ptr1+2); - *(ptr2++) = *(ptr1+1); - *(ptr2++) = *(ptr1); - ptr1 += 4; - } - } - (void) jpeg_write_scanlines(&cinfo, &outRow, 1); - } - - /* Step 6: Finish compression */ - - jpeg_finish_compress(&cinfo); - - /* After finish_compress, we can close the output file. */ - fclose(outfile); - - /* Step 7: release JPEG compression object */ - - /* This is an important step since it will release a good deal of memory. */ - jpeg_destroy_compress(&cinfo); - - /* And we're done! */ - - return TRUE; -} - -VOID plot(int X, int Y, COLORREF rgb) -{ - char * nptr; - int i, j; - unsigned int val; - - if ((X > (WIDTH - 3)) || (Y > (HEIGHT - 3))) - return; - - nptr = &Image[(Y * WIDTH * Bytesperpixel) + (X * Bytesperpixel)]; - - for (j = 0; j < 2; j++) - { - for (i = 0; i < 2; i++) - { - if (Bytesperpixel == 4) - { - *(nptr++) = (rgb >> 16) & 0xff; - *(nptr++) = (rgb >> 8) & 0xff; - *(nptr++) = GetRValue(rgb); - nptr++; - } - else - { - val = ((rgb & 0xff) >> 3) << 11; // Red - val |= (GetGValue(rgb) >> 2) << 5; - val |= (rgb >> 19); // Blue - *(nptr++) = (val & 0xff); - *(nptr++) = (unsigned char)(val >> 8); - } - - } - nptr += (WIDTH - 2) * Bytesperpixel; - } -} - -// Algorithm assumes y increases slower than x. If not, swap x and y in plotline and plotpoint - -void plotLineTB(int x0, int y0, int x1, int y1, COLORREF rgb); -void plotLineLR(int x0, int y0, int x1, int y1, COLORREF rgb); - -void plotLine(int x0, int y0, int x1, int y1, COLORREF rgb) -{ - if (abs(x1 - x0) > abs(y1 - y0)) - plotLineLR(x0, y0, x1, y1, rgb); - else - plotLineTB(y0, x0, y1, x1, rgb); -} - -void plotLineLR(int x0, int y0, int x1, int y1, COLORREF rgb) -{ - int dx; - int dy; - int D, x, y; - - // Must draw with increacing x and y, but can draw either way round, so if x is decreasing, - // just swap ends, so we always draw left to right - - if (x0 > x1) - { - x = x0; - x0 = x1; - x1 = x; - - y = y0; - y0 = y1; - y1 = y; - } - - // if y is now decreasing, we must reverse algorithm - - if (y1 > y0) - { - dx = x1 - x0; - dy = y1 - y0; - D = 2 * dy - dx; - - plot (x0, y0, 0); - - y = y0; - - for (x = x0+1; x < x1; x++) - { - if (D < 0) - { - D = D + (2*dy); - } - else - { - y = y+1; - D = D + (2*dy-2*dx); - - } - plot(x, y, rgb); - } - } - else - { - dx = x1 - x0; - dy = y0 - y1; - D = 2 * dy - dx; - - plot (x0, y0, rgb); - - y = y0; - - for (x = x0+1; x <= x1; x++) - { - if (D > 0) - { - y = y-1; - plot(x, y, rgb); - D = D + (2*dy-2*dx); - } - else - { - plot(x, y, rgb); - D = D + (2*dy); - } - } - } - -} - -void plotLineTB(int x0, int y0, int x1, int y1, COLORREF rgb) -{ - int dx; - int dy; - int D, x, y; - - // Must draw with increacing x and y, but can draw either way round, so if x is decreasing, - // just swap ends, so we always draw left to right - - if (x0 > x1) - { - x = x0; - x0 = x1; - x1 = x; - - y = y0; - y0 = y1; - y1 = y; - } - - // if y is now decreasing, we must reverse algorithm - - if (y1 > y0) - { - dx = x1 - x0; - dy = y1 - y0; - D = 2 * dy - dx; - - plot (y0, x0, 0); - - y = y0; - - for (x = x0+1; x < x1; x++) - { - if (D < 0) - { - D = D + (2*dy); - } - else - { - y = y+1; - D = D + (2*dy-2*dx); - - } - plot(y, x, rgb); - } - } - else - { - dx = x1 - x0; - dy = y0 - y1; - D = 2 * dy - dx; - - plot (y0, x0, 0); - - y = y0; - - for (x = x0+1; x <= x1; x++) - { - if (D > 0) - { - y = y-1; - D = D + (2*dy-2*dx); - } - else - { - D = D + (2*dy); - } - plot(y, x, rgb); - - } - } -} - - -png_const_charp msg; - - -static png_structp png_ptr = NULL; -static png_infop info_ptr = NULL; - - -// cexcept interface - -static void -png_cexcept_error(png_structp png_ptr, png_const_charp msg) -{ - if(png_ptr) - ; -#ifndef PNG_NO_CONSOLE_IO - fprintf(stderr, "libpng error: %s\n", msg); -#endif - { -// Throw msg; - } -} - - -int LoadImageFile (void * hwnd, char * pstrPathName, - png_byte **ppbImage, int *pxImgSize, int *pyImgSize, - int *piChannels, png_color *pBkgColor) -{ - - // if there's an existing PNG, free the memory - - if (*ppbImage) - { - free (*ppbImage); - *ppbImage = NULL; - } - - PngLoadImage (pstrPathName, ppbImage, pxImgSize, pyImgSize, piChannels, - pBkgColor); - - - - if (*ppbImage != NULL) - { - // sprintf (szTmp, "VisualPng - %s", strrchr(pstrPathName, '\\') + 1); - // SetWindowText (hwnd, szTmp); - } - else - { - return FALSE; - } - - return TRUE; -} - -//---------------- -// PNG image handler functions - -BOOL PngLoadImage (char * pstrFileName, png_byte **ppbImageData, - png_uint_32 *piWidth, png_uint_32 *piHeight, int *piChannels, png_color *pBkgColor) -{ - static FILE *pfFile; - png_byte pbSig[8]; - int iBitDepth; - int iColorType; - double dGamma; - png_color_16 *pBackground; - png_uint_32 ulChannels; - png_uint_32 ulRowBytes; - png_byte *pbImageData = *ppbImageData; - static png_byte **ppbRowPointers = NULL; - int i; - - // open the PNG input file - - if (!pstrFileName) - { - *ppbImageData = pbImageData = NULL; - printf("Load PNG Failed 1\n"); - return FALSE; - } - - if (!(pfFile = fopen(pstrFileName, "rb"))) - { - *ppbImageData = pbImageData = NULL; - printf("Load PNG Failed 2\n"); - return FALSE; - } - - // first check the eight byte PNG signature - - fread(pbSig, 1, 8, pfFile); - - if(png_sig_cmp(pbSig, 0, 8) != 0) - //if (!png_check_sig(pbSig, 8)) - { - *ppbImageData = pbImageData = NULL; - - if (pfFile) - fclose (pfFile); - - printf("Bad file %s", pstrFileName); - unlink(pstrFileName); - - return FALSE; - } - - // create the two png(-info) structures - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, - (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL); - if (!png_ptr) - { - *ppbImageData = pbImageData = NULL; - printf("Load PNG Failed 4\n"); - return FALSE; - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, NULL, NULL); - *ppbImageData = pbImageData = NULL; - printf("Load PNG Failed 5\n"); - return FALSE; - } - -// Try - { - - // initialize the png structure - -#if !defined(PNG_NO_STDIO) - png_init_io(png_ptr, pfFile); -#else - png_set_read_fn(png_ptr, (png_voidp)pfFile, png_read_data); -#endif - - png_set_sig_bytes(png_ptr, 8); - - // read all PNG info up to image data - - png_read_info(png_ptr, info_ptr); - - // get width, height, bit-depth and color-type - - png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth, - &iColorType, NULL, NULL, NULL); - - // expand images of all color-type and bit-depth to 3x8 bit RGB images - // let the library process things like alpha, transparency, background - - if (iBitDepth == 16) - png_set_strip_16(png_ptr); - if (iColorType == PNG_COLOR_TYPE_PALETTE) - png_set_expand(png_ptr); - if (iBitDepth < 8) - png_set_expand(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_expand(png_ptr); - if (iColorType == PNG_COLOR_TYPE_GRAY || - iColorType == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); - - // set the background color to draw transparent and alpha images over. - if (png_get_bKGD(png_ptr, info_ptr, &pBackground)) - { - png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); - pBkgColor->red = (byte) pBackground->red; - pBkgColor->green = (byte) pBackground->green; - pBkgColor->blue = (byte) pBackground->blue; - } - else - { - pBkgColor = NULL; - } - - // if required set gamma conversion - if (png_get_gAMA(png_ptr, info_ptr, &dGamma)) - png_set_gamma(png_ptr, (double) 2.2, dGamma); - - // after the transformations have been registered update info_ptr data - - png_read_update_info(png_ptr, info_ptr); - - // get again width, height and the new bit-depth and color-type - - png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth, - &iColorType, NULL, NULL, NULL); - - - // row_bytes is the width x number of channels - - ulRowBytes = png_get_rowbytes(png_ptr, info_ptr); - ulChannels = png_get_channels(png_ptr, info_ptr); - - *piChannels = ulChannels; - - // now we can allocate memory to store the image - - if (pbImageData) - { - free (pbImageData); - pbImageData = NULL; - } - if ((pbImageData = (png_byte *) malloc(ulRowBytes * (*piHeight) - * sizeof(png_byte))) == NULL) - { - png_error(png_ptr, "Visual PNG: out of memory"); - } - *ppbImageData = pbImageData; - - // and allocate memory for an array of row-pointers - - if ((ppbRowPointers = (png_bytepp) malloc((*piHeight) - * sizeof(png_bytep))) == NULL) - { - png_error(png_ptr, "Visual PNG: out of memory"); - } - - // set the individual row-pointers to point at the correct offsets - - for (i = 0; i < (*piHeight); i++) - ppbRowPointers[i] = pbImageData + i * ulRowBytes; - - // now we can go ahead and just read the whole image - - png_read_image(png_ptr, ppbRowPointers); - - // read the additional chunks in the PNG file (not really needed) - - png_read_end(png_ptr, NULL); - - // and we're done - - free (ppbRowPointers); - ppbRowPointers = NULL; - - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - - - // yepp, done - } -/* - Catch (msg) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - - *ppbImageData = pbImageData = NULL; - - if(ppbRowPointers) - free (ppbRowPointers); - - fclose(pfFile); - - return FALSE; - } -*/ - if (pfFile) - fclose (pfFile); - - return TRUE; -} - diff --git a/.svn/pristine/09/091a2424fc9a479a4b97e349b069851ef8cd3fc2.svn-base b/.svn/pristine/09/091a2424fc9a479a4b97e349b069851ef8cd3fc2.svn-base deleted file mode 100644 index 4272c12..0000000 --- a/.svn/pristine/09/091a2424fc9a479a4b97e349b069851ef8cd3fc2.svn-base +++ /dev/null @@ -1,135 +0,0 @@ -/* LzmaLib.h -- LZMA library interface -2008-08-05 -Igor Pavlov -Public domain */ - -#ifndef __LZMALIB_H -#define __LZMALIB_H - -#include "types.h" - -#ifdef __cplusplus - #define MY_EXTERN_C extern "C" -#else - #define MY_EXTERN_C extern -#endif - -#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL - -#define LZMA_PROPS_SIZE 5 - -/* -RAM requirements for LZMA: - for compression: (dictSize * 11.5 + 6 MB) + state_size - for decompression: dictSize + state_size - state_size = (4 + (1.5 << (lc + lp))) KB - by default (lc=3, lp=0), state_size = 16 KB. - -LZMA properties (5 bytes) format - Offset Size Description - 0 1 lc, lp and pb in encoded form. - 1 4 dictSize (little endian). -*/ - -/* -LzmaCompress ------------- - -outPropsSize - - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. - Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. - - LZMA Encoder will use defult values for any parameter, if it is - -1 for any from: level, loc, lp, pb, fb, numThreads - 0 for dictSize - -level - compression level: 0 <= level <= 9; - - level dictSize algo fb - 0: 16 KB 0 32 - 1: 64 KB 0 32 - 2: 256 KB 0 32 - 3: 1 MB 0 32 - 4: 4 MB 0 32 - 5: 16 MB 1 32 - 6: 32 MB 1 32 - 7+: 64 MB 1 64 - - The default value for "level" is 5. - - algo = 0 means fast method - algo = 1 means normal method - -dictSize - The dictionary size in bytes. The maximum value is - 128 MB = (1 << 27) bytes for 32-bit version - 1 GB = (1 << 30) bytes for 64-bit version - The default value is 16 MB = (1 << 24) bytes. - It's recommended to use the dictionary that is larger than 4 KB and - that can be calculated as (1 << N) or (3 << N) sizes. - -lc - The number of literal context bits (high bits of previous literal). - It can be in the range from 0 to 8. The default value is 3. - Sometimes lc=4 gives the gain for big files. - -lp - The number of literal pos bits (low bits of current position for literals). - It can be in the range from 0 to 4. The default value is 0. - The lp switch is intended for periodical data when the period is equal to 2^lp. - For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's - better to set lc=0, if you change lp switch. - -pb - The number of pos bits (low bits of current position). - It can be in the range from 0 to 4. The default value is 2. - The pb switch is intended for periodical data when the period is equal 2^pb. - -fb - Word size (the number of fast bytes). - It can be in the range from 5 to 273. The default value is 32. - Usually, a big number gives a little bit better compression ratio and - slower compression process. - -numThreads - The number of thereads. 1 or 2. The default value is 2. - Fast mode (algo = 0) can use only 1 thread. - -Out: - destLen - processed output size -Returns: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater - SZ_ERROR_OUTPUT_EOF - output buffer overflow - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) -*/ - -MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, - unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ - int level, /* 0 <= level <= 9, default = 5 */ - unsigned dictSize, /* default = (1 << 24) */ - int lc, /* 0 <= lc <= 8, default = 3 */ - int lp, /* 0 <= lp <= 4, default = 0 */ - int pb, /* 0 <= pb <= 4, default = 2 */ - int fb, /* 5 <= fb <= 273, default = 32 */ - int numThreads /* 1 or 2, default = 2 */ - ); - -/* -LzmaUncompress --------------- -In: - dest - output data - destLen - output data size - src - input data - srcLen - input data size -Out: - destLen - processed output size - srcLen - processed input size -Returns: - SZ_OK - OK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation arror - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) -*/ - -MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, - const unsigned char *props, size_t propsSize); - -#endif diff --git a/.svn/pristine/0a/0a715995817f6af3c897a4b559859d3abacad0d6.svn-base b/.svn/pristine/0a/0a715995817f6af3c897a4b559859d3abacad0d6.svn-base deleted file mode 100644 index a57a91c..0000000 Binary files a/.svn/pristine/0a/0a715995817f6af3c897a4b559859d3abacad0d6.svn-base and /dev/null differ diff --git a/.svn/pristine/0a/0ab80fa8538be287532e4ec6563efe6456432d68.svn-base b/.svn/pristine/0a/0ab80fa8538be287532e4ec6563efe6456432d68.svn-base deleted file mode 100644 index 17a7946..0000000 --- a/.svn/pristine/0a/0ab80fa8538be287532e4ec6563efe6456432d68.svn-base +++ /dev/null @@ -1,30 +0,0 @@ -/* See md5.c for explanation and copyright information. */ - -/* - * $FreeBSD: src/contrib/cvs/lib/md5.h,v 1.2 1999/12/11 15:10:02 peter Exp $ - */ - -#ifndef MD5_H -#define MD5_H - -/* Unlike previous versions of this code, uint32 need not be exactly - 32 bits, merely 32 bits or more. Choosing a data type which is 32 - bits instead of 64 is not important; speed is considerably more - important. ANSI guarantees that "unsigned long" will be big enough, - and always using it seems to have few disadvantages. */ -typedef unsigned long cvs_uint32; - -struct cvs_MD5Context { - cvs_uint32 buf[4]; - cvs_uint32 bits[2]; - unsigned char in[64]; -}; - -void cvs_MD5Init(struct cvs_MD5Context *context); -void cvs_MD5Update(struct cvs_MD5Context *context, - unsigned char const *buf, unsigned len); -void cvs_MD5Final(unsigned char digest[16], - struct cvs_MD5Context *context); -void cvs_MD5Transform(cvs_uint32 buf[4], const unsigned char in[64]); - -#endif /* !MD5_H */ diff --git a/.svn/pristine/0b/0b2525a7593ec9c79302aca324e8bd42b0ed4e56.svn-base b/.svn/pristine/0b/0b2525a7593ec9c79302aca324e8bd42b0ed4e56.svn-base deleted file mode 100644 index 944010b..0000000 --- a/.svn/pristine/0b/0b2525a7593ec9c79302aca324e8bd42b0ed4e56.svn-base +++ /dev/null @@ -1,6751 +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 end of session code (58) -// 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 - -#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/.svn/pristine/0c/0c8d0dde1866e8f5b2214eab03930e5891967d4f.svn-base b/.svn/pristine/0c/0c8d0dde1866e8f5b2214eab03930e5891967d4f.svn-base deleted file mode 100644 index a06d3b6..0000000 --- a/.svn/pristine/0c/0c8d0dde1866e8f5b2214eab03930e5891967d4f.svn-base +++ /dev/null @@ -1,424 +0,0 @@ -// Mail and Chat Server for BPQ32 Packet Switch -// -// Monitor Window(s) Module - -#include "bpqmail.h" - -static char ClassName[]="BPQMONWINDOW"; - -char SYSOPCall[50]; - -static WNDPROC wpOrigInputProc; -static WNDPROC wpOrigOutputProc; - -HWND hMonitor; - -static HWND hwndInput; -static HWND hwndOutput; - -static HMENU hMenu; // handle of menu - - -#define InputBoxHeight 25 -RECT MonitorRect; -RECT OutputRect; - -int Height, Width, LastY; - -static char kbbuf[160]; -static int kbptr=0; - -static char * readbuff; -static int readbufflen; - -static BOOL StripLF = TRUE; -BOOL MonBBS = TRUE; -BOOL MonCHAT = TRUE; -BOOL MonTCP = TRUE; - -BOOL LogBBS = TRUE; -BOOL LogCHAT = TRUE; -BOOL LogTCP = TRUE; - - -static int PartLinePtr=0; -static int PartLineIndex=0; // Listbox index of (last) incomplete line - - -static LRESULT CALLBACK MonWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -static LRESULT APIENTRY InputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; -static LRESULT APIENTRY OutputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; -static LRESULT APIENTRY MonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; -static void MoveWindows(); -static void MoveMCWindows(); - -#define BGCOLOUR RGB(236,233,216) - -BOOL CreateMonitor() -{ - WNDCLASS wc; - HBRUSH bgBrush; - - if (hMonitor) - { - ShowWindow(hMonitor, SW_SHOWNORMAL); - SetForegroundWindow(hMonitor); - return FALSE; // Alreaqy open - } - - bgBrush = CreateSolidBrush(BGCOLOUR); - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = MonWndProc; - - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInst; - wc.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(BPQICON) ); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = bgBrush; - - wc.lpszMenuName = NULL; - wc.lpszClassName = ClassName; - - RegisterClass(&wc); - - hMonitor=CreateDialog(hInst,ClassName,0,NULL); - - if (!hMonitor) - return (FALSE); - - readbuff = zalloc(1000); - readbufflen = 1000; - - hMenu=GetMenu(hMonitor); - - CheckMenuItem(hMenu,MONBBS, MonBBS ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,MONCHAT, MonCHAT ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,MONTCP, MonTCP ? MF_CHECKED : MF_UNCHECKED); - - DrawMenuBar(hWnd); - - // Retrieve the handlse to the edit controls. - - hwndOutput = GetDlgItem(hMonitor, 121); - - // Set our own WndProcs for the controls. - - wpOrigOutputProc = (WNDPROC)SetWindowLong(hwndOutput, GWL_WNDPROC, (LONG)OutputProc); - - if (cfgMinToTray) - AddTrayMenuItem(hMonitor, "Mail Monitor"); - - ShowWindow(hMonitor, SW_SHOWNORMAL); - - if (MonitorRect.right < 100 || MonitorRect.bottom < 100) - { - GetWindowRect(hMonitor, &MonitorRect); - } - - MoveWindow(hMonitor,MonitorRect.left,MonitorRect.top, MonitorRect.right-MonitorRect.left, MonitorRect.bottom-MonitorRect.top, TRUE); - - MoveWindows(); - - return TRUE; - -} - -static void MoveWindows() -{ - RECT rcMain, rcClient; - int ClientHeight, ClientWidth; - - GetWindowRect(hMonitor, &rcMain); - GetClientRect(hMonitor, &rcClient); - - ClientHeight = rcClient.bottom; - ClientWidth = rcClient.right; - -// MoveWindow(hwndMon,2, 0, ClientWidth-4, SplitPos, TRUE); - MoveWindow(hwndOutput,2, 2, ClientWidth-4, ClientHeight-4, TRUE); -// MoveWindow(hwndSplit,0, SplitPos, ClientWidth, SplitBarHeight, TRUE); -} - -static LRESULT CALLBACK MonWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - LPRECT lprc; - - switch (message) - { - - case WM_ACTIVATE: - - SetFocus(hwndInput); - break; - - case WM_CLOSE: - if (wParam) // Used by Close All Programs. - return 0; - - return (DefWindowProc(hWnd, message, wParam, lParam)); - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) { - - case MONBBS: - - ToggleParam(hMenu, hWnd, &MonBBS, MONBBS); - break; - - case MONCHAT: - - ToggleParam(hMenu, hWnd, &MonCHAT, MONCHAT); - break; - - case MONTCP: - - ToggleParam(hMenu, hWnd, &MonTCP, MONTCP); - break; - - - case BPQCLEAROUT: - - SendMessage(hwndOutput,LB_RESETCONTENT, 0, 0); - break; - - case BPQCOPYOUT: - - CopyToClipboard(hwndOutput); - break; - - - - //case BPQHELP: - - // HtmlHelp(hWnd,"BPQTerminal.chm",HH_HELP_FINDER,0); - // break; - - default: - - return 0; - - } - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) { - - case SC_MINIMIZE: - - if (cfgMinToTray) - return ShowWindow(hWnd, SW_HIDE); - - default: - - return (DefWindowProc(hWnd, message, wParam, lParam)); - } - - case WM_SIZING: - - lprc = (LPRECT) lParam; - - Height = lprc->bottom-lprc->top; - Width = lprc->right-lprc->left; - - MoveWindows(); - - return TRUE; - - - case WM_DESTROY: - - // Remove the subclass from the edit control. - - GetWindowRect(hWnd, &MonitorRect); // For save soutine - - SetWindowLong(hwndInput, GWL_WNDPROC, - (LONG) wpOrigInputProc); - - - if (cfgMinToTray) - DeleteTrayMenuItem(hWnd); - - - hMonitor = NULL; - - free(readbuff); - readbufflen = 0; - - break; - - default: - return (DefWindowProc(hWnd, message, wParam, lParam)); - - } - return (0); -} - - - -LRESULT APIENTRY OutputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - - // Trap mouse messages, so we cant select stuff in output and mon windows, - // otherwise scrolling doesnt work. - - if (uMsg >= WM_MOUSEFIRST && uMsg <= WM_LBUTTONDBLCLK) - return TRUE; - - return CallWindowProc(wpOrigOutputProc, hwnd, uMsg, wParam, lParam); -} - -int WritetoMonitorWindow(char * Msg, int len) -{ - char * ptr1, * ptr2; - int index; - - if (len+PartLinePtr > readbufflen) - { - readbufflen += len+PartLinePtr; - readbuff = realloc(readbuff, readbufflen); - } - - if (PartLinePtr != 0) - SendMessage(hwndOutput,LB_DELETESTRING,PartLineIndex,(LPARAM)(LPCTSTR) 0 ); - - memcpy(&readbuff[PartLinePtr], Msg, len); - - len=len+PartLinePtr; - - ptr1=&readbuff[0]; - readbuff[len]=0; - - do { - ptr2=memchr(ptr1,7,len); - - if (ptr2) - *(ptr2)=32; - - } while (ptr2); - -lineloop: - -// if (PartLinePtr > 300) -// PartLinePtr = 0; - - if (len > 0) - { - // copy text to control a line at a time - - ptr2=memchr(ptr1,13,len); - - if (ptr2 == 0) - { - // no newline. Move data to start of buffer and Save pointer - - PartLinePtr=len; - memmove(readbuff,ptr1,len); - PartLineIndex=SendMessage(hwndOutput,LB_ADDSTRING,0,(LPARAM)(LPCTSTR) ptr1 ); - SendMessage(hwndOutput,LB_SETCARETINDEX,(WPARAM) PartLineIndex, MAKELPARAM(FALSE, 0)); - - return (0); - - } - - *(ptr2++)=0; - - index=SendMessage(hwndOutput,LB_ADDSTRING,0,(LPARAM)(LPCTSTR) ptr1 ); - - // if (LogOutput) WriteMonitorLine(ptr1, ptr2 - ptr1); - - PartLinePtr=0; - - len-=(ptr2-ptr1); - - ptr1=ptr2; - - if ((len > 0) && StripLF) - { - if (*ptr1 == 0x0a) // Line Feed - { - ptr1++; - len--; - } - } - - if (index > 1200) - - do{ - - index=SendMessage(hwndOutput,LB_DELETESTRING, 0, 0); - - } while (index > 1000); - - SendMessage(hwndOutput,LB_SETCARETINDEX,(WPARAM) index, MAKELPARAM(FALSE, 0)); - - goto lineloop; - } - - - return (0); -} - -static int ToggleParam(HMENU hMenu, HWND hWnd, BOOL * Param, int Item) -{ - *Param = !(*Param); - - CheckMenuItem(hMenu,Item, (*Param) ? MF_CHECKED : MF_UNCHECKED); - - return (0); -} - -static void CopyToClipboard(HWND hWnd) -{ - int i,n, len=0; - HGLOBAL hMem; - char * ptr; - // - // Copy List Box to clipboard - // - - n = SendMessage(hWnd, LB_GETCOUNT, 0, 0); - - for (i=0; i -#include -#include -#endif -#include "bpq32.h" - -#ifndef LINBPQ -#include "kernelresource.h" -#include -#endif - -#include - -#define WSA_ACCEPT WM_USER + 1 -#define WSA_DATA WM_USER + 2 -#define WSA_CONNECT WM_USER + 3 - -// Cater for only systems without IPV6_V6ONLY - -#ifndef IPV6_V6ONLY -#define IPV6_V6ONLY 0x27 -#endif - -#ifndef MAXGETHOSTSTRUCT -#define MAXGETHOSTSTRUCT 1024 -#endif - - -#define FEND 0xC0 // KISS CONTROL CODES -#define FESC 0xDB -#define TFEND 0xDC -#define TFESC 0xDD - -int ResolveDelay = 0; - - -extern BOOL StartMinimized; - -VOID * zalloc(int len); - -int ResetExtDriver(int num); -BOOL ProcessConfig(); -VOID FreeConfig(); - -extern UCHAR BPQDirectory[]; - - -extern int OffsetH, OffsetW; - -static void ResolveNames(struct AXIPPORTINFO * PORT); -void OpenSockets(struct AXIPPORTINFO * PORT); -void CloseSockets(struct AXIPPORTINFO * PORT); - - -static int CONVFROMAX25(char * incall, char * outcall); -void CreateMHWindow(struct AXIPPORTINFO * PORT); -int Update_MH_List(struct AXIPPORTINFO * PORT, UCHAR * ipad, char * call, char proto, short port, BOOL IPv6); -int Update_MH_KeepAlive(struct AXIPPORTINFO * PORT, struct in_addr ipad, char proto, short port); -unsigned short int compute_crc(unsigned char *buf,int l); -unsigned int find_arp(unsigned char * call); -BOOL add_arp_entry(struct AXIPPORTINFO * PORT, unsigned char * call, UCHAR * ip, int len, int port,unsigned char * name, - int keepalive, BOOL BCFlag, BOOL AutoAdded, int TCPMode, int SourcePort, BOOL IPv6, int noUpdate, int useSourcePort); -BOOL add_bc_entry(struct AXIPPORTINFO * PORT, unsigned char * call, int len); -BOOL convtoax25(unsigned char * callsign, unsigned char * ax25call, int * calllen); -static BOOL ReadConfigFile(int Port); -static int ProcessLine(char * buf, struct AXIPPORTINFO * PORT); -int CheckKeepalives(struct AXIPPORTINFO * PORT); -BOOL CopyScreentoBuffer(char * buff, struct AXIPPORTINFO * PORT); -int DumpFrameInHex(unsigned char * msg, int len); -VOID SendFrame(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp_table, UCHAR * buff, int txlen); -BOOL CheckSourceisResolvable(struct AXIPPORTINFO * PORT, char * call, int FromPort, VOID * rxaddr, int ToPort); -int DataSocket_Read(struct arp_table_entry * sockptr, SOCKET sock); -int GetMessageFromBuffer(struct AXIPPORTINFO * PORT, char * Buffer); -int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); -int KissDecode(UCHAR * inbuff, int len); -int Socket_Accept(int SocketId); -int Socket_Connect(int SocketId, int Error); -int Socket_Data(int sock, int error, int eventcode); -VOID TCPConnectThread(struct arp_table_entry * arp); -VOID __cdecl Debugprintf(const char * format, ...); -VOID __cdecl Consoleprintf(const char * format, ...); -BOOL OpenListeningSocket(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp); -VOID Format_Addr(unsigned char * Addr, char * Output, BOOL IPV6); -static void CreateResolverWindow(struct AXIPPORTINFO * PORT); -VOID SaveMDIWindowPos(HWND hWnd, char * RegKey, char * Value, BOOL Minimized); -VOID SaveAXIPCache(struct AXIPPORTINFO * PORT); -VOID GetAXIPCache(struct AXIPPORTINFO * PORT); - - -union -{ - struct sockaddr_in sinx; - struct sockaddr_in6 sinx6; -} sinx; -/* -union -{ - struct sockaddr_in destaddr; - struct sockaddr_in6 destaddr6; -} destaddr; -*/ - -#define IP_AXIP 93 // IP Protocol for AXIP - -#pragma pack(1) - -struct iphdr { -// unsigned int version:4; // Version of IP -// unsigned int h_len:4; // length of the header - unsigned char h_lenvers; // Version + length of the header - unsigned char tos; // Type of service - unsigned short total_len; // total length of the packet - unsigned short ident; // unique identifier - unsigned short frag_and_flags; // flags - unsigned char ttl; - unsigned char proto; // protocol (TCP, UDP etc) - unsigned short checksum; // IP checksum - - unsigned int sourceIP; - unsigned int destIP; - -}; - -#pragma pack() - - -#define TCPMaster 1 -#define TCPSlave 2 - -#define TCPListening 1 -#define TCPConnecting 2 -#define TCPConnected 4 - -#ifndef LINBPQ - -LOGFONT LFTTYFONT ; - -extern HFONT hFont ; - -RECT ResRect; -RECT MHRect; - -extern HKEY REGTREE; - -extern HWND ClientWnd, FrameWnd; -extern HMENU hMainFrameMenu, hBaseMenu, hWndMenu; -extern HBRUSH bgBrush; - -#endif - -//struct tagMSG Msg; - -//char buf[MAXGETHOSTSTRUCT]; - -int addrlen6 = sizeof(struct sockaddr_in6); -int addrlen = sizeof(struct sockaddr_in); - -extern unsigned short CRCTAB[]; -unsigned int AXIPInst = 0; - -char CantReplyList[512] = ""; // To suppress duplicate "Can't Reply" messages - -DWORD n; - -struct AXIPPORTINFO * Portlist[MaxBPQPortNo + 1]; - -int InitAXIP(int Port); - -int CurrentResEntries; - -static char ConfigClassName[]="CONFIG"; - -HANDLE hInstance; - -VOID SaveAXIPWindowPos(int port) -{ -#ifndef LINBPQ - struct AXIPPORTINFO * PORT; - char Key[80]; - - PORT = Portlist[port]; - - if (PORT == NULL) - return; - - sprintf(Key, "PACTOR\\PORT%d", port); - - SaveMDIWindowPos(PORT->hMHWnd, Key, "MHSize", PORT->MHMinimized); - SaveMDIWindowPos(PORT->hResWnd, Key, "ResSize", PORT->ResMinimized); -#endif - return; -} - - -static size_t ExtProc(int fn, int port, PMESSAGE buff) -{ - struct iphdr * iphdrptr; - int len,txlen=0,err,index,digiptr,i; - unsigned short int crc; - char rxbuff[5000]; - char axcall[7]; - char errmsg[100]; - union - { - struct sockaddr_in rxaddr; - struct sockaddr_in6 rxaddr6; - } RXaddr; - struct AXIPPORTINFO * PORT = Portlist[port]; - - switch (fn) - { - case 1: // poll - - // - // Check Keepalive timers - // - time(&PORT->ltime); - - if (PORT->ltime-PORT->lasttime >9 ) - { - PORT->lasttime=PORT->ltime; - CheckKeepalives(PORT); - } - - if (PORT->needip) - { - char call[7]; - - len = recvfrom(PORT->sock,rxbuff,500,0,(struct sockaddr *)&RXaddr.rxaddr,&addrlen); - - if (len == -1) - { - err = WSAGetLastError(); - } - else - { - iphdrptr=(struct iphdr *)&rxbuff; - - if (len == ntohs(iphdrptr->total_len)) - { - len-=20; // IP HEADER - - if (memcmp(&rxbuff[20], "Keepalive", 9) == 0 ) - { - if (PORT->MHEnabled) - Update_MH_KeepAlive(PORT, RXaddr.rxaddr.sin_addr,'I',93); - - return 0; - } - crc = compute_crc(&rxbuff[20], len); - - if (crc == 0xf0b8) // Good CRC - { - len-=2; // Remove CRC - - if (len > MAXDATA) - { - sprintf(errmsg,"BPQAXIP Invalid Msg Len=%d Source=%s",len,inet_ntoa(RXaddr.rxaddr.sin_addr)); - OutputDebugString(errmsg); - DumpFrameInHex(&rxbuff[20], len); - return 0; - } - - memcpy(&buff->DEST, &rxbuff[20],len); - len += (3 + sizeof(void *)); - - PutLengthinBuffer((PDATAMESSAGE)buff, len); // Needed for arm5 portability - - memcpy(call, &buff->ORIGIN, 7); - call[6] &= 0x7e; // Mask End of Address bit - - // - // Do MH Proccessing if enabled - // - - if (PORT->MHEnabled) - Update_MH_List(PORT, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, &buff->ORIGIN[0], 'I', 93, 0); - - // Check Exclude - - if (CheckExcludeList(call) == 0) - return 0; - - - if (PORT->Checkifcanreply) - { - if (CheckSourceisResolvable(PORT, call, 0, &RXaddr, 0)) - - return 1; - - else - // Can't reply. If AutoConfig is set, add to table and accept, else reject - - if (PORT->AutoAddARP) - return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, 7, 0, inet_ntoa(RXaddr.rxaddr.sin_addr), 0, PORT->AutoAddBC, TRUE, 0, 0, FALSE, 0, 0); - else - { - char From[11] = "|"; - From[ConvFromAX25(call, &From[1]) + 1] = 0; - if (strstr(CantReplyList, From) == 0) - { - if (strlen(CantReplyList) < 500); - strcat(CantReplyList, From); - Debugprintf("AXIP Packet from %s dropped - can't reply", &From[1]); - } - return 0; - } - } - else - return(1); - } - // - // CRC Error - // - - sprintf(errmsg,"BPQAXIP Invalid CRC=%d Source=%s",crc,inet_ntoa(RXaddr.rxaddr.sin_addr)); - OutputDebugString(errmsg); - - return (0); - } - - // - // Bad Length - // - - return (0); - } - } - - for (i=0;iNumberofUDPPorts;i++) - { - char call[7]; - - if (PORT->IPv6[i]) - len = recvfrom(PORT->udpsock[i],rxbuff,500,0,(struct sockaddr *)&RXaddr.rxaddr, &addrlen6); - else - len = recvfrom(PORT->udpsock[i],rxbuff,500,0,(struct sockaddr *)&RXaddr.rxaddr, &addrlen); - - if (len == -1) - { - err = WSAGetLastError(); - } - else - { - if (memcmp(rxbuff, "Keepalive", 9) == 0 ) - { - if (PORT->MHEnabled) - Update_MH_KeepAlive(PORT, RXaddr.rxaddr.sin_addr, 'U', PORT->udpport[i]); - - continue; - } - - crc = compute_crc(&rxbuff[0], len); - - if (crc == 0xf0b8) // Good CRC - { - len-=2; // Remove CRC - - if (len > MAXDATA) - { - sprintf(errmsg,"BPQAXIP Invalid Msg Len=%d Source=%s Port %d",len,inet_ntoa(RXaddr.rxaddr.sin_addr),PORT->udpport[i]); - OutputDebugString(errmsg); - DumpFrameInHex(&rxbuff[0], len); - return 0; - } - - memcpy(&buff->DEST, &rxbuff[0], len); - - len += (3 + sizeof(void *)); - - PutLengthinBuffer((PDATAMESSAGE)buff, len); - - memcpy(call, &buff->ORIGIN, 7); - - call[6] &= 0x7e; // Mask End of Address bit - - // - // Do MH Proccessing if enabled - // - - if (PORT->MHEnabled) - if (PORT->IPv6[i]) - Update_MH_List(PORT, (UCHAR *)&RXaddr.rxaddr6.sin6_addr, &buff->ORIGIN[0], 'U', PORT->udpport[i], TRUE); - else - Update_MH_List(PORT, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, &buff->ORIGIN[0], 'U', PORT->udpport[i], FALSE); - - // Check Exclude - - if (CheckExcludeList(call) == 0) - return 0; - - if (PORT->Checkifcanreply) - { - if (CheckSourceisResolvable(PORT, call, htons(RXaddr.rxaddr.sin_port), &RXaddr, PORT->udpport[i])) - return 1; - else - { - // Can't reply. If AutoConfig is set, add to table and accept, else reject - - if (PORT->AutoAddARP) - if (PORT->IPv6[i]) - { - char Addr[80]; - Format_Addr((UCHAR *)&RXaddr.rxaddr6.sin6_addr, Addr, TRUE); - return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr6.sin6_addr, 7, htons(RXaddr.rxaddr6.sin6_port), Addr, 0, PORT->AutoAddBC, TRUE, 0, PORT->udpport[i], TRUE, 0, 0); - } - else - return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, 7, htons(RXaddr.rxaddr.sin_port), inet_ntoa(RXaddr.rxaddr.sin_addr), 0, PORT->AutoAddBC, TRUE, 0, PORT->udpport[i], FALSE, 0, 0); - else - { - char From[11] = "|"; - From[ConvFromAX25(call, &From[1]) + 1] = 0; - if (strstr(CantReplyList, From) == 0) - { - if (strlen(CantReplyList) < 500); - strcat(CantReplyList, From); - Debugprintf("AXIP Packet from %s dropped - can't reply", &From[1]); - } - return 0; - } - } - } - else - return(1); - } - - // - // CRC Error - // - - sprintf(errmsg,"BPQAXIP Invalid CRC=%d Source=%s Port %d",crc,inet_ntoa(RXaddr.rxaddr.sin_addr),PORT->udpport[i]); - Debugprintf(errmsg); - rxbuff[len] = 0; - Debugprintf(rxbuff); - - - return (0); - } - } - - if (PORT->NeedTCP) - { - len = GetMessageFromBuffer(PORT, rxbuff); - - if (len) - { - len = KissDecode(rxbuff, len-1); // Len includes FEND - len -= 2; // Ignore Checksum - - if (len < MAXDATA) - { - memcpy(&buff->DEST, &rxbuff[0], len); - len += (3 + sizeof(void *)); - - PutLengthinBuffer((PDATAMESSAGE)buff, len); // fix big endian issue - return 1; - } - else - { - Debugprintf("Oversized AX/TCP frame %d", len); - return 0; - } - } - } - - return (0); - - case 2: // send - -// txlen=(buff[6]<<8) + buff[5] - 5; // Len includes buffer header (7) but we add crc - - txlen = GetLengthfromBuffer((PDATAMESSAGE)buff) - (MSGHDDRLEN - 2); // 2 for CRC - - crc=compute_crc(&buff->DEST[0], txlen - 2); - crc ^= 0xffff; - - buff->DEST[txlen - 2] = (crc & 0xff); - buff->DEST[txlen - 1] = (crc >> 8); - - memcpy(axcall, &buff->DEST, 7); // Set to send to dest addr - - // if digis are present, scan down list for first non-used call - - if (buff->ORIGIN[6] == 0) - { - // end of addr bit not set, so scan digis - - digiptr = 13; // start of first digi - - while (((buff->ORIGIN[digiptr] & 0x80) == 0x80) && ((buff->ORIGIN[digiptr] & 0x1) == 0)) - { - // This digi has been used, and it is not the last - - digiptr+=7; - } - - // if this has not been used, use it - - if ((buff->ORIGIN[digiptr] & 0x80) == 0) - memcpy(axcall,&buff->ORIGIN[digiptr - 6], 7); // get next call - } - - axcall[6] &= 0x7e; - -// If addresses to a broadcast address, send to all entries - - for (i=0; i< PORT->NumberofBroadcastAddreses; i++) - { - if (memcmp(axcall, PORT->BroadcastAddresses[i].callsign, 7) == 0) - { - for (index = 0; index < PORT->arp_table_len; index++) - { - if (PORT->arp_table[index].BCFlag) - SendFrame(PORT, &PORT->arp_table[index], &buff->DEST[0], txlen); - } - return 0; - } - } - -// Send to all matching calls in arp table - - index = 0; - - while (index < PORT->arp_table_len) - { - if (memcmp(PORT->arp_table[index].callsign,axcall,PORT->arp_table[index].len) == 0) - { - SendFrame(PORT, &PORT->arp_table[index],&buff->DEST[0], txlen); - } - index++; - } - return (0); - - case 3: // CHECK IF OK TO SEND - - return (0); // OK - - case 4: // reinit - - CloseSockets(PORT); - - if (ProcessConfig()) - { - FreeConfig(); - ReadConfigFile(port); - } - else - Consoleprintf("Failed to reread config file - leaving config unchanged"); - - _beginthread(OpenSockets, 0, PORT ); - - GetAXIPCache(PORT); - - ResolveDelay = 2; -#ifndef LINBPQ - InvalidateRect(PORT->hResWnd,NULL,TRUE); -#endif - break; - - case 5: // Terminate - - CloseSockets(PORT); -#ifndef LINBPQ - SendMessage(PORT->hMHWnd, WM_CLOSE, 0, 0); - SendMessage(PORT->hResWnd, WM_CLOSE, 0, 0); -#endif - break; - } - return (0); -} - -VOID SendFrame(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp_table, UCHAR * buff, int txlen) -{ - int i; - SOCKET txsock, SourceSocket; - - if (arp_table->TCPMode) - { - if (arp_table->TCPState == TCPConnected) - { - char outbuff[1000]; - int newlen; - - newlen = KissEncode(buff, outbuff, txlen); - send(arp_table->TCPSock, outbuff, newlen, 0); - } - - return; - } - - // Select source port by choosing right socket - - // First Set Default for Protocol - - for (i = 0; i < PORT->NumberofUDPPorts; i++) - { - if (PORT->IPv6[i] == arp_table->IPv6) - { - SourceSocket = PORT->udpsock[i]; // Use as source socket, therefore source port - break; - } - } - - for (i = 0; i < PORT->NumberofUDPPorts; i++) - { - if (PORT->udpport[i] == arp_table->SourcePort && PORT->IPv6[i] == arp_table->IPv6) - { - SourceSocket = PORT->udpsock[i]; // Use as source socket, therefore source port - break; - } - } - - if (arp_table->error == 0) - { - int sent = 0; - - if (arp_table->port == 0) txsock = PORT->sock; else txsock = SourceSocket; - - if (arp_table->IPv6) - sent = sendto(txsock, buff, txlen, 0, (struct sockaddr *)&arp_table->destaddr6, sizeof(arp_table->destaddr6)); - else - if (arp_table->destaddr.sin_addr.s_addr) - sent = sendto(txsock, buff, txlen, 0, (struct sockaddr *)&arp_table->destaddr, sizeof(arp_table->destaddr)); - - if (sent != txlen) - { - int i = GetLastError(); -// perror("Sendto"); - } - - // reset Keepalive Timer - - arp_table->keepalive=arp_table->keepaliveinit; - } -} - -unsigned short int compute_crc_ccitt(unsigned char *buf, int len); -unsigned short CCCITTChecksum(unsigned char* data, unsigned int length); - -VOID * AXIPExtInit(struct PORTCONTROL * PortEntry) -{ -// char Msg[10] = {0xD0, 01, 00, 0x11, 00, 0x0B}; -// unsigned short crc; - -// crc = CCCITTChecksum(Msg, 4); - -// crc = CalcCRC(Msg, 4); - - WritetoConsole("AXIP "); - - InitAXIP(PortEntry->PORTNUMBER); - - WritetoConsole("\n"); - - return ExtProc; -} - -int InitAXIP(int Port) -{ - struct AXIPPORTINFO * PORT; - - // - // Read config first, to get UDP info if needed - // - - if (!ReadConfigFile(Port)) - return (FALSE); - - PORT = Portlist[Port]; - - if (PORT == NULL) - return FALSE; - - PORT->Port = Port; - - GetAXIPCache(PORT); // Prime resolver from cache - - // - // Start Resolver Thread if needed - // - - if (PORT->NeedResolver) - { - CreateResolverWindow(PORT); - _beginthread(ResolveNames, 0, PORT ); - } - - time(&PORT->lasttime); // Get initial time value - - _beginthread(OpenSockets, 0, PORT ); - - // Start TCP outward connect threads - // - // Open MH window if needed - - if (PORT->MHEnabled) - CreateMHWindow(PORT); - - return (TRUE); -} - -void OpenSockets(struct AXIPPORTINFO * PORT) -{ - char Msg[255]; - int err; - u_long param=1; - BOOL bcopt=TRUE; - int i; - int index = 0; - struct arp_table_entry * arp; - - // Moved from InitAXIP, to avoid hang if started too early on XP SP2 - - // Create and bind socket - - if (PORT->needip) - { - PORT->sock=socket(AF_INET,SOCK_RAW,IP_AXIP); - - if (PORT->sock == INVALID_SOCKET) - { - err = WSAGetLastError(); - sprintf(Msg, "AXIP Failed to create RAW socket - Error %d\n", err); - WritetoConsole(Msg); - } - else - { - - ioctl (PORT->sock,FIONBIO,¶m); - - setsockopt (PORT->sock,SOL_SOCKET,SO_BROADCAST,(const char FAR *)&bcopt,4); - - sinx.sinx.sin_family = AF_INET; - sinx.sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sinx.sin_port = 0; - - if (bind(PORT->sock, (struct sockaddr *) &sinx, sizeof(sinx)) != 0 ) - { - // - // Bind Failed - // - err = WSAGetLastError(); - sprintf(Msg, "Bind Failed for RAW socket - error code = %d", err); - WritetoConsole(Msg); - return; - } - } - } - - for (i=0;iNumberofUDPPorts;i++) - { - int ret; - - if (PORT->IPv6[i]) - PORT->udpsock[i]=socket(AF_INET6,SOCK_DGRAM,0); - else - PORT->udpsock[i]=socket(AF_INET,SOCK_DGRAM,0); - - if (PORT->udpsock[i] == INVALID_SOCKET) - { - WritetoConsole("Failed to create UDP socket"); - err = WSAGetLastError(); - continue; - } - - ioctl (PORT->udpsock[i],FIONBIO,¶m); - - setsockopt (PORT->udpsock[i],SOL_SOCKET,SO_BROADCAST,(const char FAR *)&bcopt,4); - -#ifndef WIN32 - - if (PORT->IPv6[i]) - if (setsockopt(PORT->udpsock[i], IPPROTO_IPV6, IPV6_V6ONLY, ¶m, sizeof(param)) < 0) - perror("setting option IPV6_V6ONLY"); - -#endif - - if (PORT->IPv6[i]) - { - sinx.sinx.sin_family = AF_INET6; - memset (&sinx.sinx6.sin6_addr, 0, 16); - } - else - { - sinx.sinx.sin_family = AF_INET; - sinx.sinx.sin_addr.s_addr = INADDR_ANY; - } - - sinx.sinx.sin_port = htons(PORT->udpport[i]); - - if (PORT->IPv6[i]) - ret = bind(PORT->udpsock[i], (struct sockaddr *) &sinx.sinx, sizeof(sinx.sinx6)); - else - ret = bind(PORT->udpsock[i], (struct sockaddr *) &sinx.sinx, sizeof(sinx.sinx)); - - if (ret != 0) - { - // Bind Failed - - err = WSAGetLastError(); - sprintf(Msg, "Bind Failed for UDP socket %d - error code = %d", PORT->udpport[i], err); - WritetoConsole(Msg); - continue; - } - } - - // Open any TCP sockets - - while (index < PORT->arp_table_len) - { - arp = &PORT->arp_table[index++]; - - if (arp->TCPMode == TCPMaster) - { - arp->TCPBuffer=malloc(4000); - arp->TCPState = 0; - - if (arp->TCPThreadID == 0) - { - arp->TCPThreadID = _beginthread(TCPConnectThread, 0, arp); - Debugprintf("TCP Connect thread created for %s Handle %x", arp->hostname, arp->TCPThreadID); - } - continue; - } - - if (arp->TCPMode == TCPSlave) - { - OpenListeningSocket(PORT, arp); - } - } -} -int OpenListeningSocket(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp) -{ - char Msg[255]; - struct sockaddr_in * psin; - BOOL bOptVal = TRUE; - struct sockaddr_in local_sin; /* Local socket - internet style */ - u_long param = 1; - arp->TCPBuffer = malloc(4000); - arp->TCPState = 0; - - arp->TCPListenSock = socket(AF_INET, SOCK_STREAM, 0); - - ioctl (arp->TCPListenSock, FIONBIO, ¶m); - - if (arp->TCPListenSock == INVALID_SOCKET) - { - sprintf(Msg, "socket() failed error %d", WSAGetLastError()); - WritetoConsole(Msg); - return FALSE; - } - -// Debugprintf("TCP Listening Socket Created - socket %d port %d ", arp->TCPListenSock, arp->port); - - setsockopt (arp->TCPListenSock, SOL_SOCKET, SO_REUSEADDR, (char *)¶m,4); - - psin=&local_sin; - psin->sin_family = AF_INET; - psin->sin_addr.s_addr = htonl(INADDR_ANY); // Local Host Only - - psin->sin_port = htons(arp->port); /* Convert to network ordering */ - - if (bind(arp->TCPListenSock , (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) - { - sprintf(Msg, "bind(sock) failed Port %d Error %d\n", arp->port, WSAGetLastError()); - Debugprintf(Msg); - closesocket(arp->TCPListenSock); - - return FALSE; - } - - if (listen(arp->TCPListenSock, 1) < 0) - { - sprintf(Msg, "listen(sock) failed Error %d", WSAGetLastError()); - Debugprintf(Msg); - closesocket(arp->TCPListenSock); - return FALSE; - } - - arp->TCPState = TCPListening; - return TRUE; -} - -void CloseSockets(struct AXIPPORTINFO * PORT) -{ - int i; - int index = 0; - struct arp_table_entry * arp; - - if (PORT->needip) - closesocket(PORT->sock); - - for (i=0;iNumberofUDPPorts;i++) - { - closesocket(PORT->udpsock[i]); - } - - // Close any open or listening TCP sockets - - while (index < PORT->arp_table_len) - { - arp = &PORT->arp_table[index++]; - - if (arp->TCPMode == TCPMaster) - { - if (arp->TCPState) - { - closesocket(arp->TCPSock); - arp->TCPSock = 0; - } - continue; - } - - if (arp->TCPMode == TCPSlave) - { - if (arp->TCPState) - { - closesocket(arp->TCPSock); - arp->TCPSock = 0; - } - - closesocket(arp->TCPListenSock); - continue; - } - } - return ; -} - -#ifndef LINBPQ - -static LRESULT CALLBACK AXResWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - PAINTSTRUCT ps; - HDC hdc; - HFONT hOldFont ; - char line[100]; - char outcall[10]; - int index,displayline; - struct AXIPPORTINFO * PORT; - MINMAXINFO * mmi; - int nScrollCode,nPos; - int i, Port; - char Flags[10]; - struct arp_table_entry * arp; - - // Find our PORT Entry - - for (Port = 1; Port < 33; Port++) - { - PORT = Portlist[Port]; - if (PORT == NULL) - continue; - - if (PORT->hResWnd == hWnd) - break; - } - - if (PORT == NULL) - return DefMDIChildProc(hWnd, message, wParam, lParam); - - i=1; - - switch (message) - { - case WM_GETMINMAXINFO: - - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = 600; - mmi->ptMaxSize.y = PORT->MaxResWindowlength; - mmi->ptMaxTrackSize.x = 55600; - mmi->ptMaxTrackSize.y = PORT->MaxResWindowlength; - - 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_PTR)PORT->hResMenu, "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_CHAR: - - if (PORT->MHEnabled == FALSE && PORT->MHAvailable) - { - PORT->MHEnabled=TRUE; - CreateMHWindow(PORT); - ShowWindow(PORT->hMHWnd, SW_RESTORE); // In case Start Minimized set - } - break; - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - - if (wmId == BPQREREAD) - { - CloseSockets(PORT); - - if (ProcessConfig()) - { - FreeConfig(); - ReadConfigFile(Port); - } - else - Consoleprintf("Failed to reread config file - leaving config unchanged"); - - _beginthread(OpenSockets, 0, PORT); - - ResolveDelay = 2; - InvalidateRect(hWnd,NULL,TRUE); - - return 0; - } - - if (wmId == BPQADDARP) - { - if (PORT->ConfigWnd == 0) - { - PORT->ConfigWnd=CreateDialog(hInstance, ConfigClassName, 0, NULL); - - if (!PORT->ConfigWnd) - { - return (FALSE); - } - ShowWindow(PORT->ConfigWnd, SW_SHOW); - UpdateWindow(PORT->ConfigWnd); - } - - SetForegroundWindow(PORT->ConfigWnd); - - return(0); - } - 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_RESTORE: - - PORT->ResMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - - break; - - case SC_MINIMIZE: - - PORT->ResMinimized = TRUE; - - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - - case WM_VSCROLL: - - nScrollCode = (int) LOWORD(wParam); // scroll bar value - nPos = (short int) HIWORD(wParam); // scroll box position - - //hwndScrollBar = (HWND) lParam; // handle of scroll bar - - if (nScrollCode == SB_LINEUP || nScrollCode == SB_PAGEUP) - { - PORT->baseline--; - if (PORT->baseline <0) - PORT->baseline=0; - } - - if (nScrollCode == SB_LINEDOWN || nScrollCode == SB_PAGEDOWN) - { - PORT->baseline++; - if (PORT->baseline > PORT->arp_table_len) - PORT->baseline = PORT->arp_table_len; - } - - if (nScrollCode == SB_THUMBTRACK) - { - PORT->baseline=nPos; - } - - SetScrollPos(hWnd,SB_VERT,PORT->baseline,TRUE); - - InvalidateRect(hWnd,NULL,TRUE); - break; - - - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - - hOldFont = SelectObject( hdc, hFont) ; - - index = PORT->baseline; - displayline=0; - - while (index < PORT->arp_table_len) - { - arp = &PORT->arp_table[index]; - - Flags[0] = 0; - - if (arp->BCFlag) - strcat(Flags, "B "); - - if (arp->TCPState == TCPConnected) - strcat(Flags, "C "); - - if (arp->AutoAdded) - strcat(Flags, "A"); - - if (arp->ResolveFlag && arp->error != 0) - { - // resolver error - Display Error Code - sprintf(PORT->hostaddr,"Error %d",arp->error); - } - else - { - if (arp->IPv6) - Format_Addr((unsigned char *)&arp->destaddr6.sin6_addr, PORT->hostaddr, TRUE); - else - Format_Addr((unsigned char *)&arp->destaddr.sin_addr, PORT->hostaddr, FALSE); - } - - CONVFROMAX25(arp->callsign,outcall); - - if (arp->port == arp->SourcePort) - i=sprintf(line,"%.10s = %.64s %d = %-.30s %s ", - outcall, - arp->hostname, - arp->port, - PORT->hostaddr, - Flags); - else - i=sprintf(line,"%.10s = %.64s %d<%d = %-.30s %s ", - outcall, - arp->hostname, - arp->port, - arp->SourcePort, - PORT->hostaddr, - Flags); - - TextOut(hdc, 0, (displayline++)*14+2, line, i); - - index++; - } - - SelectObject( hdc, hOldFont ) ; - EndPaint (hWnd, &ps); - - break; - - case WM_DESTROY: - -// PostQuitMessage(0); - - break; - - - default: - return DefMDIChildProc(hWnd, message, wParam, lParam); - - } - return DefMDIChildProc(hWnd, message, wParam, lParam); - -} - -LRESULT FAR PASCAL ConfigWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) -{ - int cmd,id,i; - HWND hwndChild; - BOOL OK1,OK2,OK3; - - char call[10], host[65]; - int Interval; - int calllen; - int port; - char axcall[7]; - BOOL UDPFlag, BCFlag; - struct AXIPPORTINFO * PORT; - int useSourcePort = 0; - - for (i=1; i <= MAXBPQPORTS; i++) - { - PORT = Portlist[i]; - if (PORT == NULL) - continue; - - if (PORT->ConfigWnd == hWnd) - break; - } - - switch (message) - { - case WM_CTLCOLORDLG: - - return (LRESULT)bgBrush; - - case WM_COMMAND: - - id = LOWORD(wParam); - hwndChild = (HWND)(UINT)lParam; - cmd = HIWORD(wParam); - - switch (id) - { - case ID_SAVE: - - OK1=GetDlgItemText(PORT->ConfigWnd,1001,(LPSTR)call,10); - OK2=GetDlgItemText(PORT->ConfigWnd,1002,(LPSTR)host,64); - OK3=1; - - for (i=0;i<7;i++) - call[i] = toupper(call[i]); - - UDPFlag=IsDlgButtonChecked(PORT->ConfigWnd,1004); - BCFlag=IsDlgButtonChecked(PORT->ConfigWnd,1005); - - if (UDPFlag) - port=GetDlgItemInt(PORT->ConfigWnd,1003,&OK3,FALSE); - else - port=0; - - Interval=0; - - if (OK1 && OK2 && OK3==1) - { - if (convtoax25(call,axcall,&calllen)) - { - add_arp_entry(PORT, axcall,0,calllen,port,host,Interval, BCFlag, FALSE, 0, port, FALSE, 0, useSourcePort); - ResolveDelay = 2; - return(DestroyWindow(hWnd)); - } - } - - // Validation failed - - if (!OK1) SetDlgItemText(PORT->ConfigWnd,1001,"????"); - if (!OK2) SetDlgItemText(PORT->ConfigWnd,1002,"????"); - if (!OK3) SetDlgItemText(PORT->ConfigWnd,1003,"????"); - - break; - - case ID_CANCEL: - - return(DestroyWindow(hWnd)); - } - break; - -// case WM_CLOSE: - -// return(DestroyWindow(hWnd)); - - case WM_DESTROY: - - PORT->ConfigWnd=0; - - return(0); - - } - - return (DefWindowProc(hWnd, message, wParam, lParam)); - -} -#endif - -static void CreateResolverWindow(struct AXIPPORTINFO * PORT) -{ -#ifndef LINBPQ - - int WindowParam; - WNDCLASS wc; - char WindowTitle[100]; - int retCode, Type, Vallen; - HKEY hKey=0; - char Size[80]; - - HWND hResWnd; - char Key[80]; - RECT Rect = {0, 0, 300, 300}; - int Top, Left, Width, Height; - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", PORT->Port); - - retCode = RegOpenKeyEx (REGTREE, Key, 0, KEY_QUERY_VALUE, &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"ResSize",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, &PORT->ResMinimized); - - if (Rect.top < - 500 || Rect.left < - 500) - { - Rect.left = 0; - Rect.top = 0; - Rect.right = 600; - Rect.bottom = 400; - } - - if (Rect.top < OffsetH) // Make sure not off top of MDI frame - { - int Error = OffsetH - Rect.top; - Rect.top += Error; - Rect.bottom += Error; - } - - RegCloseKey(hKey); - } - - Top = Rect.top; - Left = Rect.left; - Width = Rect.right - Left; - Height = Rect.bottom - Top; - - // Register the window classes - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)AXResWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = NULL ; - wc.lpszClassName = "AXAppName"; - - RegisterClass(&wc); - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.lpfnWndProc = ConfigWndProc; - wc.lpszClassName = ConfigClassName; - RegisterClass(&wc); - - WindowParam = WS_OVERLAPPEDWINDOW | WS_VSCROLL; - - sprintf(WindowTitle,"AXIP Port %d Resolver", PORT->Port); - - PORT->hResWnd = hResWnd = CreateMDIWindow("AXAppName", WindowTitle, WindowParam, - Left - (OffsetW /2), Top - OffsetH + 4, Width, Height, ClientWnd, hInstance, 1234); - - - PORT->hResMenu = CreatePopupMenu(); - AppendMenu(PORT->hResMenu, MF_STRING, BPQREREAD, "ReRead Config"); - AppendMenu(PORT->hResMenu, MF_STRING, BPQADDARP, "Add Entry"); - - SetScrollRange(hResWnd,SB_VERT, 0, PORT->arp_table_len, TRUE); - - if (PORT->ResMinimized) - ShowWindow(hResWnd, SW_SHOWMINIMIZED); - else - ShowWindow(hResWnd, SW_RESTORE); -#endif -} -extern HWND hWndPopup; - - -static void ResolveNames(struct AXIPPORTINFO * PORT) -{ - int count = 0; - - PORT->ResolveNamesThreadId = GetCurrentThreadId(); // Detect if another started - - while(TRUE) - { - count++; // So we can trap first few loops - - ResolveDelay = 15 * 60; - - for (PORT->ResolveIndex=0; PORT->ResolveIndex < PORT->arp_table_len; PORT->ResolveIndex++) - { - struct arp_table_entry * arp = &PORT->arp_table[PORT->ResolveIndex]; - - if (arp->ResolveFlag) - { - struct addrinfo hints, *res = 0; - int n; - BOOL UseV6 = FALSE; - BOOL ForceV4 = FALSE; - - if (_memicmp(arp->hostname, "ipv6:", 5) == 0) - UseV6 = TRUE; - else if (_memicmp(arp->hostname, "ipv4:", 5) == 0) - ForceV4 = TRUE; - - memset(&hints, 0, sizeof hints); - hints.ai_socktype = SOCK_DGRAM; - - if (UseV6) - { - hints.ai_family = AF_INET6; // use IPv6 - n = getaddrinfo(&arp->hostname[5], NULL, &hints, &res); - } - else if (ForceV4) - { - hints.ai_family = AF_INET; // use IPv4 - n = getaddrinfo(&arp->hostname[5], NULL, &hints, &res); - } - else if (PORT->PortIPv6) // Can use IPv6 - { - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - n = getaddrinfo(arp->hostname, NULL, &hints, &res); - } - else - { - hints.ai_family = AF_INET; // use IPv4 only - n = getaddrinfo(arp->hostname, NULL, &hints, &res); - } - if (res) - { - arp->error = 0; - if (res->ai_family == AF_INET) - { - memcpy(&arp->destaddr.sin_addr.s_addr, &res->ai_addr->sa_data[2], 4); - arp->IPv6 = FALSE; - arp->destaddr.sin_family = AF_INET; -// Debugprintf("AXIP %s = %d.%d.%d.%d", arp->hostname, (UCHAR)res->ai_addr->sa_data[2], -// (UCHAR)res->ai_addr->sa_data[3], (UCHAR)res->ai_addr->sa_data[4], (UCHAR)res->ai_addr->sa_data[5]); - - } - else - { - struct sockaddr_in6 * sa6 = (struct sockaddr_in6 *)res->ai_addr; - - memcpy(&arp->destaddr6.sin6_addr, &sa6->sin6_addr, 16); - arp->IPv6 = TRUE; - arp->destaddr.sin_family = AF_INET6; - } - arp->destaddr.sin_port = htons(arp->port); - freeaddrinfo(res); - } - else - { - PORT->arp_table[PORT->ResolveIndex].error = WSAGetLastError(); - - if (count < 4) - ResolveDelay = 30; // if errors try again soon - } - } - } - - SaveAXIPCache(PORT); - -#ifndef LINBPQ - InvalidateRect(PORT->hResWnd,NULL,TRUE); -#endif - while(ResolveDelay-- > 0) - { - if (pthread_equal(PORT->ResolveNamesThreadId, GetCurrentThreadId()) == FALSE) - { - Debugprintf("AXIP Resolve thread %x redundant - closing", GetCurrentThreadId()); - return; - } - Sleep(1000); - } - } - Debugprintf("AXIP Resolve thread exitied"); -} - -#ifndef LINBPQ - -LRESULT CALLBACK MHWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - PAINTSTRUCT ps; - HDC hdc; - HFONT hOldFont ; - char line[100]; - char outcall[10]; - HGLOBAL hMem; - struct AXIPPORTINFO * PORT; - int index,displayline; - MINMAXINFO * mmi; - int nScrollCode,nPos; - - - int i; - - for (i=1; i <= MAXBPQPORTS; i++) - { - PORT = Portlist[i]; - if (PORT == NULL) - continue; - - if (PORT->hMHWnd == hWnd) - break; - } - - if (PORT == NULL) - return DefMDIChildProc(hWnd, message, wParam, lParam); - - switch (message) - { - case WM_GETMINMAXINFO: - - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = 600; - mmi->ptMaxSize.y = PORT->MaxMHWindowlength; - mmi->ptMaxTrackSize.x = 600; - mmi->ptMaxTrackSize.y = PORT->MaxMHWindowlength; - 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)PORT->hMHMenu, "Edit"); - 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_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) { - - case BPQCLEAR: - memset(PORT->MHTable, 0, sizeof(PORT->MHTable)); - InvalidateRect(hWnd,NULL,TRUE); - return 0; - - case BPQCOPY: - - hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, MaxMHEntries * 100); - - if (hMem != 0) - { - if (OpenClipboard(hWnd)) - { - CopyScreentoBuffer(GlobalLock(hMem), PORT); - GlobalUnlock(hMem); - EmptyClipboard(); - SetClipboardData(CF_TEXT,hMem); - CloseClipboard(); - } - else - { - GlobalFree(hMem); - } - } - return 0; - - default: - - 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_RESTORE: - - PORT->MHMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - break; - - case SC_MINIMIZE: - - PORT->MHMinimized = TRUE; - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_VSCROLL: - - nScrollCode = (int) LOWORD(wParam); // scroll bar value - nPos = (short int) HIWORD(wParam); // scroll box position - - //hwndScrollBar = (HWND) lParam; // handle of scroll bar - - if (nScrollCode == SB_LINEUP || nScrollCode == SB_PAGEUP) - { - PORT->mhbaseline--; - if (PORT->mhbaseline <0) - PORT->mhbaseline=0; - } - - if (nScrollCode == SB_LINEDOWN || nScrollCode == SB_PAGEDOWN) - { - PORT->mhbaseline++; - if (PORT->mhbaseline > PORT->CurrentMHEntries) - PORT->mhbaseline = PORT->CurrentMHEntries; - } - - if (nScrollCode == SB_THUMBTRACK) - { - PORT->mhbaseline=nPos; - } - - SetScrollPos(hWnd,SB_VERT,PORT->mhbaseline,TRUE); - - InvalidateRect(hWnd,NULL,TRUE); - break; - - - - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - hOldFont = SelectObject( hdc, hFont) ; - - index = PORT->mhbaseline; - displayline=0; - - PORT->CurrentMHEntries = 0; - - while (index < MaxMHEntries) - { - if (PORT->MHTable[index].proto != 0) - { - char Addr[80]; - - Format_Addr((unsigned char *)&PORT->MHTable[index].ipaddr6, Addr, PORT->MHTable[index].IPv6); - - CONVFROMAX25(PORT->MHTable[index].callsign,outcall); - - i=sprintf(line,"%-10s%-15s %c %-6d %-25s%c",outcall, - Addr, - PORT->MHTable[index].proto, - PORT->MHTable[index].port, - asctime(gmtime( &PORT->MHTable[index].LastHeard )), - (PORT->MHTable[index].Keepalive == 0) ? ' ' : 'K'); - - line[i-2]= ' '; // Clear CR returned by asctime - - TextOut(hdc,0,(displayline++)*14+2,line,i); - PORT->CurrentMHEntries ++; - } - index++; - } - - if (PORT->MaxMHWindowlength < PORT->CurrentMHEntries * 14 + 40) - PORT->MaxMHWindowlength = PORT->CurrentMHEntries * 14 + 40; - - SelectObject( hdc, hOldFont ) ; - EndPaint (hWnd, &ps); - - break; - - case WM_DESTROY: - - PORT->MHEnabled=FALSE; - - break; - - default: - return DefMDIChildProc(hWnd, message, wParam, lParam); - - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); -} - -#endif - -BOOL CopyScreentoBuffer(char * buff, struct AXIPPORTINFO * PORT) -{ - int index; - char outcall[10]; - - index = 0; - - while (index < MaxMHEntries) - { - if (PORT->MHTable[index].proto != 0) - { - CONVFROMAX25(PORT->MHTable[index].callsign,outcall); - - buff+=sprintf(buff,"%-10s%-15s %c %-6d %-26s",outcall, - inet_ntoa(PORT->MHTable[index].ipaddr), - PORT->MHTable[index].proto, - PORT->MHTable[index].port, - asctime(gmtime( &PORT->MHTable[index].LastHeard ))); - } - *(buff-2)=13; - *(buff-1)=10; - index++; - - } - *(buff)=0; - - return 0; -} - -void CreateMHWindow(struct AXIPPORTINFO * PORT) -{ -#ifndef LINBPQ - - WNDCLASS wc; - char WindowTitle[100]; - int retCode, Type, Vallen; - HKEY hKey=0; - char Size[80]; - HWND hMHWnd; - char Key[80]; - RECT Rect = {0, 0, 300, 300}; - int Top, Left, Width, Height; - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", PORT->Port); - - retCode = RegOpenKeyEx (REGTREE, Key, 0, KEY_QUERY_VALUE, &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"MHSize",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, &PORT->MHMinimized); - - if (Rect.top < - 500 || Rect.left < - 500) - { - Rect.left = 0; - Rect.top = 0; - Rect.right = 600; - Rect.bottom = 400; - } - - if (Rect.top < OffsetH) // Make sure not off top of MDI frame - { - int Error = OffsetH - Rect.top; - Rect.top += Error; - Rect.bottom += Error; - } - - - RegCloseKey(hKey); - } - - Top = Rect.top; - Left = Rect.left; - Width = Rect.right - Left; - Height = Rect.bottom - Top; - - PORT->MaxMHWindowlength = Height; - - wc.style = CS_HREDRAW | CS_VREDRAW ;//| CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)MHWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = NULL ; - wc.lpszClassName = "MHAppName"; - - RegisterClass(&wc); - - sprintf(WindowTitle,"AXIP Port %d MHEARD", PORT->Port); - - PORT->hMHWnd = hMHWnd = CreateMDIWindow("MHAppName", WindowTitle, - WS_OVERLAPPEDWINDOW | WS_VSCROLL, - Left - (OffsetW /2), Top - OffsetH, Width, Height, ClientWnd, hInstance, 1234); - - PORT->hMHMenu = CreatePopupMenu(); - AppendMenu(PORT->hMHMenu, MF_STRING, BPQCOPY, "Copy"); - AppendMenu(PORT->hMHMenu, MF_STRING, BPQCLEAR, "Clear"); - - if (PORT->MHMinimized) - ShowWindow(hMHWnd, SW_SHOWMINIMIZED); - else - ShowWindow(hMHWnd, SW_RESTORE); -#endif -} - -unsigned short int compute_crc(unsigned char *buf,int len) -{ - unsigned short fcs = 0xffff; - int i; - - for(i = 0; i < len; i++) - fcs = (fcs >>8 ) ^ CRCTAB[(fcs ^ buf[i]) & 0xff]; - - return fcs; -} - -/* - -static const unsigned short ccittTab[] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}; - -unsigned short int compute_crc_ccitt(unsigned char *buf, int len) -{ - int i; - unsigned short fcs = 0; - - for(i = 0; i < len; i++) - fcs = (fcs >>8 ) ^ ccittTab[(fcs ^ buf[i]) & 0xff]; - - return fcs; -} - - - union { - unsigned short m_crc16; - unsigned char m_crc8[2U]; - } fcs; - - -unsigned short CCCITTChecksum(unsigned char* data, unsigned int length) -{ - int i; - - fcs.m_crc16 = 0; - - for (i = 0U; i < length; i++) - fcs.m_crc16 = (fcs.m_crc8[0U] << 8) ^ ccittTab[fcs.m_crc8[1U] ^ data[i]]; - - return fcs.m_crc16; -} - -*/ - -static BOOL ReadConfigFile(int Port) -{ - -/* Linux Format - -broadcast QST-0 NODES-0 -# -# ax.25 route definition, define as many as you need. -# format is route (call/wildcard) (ip host at destination) -# ssid of 0 routes all ssid's -# -# route [flags] -# -# Valid flags are: -# b - allow broadcasts to be transmitted via this route -# d - this route is the default route -# -#route vk2sut-0 44.136.8.68 b -#route vk5xxx 44.136.188.221 b -#route vk2abc 44.1.1.1 -# -*/ - -//UDP 9999 # Port we listen on -//MAP G8BPQ-7 10.2.77.1 # IP 93 for compatibility -//MAP BPQ7 10.2.77.1 UDP 2222 # UDP port to send to -//MAP BPQ8 10.2.77.2 UDP 3333 # UDP port to send to - - char buf[256],errbuf[256]; - HKEY hKey=0; - char * Config; - struct AXIPPORTINFO * PORT; - - Config = PortConfig[Port]; - - if (Portlist[Port]) // Already defined, so must be re-read - { - PORT = Portlist[Port]; - - PORT->NumberofBroadcastAddreses = 0; - PORT->needip = FALSE; - PORT->NeedTCP = FALSE; - PORT->MHAvailable = FALSE; - PORT->MHEnabled = FALSE; - PORT->NumberofUDPPorts = 0; - PORT->NeedResolver = FALSE; - PORT->arp_table_len = 0; - memset(PORT->arp_table, 0, sizeof(struct arp_table_entry) * MAX_ENTRIES); - PORT->AutoAddARP = FALSE; - PORT->AutoAddBC = FALSE; - } - else - { - Portlist[Port] = PORT = zalloc(sizeof (struct AXIPPORTINFO)); - } - - PORT->Checkifcanreply = TRUE; - - if (Config) - { - char * ptr1 = Config, * ptr2; - - // Using config from bpq32.cfg - - 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 (!ProcessLine(buf, PORT)) - { - WritetoConsole("BPQAXIP - Bad config record"); - WritetoConsole(errbuf); - WritetoConsole("\n"); - } - } - - if (PORT->NumberofUDPPorts > MAXUDPPORTS) - { - n=sprintf(buf,"BPQAXIP - Too many UDP= lines - max is %d\n", MAXUDPPORTS); - WritetoConsole(buf); - } - return TRUE; - } - - WritetoConsole("No Configuration info in bpq32.cfg"); - - return FALSE; -} - -static int ProcessLine(char * buf, struct AXIPPORTINFO * PORT) -{ - char * ptr; - char * p_call; - char * p_ipad; - char * p_UDP; - char * p_udpport; - char * p_Interval; - - int calllen; - int port, SourcePort; - int bcflag; - char axcall[7]; - int Interval; - int noUpdate=FALSE; - int TCPMode; - int useSourcePort = 0; - - ptr = strtok(buf, " \t\n\r"); - - if(ptr == NULL) return (TRUE); - - if(*ptr =='#') return (TRUE); // comment - - if(*ptr ==';') return (TRUE); // comment - - if(_stricmp(ptr,"UDP") == 0) - { - if (PORT->NumberofUDPPorts > MAXUDPPORTS) PORT->NumberofUDPPorts--; - - p_udpport = strtok(NULL, " ,\t\n\r"); - - if (p_udpport == NULL) return (FALSE); - - PORT->udpport[PORT->NumberofUDPPorts] = atoi(p_udpport); - - if (PORT->udpport[PORT->NumberofUDPPorts] == 0) return (FALSE); - - ptr = strtok(NULL, " \t\n\r"); - - if (ptr && _stricmp(ptr, "ipv6") == 0) - { - PORT->PortIPv6 = TRUE; - PORT->IPv6[PORT->NumberofUDPPorts] = TRUE; - } - - PORT->NumberofUDPPorts++; - - return (TRUE); - } - - if(_stricmp(ptr,"MHEARD") == 0) - { - PORT->MHEnabled = TRUE; - PORT->MHAvailable = TRUE; - - return (TRUE); - } - - if(_stricmp(ptr,"DONTCHECKSOURCECALL") == 0) - { - PORT->Checkifcanreply = FALSE; - return (TRUE); - } - - if(_stricmp(ptr,"AUTOADDMAP") == 0) - { - PORT->AutoAddARP = TRUE; - PORT->AutoAddBC = TRUE; - return (TRUE); - } - - if(_stricmp(ptr,"AUTOADDQUIET") == 0) - { - PORT->AutoAddARP = TRUE; - PORT->AutoAddBC = FALSE; - return (TRUE); - } - - if(_stricmp(ptr,"MAP") == 0) - { - p_call = strtok(NULL, " \t\n\r"); - - if (p_call == NULL) return (FALSE); - - _strupr(p_call); - - if (_stricmp(p_call, "DUMMY") == 0) - { - Consoleprintf("MAP DUMMY is no longer needed - statement ignored"); - return TRUE; - } - - p_ipad = strtok(NULL, " \t\n\r"); - - if (p_ipad == NULL) return (FALSE); - - p_UDP = strtok(NULL, " \t\n\r"); - - Interval=0; - port=0; // Raw IP - bcflag=0; - TCPMode=0; - SourcePort = 0; - useSourcePort = 0; - -// -// Look for (optional) KEEPALIVE, DYNAMIC, UDP or BROADCAST params -// - while (p_UDP != NULL) - { - if (_stricmp(p_UDP,"NOUPDATE") == 0) - { - noUpdate = TRUE; - p_UDP = strtok(NULL, " \t\n\r"); - continue; - } - - if (_stricmp(p_UDP,"KEEPALIVE") == 0) - { - p_Interval = strtok(NULL, " \t\n\r"); - - if (p_Interval == NULL) return (FALSE); - - Interval = atoi(p_Interval); - p_UDP = strtok(NULL, " \t\n\r"); - continue; - } - - if (_stricmp(p_UDP,"UDP") == 0) - { - p_udpport = strtok(NULL, " \t\n\r"); - - if (p_udpport == NULL) return (FALSE); - - if (_stricmp(p_udpport,"FROMPORT") == 0) - { - useSourcePort = TRUE; - port = 0; - } - else - port = atoi(p_udpport); - - p_UDP = strtok(NULL, " \t\n\r"); - continue; - } - - if (_stricmp(p_UDP,"SOURCEPORT") == 0) - { - p_udpport = strtok(NULL, " \t\n\r"); - - if (p_udpport == NULL) return (FALSE); - - SourcePort = atoi(p_udpport); - p_UDP = strtok(NULL, " \t\n\r"); - continue; - } - - if (_stricmp(p_UDP,"TCP-Master") == 0) - { - p_udpport = strtok(NULL, " \t\n\r"); - - if (p_udpport == NULL) return (FALSE); - - port = atoi(p_udpport); - p_UDP = strtok(NULL, " \t\n\r"); - - TCPMode=TCPMaster; - - continue; - } - - if (_stricmp(p_UDP,"TCP-Slave") == 0) - { - p_udpport = strtok(NULL, " \t\n\r"); - - if (p_udpport == NULL) return (FALSE); - - port = atoi(p_udpport); - p_UDP = strtok(NULL, " \t\n\r"); - - TCPMode = TCPSlave; - continue; - - } - - - if (_stricmp(p_UDP,"B") == 0) - { - bcflag =TRUE; - p_UDP = strtok(NULL, " \t\n\r"); - continue; - } - - if ((*p_UDP == ';') || (*p_UDP == '#')) break; // Comment on end - - return FALSE; - - } - - if (convtoax25(p_call,axcall,&calllen)) - { - if (SourcePort == 0) - SourcePort = port; - - add_arp_entry(PORT, axcall, 0, calllen, port, p_ipad, Interval, bcflag, FALSE, TCPMode, SourcePort, FALSE, noUpdate, useSourcePort); - return (TRUE); - } - } // End of Process MAP - - if(_stricmp(ptr,"BROADCAST") == 0) - { - p_call = strtok(NULL, " \t\n\r"); - - if (p_call == NULL) return (FALSE); - - if (convtoax25(p_call,axcall,&calllen)) - { - add_bc_entry(PORT, axcall,calllen); - return (TRUE); - } - - - return (FALSE); // Failed convtoax25 - } - - // - // Bad line - // - return (FALSE); -} - -int CONVFROMAX25(char * incall, char * outcall) -{ - int in,out=0; - unsigned char chr; -// -// CONVERT AX25 FORMAT CALL IN incall TO NORMAL FORMAT IN out -// RETURNS LENGTH -// - memset(outcall,0x20,9); - outcall[9]=0; - - for (in=0;in<6;in++) - { - chr=incall[in]; - if (chr == 0x40) - break; - chr >>= 1; - outcall[out++]=chr; - } - - chr=incall[6]; // ssid - chr >>= 1; - chr &= 15; - - if (chr > 0) - { - outcall[out++]='-'; - if (chr > 9) - { - chr-=10; - outcall[out++]='1'; - } - chr+=48; - outcall[out++]=chr; - } - return (out); -} - - -BOOL convtoax25(unsigned char * callsign, unsigned char * ax25call,int * calllen) -{ - 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; - *calllen = 7; // include ssid in test - return (TRUE); - } - return (FALSE); - } - - if (callsign[i] == 0 || callsign[i] == ' ') - { - // - // End of call - no ssid - // - *calllen = 6; // wildcard ssid - return (TRUE); - } - - ax25call[i] = callsign[i] << 1; - } - - // - // Too many chars - // - - return (FALSE); -} - -BOOL add_arp_entry(struct AXIPPORTINFO * PORT, UCHAR * call, UCHAR * ip, int len, int port, - UCHAR * name, int keepalive, BOOL BCFlag, BOOL AutoAdded, int TCPFlag, int SourcePort, BOOL IPv6, int noUpdate, int useSourcePort) -{ - struct arp_table_entry * arp; - - if (PORT->arp_table_len == MAX_ENTRIES) - // - // Table full - // - return (FALSE); - - arp = &PORT->arp_table[PORT->arp_table_len]; - - if (SourcePort) - arp->SourcePort = SourcePort; - else - arp->SourcePort = port; - - arp->PORT = PORT; - - if (port == 0 && arp->replytoSourcePort == 0) - PORT->needip = 1; // Enable Raw IP Mode - - arp->ResolveFlag=TRUE; - PORT->NeedResolver=TRUE; - - memcpy (&arp->callsign,call,7); - strncpy((char *)&arp->hostname,name,64); - arp->len = len; - arp->port = port; - keepalive+=9; - keepalive/=10; - - arp->keepalive = keepalive; - arp->keepaliveinit = keepalive; - arp->BCFlag = BCFlag; - arp->AutoAdded = AutoAdded; - arp->TCPMode = TCPFlag; - arp->noUpdate = noUpdate; - PORT->arp_table_len++; - arp->replytoSourcePort = useSourcePort; - - if (PORT->MaxResWindowlength < (PORT->arp_table_len * 14) + 70) - PORT->MaxResWindowlength = (PORT->arp_table_len * 14) + 70; - - PORT->NeedResolver |= TCPFlag; // Need Resolver window to handle tcp socket messages - PORT->NeedTCP |= TCPFlag; - - if (ip) - { - // Only have an IP address if dynamically added - so update destaddr - - if (IPv6) - { - memcpy(&arp->destaddr6.sin6_addr, ip, 16); - arp->IPv6 = TRUE; - arp->destaddr.sin_family = AF_INET6; - } - else - { - memcpy(&arp->destaddr.sin_addr.s_addr, ip, 4); - arp->IPv6 = FALSE; - arp->destaddr.sin_family = AF_INET; - } - arp->destaddr.sin_port = htons(arp->port); -#ifndef LINBPQ - - SetScrollRange(PORT->hResWnd,SB_VERT, 0, PORT->arp_table_len, TRUE); - InvalidateRect(PORT->hResWnd, NULL, TRUE); -#endif - } - - return (TRUE); -} - -BOOL add_bc_entry(struct AXIPPORTINFO * PORT, unsigned char * call, int len) -{ - if (PORT->NumberofBroadcastAddreses == MAX_BROADCASTS) - // - // Table full - // - return (FALSE); - - memcpy (PORT->BroadcastAddresses[PORT->NumberofBroadcastAddreses].callsign,call,7); - PORT->BroadcastAddresses[PORT->NumberofBroadcastAddreses].len = len; - PORT->NumberofBroadcastAddreses++; - - return (TRUE); -} - - -int CheckKeepalives(struct AXIPPORTINFO * PORT) -{ - int index=0; - SOCKET txsock; - struct arp_table_entry * arp; - - if (PORT->arp_table_len >= MAX_ENTRIES) - { - Debugprintf("arp_table_len corrupt - %d", PORT->arp_table_len); - PORT->arp_table_len = MAX_ENTRIES - 1; - } - - while (index < PORT->arp_table_len) - { - if (PORT->arp_table[index].keepalive != 0) - { - arp = &PORT->arp_table[index]; - arp->keepalive--; - - if (arp->keepalive == 0) - { - // - // Send Keepalive Packet - // - arp->keepalive=arp->keepaliveinit; - - if (arp->error == 0) - { - if (arp->port == 0) txsock = PORT->sock; else txsock = PORT->udpsock[0]; - - sendto(txsock,"Keepalive",9,0,(struct sockaddr *)&arp->destaddr,sizeof(arp->destaddr)); - } - } - } - - index++; - - } - - // Decrement MH Keepalive flags - - for (index = 0; index < MaxMHEntries; index++) - { - if (PORT->MHTable[index].Keepalive != 0) - PORT->MHTable[index].Keepalive--; - } - - return (0); -} - -BOOL CheckSourceisResolvable(struct AXIPPORTINFO * PORT, char * call, int FromPort, VOID * rxaddr, int ToPort) -{ - // Makes sure we can reply to call before accepting message - - int index = 0; - struct arp_table_entry * arp; - - while (index < PORT->arp_table_len) - { - arp = &PORT->arp_table[index]; - - if (memcmp(arp->callsign, call, arp->len) == 0) - { - // Call is present - if AutoAdded, refresh IP address and Port - - // Why not refreesh resolved addresses - if dynamic addr has changed - // this will give quicker response - - if (arp->noUpdate == 0) - { - if (arp->IPv6) - { - struct sockaddr_in6 * SA6 = rxaddr; - memcpy(&arp->destaddr6.sin6_addr, &SA6->sin6_addr, 16); - } - else - { - struct sockaddr_in * SA = rxaddr; - memcpy(&arp->destaddr.sin_addr.s_addr, &SA->sin_addr, 4); - } - // Dont think I should update port unless using source port for dest - - if (arp->replytoSourcePort) - { - arp->port = FromPort; - arp->destaddr.sin_port = htons(arp->port); - if (arp->SourcePort == 0) - arp->SourcePort = ToPort; - } - } - arp->LastHeard = time(NULL); - return 1; // Ok to process - } - index++; - } - - return (0); // Not in list -} - -int Update_MH_List(struct AXIPPORTINFO * PORT, UCHAR * ipad, char * call, char proto, short port, BOOL IPv6) -{ - int index; - char callsign[7]; - int SaveKeepalive=0; - struct MHTableEntry * MH; - - memcpy(callsign,call,7); - callsign[6] &= 0x3e; // Mask non-ssid bits - - for (index = 0; index < MaxMHEntries; index++) - { - MH = &PORT->MHTable[index]; - - if (MH->callsign[0] == 0) - { - // empty entry, so call not present. Move all down, and add to front - -#ifdef WIN32 - SetScrollRange(PORT->hMHWnd, SB_VERT, 0, index + 1, TRUE); -#endif - goto MoveEntries; - } - - if (memcmp(MH->callsign,callsign,7) == 0 && - memcmp(&MH->ipaddr, ipad, (MH->IPv6) ? 16 : 4) == 0 && - MH->proto == proto && - MH->port == port) - { - // Entry found, move preceeding entries down and put on front - - SaveKeepalive = MH->Keepalive; - goto MoveEntries; - } - } - - // Table full move MaxMHEntries-1 entries down, and add on front - - index=MaxMHEntries-1; - -MoveEntries: - - // - // Move all preceeding entries down one, and put on front - // - - if (index > 0) - memmove(&PORT->MHTable[1],&PORT->MHTable[0],index*sizeof(struct MHTableEntry)); - - MH = &PORT->MHTable[0]; - - memcpy(MH->callsign,callsign,7); - memcpy(&MH->ipaddr6, ipad, (IPv6) ? 16 : 4); - MH->proto = proto; - - MH->port = port; - time(&MH->LastHeard); - MH->Keepalive = SaveKeepalive; - MH->IPv6 = IPv6; -#ifndef LINBPQ - InvalidateRect(PORT->hMHWnd,NULL,TRUE); -#endif - return 0; - -} - -int Update_MH_KeepAlive(struct AXIPPORTINFO * PORT, struct in_addr ipad, char proto, short port) -{ - int index; - - for (index = 0; index < MaxMHEntries; index++) - { - if (PORT->MHTable[index].callsign[0] == 0) - - // empty entry, so call not present. - - return 0; - - if (memcmp(&PORT->MHTable[index].ipaddr,&ipad,4) == 0 && - PORT->MHTable[index].proto == proto && - PORT->MHTable[index].port == port) - { - PORT->MHTable[index].Keepalive = 30; // 5 Minutes at 10 sec ticks - return 0; - } - } - - return 0; - -} - - -int DumpFrameInHex(unsigned char * msg, int len) -{ - char errmsg[100]; - int i=0; - - for (i=0;iarp_table_len) - { - sockptr = &PORT->arp_table[index++]; - - if (sockptr->TCPMode) - { - if (sockptr->TCPState == TCPListening) - { - int addrlen; - SOCKET sock; - BOOL bOptVal = TRUE; - struct sockaddr sin; - - addrlen = sizeof(struct sockaddr); - - sock = accept(sockptr->TCPListenSock, &sin, &addrlen); - - if (sock == INVALID_SOCKET) - { - int err = WSAGetLastError(); - - if (err == 10035 || err == 11) - continue; - - if (err == 10038 || err == 9) - { - // Not a socket - - closesocket(sockptr->TCPListenSock); - OpenListeningSocket(PORT, sockptr); - - continue; - } - - - Debugprintf("AXIP accept() failed Error %d", err); - continue; - } - - Debugprintf("AXIP Connect accepted - Socket %d Port %d", sock, sockptr->port); - - if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&bOptVal, 4) != SOCKET_ERROR) - Debugprintf("Set SO_KEEPALIVE: ON"); - - sockptr->TCPSock = sock; - sockptr->TCPState = TCPConnected; - } - - if (sockptr->TCPState == TCPConnected) - { - int InputLen; - - // Poll TCP Connection for data - - // May have several messages per packet, or message split over packets - - if (sockptr->InputLen > 3000) // Shouldnt have lines longer than this in text mode - { - sockptr->InputLen = 0; - } - - ioctl(sockptr->TCPSock, FIONBIO, ¶m); - - InputLen = recv(sockptr->TCPSock, &sockptr->TCPBuffer[sockptr->InputLen], 1000, 0); - - if (InputLen == 0) - { - Debugprintf("TCP Close received for socket %d", sockptr->TCPSock); - - if (sockptr->TCPMode == TCPSlave) - sockptr->TCPState = TCPListening; - else - sockptr->TCPState = 0; - closesocket(sockptr->TCPSock); - continue; - } - - if (InputLen < 0) - { - int err = WSAGetLastError(); - - if (err == 10035 || err == 11) - InputLen = 0; - else - { - if (sockptr->TCPMode == TCPSlave) - sockptr->TCPState = TCPListening; - else - sockptr->TCPState = 0; - - closesocket(sockptr->TCPSock); - continue; - } - } - - sockptr->InputLen += InputLen; - - if (sockptr->InputLen == 0) - { - sockptr->TCPOK++; - - if (sockptr->TCPOK > 36000) // 60 MINS - { - if (sockptr->TCPSock) - { - Debugprintf("No Data for 60 Mins on Data Sock %d State %d", - sockptr->TCPListenSock, sockptr->TCPSock, sockptr->TCPState); - - sockptr->TCPState = 0; - closesocket(sockptr->TCPSock); - sockptr->TCPSock = 0; - } - - closesocket(sockptr->TCPListenSock); - OpenListeningSocket(PORT, sockptr); - - sockptr->TCPOK = 0; - } - continue; - } - } - - ptr = memchr(sockptr->TCPBuffer, FEND, sockptr->InputLen); - - if (ptr) // FEND in buffer - { - ptr2 = &sockptr->TCPBuffer[sockptr->InputLen]; - ptr++; - - if (ptr == ptr2) - { - // Usual Case - single meg in buffer - - MsgLen = sockptr->InputLen; - sockptr->InputLen = 0; - - if (MsgLen > 1) - { - memcpy(Buffer, sockptr->TCPBuffer, MsgLen); - - if (PORT->MHEnabled) - Update_MH_List(PORT, (UCHAR *)&sockptr->destaddr.sin_addr.s_addr, &Buffer[7],'T', sockptr->port, 0); - - sockptr->TCPOK = 0; - - return MsgLen; - } - } - else - { - // buffer contains more that 1 message - - MsgLen = sockptr->InputLen - (int)((ptr2-ptr)); - memcpy(Buffer, sockptr->TCPBuffer, MsgLen); - - memmove(sockptr->TCPBuffer, ptr, sockptr->InputLen-MsgLen); - - sockptr->InputLen -= MsgLen; - - if (MsgLen > 1) - { - if (PORT->MHEnabled) - Update_MH_List(PORT, (UCHAR *)&sockptr->destaddr.sin_addr.s_addr, &Buffer[7],'T', sockptr->port, 0); - - sockptr->TCPOK = 0; - - return MsgLen; - } - } - } - } - } - return 0; - -} - -int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len) -{ - int i,txptr=0; - UCHAR c; - - outbuff[0]=FEND; - txptr=1; - - for (i=0;iTCPMode == TCPMaster) - { - if (arp->TCPState == 0) - { - arp->TCPSock=socket(AF_INET,SOCK_STREAM,0); - - if (arp->TCPSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for AX/TCP socket - error code = %d\n", WSAGetLastError()); - WritetoConsole(Msg); - goto wait; - } - - setsockopt (arp->TCPSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(arp->TCPSock, SOL_SOCKET, SO_KEEPALIVE, (char*)&bcopt, 4); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - if (bind(arp->TCPSock, (struct sockaddr *) &sinx, addrlen) != 0 ) - { - // - // Bind Failed - // - - i=sprintf(Msg, "Bind Failed for AX/TCP socket - error code = %d\n", WSAGetLastError()); - WritetoConsole(Msg); - - goto wait; - } - - arp->TCPState = TCPConnecting; - - if (connect(arp->TCPSock,(struct sockaddr *) &arp->destaddr, sizeof(arp->destaddr)) == 0) - { - // - // Connected successful - // - - arp->TCPState = TCPConnected; - OutputDebugString("AXTCP Connected\r\n"); - ioctl (arp->TCPSock, FIONBIO, ¶m); - Alerted = 0; - } - else - { - err=WSAGetLastError(); - - // Connect failed - // - - if (Alerted == 0) - { - i = sprintf(Msg, "Connect Failed for AX/TCP port %d - error code = %d\n", htons(arp->destaddr.sin_port), err); - WritetoConsole(Msg); - OutputDebugString(Msg); - Alerted = 1; - } - closesocket(arp->TCPSock); - arp->TCPSock = 0; - arp->TCPState = 0; - } - } -wait: - Sleep (115000); // 2 Mins - } - - Debugprintf("AX/TCP Connect Thread %x Closing", arp->TCPThreadID); - - arp->TCPThreadID = 0; - - return; // Not Used - -} - -VOID Format_Addr(unsigned char * Addr, char * Output, BOOL IPV6) -{ - unsigned char * src; - char zeros[12] = ""; - char * ptr; - struct - { - int base, len; - } best, cur; - unsigned int words[8]; - int i; - - if (IPV6 == FALSE) - { - sprintf((char *)Output, "%d.%d.%d.%d", Addr[0], Addr[1], Addr[2], Addr[3]); - return; - } - - src = Addr; - - // See if Encapsulated IPV4 addr - - if (src[12] != 0) - { - if (memcmp(src, zeros, 12) == 0) // 12 zeros, followed by non-zero - { - sprintf((char *)Output, "::%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 = Output; - - 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'; -} - - -#define LIBCONFIG_STATIC -#include "libconfig.h" - - - -VOID SaveAXIPCache(struct AXIPPORTINFO * PORT) -{ - config_setting_t *root, *group; - config_t cfg; - char ConfigName[256]; - int index=0; - struct arp_table_entry * arp; - unsigned char hostaddr[64]; - char Key[128]; - - if (BPQDirectory[0] == 0) - { - sprintf(ConfigName,"axipcache%d.cfg", PORT->Port); - } - else - { - sprintf(ConfigName,"%s/axipcache%d.cfg", BPQDirectory, PORT->Port); - } - - // Get rid of old config before saving - - config_init(&cfg); - - root = config_root_setting(&cfg); - - group = config_setting_add(root, "main", CONFIG_TYPE_GROUP); - - if (PORT->arp_table_len >= MAX_ENTRIES) - { - Debugprintf("arp_table_len corrupt - %d", PORT->arp_table_len); - PORT->arp_table_len = MAX_ENTRIES - 1; - } - - while (index < PORT->arp_table_len) - { - char * ptr = Key; - - arp = &PORT->arp_table[index++]; - - if (arp->IPv6) - Format_Addr((unsigned char *)&arp->destaddr6.sin6_addr, hostaddr, TRUE); - else - Format_Addr((unsigned char *)&arp->destaddr.sin_addr, hostaddr, FALSE); - - sprintf(Key, "*%s", arp->hostname); - - // libconfig keys can't contain . so replace with * - - while (*ptr) - { - if (*ptr == '.') *ptr = '*'; - ptr++; - } - - SaveStringValue(group, Key, hostaddr); - } - - if(!config_write_file(&cfg, ConfigName)) - { - fprintf(stderr, "Error while writing file.\n"); - config_destroy(&cfg); - return; - } - - config_destroy(&cfg); -} - -#ifndef LINBPQ - -static 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; - } - return FALSE; -} - -#endif - -VOID GetAXIPCache(struct AXIPPORTINFO * PORT) -{ - config_setting_t *group; - config_t cfg; - char ConfigName[256]; - int index=0; - struct arp_table_entry * arp; - unsigned char hostaddr[64]; - char Key[128]; - struct stat STAT; - - if (BPQDirectory[0] == 0) - { - sprintf(ConfigName,"axipcache%d.cfg", PORT->Port); - } - else - { - sprintf(ConfigName,"%s/axipcache%d.cfg", BPQDirectory, PORT->Port); - } - - memset((void *)&cfg, 0, sizeof(config_t)); - - config_init(&cfg); - - if (stat(ConfigName, &STAT) == -1) - return; - - if(!config_read_file(&cfg, ConfigName)) - { - fprintf(stderr, "AXIP Cache read error line %d - %s\n", config_error_line(&cfg), config_error_text(&cfg)); - config_destroy(&cfg); - return; - } - - group = config_lookup(&cfg, "main"); - - if (group == NULL) - { - config_destroy(&cfg); - return; - } - - while (index < PORT->arp_table_len) - { - char * ptr = Key; - - arp = &PORT->arp_table[index++]; - - sprintf(Key, "*%s", arp->hostname); - - // libconfig keys can't contain . so replace with * - - while (*ptr) - { - if (*ptr == '.') *ptr = '*'; - ptr++; - } - - if (GetStringValue(group, Key, hostaddr, 64)) - { - arp->destaddr.sin_addr.s_addr = inet_addr(hostaddr); - } - } - - config_destroy(&cfg); -} - diff --git a/.svn/pristine/0d/0d8bd4f1861e575d751841ff418413f30b2490aa.svn-base b/.svn/pristine/0d/0d8bd4f1861e575d751841ff418413f30b2490aa.svn-base deleted file mode 100644 index 89e03e2..0000000 --- a/.svn/pristine/0d/0d8bd4f1861e575d751841ff418413f30b2490aa.svn-base +++ /dev/null @@ -1,4551 +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 -*/ - - -#define _CRT_SECURE_NO_DEPRECATE - -#pragma data_seg("_BPQDATA") - -#define LIBCONFIG_STATIC -#include "libconfig.h" - - -#ifdef LINBPQ -#include "cheaders.h" -#endif - -#include "bpqchat.h" - -#ifndef WIN32 - -iconv_t link_toUTF8 = NULL; - - -BOOL RunEventProgram(char * Program, char * Param); - -#endif - -BOOL ProcessChatConnectScript(ChatCIRCUIT * conn, char * Buffer, int len); -VOID ChatClearQueue(ChatCIRCUIT * conn); -VOID ChatFlush(ChatCIRCUIT * conn); -VOID APIENTRY SendChatReport(SOCKET ChatReportSocket, char * buff, int txlen); -unsigned short int compute_crc(unsigned char *buf,int len); -char * ReadInfoFile(char * File); -void ChatWriteLogLine(ChatCIRCUIT * conn, int Flag, char * Msg, int MsgLen, int Flags); -extern struct SEM ChatSemaphore; -UCHAR * APIENTRY GetLogDirectory(); -char * APIENTRY GetBPQDirectory(); -VOID WriteMiniDump(); - -extern SOCKADDR_IN Chatreportdest; - -char OurNode[10]; -char OurAlias[10]; - -#define MaxSockets 64 - -int MaxChatStreams=0; -ChatCIRCUIT ChatConnections[MaxSockets+1]; - -ULONG ChatApplMask; - -int NumberofChatStreams=0; - -char ChatSignoffMsg[100]; - -char OtherNodesList[1000]; -char ChatWelcomeMsg[1000]; - -char Position[81] = ""; -char PopupText[260] = ""; -int PopupMode = 0; -int chatPaclen = 236; - -int reportChatEvents = 0; - -char RtKnown[MAX_PATH] = "RTKnown.txt"; -char RtUsr[MAX_PATH] = "STUsers.txt"; -char RtUsrTemp[MAX_PATH] = "STUsers.tmp"; - -int AXIPPort = 0; - -ChatCIRCUIT *circuit_hd = NULL; // This is a chain of RT circuits. There may be others - -CHATNODE *node_hd = NULL; // Nodes - -LINK *link_hd = NULL; // Nodes we link to -TOPIC *topic_hd = NULL; - -USER *user_hd = NULL; - -KNOWNNODE * known_hd = NULL; - -int ChatTmr = 0; - -BOOL NeedStatus = FALSE; - - -char Verstring[80]; - -static void node_dec(CHATNODE *node); -static KNOWNNODE *knownnode_add(char *call); -VOID SendChatLinkStatus(); -char * lookupuser(char * call); -VOID ChatSendWelcomeMsg(int Stream, ChatCIRCUIT * conn, struct UserInfo * user); - -static int AutoColours[20] = {0, 4, 9, 11, 13, 16, 17, 42, 45, 50, 61, 64, 66, 72, 81, 84, 85, 86, 87, 89}; - -#define MaxSockets 64 - -extern struct SEM OutputSEM; - -int NeedINFO = 1; // Send INFO Msg after 10 Secs -time_t RunningConnectScript = 0; - -//#undef free -//#define free(p) - - -struct HistoryRec * History = NULL; -int HistoryCount = 0; - - -typedef int (WINAPI FAR *FARPROCX)(); -extern FARPROCX pRunEventProgram; - -int AddtoHistory(struct user_t * user, char * text) -{ - struct HistoryRec * Rec; - struct HistoryRec * ptr; - int n = 1; - char buf[2048]; - char Stamp[16]; - struct tm * tm; - time_t Now = time(NULL); - - // Don't want to grow indefinitely and fill memory. We only allow display up to 24 hours back, so if first record is older that that - // remove and reuse it - - if (History && History->Time < Now - 86400) - { - Rec = History; - History = Rec->next; // Remove from front of chain - } - else - Rec = malloc(sizeof (struct HistoryRec)); - - memset(Rec, 0, sizeof (struct HistoryRec)); - - tm = gmtime(&Now); - - if (strlen(text) + strlen(user->name) + strlen(user->call) > 2000) - return 0; // Shouldn't be that long, but protect buffer - - sprintf(Stamp,"%02d:%02d ", tm->tm_hour, tm->tm_min); - sprintf(buf, "%s%-6.6s %s %c %s\r", Stamp, user->call, user->name, ':', text); - - Rec->Time = Now; - - Rec->Topic = _strdup(user->topic->name); - Rec->Message = _strdup(buf); - - if (History == NULL) - History = Rec; - - else - { - ptr = History; - - while (ptr && ptr->next) - { - n++; - ptr = ptr->next; - } - - n++; - ptr->next = Rec; - } - - return n; -} - - - -int ChatIsUTF8(unsigned char *ptr, int len) -{ - int n; - unsigned char * cpt = ptr; - - // This is simpler than the Term version, as it only handles complete lines of text, so cant get split sequences - - cpt--; - - for (n = 0; n < len; n++) - { - cpt++; - - if (*cpt < 128) - continue; - - if ((*cpt & 0xF8) == 0xF0) - { // start of 4-byte sequence - if (((*(cpt + 1) & 0xC0) == 0x80) - && ((*(cpt + 2) & 0xC0) == 0x80) - && ((*(cpt + 3) & 0xC0) == 0x80)) - { - cpt += 3; - n += 3; - continue; - } - return FALSE; - } - else if ((*cpt & 0xF0) == 0xE0) - { // start of 3-byte sequence - if (((*(cpt + 1) & 0xC0) == 0x80) - && ((*(cpt + 2) & 0xC0) == 0x80)) - { - cpt += 2; - n += 2; - continue; - } - return FALSE; - } - else if ((*cpt & 0xE0) == 0xC0) - { // start of 2-byte sequence - if ((*(cpt + 1) & 0xC0) == 0x80) - { - cpt++; - n++; - continue; - } - return FALSE; - } - return FALSE; - } - - return TRUE; -} - -#ifndef LINBPQ - -char * strlop(char * buf, char delim) -{ - // Terminate buf at delim, and return rest of string - - char * ptr = strchr(buf, delim); - - if (ptr == NULL) return NULL; - - *(ptr)++=0; - - return ptr; -} - - -VOID * _zalloc(size_t len) -{ - // ?? malloc and clear - - void * ptr; - - ptr=malloc(len); - memset(ptr, 0, len); - - return ptr; -} - - -VOID * _zalloc_dbg(int len, int type, char * file, int line) -{ - // ?? malloc and clear - - void * ptr; - - ptr=_malloc_dbg(len, type, file, line); - - if (ptr == NULL) - CriticalErrorHandler("malloc failed"); - - memset(ptr, 0, len); - - return ptr; -} - -#endif - -VOID __cdecl nprintf(ChatCIRCUIT * conn, const char * format, ...) - -{ - // seems to be printf to a socket - - char buff[65536]; - va_list(arglist); - - va_start(arglist, format); - vsnprintf(buff, sizeof(buff), format, arglist); - - nputs(conn, buff); -} - - -VOID nputc(ChatCIRCUIT * conn, char chr) -{ - // Seems to send chr to socket - - ChatWriteLogLine(conn, '>',&chr, 1, LOG_CHAT); - ChatQueueMsg(conn, &chr, 1); -} - -VOID nputs(ChatCIRCUIT * conn, char * buf) -{ - // Seems to send buf to socket - - ChatQueueMsg(conn, buf, (int)strlen(buf)); - - if (*buf == 0x1b) - buf += 2; // Colour Escape - - ChatWriteLogLine(conn, '>',buf, (int)strlen(buf), LOG_CHAT); -} - -int ChatQueueMsg(ChatCIRCUIT * conn, char * msg, int len) -{ - // Add Message to queue for this connection - - if (conn->rtcflags & p_linked) - conn->u.link->lastMsgReceived = time(NULL); - - // UCHAR * OutputQueue; // Messages to user - // int OutputQueueLength; // Total Malloc'ed size. Also Put Pointer for next Message - // int OutputGetPointer; // Next byte to send. When Getpointer = Queue Length all is sent - free the buffer and start again. - - // Create or extend buffer - - GetSemaphore(&OutputSEM, 0); - - while (conn->OutputQueueLength + len > conn->OutputQueueSize) - { - // Extend Queue - - conn->OutputQueueSize += 4096; - conn->OutputQueue = realloc(conn->OutputQueue, conn->OutputQueueSize); - } - - memcpy(&conn->OutputQueue[conn->OutputQueueLength], msg, len); - conn->OutputQueueLength += len; - - FreeSemaphore(&OutputSEM); - - return len; -} - -VOID ChatSendWelcomeMsg(int Stream, ChatCIRCUIT * conn, struct UserInfo * user) -{ - if (!rtloginu (conn, TRUE)) - { - // Already connected - close - - ChatFlush(conn); - Sleep(1000); - Disconnect(conn->BPQStream); - } - return; - -} - -VOID ChatExpandAndSendMessage(ChatCIRCUIT * conn, char * Msg, int LOG) -{ - char NewMessage[10000]; - char * OldP = Msg; - char * NewP = NewMessage; - char * ptr, * pptr; - int len; - char Dollar[] = "$"; - char CR[] = "\r"; - int Msgs = 0, Unread = 0; - - - ptr = strchr(OldP, '$'); - - while (ptr) - { - len = (int)(ptr - OldP); // Chars before $ - memcpy(NewP, OldP, len); - NewP += len; - - switch (*++ptr) - { - case 'I': // First name of the connected user. - - pptr = conn->UserPointer->Name; - break; - - - case 'U': // Callsign of the connected user. - - pptr = conn->UserPointer->Call; - break; - - case 'W': // Inserts a carriage return. - - pptr = CR; - break; - - break; - - default: - - pptr = Dollar; // Just Copy $ - } - - len = (int)strlen(pptr); - memcpy(NewP, pptr, len); - NewP += len; - - OldP = ++ptr; - ptr = strchr(OldP, '$'); - } - - strcpy(NewP, OldP); - - len = RemoveLF(NewMessage, (int)strlen(NewMessage)); - - ChatWriteLogLine(conn, '>', NewMessage, len, LOG); - ChatQueueMsg(conn, NewMessage, len); -} - - - -void chat_link_out (LINK *link) -{ - int n, p; - ChatCIRCUIT * conn; - char Msg[80]; - - for (n = NumberofChatStreams-1; n >= 0 ; n--) - { - conn = &ChatConnections[n]; - - if (conn->Active == FALSE) - { - p = conn->BPQStream; - memset(conn, 0, sizeof(ChatCIRCUIT)); // Clear everything - conn->BPQStream = p; - - conn->Active = TRUE; - circuit_new(conn, p_linkini); - conn->u.link = link; - conn->Flags = CHATMODE | CHATLINK; - - n=sprintf_s(Msg, sizeof(Msg), "Connecting to Chat Node %s", conn->u.link->alias); - - strcpy(conn->Callsign, conn->u.link->alias); - - ChatWriteLogLine(conn, '|',Msg, n, LOG_CHAT); - - link->ScriptIndex = -1; - RunningConnectScript = time(NULL); - link->MoreLines = TRUE; - link->scriptRunning = TRUE; - link->RTLSent = 0; - - ConnectUsingAppl(conn->BPQStream, ChatApplMask); - - // Connected Event will trigger connect to remote system - - return; - } - } - return; -} - - -VOID saywhat(ChatCIRCUIT *circuit) -{ - nputs(circuit, "Invalid Command\r"); -} - -VOID saydone(ChatCIRCUIT *circuit) -{ - nputs(circuit, "Ok\r"); -} - -VOID strnew(char ** new, char *f1) -{ - // seems to allocate a new string, and copy the old one to it - // how is this different to strdup?? - - *new = _strdup(f1); -} - -#define sl_ins_hd(link, hd) \ - if (hd == NULL)\ - hd=link;\ - else\ - {\ - link->next=hd->next;\ - hd->next=link;\ - } - -BOOL matchi(char * p1, char * p2) -{ - // Return TRUE is strings match - - if (_stricmp(p1, p2)) - return FALSE; - else - return TRUE; -} - - -VOID ProcessChatLine(ChatCIRCUIT * conn, struct UserInfo * user, char* OrigBuffer, int len) -{ - ChatCIRCUIT *c; - char * Buffer = OrigBuffer; - WCHAR BufferW[65536]; - UCHAR BufferB[65536]; - - // Sanity Check - - if (len > 32768) - return; - - // Convert to UTF8 if not already in UTF-8 - - if (len == 73 && memcmp(&OrigBuffer[40], " ", 20) == 0) - { - // Chat Signon Message. If Topic is present, switch to it - - char * Context; - char * Appl; - char * topic; - - Appl = strtok_s(OrigBuffer, " ,\r", &Context); - topic = strtok_s(NULL, " ,\r", &Context); - - if (topic == NULL) - return; // Just Chat - - // Have a Topic - - if (conn->Flags & GETTINGUSER) - { - // Need to log in before switching topic, so Give a dummy name here - - conn->Flags &= ~GETTINGUSER; - strcpy(user->Name, "?_name"); - ChatSendWelcomeMsg(conn->BPQStream, conn, user); - } - - OrigBuffer[40] = 0; - sprintf(&OrigBuffer[40],"/t %s\r", topic); - strcpy(OrigBuffer, &OrigBuffer[40]); - len = (int)strlen(OrigBuffer); - } - else - { - // Normal input - - if (conn->Flags & GETTINGUSER) - { - // Check not getting *RTL in response to Name prompt - - if (memcmp(Buffer, "*RTL", 4) == 0) - { - // Other end thinks this is a node-node link - - Logprintf(LOG_CHAT, conn, '!', "Station %s trying to start Node Protocol, but not defined as a Node", - conn->Callsign); - - knownnode_add(conn->Callsign); // So it won't happen again - - Disconnect(conn->BPQStream); - return; - } - - conn->Flags &= ~GETTINGUSER; - memcpy(user->Name, Buffer, len-1); - ChatSendWelcomeMsg(conn->BPQStream, conn, user); - - return; - } - } - - if (ChatIsUTF8(OrigBuffer, len) == FALSE) - { - // With Windows it is simple - convert using current codepage - // I think the only reliable way is to convert to unicode and back - -#ifdef WIN32 - - int wlen; - - wlen = MultiByteToWideChar(CP_ACP, 0, Buffer, len, BufferW, 65536); - len = WideCharToMultiByte(CP_UTF8, 0, BufferW, wlen, BufferB, 63336, NULL, NULL); - Buffer = BufferB; - -#else - size_t left = 65536; - size_t clen = len; - - UCHAR * BufferBP = BufferB; - struct user_t * icu = conn->u.user; - - if (conn->rtcflags & p_user) - { - if (icu->iconv_toUTF8 == NULL) - { - icu->iconv_toUTF8 = iconv_open("UTF-8//IGNORE", icu->Codepage); - - if (icu->iconv_toUTF8 == (iconv_t)-1) - icu->iconv_toUTF8 = iconv_open("UTF-8//IGNORE", "CP1252"); - } - - iconv(icu->iconv_toUTF8, NULL, NULL, NULL, NULL); // Reset State Machine - iconv(icu->iconv_toUTF8, &Buffer, &clen, (char ** __restrict__)&BufferBP, &left); - } - else - { - if (link_toUTF8 == NULL) - link_toUTF8 = iconv_open("UTF-8//IGNORE", "CP1252"); - - iconv(link_toUTF8, NULL, NULL, NULL, NULL); // Reset State Machine - iconv(link_toUTF8, &Buffer, &clen, (char ** __restrict__)&BufferBP, &left); - } - len = 65536 - left; - Buffer = BufferB; - -#endif - - } - ChatWriteLogLine(conn, '<',Buffer, len, LOG_CHAT); - - - Buffer[len] = 0; - - strlop(Buffer, '\r'); - - if (conn->rtcflags == p_linkwait) - { - //waiting for *RTL - - if (memcmp(Buffer, "*RTL", 4) == 0) - { - // Node - Node Connect - - if (rtloginl (conn, conn->Callsign)) - { - // Accepted - - conn->Flags |= CHATLINK; - return; - } - else - { - // Connection refused. rtlogin1 has sent error message and closed link - - return; - } - } - - if (Buffer[0] == '[' && Buffer[len-2] == ']') // SID - return; - - nprintf(conn, "Unexpected Message on Chat Node-Node Link - Disconnecting\r"); - ChatFlush(conn); - Sleep(500); - conn->rtcflags = p_nil; - - Disconnect(conn->BPQStream); - return; - } - - if (conn->Flags & CHATLINK) - { -#ifndef LINBPQ - - struct _EXCEPTION_POINTERS exinfo; - - __try - { - chkctl(conn, Buffer, len); - } - - #define EXCEPTMSG "Process Chat Line" - #include "StdExcept.c" - - Debugprintf("CHAT *** Was procesing Chat Node Message %s", Buffer); - Disconnect(conn->BPQStream); - CheckProgramErrors(); - } -#else - chkctl(conn, Buffer, len); -#endif - return; - } - - if(conn->u.user == NULL) - { - // A node link, but not activated yet, or a chat console which has dosconnected - - if (conn->BPQStream != -2) - return; - - // Log console user in - - if (rtloginu (conn, TRUE)) - conn->Flags |= CHATMODE; - - return; - - } - - if ((len <6) && (memcmp(Buffer, "*RTL", 4) == 0)) - { - // Other end thinks this is a node-node link - - Logprintf(LOG_CHAT, conn, '!', "Station %s trying to start Node Protocol, but not defined as a Node", - conn->Callsign); - - knownnode_add(conn->Callsign); // So it won't happen again - - Disconnect(conn->BPQStream); - return; - } - - if (Buffer[0] == '/') - { - // Process Command - - int cmdLen = 0; - char * param = strchr(&Buffer[1], ' '); - - if (param) - cmdLen = param - &Buffer[1]; - else - cmdLen = strlen(&Buffer[1]); - - if (_memicmp(&Buffer[1], "Bye", 1) == 0) - { - SendUnbuffered(conn->BPQStream, ChatSignoffMsg, (int)strlen(ChatSignoffMsg)); - - if (conn->BPQStream < 0) - { - logout(conn); - conn->Flags = 0; - if (conn->BPQStream == -2) - CloseConsole(conn->BPQStream); - } - else - ReturntoNode(conn->BPQStream); - - return; - } - - if (_memicmp(&Buffer[1], "Quit", 4) == 0) - { - SendUnbuffered(conn->BPQStream, ChatSignoffMsg, (int)strlen(ChatSignoffMsg)); - - if (conn->BPQStream < 0) - { - logout(conn); - conn->Flags = 0; - if (conn->BPQStream == -2) - CloseConsole(conn->BPQStream); - } - - else - { - Sleep(1000); - Disconnect(conn->BPQStream); - } - return; - } - - if (cmdLen > 1 && _memicmp(&Buffer[1], "History", cmdLen) == 0) // Accept Hi but not H - { - // Param is number of minutes to go back (max 24 hours) - - struct HistoryRec * ptr = History; - int interval = 0; - time_t start; - int n = HistoryCount; - - if (param) - interval = atoi(param); - - if (interval < 1) - { - nprintf(conn, "Format is /history n, where n is history time in minutes\r"); - conn->u.user->lastsendtime = time(NULL); - return; - } - - if (interval > 1440) - { - nprintf(conn, "History is only held for 24 Hours (1440 Minutes)\r"); - interval = 1440; // Limit to 1 day - } - - start = time(NULL) - (interval * 60); - - // Find first record to send - - while (ptr) - { - if (ptr->Time > start) - break; - n--; - ptr = ptr->next; - } - - // n is records found - - while (ptr) - { - nprintf(conn, ptr->Message); - ptr = ptr->next; - } - - conn->u.user->lastsendtime = time(NULL); - return; - } - - - - if (_memicmp(&Buffer[1], "Keepalive", 4) == 0) - { - conn->u.user->rtflags ^= u_keepalive; - upduser(conn->u.user); - nprintf(conn, "Keepalive is %s\r", (conn->u.user->rtflags & u_keepalive) ? "Enabled" : "Disabled"); - conn->u.user->lastsendtime = time(NULL); - return; - } - if (_memicmp(&Buffer[1], "AUTOCHARSET", 4) == 0) - { - conn->u.user->rtflags ^= u_auto; - upduser(conn->u.user); - nprintf(conn, "Automatic Character set selection is %s\r", (conn->u.user->rtflags & u_auto) ? "Enabled" : "Disabled"); - conn->u.user->lastsendtime = time(NULL); - return; - } - if (_memicmp(&Buffer[1], "UTF-8", 3) == 0) - { - conn->u.user->rtflags ^= u_noUTF8; - upduser(conn->u.user); - nprintf(conn, "Character set is %s\r", (conn->u.user->rtflags & u_noUTF8) ? "8 Bit" : "UTF-8"); - conn->u.user->lastsendtime = time(NULL); - return; - } - - if ((_memicmp(&Buffer[1], "CodePage", 3) == 0) || (_memicmp(&Buffer[1], "CP", 2) == 0)) - { - char * Context; - char * CP = strtok_s(&Buffer[1], " ,\r", &Context); -#ifndef WIN32 - iconv_t temp = NULL; -#else - int temp = 0; - WCHAR TempW[10]; -#endif - CP = strtok_s(NULL, " ,\r", &Context); - - if (CP == NULL || CP[0] == 0) - { -#ifndef WIN32 - if (conn->u.user->Codepage[0]) - nprintf(conn, "Codepage is %s\r", conn->u.user->Codepage); -#else - if (conn->u.user->Codepage) - nprintf(conn, "Codepage is %d\r", conn->u.user->Codepage); -#endif - else - nprintf(conn, "Codepage is not set\r"); - - return; - } - _strupr(CP); - -#ifndef WIN32 - - // Validate Code Page by trying to open an iconv descriptor - - temp = iconv_open("UTF-8", CP); - - if (temp == (iconv_t)-1) - { - nprintf(conn, "Invalid Codepage %s\r", CP); - return; - } - - iconv_close(conn->u.user->iconv_toUTF8); - iconv_close(conn->u.user->iconv_fromUTF8); - - conn->u.user->iconv_toUTF8 = temp; - conn->u.user->iconv_fromUTF8 = iconv_open(CP, "UTF-8"); - - strcpy(conn->u.user->Codepage, CP); - nprintf(conn, "Codepage set to %s\r", conn->u.user->Codepage); -#else - if (CP[0] == 'C') - CP +=2; - - // Validate by trying ot use it - - temp = atoi(CP); - - if (MultiByteToWideChar(temp, 0, "\r", 2, TempW, 10) == 0) - { - int err = GetLastError(); - - if (err == ERROR_INVALID_PARAMETER) - { - nprintf(conn, "Invalid Codepage %d\r", temp); - return; - } - } - - conn->u.user->Codepage = temp; - nprintf(conn, "Codepage set to %d\r", conn->u.user->Codepage); -#endif - upduser(conn->u.user); - - return; - } - - if (_memicmp(&Buffer[1], "Shownames", 4) == 0) - { - conn->u.user->rtflags ^= u_shownames; - upduser(conn->u.user); - nprintf(conn, "Shownames is %s\r", (conn->u.user->rtflags & u_shownames) ? "Enabled" : "Disabled"); - conn->u.user->lastsendtime = time(NULL); - return; - } - - if (_memicmp(&Buffer[1], "Time", 4) == 0) - { - conn->u.user->rtflags ^= u_showtime; - upduser(conn->u.user); - nprintf(conn, "Show Time is %s\r", (conn->u.user->rtflags & u_showtime) ? "Enabled" : "Disabled"); - conn->u.user->lastsendtime = time(NULL); - return; - } - - if (_memicmp(&Buffer[1], "colours", 4) == 0) - { - int i =0; - - while (i < 100) - { - nprintf(conn, "\x1b%c%02d XXXXX\r", i + 10, i); - i++; - if (i == 3) - i++; - } - return; - } - - rt_cmd(conn, Buffer); - - return; - } - - // Send message to all other connected users on same channel - - text_tellu(conn->u.user, Buffer, NULL, o_topic); // To local users. - - HistoryCount = AddtoHistory(conn->u.user, Buffer); - - conn->u.user->lastrealmsgtime = conn->u.user->lastmsgtime = time(NULL); - - // Send to Linked nodes - - for (c = circuit_hd; c; c = c->next) - { - if ((c->rtcflags & p_linked) && c->refcnt && ct_find(c, conn->u.user->topic)) - nprintf(c, "%c%c%s %s %s\r", FORMAT, id_data, OurNode, conn->u.user->call, Buffer); - } -} - -void upduser(USER *user) -{ - FILE *in, *out; - char *c; - char Buffer[2048]; - char *buf = Buffer; - - in = fopen(RtUsr, "r"); - - if (!(in)) - { - in = fopen(RtUsr, "w"); - if (in) - fclose(in); - in = fopen(RtUsr, "r"); - } - - if (!(in)) return; - - out = fopen(RtUsrTemp, "w"); - - if (!(out)) return; - - while(fgets(buf, 128, in)) - { - if (strstr(buf, "*RTL")) // Tidy user database - continue; - - c = strchr(buf, ' '); - if (c) *c = '\0'; - if (!matchi(buf, user->call)) - { - if (c) *c = ' '; - fputs(buf, out); - } - } - -#ifndef WIN32 - fprintf(out, "%s %d %s %s¬%d¬%s\n", user->call, user->rtflags, user->name, user->qth, user->Colour, user->Codepage); -#else - fprintf(out, "%s %d %s %s¬%d¬%d\n", user->call, user->rtflags, user->name, user->qth, user->Colour, user->Codepage); -#endif - fclose(in); - fclose(out); - - remove(RtUsr); - rename(RtUsrTemp, RtUsr); -} - -char * lookupuser(char * call) -{ - FILE *in; - char *flags; - char Buffer[2048]; - char *buf = Buffer; - char * name; - - in = fopen(RtUsr, "r"); - - if (in) - { - while(fgets(buf, 128, in)) - { - strlop(buf, '\n'); - - flags = strlop(buf, ' '); - if (!matchi(buf, call)) continue; - if (!flags) break; - - fclose(in); - name = strlop(flags, ' '); - strlop(name, ' '); - return _strdup(name); - } - fclose(in); - } - - return NULL; -} - - - -void rduser(USER *user) -{ - FILE *in; - char *name, *flags, *qth; - char Buffer[2048]; - char *buf = Buffer; - char * ptr; - - user->name = _strdup("?_name"); - user->qth = _strdup("?_qth"); - - in = fopen(RtUsr, "r"); - - if (in) - { - while(fgets(buf, 128, in)) - { - strlop(buf, '\n'); - - flags = strlop(buf, ' '); - if (!matchi(buf, user->call)) continue; - if (!flags) break; - - name = strlop(flags, ' '); - user->rtflags = atoi(flags); - - qth = strlop(name, ' '); - strnew(&user->name, name); - - if (!qth) break; - - // Colour Code may follow QTH, and Code Page may follow Colour - - ptr = strchr(qth, '¬'); - if (ptr) - { - *ptr++ = 0; - user->Colour = atoi(ptr); - - ptr = strchr(ptr, '¬'); - - if (ptr) - { - *ptr++ = 0; -#ifndef WIN32 - strcpy(user->Codepage, ptr); -#else - user->Codepage = atoi(ptr); -#endif - } - } - - strnew(&user->qth, qth); - break; - } - fclose(in); - -#ifndef WIN32 - - // Open an iconv decriptor for each conversion - - if (user->Codepage[0]) - user->iconv_toUTF8 = iconv_open("UTF-8//IGNORE", user->Codepage); - else - user->iconv_toUTF8 = (iconv_t)-1; - - if (user->iconv_toUTF8 == (iconv_t)-1) - user->iconv_toUTF8 = iconv_open("UTF-8//IGNORE", "CP1252"); - - - if (user->Codepage[0]) - user->iconv_fromUTF8 = iconv_open(user->Codepage, "UTF-8"); - else - user->iconv_fromUTF8 = (iconv_t)-1; - - if (user->iconv_fromUTF8 == (iconv_t)-1) - user->iconv_fromUTF8 = iconv_open("CP1252//IGNORE", "UTF-8"); -#endif - } -} - - -void ReportBadJoin(char * ncall, char *ucall) -{ - Logprintf(LOG_CHAT, NULL, '!', "User %s Join from Node %s but already connected", ucall, ncall); -} - -void ReportBadLeave(char * ncall, char * ucall) -{ - Logprintf(LOG_CHAT, NULL, '!', "Node %s reporting Node %s as a leaving user", ncall, ucall); -} - - -struct DUPINFO DupInfo[MAXDUPS]; - -static BOOL CheckforDups(ChatCIRCUIT * circuit, char * Call, char * Msg) -{ - // Primitive duplicate suppression - see if same call and text reeived in last few secons - - time_t Now = time(NULL); - time_t DupCheck = Now - DUPSECONDS; - int i, saveindex = -1; - - 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; - } - continue; - } - - if ((strcmp(Call, DupInfo[i].DupUser) == 0) && (memcmp(Msg, DupInfo[i].DupText, strlen(DupInfo[i].DupText)) == 0)) - { - // Duplicate, so discard, but save time - - DupInfo[i].DupTime = Now; - Logprintf(LOG_CHAT, circuit, '?', "Duplicate Message From %s %s suppressed", Call, Msg); - - return TRUE; // Duplicate - } - - } - - // Not in list - - if (saveindex == -1) // List is full - saveindex = MAXDUPS - 1; // Stick on end - - DupInfo[saveindex].DupTime = Now; - strcpy(DupInfo[saveindex].DupUser, Call); - - if (strlen(Msg) > 99) - { - memcpy(DupInfo[saveindex].DupText, Msg, 99); - DupInfo[saveindex].DupText[99] = 0; - } - else - strcpy(DupInfo[saveindex].DupText, Msg); - - return FALSE; -} - -void chkctl(ChatCIRCUIT *ckt_from, char * Buffer, int Len) -{ - CHATNODE * node, *ln; - ChatCIRCUIT * ckt_to; - USER * user, * su; - time_t Now = time(NULL); - LINK * Link = ckt_from->u.link; - - char * ncall, * ucall, * f1, * f2, * buf; - int i; - - if (Buffer[FORMAT_O] != FORMAT) return; // Not a control message. - - // Check for corruption - - for (i = 1; i < (Len - 1); i++) - { - if (Buffer[i] < 32) - { - if (Buffer[i] == 9) - { - Buffer[i] = 32; - continue; - } - Debugprintf("Corrupt Chat Link Messages %s", Buffer); - return; - } - } - - buf = _strdup(Buffer + DATA_O); - -// FORMAT and TYPE bytes are followed by node and user callsigns. - - ncall = buf; - ucall = strlop(buf, ' '); - if (!ucall) { free(buf); return; } // Not a control message. - -// There may be at least one field after the node and user callsigns. -// Node leave (id_unlink) has no F1. - - f1 = strlop(ucall, ' '); - strlop(ucall, 9); // some have tabs ?? - -// If the frame came from an unknown node ignore it. -// If the frame came from us ignore it (loop breaking). - - node = node_find(ncall); - if (!node || matchi(ncall, OurNode)) { free(buf); return; } - - if (ckt_from->rtcflags & p_linked) - ckt_from->u.link->lastMsgReceived = Now; - - switch(Buffer[TYPE_O]) - { - // Data from user ucall at node ncall. - - case id_data : - - // Check for dups - - if (CheckforDups(ckt_from, ucall, f1)) - break; - - user = user_find(ucall, ncall); - - if (!user) - break; - - user->lastrealmsgtime = user->lastmsgtime = time(NULL); - - text_tellu(user, f1, NULL, o_topic); - HistoryCount = AddtoHistory(user, f1); - - for (ckt_to = circuit_hd; ckt_to; ckt_to = ckt_to->next) - { - if ((ckt_to->rtcflags & p_linked) && ckt_to->refcnt && - !cn_find(ckt_to, node) && ct_find(ckt_to, user->topic)) - nprintf(ckt_to, "%s\r", Buffer); - } - break; - - // User ucall at node ncall changed their Name/QTH info. - - case id_user : - - user = user_find(ucall, ncall); - if (!user) break; - f2 = strlop(f1, ' '); - if (!f2) break; - - if ((strcmp(user->name, f1) == 0) && (strcmp(user->qth, f2) == 0)) // No Change? - break; - - echo(ckt_from, node, Buffer); // Relay to other nodes. - strnew(&user->name, f1); - strnew(&user->qth, f2); - upduser(user); - break; - - // User ucall logged into node ncall. - - case id_join : - - user = user_find(ucall, ncall); - - if (user) - { - // Already Here - - // If last join was less the 5 secs ago don't report - probably a "Join/Leave Storm" - - if (time(NULL) - user->timeconnected > 5) - ReportBadJoin(ncall, ucall); - - //if (strcmp(user->node->call, OurNode) == 0) - //{ - // Locally connected, and at another node - //} - - user->timeconnected = time(NULL); - break; // We have this user as an active Node - } - - // update join time - - echo(ckt_from, node, Buffer); // Relay to other nodes. - f2 = strlop(f1, ' '); - if (!f2) break; - user = user_join(ckt_from, ucall, ncall, NULL, FALSE); - if (!user) break; - ckt_from->refcnt++; - text_tellu_Joined(user); - strnew(&user->name, f1); - strnew(&user->qth, f2); - upduser(user); -// makelinks(); // Bring up our links if not already up - - break; - - // User ucall logged out of node ncall. - - case id_leave : - - user = user_find(ucall, ncall); - if (!user) - { - Debugprintf("CHAT: Leave for %s from %s when not on list", ucall, ncall); - break; - } - - // if connected for for less than 3 seconds ignore. May give stuck nodes but should stop "Join/Leave Storm" - // we can't just silently leave as next join will propagate - - if (time(NULL) - user->timeconnected < 3) - break; - - echo(ckt_from, node, Buffer); // Relay to other nodes. - - f2 = strlop(f1, ' '); - if (!f2) break; - - text_tellu(user, rtleave, NULL, o_all); - ckt_from->refcnt--; - strnew(&user->name, f1); - strnew(&user->qth, f2); - upduser(user); - user_leave(user); - - cn_dec(ckt_from, node); - node_dec(node); - - break; - - // Node ncall lost its link to node ucall, alias f1. - - case id_unlink : - - // Only relay to other nodes if we had node. Could get loop otherwise. - // ?? This could possibly cause stuck nodes - - ln = node_find(ucall); - - // if connected for for less than 3 seconds ignore. May give stuck nodes but should stop "Join/Leave Storm" - // we can't just silently leave as next join will propagate - - if (ln) - { - if (time(NULL) - ln->timeconnected < 3) - break; - - // is it on this circuit? - - if (cn_find(ckt_from, ln)) - { - cn_dec(ckt_from, ln); - node_dec(ln); - echo(ckt_from, node, Buffer); // Relay to other nodes if we had node. COuld get loop if - } - else - { - Debugprintf("CHAT: node %s unlink for %s when not on this link", ncall, ucall); - } - } - else - { - Debugprintf("CHAT: node %s unlink for %s when not on list", ncall, ucall); - } - - break; - - // Node ncall acquired a link to node ucall, alias f1. - // If we are not linked, is no problem, don't link. - // If we are linked, is a loop, do what? (Try ignore!) - - case id_link : - - ln = node_find(ucall); - - if (!ln && !matchi(ncall, OurNode)) - { - f2 = strlop(f1, ' '); - cn_inc(ckt_from, ucall, f1, f2); - echo(ckt_from, node, Buffer); // Relay to other nodes. - } - else - { - // If last join was less the 5 secs ago don't report - probably a "Join/Leave Storm" - - if (time(NULL) - ln->timeconnected > 5) - Debugprintf("CHAT: node %s link for %s when already on list", ncall, ucall); - - // update join time - - ln->timeconnected = time(NULL); - break; - } - - break; - - // User ucall at node ncall sent f2 to user f1. - - case id_send : - user = user_find(ucall, ncall); - if (!user) break; - f2 = strlop(f1, ' '); - if (!f2) break; - su = user_find(f1, NULL); - if (!su) break; - - if (su->circuit->rtcflags & p_user) - text_tellu(user, f2, f1, o_one); - else - echo(ckt_from, node, Buffer); // Relay to other nodes. - break; - - // User ucall at node ncall changed topic. - - case id_topic : - user = user_find(ucall, ncall); - if (user) - { - if (_stricmp(user->topic->name, f1) != 0) - { - echo(ckt_from, node, Buffer); // Relay to other nodes. - topic_chg(user, f1); - } - } - break; - - - case id_keepalive : - - ln = node_find(ncall); - if (ln) - { - if (ln->Version == NULL) - if (f1) - ln->Version = _strdup(f1); - } - - nprintf(ckt_from, "%c%c%s %s\r", FORMAT, id_pollresp, OurNode, Link->call); - break; - - case id_poll: - - // Send Poll Response - - Link->supportsPolls = Now; - nprintf(ckt_from, "%c%c%s %s\r", FORMAT, id_pollresp, OurNode, Link->call); - break; - - case id_pollresp: - - Link->supportsPolls = Now; - Link->RTT = Now - Link->timePollSent; - Link->timePollSent = 0; // Cancel Timeout - break; - - default: - break; - } - - free(buf); -} - -// Tell another node about nodes known by this node. -// Do not tell it about this node, the other node knows who it -// linked to (or who linked to it). -// Tell another node about users known by this node. -// Done at incoming or outgoing link establishment. - -void state_tell(ChatCIRCUIT *circuit, char * Version) -{ - CHATNODE *node; - USER *user; - - node = cn_inc(circuit, circuit->u.link->call, circuit->u.link->alias, Version); - node_tell(node, id_link); // Tell other nodes about this new link - - // Tell the node that just linked here about nodes known on other links. - - for (node = node_hd; node; node = node->next) - { - if (!matchi(node->call, OurNode)) - node_xmit(node, id_link, circuit); - } - - // Tell the node that just linked here about known users, and their topics. - - for (user = user_hd; user; user = user->next) - { - user_xmit(user, id_join, circuit); - topic_xmit(user, circuit); - } -} - -static void circuit_free(ChatCIRCUIT *circuit) -{ - ChatCIRCUIT *c, *cp; - CN *ncn; - CHATNODE *nn; - TOPIC *tn; - - cp = NULL; - - for (c = circuit_hd; c; cp = c, c = c->next) - { - if (c == circuit) - { - if (cp) cp->next = c->next; else circuit_hd = c->next; - - while (c->hnode) - { - ncn = c->hnode->next; - free(c->hnode); - c->hnode = ncn; - } - - break; - } - } - - if (circuit_hd) return; - -// RT has gone inactive. Clean up. - - while (node_hd) - { - nn = node_hd->next; - free(node_hd->alias); - free(node_hd->call); - free(node_hd); - node_hd = nn; - } - - while (topic_hd) - { - tn = topic_hd->next; - free(topic_hd->name); - free(topic_hd); - topic_hd = tn; - } -} - - -// Find a node in the node list. - -CHATNODE *node_find(char *call) -{ - CHATNODE *node; - - for (node = node_hd; node; node = node->next) - { - //if (node->refcnt && matchi(node->call, call)) I don't think this is right!!! - if (matchi(node->call, call)) - break; - } - - return node; -} - -// Add a reference to a node. - -static CHATNODE *node_inc(char *call, char *alias, char * Version) -{ - CHATNODE *node; - - node = node_find(call); - - if (!node) - { - knownnode_add(call); - - node = zalloc(sizeof(CHATNODE)); - sl_ins_hd(node, node_hd); - node->call = _strdup(call); - node->alias = _strdup(alias); - if (Version) - node->Version = _strdup(Version); - - node->timeconnected = time(NULL); - -// Debugprintf("New Node Rec Created at %x for %s %s", node, node->call, node->alias); - } - - node->refcnt++; - return node; -} - -// Remove a reference to a node. - -static void node_dec(CHATNODE *node) -{ - CHATNODE *t, *tp; - USER *user; - - ChatCIRCUIT *circuit; - CN *cn; - - if (--node->refcnt) return; // Other references. - - // Remove the node from the node list. - - tp = NULL; - - // Make sure there aren't any user or circuit records pointing to it - - for (user = user_hd; user; user = user->next) - { - if (user->node == node) - { - Debugprintf("Trying to remove node %s that is linked from user %s", node->call, user->call); - node->refcnt++; - } - } - - for (circuit = circuit_hd; circuit; circuit = circuit->next) - { - if (circuit->rtcflags & p_linked) - { - for (cn = circuit->hnode; cn; cn = cn->next) - { - if (cn->node == node) - { - Debugprintf("Trying to remove node %s that is linked from circuit %s", node->call, circuit->Callsign); - node->refcnt++; - } - } - } - } - - if (node->refcnt) return; // Now have other references. - - for (t = node_hd; t; tp = t, t = t->next) - { - if (t == node) - { - if (tp) tp->next = t->next; else node_hd = t->next; - free(t->alias); - t->alias = NULL; - free(t->call); - t->call = NULL; - free(t); - break; - } - } -} - -// User joins a topic. - -static TOPIC *topic_join(ChatCIRCUIT *circuit, char *s) -{ - CT *ct; - TOPIC *topic; - -// Look for an existing topic. - - for (topic = topic_hd; topic; topic = topic->next) - { - if (matchi(topic->name, s)) - break; - } - -// Create a new topic, if needed. - - if (!topic) - { - topic = zalloc(sizeof(TOPIC)); - sl_ins_hd(topic, topic_hd); - topic->name = _strdup(s); - } - - topic->refcnt++; // One more user in this topic. - - Logprintf(LOG_CHAT, circuit, '?', "topic_join complete user %s topic %s addr %x ref %d", - circuit->u.user->call, topic->name, topic, topic->refcnt); - - -// Add the circuit / topic association. - - for (ct = circuit->topic; ct; ct = ct->next) - { - if (ct->topic == topic) - { - ct->refcnt++; - return topic; - } - } - - ct = zalloc(sizeof(CT)); - sl_ins_hd(ct, circuit->topic); - ct->topic = topic; - ct->refcnt = 1; - return topic; -} - -// User leaves a topic. - -static void topic_leave(ChatCIRCUIT *circuit, TOPIC *topic) -{ - CT *ct, *ctp; - TOPIC *t, *tp; - - Logprintf(LOG_CHAT, circuit, '?', "topic_leave user %s topic %s addr %x ref %d", - circuit->u.user->call, topic->name, topic, topic->refcnt); - - topic->refcnt--; - - ctp = NULL; - - for (ct = circuit->topic; ct; ctp = ct, ct = ct->next) - { - if (ct->topic == topic) - { - if (!--ct->refcnt) - { - if (ctp) ctp->next = ct->next; else circuit->topic = ct->next; - free(ct); - break; - } - } - } - - tp = NULL; - - for (t = topic_hd; t; tp = t, t = t->next) - { - if (!t->refcnt && (t == topic)) - { - if (tp) tp->next = t->next; else topic_hd = t->next; - free(t->name); - free(t); - break; - } - } -} - -// Find a circuit/topic association. - -int ct_find(ChatCIRCUIT *circuit, TOPIC *topic) -{ - CT *ct; - - for (ct = circuit->topic; ct; ct = ct->next) - { - if (ct->topic == topic) - return ct->refcnt; - } - return 0; -} - -// Nodes reached from each circuit. Used only if the circuit is a link. - -// Remove a circuit/node association. - -static void cn_dec(ChatCIRCUIT *circuit, CHATNODE *node) -{ - CN *c, *cp; - -// Debugprintf("CHAT: Remove c/n %s ", node->call); - - cp = NULL; - - for (c = circuit->hnode; c; cp = c, c = c->next) - { - if (c->node == node) - { -// CN * cn; -// int len; -// char line[1000]=""; - - if (--c->refcnt) - { -// Debugprintf("CHAT: Remove c/n Node %s still in use refcount %d", node->call, c->refcnt); - return; // Still in use - } - - if (cp) - cp->next = c->next; - else - circuit->hnode = c->next; - - free(c); - - break; - } - } - - if (c == NULL) - { - CN * cn; - int len; - char line[1000]=""; - - // not found?? - - Debugprintf("CHAT: !! Remove c/n Node %s addr %x not found cn chain follows", node->call, node); - - line[0] = 0; - - for (cn = circuit->hnode; cn; cn = cn->next) - { - if (cn->node && cn->node->call) - { -#ifndef LINBPQ - __try - { -#endif - len += sprintf(&line[len], " %p %s", cn->node, cn->node->alias); - if (len > 80) - { - Debugprintf("%s", line); - len = sprintf(line, " "); - } -#ifndef LINBPQ - } - __except(EXCEPTION_EXECUTE_HANDLER) - {len = sprintf("%s *PE* Corrupt Rec %x %x ", line, cn, cn->node);} -#endif - } - else - { - len = sprintf("%s Corrupt Rec %x %x ", line, cn, cn->node); - } - } - Debugprintf("%s", line); - - } - - -} - -// Add a circuit/node association. - -static CHATNODE *cn_inc(ChatCIRCUIT *circuit, char *call, char *alias, char * Version) -{ - CHATNODE *node; - CN *cn; - - node = node_inc(call, alias, Version); - - for (cn = circuit->hnode; cn; cn = cn->next) - { - if (cn->node == node) - { - cn->refcnt++; -// Debugprintf("cn_inc cn Refcount for %s->%s incremented to %d - adding Call %s", -// circuit->Callsign, node->call, cn->refcnt, call); - - return node; - } - } - - cn = zalloc(sizeof(CN)); - sl_ins_hd(cn, circuit->hnode); - cn->node = node; - cn->refcnt = 1; - -// Debugprintf("cn_inc New cn for %s->%s - adding Call %s", -// circuit->Callsign, node->call, call); - - return node; -} - -// Find a circuit/node association. - -static int cn_find(ChatCIRCUIT *circuit, CHATNODE *node) -{ - CN *cn; - - for (cn = circuit->hnode; cn; cn = cn->next) - { - if (cn->node == node) - return cn->refcnt; - } - return 0; -} - -// From a local user to a specific user at another node. - -static void text_xmit(USER *user, USER *to, char *text) -{ - nprintf(to->circuit, "%c%c%s %s %s %s\r", - FORMAT, id_send, OurNode, user->call, to->call, text); -} - -void put_text(ChatCIRCUIT * circuit, USER * user, UCHAR * buf) -{ - UCHAR BufferB[4096]; - - // Text is UTF-8 internally. If user doen't want UTF-8. convert to Node's locale - - if (circuit->u.user->rtflags & u_noUTF8) - { -#ifdef WIN32 - char * Buffer = buf; - WCHAR BufferW[4096]; - int wlen, blen; - BOOL DefaultUsed = FALSE; - char Subst = '?'; - - wlen = MultiByteToWideChar(CP_UTF8, 0, buf, (int)strlen(buf) + 1, BufferW, 4096); - blen = WideCharToMultiByte(circuit->u.user->Codepage, 0, BufferW, wlen, BufferB + 2, 4096, &Subst, &DefaultUsed); - - if (blen == 0) // Probably means invalid code page - blen = WideCharToMultiByte(CP_ACP, 0, BufferW, wlen, BufferB + 2, 4096, &Subst, &DefaultUsed); - - buf = BufferB + 2; - BufferB[blen + 2] = 0; -#else - - size_t left = 4096; - UCHAR * BufferBP = BufferB; - size_t len = strlen(buf) + 1; - struct user_t * icu = circuit->u.user; - - if (icu->iconv_fromUTF8 == NULL) - { - icu->iconv_fromUTF8 = iconv_open(icu->Codepage, "UTF-8"); - - if (icu->iconv_fromUTF8 == (iconv_t)-1) - icu->iconv_fromUTF8 = iconv_open("CP1252//IGNORE", "UTF-8"); - } - - iconv(icu->iconv_fromUTF8, NULL, NULL, NULL, NULL); // Reset State Machine - iconv(icu->iconv_fromUTF8, (char ** __restrict__)&buf, &len, (char ** __restrict__)&BufferBP, &left); - - len = 4096 - left; - buf = BufferB; - -#endif - - } - - - if (circuit->u.user->rtflags & u_colour) // Use Colour - { - // Put a colour header on message - - *(--buf) = user->Colour; - *(--buf) = 0x1b; - nputs(circuit, buf); - buf +=2; - } - else - nputs(circuit, buf); - - - - circuit->u.user->lastsendtime = time(NULL); -} - -void text_tellu(USER *user, char *text, char *to, int who) -{ - ChatCIRCUIT *circuit; - UCHAR Buffer[2048]; - UCHAR *buf = &Buffer[4]; - char * Time; - struct tm * tm; - char Stamp[20]; - time_t T; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(Stamp,"%02d:%02d ", tm->tm_hour, tm->tm_min); - -// Send it to all connected users in the same topic. -// Echo to originator if requested. - - for (circuit = circuit_hd; circuit; circuit = circuit->next) - { - if (!(circuit->rtcflags & p_user)) continue; // Circuit is a link. - - if ((circuit->u.user == user) && !(user->rtflags & u_echo)) continue; - - if (circuit->u.user->rtflags & u_showtime) - Time = Stamp; - else - Time = ""; - - if (circuit->u.user->rtflags & u_shownames) - sprintf(buf, "%s%-6.6s %s %c %s\r", Time, user->call, user->name, (who == o_one) ? '>' : ':', text); - else - sprintf(buf, "%s%-6.6s %c %s\r", Time, user->call, (who == o_one) ? '>' : ':', text); - - - switch(who) - { - case o_topic : - if (circuit->u.user->topic == user->topic) - put_text(circuit, user, buf); // Send adding Colour if wanted - - break; - - case o_all: - - put_text(circuit, user, buf); // Send adding Colour if wanted - - break; - - case o_one : - if (matchi(circuit->u.user->call, to)) - put_text(circuit, user, buf); // Send adding Colour if wanted - break; - } - } -} - -extern int FlashOnConnect; - -void text_tellu_Joined(USER * user) -{ - ChatCIRCUIT *circuit; - UCHAR Buffer[200]; - UCHAR *buf = &Buffer[4]; - char * Time; - struct tm * tm; - char Stamp[20]; - time_t T; - char prog[256] = ""; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(Stamp,"%02d:%02d ", tm->tm_hour, tm->tm_min); - - sprintf(buf, "%s%-6.6s : %s *** Joined Chat, Topic %s", Stamp, user->call, user->name, user->topic->name); - - if (reportChatEvents) - { - -#ifdef WIN32 - if (pRunEventProgram) - pRunEventProgram("ChatNewUser.exe", user->call); -#else - sprintf(prog, "%s/%s", BPQDirectory, "ChatNewUser"); - RunEventProgram(prog, user->call); -#endif - } - -// Send it to all connected users in the same topic. -// Echo to originator if requested. - - for (circuit = circuit_hd; circuit; circuit = circuit->next) - { - if (!(circuit->rtcflags & p_user)) continue; // Circuit is a link. - if ((circuit->u.user == user) && !(user->rtflags & u_echo)) continue; - - if (circuit->u.user->rtflags & u_showtime) - Time = Stamp; - else - Time = ""; - - sprintf(buf, "%s%-6.6s : %s *** Joined Chat, Topic %s", Time, user->call, user->name, user->topic->name); - - put_text(circuit, user, buf); // Send adding Colour if wanted - - if (circuit->u.user->rtflags & u_bells) - if (circuit->BPQStream < 0) // Console - { -#ifndef LINBPQ - if (FlashOnConnect) FlashWindow(ConsHeader[1]->hConsole, TRUE); -#endif - nputc(circuit, 7); -// PlaySound ("BPQCHAT_USER_LOGIN", NULL, SND_ALIAS | SND_APPLICATION | SND_ASYNC); - } - else - nputc(circuit, 7); - - nputc(circuit, 13); - } -} -// Tell one link circuit about a local user change of topic. - -static void topic_xmit(USER *user, ChatCIRCUIT *circuit) -{ - nprintf(circuit, "%c%c%s %s %s\r", - FORMAT, id_topic, OurNode, user->call, user->topic->name); -} - -// Tell another node about one known node on a link add or drop -// if that node is from some other link. - -static void node_xmit(CHATNODE *node, char kind, ChatCIRCUIT *circuit) -{ -#ifndef LINBPQ - struct _EXCEPTION_POINTERS exinfo; - - __try - { -#endif - if (!cn_find(circuit, node)) - if (node->Version && (kind == id_link)) - nprintf(circuit, "%c%c%s %s %s %s\r", FORMAT, kind, OurNode, node->call, node->alias, node->Version); - else - nprintf(circuit, "%c%c%s %s %s\r", FORMAT, kind, OurNode, node->call, node->alias); - -#ifndef LINBPQ - } - - #define EXCEPTMSG "node_xmit" - #include "StdExcept.c" - - Debugprintf("Corrupt Rec %x %x %x", node, node->call, node->alias); - } -#endif -} - -// Tell all other nodes about one node known by this node. - -static void node_tell(CHATNODE *node, char kind) -{ - ChatCIRCUIT *circuit; - - for (circuit = circuit_hd; circuit; circuit = circuit->next) - { - if (circuit->rtcflags & p_linked) - node_xmit(node, kind, circuit); - } -} - -// Tell another node about a user login/logout at this node. - -static void user_xmit(USER *user, char kind, ChatCIRCUIT *circuit) -{ - CHATNODE *node; - - node = user->node; - - if (!cn_find(circuit, node)) - nprintf(circuit, "%c%c%s %s %s %s\r", FORMAT, kind, node->call, user->call, user->name, user->qth); -} - -// Tell all other nodes about a user login/logout at this node. - -static void user_tell(USER *user, char kind) -{ - ChatCIRCUIT *circuit; - - for (circuit = circuit_hd; circuit; circuit = circuit->next) - { - if (circuit->rtcflags & p_linked) - user_xmit(user, kind, circuit); - } -} - -// Find the user record for call@node. Node can be NULL, meaning any node - -USER *user_find(char *call, char * node) -{ - USER *user; - - for (user = user_hd; user; user = user->next) - { - if (node) - { - if (matchi(user->call, call) && matchi(user->node->call, node)) - break; - } - else - { - if (matchi(user->call, call)) - break; - } - } - - return user; -} - -static void user_leave(USER *user) -{ - USER *t, *tp; - - topic_leave(user->circuit, user->topic); - - tp = NULL; - - for (t = user_hd; t; tp = t, t = t->next) - { - if (t == user) - { - if (tp) tp->next = t->next; else user_hd = t->next; - - free(t->name); - free(t->call); - free(t->qth); -#ifndef WIN32 - if (t->iconv_fromUTF8) - iconv_close(t->iconv_fromUTF8); - if (t->iconv_toUTF8) - iconv_close(t->iconv_toUTF8); -#endif - free(t); - break; - } - } - - if (user_hd == NULL) - ChatTmr = 59; // If no users, disconnect links after 10-20 secs -} - -// User changed to a different topic. - -static BOOL topic_chg(USER *user, char *s) -{ - char buf[128]; - - if (_stricmp(user->topic->name, s) == 0) return FALSE; // Not Changed - - sprintf(buf, "*** Left Topic: %s", user->topic->name); - text_tellu(user, buf, NULL, o_topic); // Tell everyone in the old topic. - topic_leave(user->circuit, user->topic); - user->topic = topic_join(user->circuit, s); - sprintf(buf, "*** Joined Topic: %s", user->topic->name); - text_tellu(user, buf, NULL, o_topic); // Tell everyone in the new topic. - - return TRUE; -} - -// Create a user record for this user. - -static USER *user_join(ChatCIRCUIT *circuit, char *ucall, char *ncall, char *nalias, BOOL Local) -{ - CHATNODE *node; - USER *user; - - if (Local) - { - node = cn_inc(circuit, ncall, nalias, Verstring); - } - else - node = cn_inc(circuit, ncall, nalias, NULL); - -// Is this user already logged in at this node? - - for (user = user_hd; user; user = user->next) - { - if (matchi(user->call, ucall) && (user->node == node)) - return user; - } - -// User is not logged in, create a user record for them. - - user = zalloc(sizeof(USER)); - sl_ins_hd(user, user_hd); - user->circuit = circuit; - user->call = _strdup(ucall); - _strupr(user->call); - user->node = node; - rduser(user); - - if (user->Colour == 0 || user->Colour == 11) // None or default - { - // Allocate Random - int sum = 0, i; - - for (i = 0; i < 9; i++) - sum += user->call[i]; - sum %= 20; - - user->Colour = AutoColours[sum] + 10; // Best 20 colours - } - - if (circuit->rtcflags & p_user) - circuit->u.user = user; - - user->timeconnected = user->lastrealmsgtime = user->lastmsgtime = time(NULL); - - user->topic = topic_join(circuit, deftopic); - return user; -} - -// Link went away. We dropped it, or the other node dropped it. -// Drop nodes and users connected from this link. -// Tell other (still connected) links what was dropped. - -void link_drop(ChatCIRCUIT *circuit) -{ - USER *user, *usernext; - CN *cn; - -// So we don't try and send anything on this circuit. - - if (circuit->u.link) - if (circuit->rtcflags == p_linkini) - Debugprintf("Chat link %s Link Setup Failed", circuit->u.link->call); - - if (circuit->rtcflags == p_linkini) - circuit->u.link->flags = p_linkfailed; - else - circuit->u.link->flags = 0; - - circuit->rtcflags = p_nil; - -// Users connected on the dropped link are no longer connected. - - for (user = user_hd; user; user = usernext) - { - usernext = user->next; // Save next pointer in case entry is free'd - - if (user->circuit == circuit) - { - CHATNODE *node; - - node = user->node; - - text_tellu(user, rtleave, NULL, o_all); - user_tell(user, id_leave); - user_leave(user); - - circuit->refcnt--; - if (node) - node_dec(node); - } - } - -// Any node known from the dropped link is no longer known. - - for (cn = circuit->hnode; cn; cn = cn->next) - { - node_tell(cn->node, id_unlink); - node_dec(cn->node); - } - -// The circuit is no longer used. - - circuit_free(circuit); - NeedStatus = TRUE; -} - -// Handle an incoming control frame from a linked RT system. - -static void echo(ChatCIRCUIT *fc, CHATNODE *node, char * Buffer) -{ - ChatCIRCUIT *tc; - - for (tc = circuit_hd; tc; tc = tc->next) - { - if ((tc != fc) && (tc->rtcflags & p_linked) && !cn_find(tc, node)) - nprintf(tc, "%s\r", Buffer); - } -} - -char ** SeparateConnectScript(char * MultiString) -{ - char * ptr1 = MultiString; - char ** Value; - int Count = 0; - char * ptr; - - // Convert to string array - - Value = zalloc(sizeof(void *)); // always NULL entry on end even if no values - Value[0] = NULL; - - ptr = MultiString; - - while (ptr && strlen(ptr)) - { - ptr1 = strchr(ptr, '|'); - - if (ptr1) - *(ptr1++) = 0; - - if (strlen(ptr)) - { - Value = realloc(Value, (Count + 2) * sizeof(void *)); - Value[Count++] = _strdup(ptr); - } - ptr = ptr1; - } - - Value[Count] = NULL; - return Value; -} - -// Add an entry to list of link partners - -int rtlink (char * Call) -{ - LINK *link, *temp; - char *c; - char * script; - - _strupr(Call); - script = strlop(Call, '|'); - - c = strlop(Call, ':'); - if (!c) return FALSE; - - link = zalloc(sizeof(LINK)); - - link->alias = _strdup(Call); - link->call = _strdup(c); - - if (script) - { - link->ConnectScript = SeparateConnectScript(script); - link->Lines = 0; - while (link->ConnectScript[++link->Lines]); - } - else - { - // Create Script with one entry to call partner direct; - - link->ConnectScript = zalloc(sizeof(void *) * 2); // always NULL entry on end - link->ConnectScript[0] = malloc(32); - sprintf(link->ConnectScript[0], "C %s", c); - link->Lines = 1; - } - - if (link_hd == NULL) - link_hd = link; - else - { - temp = link_hd; - while(temp->next) - temp = temp->next; - - temp->next = link; - } - - return TRUE; -} - -VOID removelinks() -{ - LINK *link, *nextlink; - - for (link = link_hd; link; link = nextlink) - { - nextlink = link->next; - - if (link->ConnectScript) - { - int n = 0; - while(link->ConnectScript[n]) - free(link->ConnectScript[n++]); - - free(link->ConnectScript); - } - - free(link->alias); - link->alias = 0; - free(link->call); - link->call = 0; - free(link); - link = 0; - } - link_hd = NULL; -} -VOID removeknown() -{ - // Save Known Nodes list and free struct - - KNOWNNODE *node, *nextnode; - FILE *out; - - out = fopen(RtKnown, "w"); - - if (!out) - return; - - for (node = known_hd; node; node = nextnode) - { - fprintf(out, "%s %u\n", node->call, (unsigned int)node->LastHeard); - - nextnode = node->next; - free(node->call); - free(node); - } - known_hd = NULL; - - fclose(out); -} - -VOID LoadKnown() -{ - // Reload Known Nodes list - - FILE *in; - char buf[128]; - char * ptr; - - in = fopen(RtKnown, "r"); - - if (in == NULL) - return; - - while(fgets(buf, 128, in)) - { - ptr = strchr(buf, ' '); - if (ptr) - { - *(ptr) = 0; - knownnode_add(buf); - } - } - - fclose(in); -} - -// We don't allocate memory for circuit, but we do chain it - -ChatCIRCUIT *circuit_new(ChatCIRCUIT *circuit, int flags) -{ - // Make sure circuit isn't already on list - - ChatCIRCUIT *c; - - circuit->rtcflags = flags; - circuit->next = NULL; - - for (c = circuit_hd; c; c = c->next) - { - if (c == circuit) - { - Debugprintf("CHAT: Attempting to add Circuit when already on list"); - return circuit; - } - } - - sl_ins_hd(circuit, circuit_hd); - - return circuit; -} - -// Handle an incoming link. We should only get here if we think the station is a node. - -int rtloginl (ChatCIRCUIT *conn, char * call) -{ - LINK * link; - - if (node_find(call)) - { - Logprintf(LOG_CHAT, conn, '|', "Refusing link from %s to %s to prevent a loop", conn->Callsign, OurNode); - - nprintf(conn, "Refusing link from %s to %s to prevent a loop.\n", conn->Callsign, OurNode); - ChatFlush(conn); - Sleep(500); - conn->rtcflags = p_nil; - Disconnect(conn->BPQStream); - return FALSE; // Already linked. - } - - for (link = link_hd; link; link = link->next) - { - if (matchi(call, link->call)) - break; - } - - if (!link) - { - // We don't link with this system. Shouldn't happen, as we checked earlier - - nprintf(conn, "Node %s does not have %s defined as a node to link to - closing.\r", - OurNode, conn->Callsign); - ChatFlush(conn); - Sleep(500); - conn->rtcflags = p_nil; - Disconnect(conn->BPQStream); - return FALSE; - } - - if (link->flags & (p_linked | p_linkini)) - { - // Already Linked. Used to Disconnect, but that can cause sync errors - // Try closing old link and keeping new - - ChatCIRCUIT *c; - int len; - char Msg[80]; - - for (c = circuit_hd; c; c = c->next) - { - if (c->u.link == link) - { - len=sprintf_s(Msg, sizeof(Msg), "Chat Node %s Connect when Connected - Old Connection Closed", call); - ChatWriteLogLine(conn, '|',Msg, len, LOG_CHAT); - - c->Active = FALSE; // So we don't try to clear circuit again - Disconnect(c->BPQStream); - link_drop(c); - RefreshMainWindow(); - break; - } - } - } - -// Accept the link request. - - circuit_new(conn, p_linked); - conn->u.link = link; - nputs(conn, "OK\r"); - link->flags = p_linked; - link->delay = 0; // Dont delay first restart - state_tell(conn, NULL); - conn->u.link->timePollSent = time(NULL); // Keepalive is a poll - nprintf(conn, "%c%c%s %s %s\r", FORMAT, id_keepalive, OurNode, conn->u.link->call, Verstring); - - NeedStatus = TRUE; - - return TRUE; -} - -// User connected to chat, or did chat command from BBS - -int rtloginu (ChatCIRCUIT *circuit, BOOL Local) -{ - USER *user; - -// Is this user already logged in to RT somewhere else? - - user = user_find(circuit->UserPointer->Call, NULL); - - if (user) - { - // if connected at this node, kill old connection and allow new login - - if (user->node == node_find(OurNode)) - { - nputs(circuit, "*** Already connected at this node - old session will be closed.\r"); - - if (user->circuit->BPQStream < 0) - { - CloseConsole(user->circuit->BPQStream); - } - else - { - Disconnect(user->circuit->BPQStream); - } - } - else - nputs(circuit, "*** Already connected at another node.\r"); - - return FALSE; - } - -// Create the user entry. - - circuit_new(circuit, p_user); - - user = user_join(circuit, circuit->UserPointer->Call, OurNode, OurAlias, Local); - circuit->u.user = user; - - if (strcmp(user->name, "?_name") == 0) - { - user->name = _strdup(circuit->UserPointer->Name); - } - upduser(user); - - ChatExpandAndSendMessage(circuit, ChatWelcomeMsg, LOG_CHAT); - text_tellu_Joined(user); - user_tell(user, id_join); - show_users(circuit); - user->lastsendtime = time(NULL); -// makelinks(); - - return TRUE; -} - -void logout(ChatCIRCUIT *circuit) -{ - USER *user; - CHATNODE *node; - - circuit->rtcflags = p_nil; - user = circuit->u.user; - - if (user) // May not have logged in if already conencted - { - node = user->node; - - user_tell(user, id_leave); - text_tellu(user, rtleave, NULL, o_all); - user_leave(user); - - // order changed so node_dec can check if a node that is about the be deleted has eny users - - if (node) - { - cn_dec(circuit, node); - node_dec(node); - } - - circuit->u.user = NULL; - } - - circuit_free(circuit); -} - -void show_users(ChatCIRCUIT *circuit) -{ - USER *user; - char * Alias; - char * Topic; - - int i = 0; - - // First count them - - for (user = user_hd; user; user = user->next) - { - i++; - } - - nprintf(circuit, "%d Station(s) connected:\r", i); - - for (user = user_hd; user; user = user->next) - { - if ((user->node == 0) || (user->node->alias == 0)) - Alias = "(Corrupt Alias)"; - else - Alias = user->node->alias; - - if ((user->topic == 0) || (user->topic->name == 0)) - Topic = "(Corrupt Topic)"; - else - Topic = user->topic->name; - -#ifndef LINBPQ - __try - { -#endif - if (circuit->u.user->rtflags & u_colour) // Use Colour - nprintf(circuit, "\x1b%c%-6.6s at %-9.9s %s, %s [%s] Idle for %d seconds\r", - user->Colour, user->call, Alias, user->name, user->qth, Topic, time(NULL) - user->lastrealmsgtime); - else - nprintf(circuit, "%-6.6s at %-9.9s %s, %s [%s] Idle for %d seconds\r", - user->call, Alias, user->name, user->qth, Topic, time(NULL) - user->lastrealmsgtime); -#ifndef LINBPQ - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - Debugprintf("MAILCHAT *** Program Error in show_users"); - CheckProgramErrors(); - } -#endif - } -} - - -static void show_nodes(ChatCIRCUIT *circuit) -{ - CHATNODE *node; - - nputs(circuit, "Known Nodes:\r"); - - for (node = node_hd; node; node = node->next) - { - if (node->refcnt) - if (node->Version) - nprintf(circuit, "%s:%s %s %u\r", node->alias, node->call, node->Version, node->refcnt); - else - nprintf(circuit, "%s:%s %s %u\r", node->alias, node->call, "Not Known", node->refcnt); - } -} - -// /P Command: List circuits and remote RT on them. - -#define xxx "\r " - -static void show_circuits(ChatCIRCUIT *conn, char Flag) -{ - ChatCIRCUIT *circuit; - CHATNODE *node; - LINK *link; - char line[1000]; - int len = 0; - CN *cn; - - int i = 0; - - // First count them - - for (node = node_hd; node; node = node->next) - { - i++; - } - - nprintf(conn, "%d Node(s)\r", i); - - if (Flag == 'c') - len = sprintf(line, "Here %-6.6s <-", OurNode); - else - len = sprintf(line, "Here %-6.6s <-", OurAlias); - - for (node = node_hd; node; node = node->next) if (node->refcnt) - { - if (Flag == 'c') - len += sprintf(&line[len], " %s", node->call); - else - len += sprintf(&line[len], " %s", node->alias); - if (len > 80) - { - nprintf(conn, "%s\r", line); - len = sprintf(line, " "); - } - } - - nprintf(conn, "%s\r", line); - - for (circuit = circuit_hd; circuit; circuit = circuit->next) - { - if (circuit->rtcflags & p_linked) - { - if (Flag == 'c') - len = sprintf(line, "Nodes via %-6.6s(%d) -", circuit->u.link->call, circuit->refcnt); - else - len = sprintf(line, "Nodes via %-6.6s(%d) -", circuit->u.link->alias, circuit->refcnt); - -#ifndef LINBPQ - __try{ - for (cn = circuit->hnode; cn; cn = cn->next) - { - if (cn->node && cn->node->alias) - { - __try - { - if (Flag == 'c') - len += sprintf(&line[len], " %s", cn->node->call); - else - len += sprintf(&line[len], " %s", cn->node->alias); - if (len > 80) - { - nprintf(conn, "%s\r", line); - len = sprintf(line, " "); - } - } - __except(EXCEPTION_EXECUTE_HANDLER) - {len += sprintf(&line[len], " *PE* Corrupt Rec %x %x", cn, cn->node);} - } - else - len = sprintf(&line[len], " Corrupt Rec %x %x ", cn, cn->node); - } - } - __except(EXCEPTION_EXECUTE_HANDLER) - {len += sprintf(&line[len], " *PE* Corrupt Rec %x %x ", cn, cn->node);} -#else - for (cn = circuit->hnode; cn; cn = cn->next) - { - if (cn->node && cn->node->alias) - { - if (Flag == 'c') - len += sprintf(&line[len], " %s", cn->node->call); - else - len += sprintf(&line[len], " %s", cn->node->alias); - if (len > 80) - { - nprintf(conn, "%s\r", line); - len = sprintf(line, " "); - } - } - else - len += sprintf(&line[len], " Corrupt Rec %p %p ", cn, cn->node); - } -#endif - nprintf(conn, "%s\r", line); - - } - else if (circuit->rtcflags & p_user) - nprintf(conn, "User %-6.6s\r", circuit->u.user->call); - else if (circuit->rtcflags & p_linkini) - { - if (circuit->u.link) - { if (Flag == 'c') - nprintf(conn, "Link %-6.6s (setup)\r", circuit->u.link->call); - else - nprintf(conn, "Link %-6.6s (setup)\r", circuit->u.link->alias); - - } - else - nprintf(conn, "Link ?? (setup)\r"); - } - } - - nprintf(conn, "Links Defined:\r"); - - for (link = link_hd; link; link = link->next) - { - if (link->flags & p_linked ) - if (link->supportsPolls) - nprintf(conn, " %-10.10s Open RTT %d\r", link->call, link->RTT); - else - nprintf(conn, " %-10.10s Open\r", link->call); - else if (link->flags & (p_linked | p_linkini)) - nprintf(conn, " %-10.10s Connecting\r", link->call); - else if (link->flags & p_linkfailed) - nprintf(conn, " %-10.10s Connect failed\r", link->call); - else - nprintf(conn, " %-10.10s Idle\r", link->call); - } -} - -// /T Command: List topics and users in them. - -static void show_topics(ChatCIRCUIT *conn) -{ - TOPIC *topic; - USER *user; - - nputs(conn, "Active Topics are:\r"); - - for (topic = topic_hd; topic; topic = topic->next) - { - nprintf(conn, "%s\r", topic->name); - - if (topic->refcnt) - { - nputs(conn, " "); - for (user = user_hd; user; user = user->next) - { - if (user->topic == topic) - nprintf(conn, " %s", user->call); - } - nputc(conn, '\r'); - } - } -} - -static void show_users_in_topic(ChatCIRCUIT *conn) -{ - TOPIC *topic; - USER *user; - - nputs(conn, "Users in Topic:\r"); - - topic = conn->u.user->topic; - { - if (topic->refcnt) - { - for (user = user_hd; user; user = user->next) - { - if (user->topic == topic) - nprintf(conn, "%s ", user->call); - } - nputc(conn, '\r'); - } - } -} - -// Do a user command. - -int rt_cmd(ChatCIRCUIT *circuit, char * Buffer) -{ - ChatCIRCUIT *c; - USER *user, *su; - char *f1, *f2; - - user = circuit->u.user; - -// user->lastsendtime = time(NULL); - - switch(tolower(Buffer[1])) - { - case 'a' : - user->rtflags ^= u_bells; - upduser(user); - nprintf(circuit, "Alert %s\r", (user->rtflags & u_bells) ? "Enabled" : "Disabled"); - return TRUE; - - case 'b' : return FALSE; - - case 'c' : - user->rtflags ^= u_colour; - upduser(user); - nprintf(circuit, "Colour Mode %s\r", (user->rtflags & u_colour) ? "Enabled" : "Disabled"); - return TRUE; - - case 'e' : - user->rtflags ^= u_echo; - upduser(user); - nprintf(circuit, "Echo %s\r", (user->rtflags & u_echo) ? "Enabled" : "Disabled"); - return TRUE; - - case 'f' : makelinks(); return TRUE; - - case 'h' : - case '?' : - { - char * Save; - char * MsgBytes = Save = ReadInfoFile("chathelp.txt"); - - if (MsgBytes) - { - int Length; - - // Remove lf chars - - Length = RemoveLF(MsgBytes, (int)strlen(MsgBytes)); - - ChatQueueMsg(circuit, MsgBytes, Length); - free(Save); - } - else - { - nputs(circuit, "Commands can be in upper or lower case.\r"); - nputs(circuit, "/U - Show Users.\r/N - Enter your Name.\r/Q - Enter your QTH.\r/T - Show Topics.\r"); - nputs(circuit, "/T Name - Join Topic or Create new Topic. Topic Names are not case sensitive\r/P - Show Ports and Links.\r"); - nprintf(circuit, "/A - Toggle Alert on user join - %s.\r", - (user->rtflags & u_bells) ? "Enabled" : "Disabled"); - nprintf(circuit, "/C - Toggle Colour Mode on or off (only works on Console or BPQTerm/TermTCP/QtTermTCP - %s.\r", - (user->rtflags & u_colour) ? "Enabled" : "Disabled"); - nputs(circuit, "/Codepage CPnnnn - Set Codepage to use if UTF-8 is disabled.\r"); - nprintf(circuit, "/E - Toggle Echo - %s .\r", - (user->rtflags & u_echo) ? "Enabled" : "Disabled"); - nprintf(circuit, "/Keepalive - Toggle sending Keepalive messages every 10 minutes - %s.\r", - (user->rtflags & u_keepalive) ? "Enabled" : "Disabled"); - nprintf(circuit, "/ShowNames - Toggle displaying name as well as call on each message - %s\r", - (user->rtflags & u_shownames) ? "Enabled" : "Disabled"); - nprintf(circuit, "/Auto - Toggle Automatic character set selection - %s.\r", - (user->rtflags & u_auto) ? "Enabled" : "Disabled"); - nprintf(circuit, "/UTF-8 - Character set Selection - %s.\r", - (user->rtflags & u_noUTF8) ? "8 Bit" : "UTF-8"); - nprintf(circuit, "/Time - Toggle displaying timestamp on each message - %s.\r", - (user->rtflags & u_showtime) ? "Enabled" : "Disabled"); - nputs(circuit, "/S CALL Text - Send Text to that station only.\r"); - nputs(circuit, "/F - Force all links to be made.\r/K - Show Known nodes.\r"); - nputs(circuit, "/B - Leave Chat and return to node.\r/QUIT - Leave Chat and disconnect from node.\r"); - nputs(circuit, "/History nn - Display chat messages received in last nn minutes.\r"); - } - } - return TRUE; - - case 'k' : show_nodes(circuit); return TRUE; - - case 'n' : - - f1 = &Buffer[2]; - - while ((*f1 != 0) && (*f1 == ' ')) - f1++; - - if (*f1 == 0) - { - nprintf(circuit, "Name is %s\r", user->name); - return TRUE; - } - - strnew(&user->name, f1); - nprintf(circuit, "Name set to %s\r", user->name); - upduser(user); - user_tell(user, id_user); - return TRUE; - - case 'p' : show_circuits(circuit, Buffer[3]); return TRUE; - - case 'q' : - - f1 = &Buffer[2]; - - while ((*f1 != 0) && (*f1 == ' ')) - f1++; - - if (*f1 == 0) - { - nprintf(circuit, "QTH is %s\r", user->qth); - return TRUE; - } - - strnew(&user->qth, f1); - - nprintf(circuit, "QTH set to %s\r", user->qth); - upduser(user); - user_tell(user, id_user); - return TRUE; - - case 's' : - strcat(Buffer, "\r"); - f1 = strlop(Buffer, ' '); // To. - if (!f1) break; - f2 = strlop(f1, ' '); // Text to send. - if (!f2) break; - _strupr(f1); - su = user_find(f1, NULL); - - if (!su) - { - nputs(circuit, "*** That user is not logged in.\r"); - return TRUE; - } - - // Send to the desired user only. - - if (su->circuit->rtcflags & p_user) - text_tellu(user, f2, f1, o_one); - else - text_xmit(user, su, f2); - - return TRUE; - - case 't' : - f1 = strlop(Buffer, ' '); - if (f1) - { - if (topic_chg(user, f1)) - { - nprintf(circuit, "Switched to Topic %s\r", user->topic->name); - show_users_in_topic(circuit); - - // Tell all link circuits about the change of topic. - - for (c = circuit_hd; c; c = c->next) - { - if (c->rtcflags & p_linked) - topic_xmit(user, c); - } - } - else - { - // Already in topic - - nprintf(circuit, "You were already in Topic %s\r", user->topic->name); - } - } - else - show_topics(circuit); - return TRUE; - - case 'u' : show_users(circuit); return TRUE; - - default : break; - } - - saywhat(circuit); - return TRUE; -} - -void makelinks(void) -{ - LINK *link; - ChatCIRCUIT *circuit; - - // Make the links. Called every 10 seconds - - // Make sure previous link has completed or failed - - if (RunningConnectScript) - { - // Make sure Connect Script isn't taking too long - - if (time(NULL) - RunningConnectScript < 30) - return; - - // Running too long - close it - - for (circuit = circuit_hd; circuit; circuit = circuit->next) - { - // Find the link - - if (circuit->rtcflags & (p_linkini)) - { - link = circuit->u.link; - link->flags = p_linkfailed; - RunningConnectScript = 0; - link->scriptRunning = 0; // so it doesn't get reentered - Logprintf(LOG_CHAT, circuit, '|', "Connect to %s timed out", circuit->Callsign); - - Disconnect(circuit->BPQStream); - } - } - RunningConnectScript = 0; - } - - for (link = link_hd; link; link = link->next) - { - // Is this link already established? - - if (link->flags & (p_linked | p_linkini)) - continue; - - // Already linked through some other node? - // If so, making this link would create a loop. - - if (node_find(link->call)) - continue; - - // Fire up the process to handle this link. - - if (link->delay == 0) - { - link->flags = p_linkini; - link->delay = 12; // 2 mins - chat_link_out(link); - return; // One at a time - } - else - link->delay--; - } -} - -VOID node_close() -{ - // Close all Node-Node Links - - ChatCIRCUIT *circuit; - - for (circuit = circuit_hd; circuit; circuit = circuit->next) - { - if (circuit->rtcflags & (p_linked | p_linkini | p_linkwait)) - Disconnect(circuit->BPQStream); - } -} - -// Send Keepalives to all connected nodes - -static void node_keepalive() -{ - ChatCIRCUIT *circuit; - - NeedStatus = TRUE; // Send Report to Monitor - - if (user_hd) // Any Users? - { - for (circuit = circuit_hd; circuit; circuit = circuit->next) - { - if (circuit->rtcflags & p_linked && circuit->u.link) - { - nprintf(circuit, "%c%c%s %s %s\r", FORMAT, id_keepalive, OurNode, circuit->u.link->call, Verstring); - circuit->u.link->timePollSent = time(NULL); // Also acts as poll - } - } - } - else - { - // No users. Close links - - node_close(); - } -} - -VOID ChatTimer() -{ - // Entered every 10 seconds - - int i = 0; - ChatCIRCUIT *c; - -#ifndef LINBPQ - int len; - CHATNODE *node; - TOPIC *topic; - char Msg[256]; -#endif - USER *user; - time_t NOW = time(NULL); - - GetSemaphore(&ChatSemaphore, 0); - - if (NeedStatus) - { - NeedStatus = FALSE; - SendChatLinkStatus(); - } - -#ifndef LINBPQ - - ClearDebugWindow(); - - WritetoDebugWindow("Chat Nodes\r\n", 12); - - for (node = node_hd; node; node = node->next) - { - len = sprintf_s(Msg, sizeof(Msg), "%s Version %s Count %d\r\n", - node->call, node->Version, node->refcnt); - WritetoDebugWindow(Msg, len); - - i++; - } - - SetDlgItemInt(hWnd, IDC_NODES, i, FALSE); - - WritetoDebugWindow("Chat Links\r\n", 12); - - i = 0; - for (c = circuit_hd; c; c = c->next) - { - if (c->rtcflags & p_linked) - { - char buff[1000]; - int ptr; - CT * ct; - ptr = sprintf_s(buff, sizeof(buff), "%s Topics: ", c->u.user->call); - - if (c->topic) - { - for (ct = c->topic; ct; ct = ct->next) - { - ptr+= sprintf_s(&buff[ptr], sizeof(buff) - ptr, "%s ", ct->topic->name); - } - } - WritetoDebugWindow(buff, ptr); - WritetoDebugWindow("\r\n", 2); - - i++; - } - } - - SetDlgItemInt(hWnd, IDC_LINKS, i, FALSE); - - WritetoDebugWindow("Chat Topics\r\n", 12); - - i = 0; - for (topic = topic_hd; topic; topic = topic->next) - { - len = sprintf_s(Msg, sizeof(Msg), "%s %d\r\n", topic->name, topic->refcnt); - WritetoDebugWindow(Msg, len); - i++; - } - - WritetoDebugWindow("Chat Users\r\n", 12); - - i = 0; - for (user = user_hd; user; user = user->next) - { - len = sprintf_s(Msg, sizeof(Msg), "%s Topic %s\r\n", user->call, - (user->topic) ? user->topic->name : "** Missing Topic **"); - WritetoDebugWindow(Msg, len); - i++; - - if (user->circuit && user->circuit->rtcflags & p_user) // Local User - { - time_t Idle = NOW - user->lastmsgtime; - - if (Idle > 7200) - { - nprintf(user->circuit, "*** Disconnected - Idle time exceeded\r"); - Sleep(1000); - - if (user->circuit->BPQStream < 0) - { - CloseConsole(user->circuit->BPQStream); - break; - } - else - { - Disconnect(user->circuit->BPQStream); - break; - } - } - - if ((user->rtflags & u_keepalive) && (NOW - user->lastsendtime) > 600) - { - nprintf(user->circuit, "Chat Keepalive\r"); - user->lastsendtime = NOW; - } - } - } - - SetDlgItemInt(hWnd, IDC_USERS, i, FALSE); - -#else - - for (user = user_hd; user; user = user->next) - { - if (user->circuit && user->circuit->rtcflags & p_user) // Local User - { - if ((NOW - user->lastmsgtime) > 7200) - { - nprintf(user->circuit, "*** Disconnected - Idle time exceeded\r"); - Sleep(1000); - - if (user->circuit->BPQStream < 0) - { - CloseConsole(user->circuit->BPQStream); - break; - } - else - { - Disconnect(user->circuit->BPQStream); - break; - } - } - - if ((user->rtflags & u_keepalive) && (NOW - user->lastsendtime) > 600) - { - nprintf(user->circuit, "Chat Keepalive\r"); - user->lastsendtime = NOW; - } - } - } - -#endif - - // if no message on a Node-Node link, send poll - - for (c = circuit_hd; c; c = c->next) - { - if (c->rtcflags & p_linked && c->u.link) - { - time_t Now = time(NULL); - LINK * Link = c->u.link; - - if (Now - Link->lastMsgReceived > 60) - { - // if we have a poll outstanding for ? 30 secs close link - // but check other end can handle polls - - if (Link->supportsPolls && Link->timePollSent && Now - Link->timePollSent > 30) - { - Logprintf(LOG_CHAT, c, '|', "%s No Poll Response for %d Secs - Dropping Link", - c->Callsign, Now - Link->timePollSent); - - Disconnect(c->BPQStream); - continue; - } - - Link->timePollSent = Now; - nprintf(c, "%c%c%s %s\r", FORMAT, id_poll, OurNode, Link->call); - } - } - } - - ChatTmr++; - - if (user_hd) // Any Users? - makelinks(); - - if (ChatTmr > 60) // 10 Mins - { - ChatTmr = 1; - node_keepalive(); - } - - FreeSemaphore(&ChatSemaphore); - - if (NeedINFO) - { - NeedINFO--; - - if (NeedINFO == 0) - { - // Send INFO to Chatmap - - char Msg[500]; - int len; - - NeedINFO = 360; // Send Every Hour - - if (Position[0]) - { - len = sprintf(Msg, "INFO %s|%s|%d|\r", Position, PopupText, PopupMode); - - if (len < 256) - Send_MON_Datagram(Msg, len); - } - } - } -} - -VOID FreeChatMemory() -{ - removelinks(); - removeknown(); -} - -// Find a call in the known node list. - -KNOWNNODE *knownnode_find(char *call) -{ - KNOWNNODE *node; - - for (node = known_hd; node; node = node->next) - { - if (matchi(node->call, call)) - break; - } - - return node; -} - -// Add a known node. - -static KNOWNNODE *knownnode_add(char *call) -{ - KNOWNNODE *node; - - node = knownnode_find(call); - - if (!node) - { - node = zalloc(sizeof(KNOWNNODE)); - sl_ins_hd(node, known_hd); - node->call = _strdup(call); - } - - node->LastHeard = time(NULL); - return node; -} - -static char UIDEST[10] = "DUMMY"; -static char AXDEST[7]; -static char ChatMYCALL[7]; - -#pragma pack(1) - - -typedef struct _MESSAGEX -{ -// BASIC LINK LEVEL MESSAGE BUFFER LAYOUT - - struct _MESSAGE * 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]; - -}MESSAGEX, *PMESSAGEX; - -#pragma pack() - -SOCKET ChatReportSocket = 0; - - -VOID SetupChat() -{ - u_long param=1; - BOOL bcopt=TRUE; - - ConvToAX25(OurNode, ChatMYCALL); - ConvToAX25(UIDEST, AXDEST); - - sprintf(Verstring, "%d.%d.%d.%d", Ver[0], Ver[1], Ver[2], Ver[3]); - - LoadKnown(); - - ChatReportSocket = socket(AF_INET,SOCK_DGRAM,0); - - if (ChatReportSocket == INVALID_SOCKET) - { - Debugprintf("Failed to create Chat Reporting socket"); - ChatReportSocket = 0; - return; - } - - ioctlsocket (ChatReportSocket, FIONBIO, ¶m); - setsockopt (ChatReportSocket, SOL_SOCKET, SO_BROADCAST, (const char FAR *)&bcopt,4); -} - - -VOID Send_MON_Datagram(UCHAR * Msg, DWORD Len) -{ - MESSAGEX AXMSG; - PMESSAGEX AXPTR = &AXMSG; - - if (Len > 256) - { - Debugprintf("Send_MON_Datagram Error Msg = %s Len = %d", Msg, Len); - return; - } - -// ConvToAX25("GM4OAS-5", ChatMYCALL); - - // Block includes the Msg Header (7 bytes), Len Does not! - - memcpy(AXPTR->DEST, AXDEST, 7); - memcpy(AXPTR->ORIGIN, ChatMYCALL, 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->DATA, Msg, Len); - - SendChatReport(ChatReportSocket, (char *)&AXMSG.DEST, Len + 16); - - return; - -} - -VOID SendChatLinkStatus() -{ - char Msg[256] = {0}; - LINK * link; - int len = 0; - ChatCIRCUIT *circuit; - - if (ChatApplNum == 0) - return; - -// if (AXIPPort == 0) -// return; - - if (ChatMYCALL[0] == 0) - return; - - for (link = link_hd; link; link = link->next) - { - if (link->flags & p_linked) - { - // Verify connection - - for (circuit = circuit_hd; circuit; circuit = circuit->next) - { - if (strcmp(circuit->Callsign, link->alias) == 0) - { - if (circuit->Active == 0) - { - // BPQ Session is dead - Simulate a Disconnect - - circuit->Active = TRUE; // So disconnect will work - Disconnected(circuit->BPQStream); - NeedStatus = TRUE; // Reenter - return; // Link Chain has changed - } - break; - } - } - - if (circuit == 0) - { - // No BPQ Session - is the only answer to restart the node? - - // Logprintf(LOG_DEBUGx, NULL, '!', "Stuck Chat Sesion Detected"); - // Logprintf(LOG_DEBUGx, NULL, '!', "Chat is a mess - forcing a restart"); - // ProgramErrors = 26; - // CheckProgramErrors(); - } - } - - len += sprintf(&Msg[len], "%s %c ", link->call, '0' + link->flags); - - if (len > 240) - break; - } - Msg[len++] = '\r'; - - Send_MON_Datagram(Msg, len); -} - -VOID ClearChatLinkStatus() -{ - LINK * link; - - for (link = link_hd; link; link = link->next) - { - link->flags = 0; - } -} - -BOOL ProcessChatConnectScript(ChatCIRCUIT * conn, char * Buffer, int len) -{ - LINK * link = conn->u.link; - char ** Scripts; - - ChatWriteLogLine(conn, '<', Buffer, len-1, LOG_CHAT); - - Buffer[len] = 0; - _strupr(Buffer); - - Scripts = link->ConnectScript; - - if (strstr(Buffer, "BUSY") || strstr(Buffer, "FAILURE") || - (strstr(Buffer, "DOWNLINK") && strstr(Buffer, "ATTEMPTING") == 0) || - strstr(Buffer, "SORRY") || strstr(Buffer, "INVALID") || strstr(Buffer, "RETRIED") || - strstr(Buffer, "NO CONNECTION TO") || strstr(Buffer, "ERROR - ") || - strstr(Buffer, "UNABLE TO CONNECT") || strstr(Buffer, "DISCONNECTED") || - strstr(Buffer, "FAILED TO CONNECT") || strstr(Buffer, "REJECTED")) - { - // Connect Failed - - link->flags = p_linkfailed; - RunningConnectScript = 0; - link->scriptRunning = 0; // so it doesn't get reentered - Disconnect(conn->BPQStream); - return FALSE; - } - - // The pointer is only updated when we get the connect, so we can tell when the last line is acked - // The first entry is always from Connected event, so don't have to worry about testing entry -1 below - - - if (link->RTLSent) - { - RunningConnectScript = 0; - link->scriptRunning = 0; - link->RTLSent = 0; - - if (memcmp(Buffer, "OK", 2) == 0) - { - // Reply to *RTL - - // Make sure node isn't known. There is a window here that could cause a loop - - if (node_find(conn->u.link->call)) - { - Logprintf(LOG_CHAT, conn, '|', "Dropping link with %s to prevent a loop", conn->Callsign); - Disconnect(conn->BPQStream); - return FALSE; - } - - conn->u.link->flags = p_linked; - conn->rtcflags = p_linked; - state_tell(conn, conn->FBBReplyChars); - NeedStatus = TRUE; - - return TRUE; - } - - // Some other response to *RTL - disconnect - - Logprintf(LOG_CHAT, conn, '|', "Unexpected Response %s to *RTL - Dropping link", Buffer); - Disconnect(conn->BPQStream); - return FALSE; - - } - - if (strstr(Buffer, " CONNECTED") || strstr(Buffer, "PACLEN") || strstr(Buffer, "IDLETIME") || - strstr(Buffer, "OK") || strstr(Buffer, "###LINK MADE") || strstr(Buffer, "VIRTUAL CIRCUIT ESTABLISHED")) - { - char * Cmd; - -LoopBack: - - Cmd = Scripts[++link->ScriptIndex]; - - // Only Check until script is finished - - if (Cmd == 0 || link->ScriptIndex >= link->Lines) - { - link->MoreLines = FALSE; - return TRUE; - } - - if (Cmd && (strcmp(Cmd, " ") == 0 || Cmd[0] == ';' || Cmd[0] == '#')) - goto LoopBack; // Blank line - - // Replace \ with # so can send commands starting with # - - if (Cmd[0] == '\\') - { - Cmd[0] = '#'; - nprintf(conn, "%s\r", Cmd); - Cmd[0] = '\\'; // Put \ back in script - } - else - nprintf(conn, "%s\r", Cmd); - - return TRUE; - } - - if (memcmp(Buffer, "[BPQCHATSERVER-", 15) == 0) - { - char * ptr = strchr(Buffer, ']'); - if (ptr) - { - *ptr = 0; - strcpy(conn->FBBReplyChars, &Buffer[15]); - } - else - conn->FBBReplyChars[0] = 0; - - // Connected - Send *RTL - - nputs(conn, "*RTL\r"); // Log in to the remote RT system. - - conn->u.link->timePollSent = time(NULL); // Keepalive is a poll - nprintf(conn, "%c%c%s %s %s\r", FORMAT, id_keepalive, OurNode, conn->u.link->call, Verstring); - link->RTLSent = 1; - conn->u.link->lastMsgSent = time(NULL); - - return TRUE; - } - -// Anthing else could be ctext. etc. Ignore - - return TRUE; -} - - - -#ifdef LINBPQ - -// LINCHAT specific code - -extern struct SEM OutputSEM; - -static config_t cfg; -static config_setting_t * group; - -extern char pgm[256]; - -char ChatSYSOPCall[50] = ""; - -VOID ChatSendWelcomeMsg(int Stream, ChatCIRCUIT * conn, struct UserInfo * user); - - -int ChatConnected(int Stream) -{ - int n; - ChatCIRCUIT * conn; - struct UserInfo * user = NULL; - char callsign[10]; - int port, paclen, maxframe, l4window; - char ConnectedMsg[] = "*** CONNECTED "; - char Msg[100]; - LINK *link; - KNOWNNODE *node; - - for (n = 0; n < NumberofChatStreams; n++) - { - conn = &ChatConnections[n]; - - if (Stream == conn->BPQStream) - { - if (conn->Active) - { - // Probably an outgoing connect - - if (conn->rtcflags == p_linkini) - { - conn->paclen = chatPaclen; - - // Run first line of connect script - - ProcessChatConnectScript(conn, ConnectedMsg, 15); -// nprintf(conn, "c %s\r", conn->u.link->call); - } - return 0; - } - - memset(conn, 0, sizeof(ChatCIRCUIT)); // Clear everything - conn->Active = TRUE; - conn->BPQStream = Stream; - - conn->Secure_Session = GetConnectionInfo(Stream, callsign, - &port, &conn->SessType, &paclen, &maxframe, &l4window); - - if (paclen == 0) - paclen = 256; - - if (paclen > chatPaclen) - paclen = chatPaclen; - - conn->paclen = paclen; - - strlop(callsign, ' '); // Remove trailing spaces - - memcpy(conn->Callsign, callsign, 10); - - strlop(callsign, '-'); // Remove any SSID - - user = zalloc(sizeof(struct UserInfo)); - - strcpy(user->Call, callsign); - - conn->UserPointer = user; - - n=sprintf_s(Msg, sizeof(Msg), "Incoming Connect from %s", user->Call); - - // Send SID and Prompt - - ChatWriteLogLine(conn, '|',Msg, n, LOG_CHAT); - conn->Flags |= CHATMODE; - - nprintf(conn, ChatSID, Ver[0], Ver[1], Ver[2], Ver[3]); - - // See if from a defined node - - for (link = link_hd; link; link = link->next) - { - if (matchi(conn->Callsign, link->call)) - { - conn->rtcflags = p_linkwait; - return 0; // Wait for *RTL - } - } - - // See if from a previously known node - - node = knownnode_find(conn->Callsign); - - if (node) - { - // A node is trying to link, but we don't have it defined - close - - Logprintf(LOG_CHAT, conn, '!', "Node %s connected, but is not defined as a Node - closing", - conn->Callsign); - - nprintf(conn, "Node %s does not have %s defined as a node to link to - closing.\r", - OurNode, conn->Callsign); - - ChatFlush(conn); - - Sleep(500); - conn->rtcflags = p_nil; - - Disconnect(conn->BPQStream); - - return 0; - } - - if (user->Name[0] == 0) - { - char * Name = lookupuser(user->Call); - - if (Name) - { - if (strlen(Name) > 17) - Name[17] = 0; - - strcpy(user->Name, Name); - free(Name); - } - else - { - conn->Flags |= GETTINGUSER; - nputs(conn, NewUserPrompt); - return TRUE; - } - } - - ChatSendWelcomeMsg(Stream, conn, user); - RefreshMainWindow(); - ChatFlush(conn); - - return 0; - } - } - - return 0; -} - -int ChatDisconnected (ChatCIRCUIT * conn) -{ - struct UserInfo * user = NULL; - int Stream = conn->BPQStream; - char Msg[255]; - int len; - - if (conn->Active == FALSE) - return 0; - - ChatClearQueue(conn); - - conn->Active = FALSE; - - if (conn->Flags & CHATMODE) - { - if (conn->Flags & CHATLINK && conn->u.link) - { - // if running connect script, clear script active - - if (conn->u.link->flags & p_linkini) - { - RunningConnectScript = 0; - conn->u.link->scriptRunning = 0; - } - - len=sprintf_s(Msg, sizeof(Msg), "Chat Node %s Disconnected", conn->u.link->call); - ChatWriteLogLine(conn, '|',Msg, len, LOG_CHAT); - link_drop(conn); - - } - else - { - len=sprintf_s(Msg, sizeof(Msg), "Chat User %s Disconnected", conn->Callsign); - ChatWriteLogLine(conn, '|',Msg, len, LOG_CHAT); - - logout(conn); - - } - - conn->Flags = 0; - conn->u.link = NULL; - conn->UserPointer = NULL; - return 0; - } - - return 0; -} - -int ChatDoReceivedData(ChatCIRCUIT * conn) -{ - int count, InputLen; - UINT MsgLen; - int Stream = conn->BPQStream; - struct UserInfo * user; - char * ptr, * ptr2; - char Buffer[10000]; - - - // May have several messages per packet, or message split over packets - - if (conn->InputLen + 1000 > 10000) // Shouldnt have lines longer than this in text mode - conn->InputLen = 0; // discard - - GetMsg(Stream, &conn->InputBuffer[conn->InputLen], &InputLen, &count); - - if (InputLen == 0) return 0; - - conn->Watchdog = 900; // 15 Minutes - conn->InputLen += InputLen; - -loop: - - if (conn->InputLen == 1 && conn->InputBuffer[0] == 0) // Single Null - { - conn->InputLen = 0; - - if (conn->u.user->circuit && conn->u.user->circuit->rtcflags & p_user) // Local User - conn->u.user->lastmsgtime = time(NULL); - - return 0; - } - - ptr = memchr(conn->InputBuffer, '\r', conn->InputLen); - - if (ptr) // CR in buffer - { - user = conn->UserPointer; - - ptr2 = &conn->InputBuffer[conn->InputLen]; - - if (++ptr == ptr2) - { - // Usual Case - single meg in buffer - - if (conn->rtcflags == p_linkini) // Chat Connect - ProcessChatConnectScript(conn, conn->InputBuffer, conn->InputLen); - else - ProcessChatLine(conn, user, conn->InputBuffer, conn->InputLen); - conn->InputLen=0; - } - else - { - // buffer contains more that 1 message - - MsgLen = conn->InputLen - (int)(ptr2-ptr); - - memcpy(Buffer, conn->InputBuffer, MsgLen); - - if (conn->rtcflags == p_linkini) - ProcessChatConnectScript(conn, Buffer, MsgLen); - else - ProcessChatLine(conn, user, Buffer, MsgLen); - - if (*ptr == 0 || *ptr == '\n') - { - /// CR LF or CR Null - - ptr++; - conn->InputLen--; - } - - memmove(conn->InputBuffer, ptr, conn->InputLen-MsgLen); - conn->InputLen -= MsgLen; - - goto loop; - - } - } - return 0; -} - - -int ChatPollStreams() -{ - int state,change; - ChatCIRCUIT * conn; - int n; - struct UserInfo * user = NULL; - char ConnectedMsg[] = "*** CONNECTED "; - - for (n = 0; n < NumberofChatStreams; n++) - { - conn = &ChatConnections[n]; - - SessionState(conn->BPQStream, &state, &change); - - if (change == 1) - { - if (state == 1) // Connected - { - GetSemaphore(&ConSemaphore, 0); - ChatConnected(conn->BPQStream); - FreeSemaphore(&ConSemaphore); - } - else - { - GetSemaphore(&ConSemaphore, 0); - ChatDisconnected(conn); - FreeSemaphore(&ConSemaphore); - } - } - - ChatDoReceivedData(conn); - } - - return 0; -} - - -BOOL GetChatConfig(char * ConfigName) -{ - config_init(&cfg); - - /* Read the file. If there is an error, report it and exit. */ - - if(! config_read_file(&cfg, ConfigName)) - { - fprintf(stderr, "%d - %s\n", - config_error_line(&cfg), config_error_text(&cfg)); - config_destroy(&cfg); - return(EXIT_FAILURE); - } - - group = config_lookup (&cfg, "Chat"); - - if (group == NULL) - return EXIT_FAILURE; - - ChatApplNum = GetIntValue(group, "ApplNum"); - MaxChatStreams = GetIntValue(group, "MaxStreams"); - reportChatEvents = GetIntValue(group, "reportChatEvents"); - chatPaclen = GetIntValue(group, "chatPaclen"); - GetStringValue(group, "OtherChatNodes", OtherNodesList, 1000); - GetStringValue(group, "ChatWelcomeMsg", ChatWelcomeMsg, 1000); - GetStringValue(group, "MapPosition", Position, 81); - GetStringValue(group, "MapPopup", PopupText, 260); - PopupMode = GetIntValue(group, "PopupMode"); - - if (chatPaclen == 0) - chatPaclen = 236; - - if (chatPaclen < 60) - chatPaclen = 60; - - - return EXIT_SUCCESS; -} - -VOID SaveChatConfigFile(char * ConfigName) -{ - config_setting_t *root, *group; - - // Get rid of old config before saving - - config_init(&cfg); - - root = config_root_setting(&cfg); - - group = config_setting_add(root, "Chat", CONFIG_TYPE_GROUP); - - SaveIntValue(group, "ApplNum", ChatApplNum); - SaveIntValue(group, "MaxStreams", MaxChatStreams); - SaveIntValue(group, "reportChatEvents", reportChatEvents); - SaveIntValue(group, "chatPaclen", chatPaclen); - SaveStringValue(group, "OtherChatNodes", OtherNodesList); - SaveStringValue(group, "ChatWelcomeMsg", ChatWelcomeMsg); - - SaveStringValue(group, "MapPosition", Position); - SaveStringValue(group, "MapPopup", PopupText); - SaveIntValue(group, "PopupMode", PopupMode); - - if(! config_write_file(&cfg, ConfigName)) - { - fprintf(stderr, "Error while writing file.\n"); - config_destroy(&cfg); - return; - } - config_destroy(&cfg); -} - -BOOL ChatInit() -{ - char * ptr1 = GetApplCall(ChatApplNum); - char * ptr2; - char * Context; - int i; - ChatCIRCUIT * conn; - - - if (*ptr1 < 0x21) - { - printf("No APPLCALL for Chat APPL\n"); - return FALSE; - } - - memcpy(OurNode, ptr1, 10); - strlop(OurNode, ' '); - - ptr1 = GetApplAlias(ChatApplNum); - memcpy(OurAlias, ptr1,10); - strlop(OurAlias, ' '); - - if (ChatSYSOPCall[0] == 0) - { - strcpy(ChatSYSOPCall, OurNode); - strlop(ChatSYSOPCall, '-'); - } - - sprintf(ChatSignoffMsg, "73 de %s\r", ChatSYSOPCall); - - if (ChatWelcomeMsg[0] == 0) - sprintf(ChatWelcomeMsg, "%s's Chat Server.$WType /h for command summary.$WBringing up links to other nodes.$W" - "This may take a minute or two.$WThe /p command shows what nodes are linked.$W", ChatSYSOPCall); - - ChatApplMask = 1<<(ChatApplNum-1); - - // Set up other nodes list. rtlink messes with the string so pass copy - - // On first run config will have spaces not newlines - - if (strchr(OtherNodesList, '\r')) // Has connect script entries - { - ptr2 = ptr1 = strtok_s(_strdup(OtherNodesList), "\r\n", &Context); - - while (ptr1 && ptr1[0]) - { - rtlink(ptr1); - ptr1 = strtok_s(NULL, "\r\n", &Context); - } - } - else - { - ptr2 = ptr1 = strtok_s(_strdup(OtherNodesList), " ,\r", &Context); - - while (ptr1) - { - rtlink(ptr1); - ptr1 = strtok_s(NULL, " ,\r", &Context); - } - } - - free(ptr2); - - SetupChat(); - - // Allocate Streams - - strcpy(pgm, "CHAT"); - - for (i = 0; i < MaxChatStreams; i++) - { - conn = &ChatConnections[i]; - conn->BPQStream = FindFreeStream(); - - if (conn->BPQStream == 255) break; - - NumberofChatStreams++; - - SetAppl(conn->BPQStream, 3, ChatApplMask); - Disconnect(conn->BPQStream); - } - - strcpy(pgm, "LINBPQ"); - - return TRUE; -} - -#endif - -void ChatFlush(ChatCIRCUIT * conn) -{ - int tosend, len, sent; - - // Try to send data to user. May be stopped by user paging or node flow control - - // UCHAR * OutputQueue; // Messages to user - // int OutputQueueLength; // Total Malloc'ed size. Also Put Pointer for next Message - // int OutputGetPointer; // Next byte to send. When Getpointer = Quele Length all is sent - free the buffer and start again. - - // BOOL Paging; // Set if user wants paging - // int LinesSent; // Count when paging - // int PageLen; // Lines per page - - - tosend = conn->OutputQueueLength - conn->OutputGetPointer; - - sent = 0; - - while (tosend > 0) - { - if (TXCount(conn->BPQStream) > 4) - return; // Busy - - if (tosend <= conn->paclen) - len = tosend; - else - len=conn->paclen; - - GetSemaphore(&OutputSEM, 0); - - SendUnbuffered(conn->BPQStream, &conn->OutputQueue[conn->OutputGetPointer], len); - - conn->OutputGetPointer += len; - - FreeSemaphore(&OutputSEM); - - tosend -= len; - sent++; - - if (sent > 4) - return; - } - - // All Sent. Free buffers and reset pointers - - ChatClearQueue(conn); -} - -VOID ChatClearQueue(ChatCIRCUIT * conn) -{ - GetSemaphore(&OutputSEM, 0); - - conn->OutputGetPointer = 0; - conn->OutputQueueLength = 0; - - FreeSemaphore(&OutputSEM); -} - -#ifdef LINBPQ -void ChatTrytoSend() -{ - // call Flush on any connected streams with queued data - - ChatCIRCUIT * conn; - - int n; - - for (n = 0; n < NumberofChatStreams; n++) - { - conn = &ChatConnections[n]; - - if (conn->Active == TRUE) - ChatFlush(conn); - } -} - -VOID CloseChat() -{ - int BPQStream, n; - - for (n = 0; n < NumberofChatStreams; n++) - { - BPQStream = ChatConnections[n].BPQStream; - - if (BPQStream) - { - SetAppl(BPQStream, 0, 0); - Disconnect(BPQStream); - DeallocateStream(BPQStream); - } - } - - ClearChatLinkStatus(); - SendChatLinkStatus(); - Sleep(1000); // A bit of time for links to close - SendChatLinkStatus(); // Send again to reduce chance of being missed - FreeChatMemory(); -} - -VOID 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)); - -} - -#endif - - -#ifndef WIN32 -#define INVALID_HANDLE_VALUE (void *)-1 -#endif - -static FILE * LogHandle[4] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; - -static time_t LastLogTime[4] = {0, 0, 0, 0}; - -static char FilesNames[4][100] = {"", "", "", ""}; - -static char * Logs[4] = {"BBS", "CHAT", "TCP", "DEBUG"}; - - -BOOL ChatOpenLogfile(int Flags) -{ - UCHAR FN[MAX_PATH]; - time_t LT; - struct tm * tm; - - LT = time(NULL); - tm = gmtime(<); - - sprintf(FN,"%s/logs/log_%02d%02d%02d_%s.txt", GetLogDirectory(), tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, Logs[Flags]); - - LogHandle[Flags] = fopen(FN, "ab"); - -#ifndef WIN32 - - if (strcmp(FN, &FilesNames[Flags][0])) - { - UCHAR SYMLINK[MAX_PATH]; - - sprintf(SYMLINK,"%s/logLatest_%s.txt", GetBPQDirectory(), Logs[Flags]); - unlink(SYMLINK); - strcpy(&FilesNames[Flags][0], FN); - symlink(FN, SYMLINK); - } - -#endif - - return (LogHandle[Flags] != NULL); -} - -void ChatWriteLogLine(ChatCIRCUIT * conn, int Flag, char * Msg, int MsgLen, int Flags) -{ - char CRLF[2] = {0x0d,0x0a}; - struct tm * tm; - char Stamp[20]; - time_t T; - -#ifndef LINBPQ - - if (hMonitor) - { - if (Flags == LOG_CHAT) - { - WritetoMonitorWindow((char *)&Flag, 1); - - if (conn && conn->Callsign[0]) - { - char call[20]; - sprintf(call, "%s ", conn->Callsign); - WritetoMonitorWindow(call, 10); - } - else - WritetoMonitorWindow(" ", 10); - - WritetoMonitorWindow(Msg, MsgLen); - if (Msg[MsgLen-1] != '\r') - WritetoMonitorWindow(CRLF , 1); - } - else if (Flags == LOG_DEBUGx) - { - WritetoMonitorWindow((char *)&Flag, 1); - WritetoMonitorWindow(Msg, MsgLen); - WritetoMonitorWindow(CRLF , 1); - } - - } - -#endif - - if (Flags == LOG_CHAT && !LogCHAT) - return; - - if (LogHandle[Flags] == INVALID_HANDLE_VALUE) ChatOpenLogfile(Flags); - - if (LogHandle[Flags] == INVALID_HANDLE_VALUE) return; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(Stamp,"%02d%02d%02d %02d:%02d:%02d %c", - tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, Flag); - - fwrite(Stamp, 1, strlen(Stamp), LogHandle[Flags]); - - if (conn && conn->Callsign[0]) - { - char call[20]; - sprintf(call, "%s ", conn->Callsign); - fwrite(call, 1, 10, LogHandle[Flags]); - } - else - fwrite(" ", 1, 10, LogHandle[Flags]); - - fwrite(Msg, 1, MsgLen, LogHandle[Flags]); - - if (Flags == LOG_CHAT && Msg[MsgLen-1] == '\r') - fwrite(&CRLF[1], 1, 1, LogHandle[Flags]); - else - fwrite(CRLF, 1, 2, LogHandle[Flags]); - - fclose(LogHandle[Flags]); - LogHandle[Flags] = INVALID_HANDLE_VALUE; -} - - diff --git a/.svn/pristine/0d/0dfe91be8ae70b991986eaaa9e579a14e878d39f.svn-base b/.svn/pristine/0d/0dfe91be8ae70b991986eaaa9e579a14e878d39f.svn-base deleted file mode 100644 index 0a8bf06..0000000 --- a/.svn/pristine/0d/0dfe91be8ae70b991986eaaa9e579a14e878d39f.svn-base +++ /dev/null @@ -1,1652 +0,0 @@ -#ifndef WINVER // Allow use of features specific to Windows XP or later. -#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. -#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. -#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. -#endif - -#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. -#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. -#endif - - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -#define _CRT_SECURE_NO_DEPRECATE -#define _WINSOCK_DEPRECATED_NO_WARNINGS - -#define LIBCONFIG_STATIC -#include - -#ifndef WIN32 -#include -#endif - -#include "compatbits.h" - -#ifndef LINBPQ -#include "bpq32.h" -#include "BPQMailrc.h" -#include "dbghelp.h" -#else -#include "cheaders.h" -#endif - -#include "asmstrucs.h" - -#define MaxBPQPortNo 63 // Port 64 reserved for BBS Mon -#define MAXBPQPORTS 63 - -#define NEWROUTING - -extern int FOURCHARCONT; - -// Standard __except handler for try/except - -VOID CheckProgramErrors(); -VOID WriteMiniDump(); - -extern int ProgramErrors; - -extern struct _EXCEPTION_POINTERS exinfox; - -#ifdef WIN32 -void Dump_Process_State(struct _EXCEPTION_POINTERS * exinfo, char * Msg); - -#define My__except_Routine(Message) \ -__except(memcpy(&exinfo, GetExceptionInformation(), sizeof(struct _EXCEPTION_POINTERS)), EXCEPTION_EXECUTE_HANDLER)\ -{\ - Debugprintf("MAILCHAT *** Program Error %x at %x in %s EAX %x EBX %x ECX %x EDX %x ESI %x EDI %x",\ - exinfo.ExceptionRecord->ExceptionCode, exinfo.ExceptionRecord->ExceptionAddress, Message,\ - exinfo.ContextRecord->Eax, exinfo.ContextRecord->Ebx, exinfo.ContextRecord->Ecx,\ - exinfo.ContextRecord->Edx, exinfo.ContextRecord->Esi, exinfo.ContextRecord->Edi);\ - CheckProgramErrors();\ - WriteMiniDump();\ -} - - -/* -#define My__except_Routine(Message) \ -__except(memcpy(&exinfox, GetExceptionInformation(), sizeof(struct _EXCEPTION_POINTERS)), EXCEPTION_EXECUTE_HANDLER)\ -{\ - Dump_Process_State(&exinfox, Message);\ - CheckProgramErrors();\ -} - -#define My__except_RoutineWithDisconnect(Message) \ -__except(memcpy(&exinfo, GetExceptionInformation(), sizeof(struct _EXCEPTION_POINTERS)), EXCEPTION_EXECUTE_HANDLER)\ -{\ - Debugprintf("MAILCHAT *** Program Error %x at %x in %s EAX %x EBX %x ECX %x EDX %x ESI %x EDI %x",\ - exinfo.ExceptionRecord->ExceptionCode, exinfo.ExceptionRecord->ExceptionAddress, Message,\ - exinfo.ContextRecord->Eax, exinfo.ContextRecord->Ebx, exinfo.ContextRecord->Ecx,\ - exinfo.ContextRecord->Edx, exinfo.ContextRecord->Esi, exinfo.ContextRecord->Edi);\ - FreeSemaphore(&ChatSemaphore);\ - if (conn->BPQStream < 0)\ - CloseConsole(conn->BPQStream);\ - else\ - Disconnect(conn->BPQStream);\ -} -*/ -#define My_except_RoutineWithDiscBBS(Message) \ -__except(memcpy(&exinfo, GetExceptionInformation(), sizeof(struct _EXCEPTION_POINTERS)), EXCEPTION_EXECUTE_HANDLER)\ -{\ - Debugprintf("MAILCHAT *** Program Error %x at %x in %s EAX %x EBX %x ECX %x EDX %x ESI %x EDI %x",\ - exinfo.ExceptionRecord->ExceptionCode, exinfo.ExceptionRecord->ExceptionAddress, Message,\ - exinfo.ContextRecord->Eax, exinfo.ContextRecord->Ebx, exinfo.ContextRecord->Ecx,\ - exinfo.ContextRecord->Edx, exinfo.ContextRecord->Esi, exinfo.ContextRecord->Edi);\ - if (conn->BPQStream < 0)\ - CloseConsole(conn->BPQStream);\ - else\ - Disconnect(conn->BPQStream);\ - CheckProgramErrors();\ -} -#endif -#define MAXUSERNAMELEN 6 - -#define WSA_ACCEPT WM_USER + 1 -#define WSA_CONNECT WM_USER + 2 -#define WSA_DATA WM_USER + 3 -#define NNTP_ACCEPT WM_USER + 4 -#define NNTP_DATA WM_USER + 5 - -#ifdef _DEBUG - -VOID * _malloc_dbg_trace(int len, int type, char * file, int line); - -#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) -#define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__) -#define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) -#define _recalloc(p, c, s) _recalloc_dbg(p, c, s, _NORMAL_BLOCK, __FILE__, __LINE__) -#define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) -#define free(p) _free_dbg(p, _NORMAL_BLOCK) -#define _strdup(s) _strdup_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) - - -#define zalloc(s) _zalloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) -#else -#define zalloc(s) _zalloc(s) -#endif - -#ifdef LINBPQ - -#undef zalloc -#define zalloc _zalloc - -#endif - -VOID * _zalloc_dbg(size_t len, int type, char * file, int line); - -#define LOG_BBS 0 -#define LOG_CHAT 1 -#define LOG_TCP 2 -#define LOG_DEBUG_X 3 - - -//Chat Duplicate suppression Code - -#define MAXDUPS 10 // Number to keep -#define DUPSECONDS 5 // TIme to Keep - -struct DUPINFO -{ - time_t DupTime; - char DupUser[10]; - char DupText[100]; -}; - - -struct UserRec -{ - char * Callsign; - char * UserName; - char * Password; -}; - - - -typedef struct ConnectionInfo_S -{ - struct ConnectionInfo_S *next; - PROC *proc; - UCHAR RadioOnlyMode; // T or R flag for Radio Only mode. - - int Number; // Number of record - for Connections display - BOOL Active; - int BPQStream; - int paclen; - UCHAR Callsign[11]; // Station call including SSID - BOOL GotHeader; - UCHAR InputMode; // Line by Line or Binary or YAPP - - UCHAR * InputBuffer; - int InputBufferLen; - int InputLen; // Data we have already = Offset of end of an incomplete packet; - - struct UserInfo * UserPointer; - int Retries; - int LoginState; // 1 = user ok, 2 = password ok - int Flags; - - // Data to the user is kept in a malloc'd buffer. This can be appended to, - // and data sucked out under both terminal and system flow control. PACLEN is - // enfored when sending to node. - - UCHAR * OutputQueue; // Messages to user - int OutputQueueLength; // Total Malloc'ed size. Also Put Pointer for next Message - int OutputGetPointer; // Next byte to send. When Getpointer = Queue Length all is sent - free the buffer and start again. - - int CloseAfterFlush; // Close session when all sent. Set to 100ms intervals to wait. - - int ErrorCount; // Invalid Command count - BOOL Paging; // Set if user wants paging - int LinesSent; // Count when paging - int PageLen; // Lines per page - - UCHAR * MailBuffer; // Mail Message being received - UCHAR * CopyBuffer; // Mail Message being forwarded - int MailBufferSize; // Total Malloc'ed size. Actual size in in Msg Struct - - long lastmsg; // Last Listed. Stored here, updated in user record only on clean close - BOOL sysop; // Set if user is authenticated as a sysop - BOOL Secure_Session; // Set if Local Terminal, or Telnet connect with SYSOP status - UINT BBSFlags; // Set if defined as a bbs and SID received - struct MsgInfo * TempMsg; // Header while message is being received - struct MsgInfo * FwdMsg; // Header while message is being forwarded - - char ** To; // May be several Recipients - int ToCount; - - int BBSNumber; // The BBS number (offset into bitlist of BBSes to forward a message to - int NextMessagetoForward; // Next index to check in forward cycle - BOOL BPQBBS; // Set if SID indicates other end is BPQ - char MSGTYPES[20]; // Any MSGTYPEFLAGS - BOOL SendT; // Send T messages - BOOL SendP; // Send P messages - BOOL SendB; // Send Bulls - BOOL SendWL2KFW; // send ;FW: - int MaxBLen; // Max Size for this session - int MaxPLen; // Max Size for this session - int MaxTLen; // Max Size for this session - BOOL DoReverse; // Request Reverse Forward - char LastForwardType; // Last type of messages forwarded - struct FBBHeaderLine * FBBHeaders; // The Headers from an FFB forward block - char FBBReplyChars[36]; //The +-=!nnnn chars for the 5 proposals - int FBBReplyIndex; // current Reply Pointer - int FBBIndex; // current propopsal number - int RestartFrom; // Restart position - BOOL NeedRestartHeader; // Set if waiting for 6 byte restart header - BOOL DontSaveRestartData; // Set if corrupt data received - BOOL FBBMsgsSent; // Messages need to be maked as complete when next command received - UCHAR FBBChecksum; // Header Checksum - BOOL OpenBCM; // OpenBCM mode (escape -xFF chars) - BOOL InTelnetExcape; // Last Char was 0xff - BOOL LocalMsg; // Set if current Send command is for a local user - BOOL NewUser; // Set if first time user has accessed BBS - BOOL Paclink; // Set if receiving messages from Paclink - BOOL RMSExpress; // Set if receiving messages from RMS Express - BOOL WL2K; // Set if communicating with a CMS - BOOL PAT; // Set if communicating with PAT - char ** PacLinkCalls; // Calls we are getting messages for - BOOL SkipPrompt; // Set if a remote node sends a > at the end of his CTEXT - BOOL SkipConn; // Node sends "connected" in its CTEXT - int Watchdog; // Hung Circuit Detect. - int SessType; // BPQ32 sesstype bits - -#define Sess_L2LINK 1 -#define Sess_SESSION 2 -#define Sess_UPLINK 4 -#define Sess_DOWNLINK 8 -#define Sess_BPQHOST 0x20 -#define Sess_PACTOR 0x40 - - HANDLE DebugHandle; // File Handle for session-based debugging - - char ARQFilename[256]; // Filename from ARQ:FILE:: Header - int ARQClearCount; // To make sure queues are flushed when sending - - int SIDResponseTimer; // Used to detect incomplete handshake - - char PQChallenge[20]; // Secure User logon challange - char SecureMsg[20]; // CMS Secure Signon Response - int MCastListenTime; // Time to run session for - - int YAPPLen; // Bytes sent/received of YAPP Message - long YAPPDate; // Date for received file - if set enables YAPPC - - int SyncCompressedLen; - int SyncXMLLen; - int SyncMsgLen; - char * SyncHost; // Saved so can send "request sync" - int SyncPort; - UCHAR * SyncMessage; // Compressed SYNC message to send - - // These are used to detect CRLF split over a packet boundary - int usingCR; // Session is (normally) using CR as terminator - int lastLineEnd; // Terminator for current line - - struct ConnectionInfo_S * SysopChatStream; // Stream sysop is chatting to - -} ConnectionInfo, CIRCUIT; - -// Flags Equates - -#define GETTINGUSER 1 -#define GETTINGBBS 2 -#define CHATMODE 4 -#define GETTINGTITLE 8 -#define GETTINGMESSAGE 16 -#define CHATLINK 32 // Link to another Chat Node -#define SENDTITLE 64 -#define SENDBODY 128 -#define WAITPROMPT 256 // Waiting for prompt after message -#define PROPOSINGSYNCMSG 512 // Sent proposal to SYNC, waiting response -#define SENDINGSYNCMSG 1024 // Sent message to SYNC, waiting response -#define REQUESTINGSYNC 2048 -#define GETTINGSYNCMESSAGE 4096 // Receiving body of a SYNC message - -// BBSFlags Equates - -#define BBS 1 -#define FBBForwarding 2 -#define FBBCompressed 4 -#define FBBB1Mode 8 -#define FBBB2Mode 16 -#define RunningConnectScript 32 -#define MBLFORWARDING 64 // MBL Style Frwarding- waiting for OK/NO or Prompt following message -#define TEXTFORWARDING 128 // Plain Text forwarding -#define OUTWARDCONNECT 256 // We connected to them -#define FLARQMODE 512 // Message from FLARQ -#define FLARQMAIL 1024 // Sending FLARQ Format Message -#define ARQMAILACK 2048 // Waiting for all data to be acked -#define NEEDLF 4096 // Add LF to forward script commands (fro Telnet -#define MCASTRX 8192 // Stream in Multicast RX Mode -#define DISCONNECTING 16384 // Disconnect sent to Node -#define YAPPTX 0x008000 // Sending YAPP file -#define SYSOPCHAT 0x010000 // Chatting to BBS console -#define WINLINKRO 0x020000 // WL2K RO (no J in SID) -#define SYNCMODE 0x040000 // RMS RELAY SYNC -#define MFJMODE 0x080000 // MFJ PMS -#define NEWPACCOM 0x100000 // PACCOM PMS 3.2 -#define SETCALLTOSENDER 0x200000 // Set calling call to message sender - - -struct FBBRestartData -{ - struct MsgInfo * TempMsg; // Header while message is being received - struct UserInfo * UserPointer; - UCHAR * MailBuffer; // Mail Message being received - int MailBufferSize; // Total Malloc'ed size. Actual size in in Msg Struct - int Count; // Give up if too many restarts -}; - -// We need to keep the B2Message file for B2 messages we are sending until the messages is acked, so -// we can restart it. Otherwise the file may change, resulting in a checksum error - - -struct B2RestartData -{ - int CSize; // Compresses Size (B2 proto) - UCHAR * CompressedMsg; // Compressed Body fo B2 - struct MsgInfo * FwdMsg; - struct UserInfo * UserPointer; - int Count; // Give up if too many restarts -}; - -//------ TAJ ----- -typedef struct PGARGS -{ - CIRCUIT * conn; - struct UserInfo * user; - char InputBuffer[80]; - int Len; -}RUNPGARGS, *RUNPGARGS_PTR; - -//--------------- - -#pragma pack(1) - -struct TempUserInfo -{ - int LastAuthCode; // Protect against playback attack - - // Fields used to allow interrupting and resuming a paged listing - - BOOL ListActive; // Doing a list - BOOL ListSuspended; // Paused doing a list - int LastListedInPagedMode; - char LastListCommand[80]; - char LastListParams[80]; - int LinesSent; - char SendFullFrom; - char ListType; - char ListDirn; - char ListStatus; - char ListSelector; // < > @ etc - - int ListRangeStart; - int ListRangeEnd; - int LLCount; // Number still to send in List Last N - int UpdateLatest; // if set, save last listed as latest - BOOL IncludeKilled; // Show Killed Messages if SYSOP - //--- TAJ --- - int PG_INDEX; // current index of PG server - int PG_SERVER; // PG server to run - RUNPGARGS_PTR RUNPGPARAMS; // pointer to RUNPGARGS for dealloc - //----------- -}; - -#define PMSG 1 -#define BMSG 2 -#define TMSG 3 - -struct OldUserInfo -{ - // Old format - without message type specific traffic counts - - char Call[10]; // Connected call without SSID -// indicat relai[8]; /* 64 Digis path */ - int lastmsg; /* 4 Last L number */ - int ConnectsIn; /* 4 Number of connexions in*/ - int TimeLastConnected; //Last connexion date */ -// long lastyap __a2__ ; /* 4 Last YN date */ - ULONG flags ; /* 4 Flags */ - - UCHAR PageLen; // Lines Per Page - UCHAR lang ; /* 1 Language */ - - int Xnewbanner; /* 4 Last Banner date */ - short Xdownload ; /* 2 download size (KB) = 100 */ - char POP3Locked ; // Nonzero if POP3 server has locked this user (stops other pop3 connections, or BBS user killing messages) - char BBSNumber; // BBS Bitmap Index Number - struct BBSForwardingInfo * ForwardingInfo; - struct UserInfo * BBSNext; // links BBS record - struct TempUserInfo * Temp; // Working Fields - not saved in user file - char xfree[6]; /* 6 Spare */ - char Xtheme; /* 1 Current topic */ - - char Name[18]; /* 18 1st Name */ - char Address[61]; /* 61 Address */ - - // Stats. Was City[31]; /* 31 City */ - - int MsgsReceived; - int MsgsSent; - int MsgsRejectedIn; // Messages we reject - int MsgsRejectedOut; // Messages Rejectd by other end - int BytesForwardedIn; - int BytesForwardedOut; - int ConnectsOut; // Forwarding Connects Out - - USHORT RMSSSIDBits; // SSID's to poll in RMS - - char Spare1; - - char HomeBBS[41]; /* 41 home BBS */ - char QRA[7]; /* 7 Qth Locator */ - char pass[13]; /* 13 Password */ - char ZIP[9]; /* 9 Zipcode */ - BOOL spare; -} ; /* Total : 360 bytes */ - -struct MsgStats -{ - int ConnectsIn; /* 4 Number of connexions in*/ - int ConnectsOut; // Forwarding Connects Out - - // Stats saveed by message type - - int MsgsReceived[4]; - int MsgsSent[4]; - int MsgsRejectedIn[4]; // Messages we reject - int MsgsRejectedOut[4]; // Messages Rejectd by other end - int BytesForwardedIn[4]; - int BytesForwardedOut[4]; -}; - -struct UserInfo -{ - // New Format - with stats maintained by message type and unused fields removed. - - // This is no longer a fixed length record so can't be saved as a binarl - - char Call[10]; // Connected call without SSID - - int Length; // To make subsequent format changes easier - - int lastmsg; /* 4 Last L number */ - int xTimeLastConnected; //Last connexion date */ - ULONG flags ; /* 4 Flags */ - - UCHAR PageLen; // Lines Per Page - - char POP3Locked ; // Nonzero if POP3 server has locked this user (stops other pop3 connections, or BBS user killing messages) - unsigned char BBSNumber; // BBS Bitmap Index Number - struct BBSForwardingInfo * ForwardingInfo; - struct UserInfo * BBSNext; // links BBS record - struct TempUserInfo * Temp; // Working Fields - not saved in user file - char Name[18]; /* 18 1st Name */ - char Address[61]; /* 61 Address */ - - USHORT RMSSSIDBits; // SSID's to poll in RMS - - char HomeBBS[41]; /* 41 home BBS */ - char QRA[7]; /* 7 Qth Locator */ - char pass[13]; /* 13 Password */ - char ZIP[9]; /* 9 Zipcode */ - - struct MsgStats Total; - struct MsgStats Last; - - char CMSPass[16]; // For Secure Signon - int WebSeqNo; - - long long TimeLastConnected; //Last connection date */ - - char Filler[44 - 8]; // So we can add a few fields wirhout another resize -}; - -// flags equates - -#define F_Excluded 0x0001 -#define F_GGG 0x0002 -#define F_Expert 0x0004 -#define F_SYSOP 0x0008 -#define F_BBS 0x0010 -#define F_RMSREDIRECT 0x0020 -#define F_BBB 0x0040 -#define F_CCC 0x0080 -#define F_DDD 0x0100 -#define F_EEE 0x0200 -#define F_FFF 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 // "Winlink Express User" -#define F_NOWINLINK 0x00020000 // Don't add Winlink.org -#define F_NOBULLS 0x00040000 -#define F_NTSMPS 0x00080000 -#define F_APRSMFOR 0x00100000 // Send APRS message for new mail -#define F_APRSSSID 0xF0000000 // (Top 4 Bits - - -struct Override -{ - char * Call; - int Days; -}; - -struct ALIAS -{ - char * Alias; - char * Dest; -}; - -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 DIGIS[56]; // Padding in case we have digis - -}MESSAGEX, *PMESSAGEX; - - -#pragma pack() - -// Message Database Entry. Designed to be compatible with FBB - -#define NBBBS 160 // Max BBSes we can forward to. Must be Multiple of 8, and must be 80 for FBB compatibliliy -#define NBMASK NBBBS/8 // Number of bytes in Forward bitlists. - -#pragma pack(1) - -struct OldMsgInfo -{ - char type ; - char status ; - int number ; - int length ; - int datereceived; - char bbsfrom[7] ; // ? BBS we got it from ? - char via[41] ; - char from[7] ; - char to[7] ; - char bid[13] ; - char title[61] ; - char bin; - int nntpnum; // Number within topic (ie Bull TO Addr) - used for nntp - - UCHAR B2Flags; - - char free[4]; - unsigned short nblu; - int theme ; - time_t datecreated ; - time_t datechanged ; - char fbbs[10] ; - char forw[10] ; - char emailfrom[41]; -} ; - - -struct MsgInfo -{ - char type; - char status; - int number; - int length; - int xdatereceived; - char bbsfrom[7]; // ? BBS we got it from ? - char via[41]; - char from[7]; - char to[7]; - char bid[13]; - char title[61]; - int nntpnum; // Number within topic (ie Bull TO Addr) - used for nntp - - UCHAR B2Flags; // Not all flags specific to B2 - - #define B2Msg 1 // Set if Message File is a formatted B2 message - #define Attachments 2 // Set if B2 message has attachments - #define FromPaclink 4 - #define FromCMS 8 - #define FromRMSExpress 16 - #define RadioOnlyMsg 32 // Received using call-T - #define RadioOnlyFwd 64 // Received using call-R - #define WarnNotForwardedSent 128 - - int xdatecreated; - int xdatechanged; - UCHAR fbbs[NBMASK]; - UCHAR forw[NBMASK]; - char emailfrom[41]; - char Locked; // Set if selected for sending (NTS Pickup) - char Defered; // FBB response '=' received - UCHAR UTF8; // Set if Message is in UTF8 (ie from POP/SMTP) - -// For 64 bit time_t compatibility define as long long -// (so struct is same with 32 or 64 bit time_t) - - int64_t datereceived; - int64_t datecreated; - int64_t datechanged; - - char Spare[61 - 24]; // For future use -} ; - -#define MSGTYPE_B 0 -#define MSGTYPE_P 1 - -#define MSGSTATUS_N 0 -#define MSGSTATUS_Y 1 -#define MSGSTATUS_F 2 -#define MSGSTATUS_K 3 -#define MSGSTATUS_H 4 -#define MSGSTATUS_D 5 -#define MSGSTATUS_$ 6 - -struct NNTPRec -{ - // Used for NNTP access to Bulls - - struct NNTPRec * Next; // Record held in chain, so can be held sorted - char NewsGroup[64]; // = Bull TO.at field - int FirstMsg; // Lowest Number - int LastMsg; // Highest Number - int Count; // Active Msgs - time_t DateCreated; // COntains Creation Date of First Bull in Group -}; - - -typedef struct { - char mode; - char BID[13]; - union - { /* array named screen */ - struct - { - unsigned short msgno; - unsigned short timestamp; - }; - CIRCUIT * conn; - } u; -} BIDRec, *BIDRecP; - - -typedef struct WPDBASE{ /* 194 bytes */ - char callsign[7]; - char name[13]; - unsigned char Type; - unsigned char changed; - unsigned short seen; - long long last_modif; - long long last_seen; - char first_homebbs[41]; - char secnd_homebbs[41]; - char first_zip[9]; - char secnd_zip[9]; - char first_qth[31]; - char secnd_qth[31]; -} WPRec, * WPRecP; - -#pragma pack() - -struct FWDBAND -{ - time_t FWDStartBand; - time_t FWDEndBand; -}; - - - -struct BBSForwardingInfo -{ - // Holds info for forwarding - - BOOL Enabled; // Forwarding Enabled - char ** ConnectScript; // Main Connect Script - char ** TempConnectScript; // Used with FWD command. - int ScriptIndex; // Next line in script - BOOL MoreLines; // Set until script is finsihed - - char ** TOCalls; // Calls in to field - char ** ATCalls; // Calls in ATBBS field - char ** HaddressesP; // Heirarchical Addresses for Personals to forward to (as stored) - char *** HADDRSP; // Heirarchical Addresses for Personals to forward to - char ** Haddresses; // Heirarchical Addresses to forward to (as stored) - char *** HADDRS; // Heirarchical Addresses to forward to - int * HADDROffet; // Elements added to complete the HR. At least n+1 must match to forward - char ** FWDTimes; // Time bands to forward - struct FWDBAND ** FWDBands; - int MsgCount; // Messages for this BBS - BOOL ReverseFlag; // Set if BBS wants to poll for reverse forwarding - BOOL Forwarding; // Forward in progress - int MaxFBBBlockSize; - BOOL AllowBlocked; // Allow FBB Blocked - BOOL AllowCompressed; // Allow FBB Compressed - BOOL AllowB1; // Enable B1 - BOOL AllowB2; // Enable B2 - BOOL SendCTRLZ; // Send Ctrl/z instead of /ex - BOOL PersonalOnly; // Only Forward Personals - BOOL SendNew; // Forward new messages immediately - int FwdInterval; - int RevFwdInterval; - int FwdTimer; - time_t LastReverseForward; - char *BBSHA; // HA of BBS - char ** BBSHAElements; // elements of HA of BBS - int ConTimeout; -// char UserCall[10]; // User we are forwarding on behalf of (Currently only for RMS) -// int UserIndex; // index of User we are forwarding on behalf of (Currently only for RMS) -}; - - -struct FBBHeaderLine -{ - // Holds the info from the (up to) 5 headers presented at the start of a Forward Block - - char Format; // Ascii or Binary - char MsgType; // P B etc - char From[7]; // Sender - char ATBBS[41]; // BBS of recipient (@ Field) - char To[7]; // Recipient - char BID[13]; - int Size; - int CSize; // Compresses Size (B2 proto) - BOOL B2Message; // Set if an FC type - UCHAR * CompressedMsg; // Compressed Body fo B2 - struct MsgInfo * FwdMsg; // Header so we can mark as complete -}; - -#define MAXSTACK 20 -//#define MAXLINE 10000 -#define INPUTLEN 512 - -#define MAXLINES 1000 -#define LINELEN 200 - -extern char RTFHeader[4000]; -extern int RTFHddrLen; - -struct ConsoleInfo -{ - struct ConsoleInfo * next; - CIRCUIT * Console; - int BPQStream; - WNDPROC wpOrigInputProc; - HWND hConsole; - HWND hwndInput; - HWND hwndOutput; - HMENU hMenu; // handle of menu - RECT ConsoleRect; - RECT OutputRect; - - int Height, Width, LastY; - - int ClientHeight, ClientWidth; - char kbbuf[INPUTLEN]; - int kbptr; - - char * readbuff; // Malloc'ed - int readbufflen; // Current Length - char * KbdStack[MAXSTACK]; - - int StackIndex; - - BOOL Bells; - BOOL FlashOnBell; // Flash instead of Beep - BOOL StripLF; - - BOOL WarnWrap; - BOOL FlashOnConnect; - BOOL WrapInput; - BOOL CloseWindowOnBye; - - unsigned int WrapLen; - int WarnLen; - int maxlinelen; - - int PartLinePtr; - int PartLineIndex; // Listbox index of (last) incomplete line - - DWORD dwCharX; // average width of characters - DWORD dwCharY; // height of characters - DWORD dwClientX; // width of client area - DWORD dwClientY; // height of client area - DWORD dwLineLen; // line length - int nCaretPosX; // horizontal position of caret - int nCaretPosY; // vertical position of caret - - COLORREF FGColour; // Text Colour - COLORREF BGColour; // Background Colour - COLORREF DefaultColour; // Default Text Colour - - int CurrentLine; // Line we are writing to in circular buffer. - - int Index; - BOOL SendHeader; - BOOL Finished; - - char OutputScreen[MAXLINES][LINELEN]; - - int Colourvalue[MAXLINES]; - int LineLen[MAXLINES]; - - int CurrentColour; - int Thumb; - int FirstTime; - BOOL Scrolled; // Set if scrolled back - int RTFHeight; // Height of RTF control in pixels - -}; - - -struct MSESSION -{ - struct MSESSION * Next; - unsigned int Key; - char * FileName; - char * OrigTimeStamp; - unsigned char * Message; - int MessageLen; - unsigned char * BlockList; - char * ID; - int BlockSize; - int BlockCount; - int BlocksReceived; - BOOL Completed; - time_t Created; - time_t LastUpdated; - int Index; // Line in Display -}; - -VOID __cdecl nprintf(CIRCUIT * conn, const char * format, ...); -char * strlop(char * buf, char delim); -int rt_cmd(CIRCUIT *circuit, char * Buffer); -CIRCUIT *circuit_new(CIRCUIT *circuit, int flags); -VOID BBSputs(CIRCUIT * conn, char * buf); -VOID FBBputs(CIRCUIT * conn, char * buf); -void makelinks(void); -VOID * _zalloc(size_t len); -VOID FreeChatMemory(); -VOID ChatTimer(); -VOID nputs(CIRCUIT * conn, char * buf); -VOID node_close(); -VOID removelinks(); -VOID SetupChat(); -VOID SendChatLinkStatus(); -VOID ClearChatLinkStatus(); -VOID Send_MON_Datagram(UCHAR * Msg, DWORD Len); - -#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) - -int EncryptPass(char * Pass, char * Encrypt); -VOID DecryptPass(char * Encrypt, unsigned char * Pass, unsigned int len); - -// TCP Connections. FOr the moment SMTP or POP3 - -typedef struct SocketConnectionInfo -{ - struct SocketConnectionInfo * Next; - int Number; // Number of record - for Connections display - SOCKET socket; - SOCKADDR_IN sin; - int Type; // SMTP or POP3 - BOOL AMPR; // Set if sending to an AMPR.ORG server - char FromDomain[50]; // Domain we are sending from - struct UserInfo * bbs; // BBS dor forwarding to AMPR - int State; // Transaction State Machine - UCHAR CallSign[10]; - UCHAR TCPBuffer[3000]; // For converting byte stream to messages - int InputLen; // Data we have alreasdy = Offset of end of an incomplete packet; - - char * MailFrom; // Envelope Sender and Receiver - char ** RecpTo; // May be several Recipients - int Recipients; - - UCHAR * MailBuffer; // Mail Message being received. malloc'ed as needed - int MailBufferSize; // Total Malloc'ed size. Actual size is in MailSize - int MailSize; - int Flags; - - struct UserInfo * POP3User; - struct MsgInfo ** POP3Msgs; // Header List of messages for this uaer - int POP3MsgCount; // No of Messages - int POP3MsgNum; // Sequence number of message being received - - struct MsgInfo * SMTPMsg; // message for this SMTP connection - - UCHAR * SendBuffer; // Message being sent if socket is busy. malloc'ed as needed - int SendBufferSize; // Total Malloc'ed size. Actual size is in MailSize - int SendSize; // Bytes in buffer - int SendPtr; // next byte to send when ready - - struct NNTPRec * NNTPGroup; // Currently Selected Group - int NNTPNum; // Currenrly Selected Msg Number - int Timeout; // Used to close a session that is open too long - -} SocketConn; - -// FBB reject.sys like filters - -typedef struct FBBFILTER -{ - struct FBBFILTER * Next; - char Action; - char Type; - char From[10]; - char AT[10]; - char TO[10]; - char BID[16]; - int MaxLen; - -} FBBFilter; - -extern FBBFilter * Filters; - -typedef struct KEYVALUES -{ - char * Key; - char * Value; -} KeyValues; - -typedef struct WEBMAILINFO -{ - // Info for HTML Forms Processing - - struct HtmlFormDir * Dir; // HTML Directory - char * txtFileName; // Template Name for current message - char * InputHTMLName; // Template to input message - char * DisplayHTMLName; // Template to display message - char * ReplyHTMLName; // Template for replying to message - char * txtFile; // Template data - char * OrigTo; // To field when template loaded - char * OrigSubject; // Subject field when template loaded - char * OrigBody; // Msg text when template loaded - char * OrigBID; - char OrigType; - char * To; - char * CC; - char * Subject; - char * Body; - char * BID; - char Type; - struct MsgInfo * Msg; // Msg record if replying - KeyValues txtKeys[1000]; // Key/Value pairs for txt template. Used when creating or displaying - KeyValues XMLKeys[1000]; // Key/Value pairs from XML attachment - BOOL isReply; - char * XMLName; - char * XML; // XML attachment - int XMLLen; - int Files; - char * FileName[100]; // Attachments - char * FileBody[100]; - int FileLen[100]; - - char * Header; - int HeaderLen; - - char * Footer; - int FooterLen; - - char * Reply; // put in here to save passing lots of parameters - int * RLen; - - BOOL Winlink; - BOOL P2P; - BOOL Packet; - - int CurrentMessageIndex; // Index of message currently displayed (for Prev and Next) -#ifdef WIN32 - void * iconv_toUTF8; // Used on Linux for char set conversion -#else - iconv_t * iconv_toUTF8; // Used on Linux for char set conversion -#endif - -}WebMailInfo; - -#define SMTPServer 1 -#define POP3SLAVE 2 -#define SMTPClient 3 -#define POP3Client 4 -#define NNTPServer 5 - -// State Values - -#define GettingUser 1 -#define GettingPass 2 -#define Authenticated 4 - -#define Connecting 8 - -// SMTP Master - -#define WaitingForGreeting 16 -#define WaitingForHELOResponse 32 -#define WaitingForFROMResponse 64 -#define WaitingForTOResponse 128 -#define WaitingForDATAResponse 256 -#define WaitingForBodyResponse 512 -#define WaitingForAUTHResponse 1024 - -// POP3 Master - -#define WaitingForUSERResponse 32 -#define WaitingForPASSResponse 64 -#define WaitingForSTATResponse 128 -#define WaitingForUIDLResponse 256 -#define WaitingForLISTResponse 512 -#define WaitingForRETRResponse 512 -#define WaitingForDELEResponse 1024 -#define WaitingForQUITResponse 2048 - - -#define SE 240 // End of subnegotiation parameters -#define NOP 241 //No operation -//#define DM 242 //Data mark Indicates the position of a Synch event within the data stream. This should always be accompanied by a TCP urgent notification. -#define BRK 243 //Break Indicates that the "break" or "attention" key was hi. -#define IP 244 //Suspend Interrupt or abort the process to which the NVT is connected. -#define AO 245 //Abort output Allows the current process to run to completion but does not send its output to the user. -#define AYT 246 //Are you there Send back to the NVT some visible evidence that the AYT was received. -#define EC 247 //Erase character The receiver should delete the last preceding undeleted character from the data stream. -#define EL 248 //Erase line Delete characters from the data stream back to but not including the previous CRLF. -#define GA 249 //Go ahead Under certain circumstances used to tell the other end that it can transmit. -#define SB 250 //Subnegotiation Subnegotiation of the indicated option follows. -#define WILL 251 //will Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option. -#define WONT 252 //wont Indicates the refusal to perform, or continue performing, the indicated option. -#define DOx 253 //do Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option. -#define DONT 254 //dont Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option. -#define IAC 255 - -#define suppressgoahead 3 //858 -//#define Status 5 //859 -//#define echo 1 //857 -#define timingmark 6 //860 -#define terminaltype 24 //1091 -#define windowsize 31 //1073 -#define terminalspeed 32 //1079 -#define remoteflowcontrol 33 //1372 -#define linemode 34 //1184 -#define environmentvariables 36 //1408 - -BOOL Initialise(); -#ifdef WIN32 -INT_PTR CALLBACK ConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); -#endif -int DisplaySessions(); -int DoStateChange(int Stream); -int DoReceivedData(int Stream); -int DoBBSMonitorData(int Stream); -int Connected(int Stream); -int Disconnected(int Stream); -//int Socket_Accept(int SocketId); -//int Socket_Data(int SocketId,int error, int eventcode); -int DataSocket_Read(SocketConn * sockptr, SOCKET sock); -int DataSocket_Write(SocketConn * sockptr, SOCKET sock); -int DataSocket_Disconnect(SocketConn * sockptr); -int RefreshMainWindow(); -int Terminate(); -int SendtoSocket(SOCKET sock,char * Msg); -int WriteLog(char * msg); -int ConnectState(int Stream); -UCHAR * EncodeCall(UCHAR * Call); -int ParseIniFile(char * fn); -struct UserInfo * AllocateUserRecord(char * Call); -struct MsgInfo * AllocateMsgRecord(); -BIDRec * AllocateBIDRecord(); -BIDRec * AllocateTempBIDRecord(); -struct UserInfo * LookupCall(char * Call); -BIDRec * LookupBID(char * BID); -BIDRec * LookupTempBID(char * BID); -VOID RemoveTempBIDS(CIRCUIT * conn); -VOID SaveUserDatabase(); -VOID GetUserDatabase(); -VOID GetMessageDatabase(); -VOID SaveMessageDatabase(); -VOID GetBIDDatabase(); -VOID SaveBIDDatabase(); -VOID GetWPDatabase(); -VOID CopyWPDatabase(); -VOID SaveWPDatabase(); -VOID GetBadWordFile(); -WPRec * LookupWP(char * Call); -VOID SendWelcomeMsg(int Stream, ConnectionInfo * conn, struct UserInfo * user); -VOID ProcessLine(ConnectionInfo * conn, struct UserInfo * user, char* Buffer, int len); -VOID ProcessChatLine(ConnectionInfo * conn, struct UserInfo * user, char* Buffer, int len); -VOID SendPrompt(ConnectionInfo * conn, struct UserInfo * user); -int QueueMsg( ConnectionInfo * conn, char * msg, int len); -VOID SendUnbuffered(int stream, char * msg, int len); -//int GetFileList(char * Dir); -BOOL ListMessage(struct MsgInfo * Msg, ConnectionInfo * conn, struct TempUserInfo * Temp); -void DoDeliveredCommand(CIRCUIT * conn, struct UserInfo * user, char * Cmd, char * Arg1, char * Context); -void DoKillCommand(ConnectionInfo * conn, struct UserInfo * user, char * Cmd, char * Arg1, char * Context); -void DoListCommand(ConnectionInfo * conn, struct UserInfo * user, char * Cmd, char * Arg1, BOOL Resuming, char * Context); -void DoReadCommand(ConnectionInfo * conn, struct UserInfo * user, char * Cmd, char * Arg1, char * Context); -void KillMessage(ConnectionInfo * conn, struct UserInfo * user, int msgno); -int KillMessagesTo(ConnectionInfo * conn, struct UserInfo * user, char * Call); -int KillMessagesFrom(ConnectionInfo * conn, struct UserInfo * user, char * Call); -void DoUnholdCommand(CIRCUIT * conn, struct UserInfo * user, char * Cmd, char * Arg1, char * Context); - -VOID FlagAsKilled(struct MsgInfo * Msg, BOOL SaveDB); -int ListMessagesFrom(ConnectionInfo * conn, struct UserInfo * user, char * Call, BOOL SendFullFrom, int Start); -int ListMessagesTo(ConnectionInfo * conn, struct UserInfo * user, char * Call, BOOL SendFullFrom, int Start); -int ListMessagesAT(ConnectionInfo * conn, struct UserInfo * user, char * Call, BOOL SendFullFrom, int Start); -void ListMessagesInRange(ConnectionInfo * conn, struct UserInfo * user, char * Call, int Start, int End, BOOL SendFullFrom ); -void ListMessagesInRangeForwards(ConnectionInfo * conn, struct UserInfo * user, char * Call, int Start, int End, BOOL SendFullFrom ); -int GetUserMsg(int m, char * Call, BOOL SYSOP); -void Flush(ConnectionInfo * conn); -VOID ClearQueue(ConnectionInfo * conn); -void TrytoSend(); -void ReadMessage(ConnectionInfo * conn, struct UserInfo * user, int msgno); -struct MsgInfo * FindMessage(char * Call, int msgno, BOOL sysop); -char * ReadMessageFile(int msgno); -char * ReadInfoFile(char * File); -char * FormatDateAndTime(time_t Datim, BOOL DateOnly); -int CriticalErrorHandler(char * error); -BOOL DoSendCommand(ConnectionInfo * conn, struct UserInfo * user, char * Cmd, char * Arg1, char * Context); -BOOL CreateMessage(ConnectionInfo * conn, char * From, char * ToCall, char * ATBBS, char MsgType, char * BID, char * Title); -VOID ProcessMsgTitle(ConnectionInfo * conn, struct UserInfo * user, char* Buffer, int len); -VOID ProcessMsgLine(CIRCUIT * conn, struct UserInfo * user, char* Buffer, int len); -VOID CreateMessageFile(ConnectionInfo * conn, struct MsgInfo * Msg); -int ProcessConnecting(CIRCUIT * circuit, char * Buffer, int Len); -VOID SaveConfig(char * ConfigName); -BOOL GetConfig(char * ConfigName); -int GetIntValue(config_setting_t * group, char * name); -//BOOL GetStringValue(config_setting_t * group, char * name, char * value, int maxlen); -BOOL GetConfigFromRegistry(); -VOID Parse_SID(CIRCUIT * conn, char * SID, int len); -VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int len); -VOID ProcessFBBLine(ConnectionInfo * conn, struct UserInfo * user, UCHAR * Buffer, int len); -VOID SetupNextFBBMessage(CIRCUIT * conn); -BOOL DecodeSendParams(CIRCUIT * conn, char * Context, char ** From, char * To, char ** ATBBS, char ** BID); -int PrintMessages(HWND hDlg, int Count, int * Indexes); -int check_fwd_bit(char *mask, int bbsnumber); -void set_fwd_bit(char *mask, int bbsnumber); -void clear_fwd_bit (char *mask, int bbsnumber); -VOID SetupForwardingStruct(struct UserInfo * user); -BOOL Forward_Message(struct UserInfo * user, struct MsgInfo * Msg); -VOID StartForwarding (int BBSNumber, char ** TempScript); -BOOL Reverse_Forward(); -int ProcessBBSConnectScript(CIRCUIT * conn, char * Buffer, int len); -BOOL FBBDoForward(CIRCUIT * conn); -BOOL FindMessagestoForward(CIRCUIT * conn); -BOOL SeeifMessagestoForward(int BBSNumber, CIRCUIT * Conn); -int CountMessagestoForward(struct UserInfo * user); -int CountBytestoForward(struct UserInfo * user); - -VOID * GetMultiLineDialogParam(HWND hDialog, int DLGItem); - - -VOID * GetMultiStringValue(config_setting_t * hKey, char * ValueName); -VOID * RegGetMultiStringValue(HKEY hKey, char * ValueName); - -int MultiLineDialogToREG_MULTI_SZ(HWND hWnd, int DLGItem, HKEY hKey, char * ValueName); -int Do_BBS_Sel_Changed(HWND hDlg); -VOID FreeForwardingStruct(struct UserInfo * user); -VOID FreeList(char ** Hddr); -int Do_User_Sel_Changed(HWND hDlg); -int Do_Msg_Sel_Changed(HWND hDlg); -VOID Do_Save_Msg(); -VOID Do_Add_User(HWND hDlg); -VOID Do_Delete_User(HWND hDlg); -VOID FlagSentMessages(CIRCUIT * conn, struct UserInfo * user); -VOID HoldSentMessages(CIRCUIT * conn, struct UserInfo * user); -VOID Do_Save_User(HWND hDlg, BOOL ShowBox); -VOID DeleteBBS(struct UserInfo * user); -VOID SaveBBSConfig(); -BOOL GetChatConfig(char * ConfigName); -VOID SaveChatConfig(); -VOID SaveISPConfig(); -VOID SaveFWDConfig(); -VOID SaveMAINTConfig(); -VOID SaveWelcomeMsgs(); -VOID SavePrompts(); -VOID ReinitializeFWDStruct(struct UserInfo * user); -VOID CopyBIDDatabase(); -VOID CopyMessageDatabase(); -VOID CopyUserDatabase(); -VOID FWDTimerProc(); -VOID CreateMessageFromBuffer(CIRCUIT * conn); -VOID __cdecl nodeprintf(ConnectionInfo * conn, const char * format, ...); -VOID __cdecl nodeprintfEx(ConnectionInfo * conn, const char * format, ...); -VOID FreeOverrides(); -VOID SendMessageToSYSOP(char * Title, char * MailBuffer, int Length); -struct UserInfo * FindRMS(); -VOID FindNextRMSUser(struct BBSForwardingInfo * FWDInfo); -BOOL ConnecttoBBS (struct UserInfo * user); -BOOL SetupNewBBS(struct UserInfo * user); -VOID CreateRegBackup(); -VOID SaveFilters(HWND hDlg); -BOOL CheckRejFilters(char * From, char * To, char * ATBBS, char * BID, char Type, int Len); -BOOL CheckHoldFilters(struct MsgInfo * Msg, char * From, char * To, char * ATBBS, char * BID); -BOOL CheckifLocalRMSUser(char * FullTo); -VOID DoWPLookup(ConnectionInfo * conn, struct UserInfo * user, char Type, char *Context); -BOOL wildcardcompare(char * Target, char * Match); -VOID SendWarningToSYSOP(struct MsgInfo * Msg); -VOID DoEditUserCmd(CIRCUIT * conn, struct UserInfo * user, char * Arg1, char * Context); -VOID DoPollRMSCmd(CIRCUIT * conn, struct UserInfo * user, char * Arg1, char * Context); -VOID DoShowRMSCmd(CIRCUIT * conn, struct UserInfo * user, char * Arg1, char * Context); -VOID DoSetIdleTime(CIRCUIT * conn, struct UserInfo * user, char * Arg1, char * Context); -VOID DoFwdCmd(CIRCUIT * conn, struct UserInfo * user, char * Arg1, char * Context); -VOID SaveFwdParams(char * Call, struct BBSForwardingInfo * ForwardingInfo); -VOID DoAuthCmd(CIRCUIT * conn, struct UserInfo * user, char * Arg1, char * Context); -VOID ProcessSuspendedListCommand(CIRCUIT * conn, struct UserInfo * user, char* Buffer, int len); -VOID DoReroute(CIRCUIT * conn, struct UserInfo * user); - -// FBB Routines - -VOID SendCompressed(CIRCUIT * conn, struct MsgInfo * FwdMsg); -VOID SendCompressedB2(CIRCUIT * conn, struct FBBHeaderLine * FBBHeader); -VOID UnpackFBBBinary(CIRCUIT * conn); -void Decode(CIRCUIT * conn, __int16 DecodeOnly); -//long Encode(char * in, char * out, long inlen, BOOL B1Protocol); - -BOOL CreateB2Message(CIRCUIT * conn, struct FBBHeaderLine * FBBHeader, char * Rline); -VOID SaveFBBBinary(CIRCUIT * conn); -BOOL LookupRestart(CIRCUIT * conn, struct FBBHeaderLine * FBBHeader); -BOOL DoWeWantIt(CIRCUIT * conn, struct FBBHeaderLine * FBBHeader); - -// Console Routines - -BOOL CreateConsole(int Stream); -int WritetoConsoleWindow(int Stream, char * Msg, int len); -int ToggleParam(HMENU hMenu, HWND hWnd, BOOL * Param, int Item); -void CopyRichTextToClipboard(HWND hWnd); -void CopyToClipboard(HWND hWnd); -VOID CloseConsole(int Stream); - -// Monitor Routines - -BOOL CreateMonitor(); -int WritetoMonitorWindow(char * Msg, int len); - -BOOL CreateDebugWindow(); -VOID WritetoDebugWindow(char * Msg, int len); -VOID ClearDebugWindow(); -int RemoveLF(char * Message, int len); - -// Utilities - -BOOL isdigits(char * string); - - -void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line); -void FreeSemaphore(struct SEM * Semaphore); - -VOID __cdecl Debugprintf(const char * format, ...); -VOID __cdecl Logprintf(int LogMode, CIRCUIT * conn, int InOut, const char * format, ...); - -VOID SortBBSChain(); -VOID ExpandAndSendMessage(CIRCUIT * conn, char * Msg, int LOG); -int ImportMessages(CIRCUIT * conn, char * FN, BOOL Nopopup); - -// TCP Routines - -BOOL InitialiseTCP(); -VOID SetupListenSet(); -VOID TCPTimer(); -VOID TCPFastTimer(); -int Socket_Data(int sock, int error, int eventcode); -static int Socket_Accept(SOCKET SocketId); -int Socket_Connect(SOCKET sock, int Error); -VOID ProcessSMTPServerMessage(SocketConn * sockptr, char * Buffer, int Len); -int CreateSMTPMessage(SocketConn * sockptr, int i, char * MsgTitle, time_t Date, char * MsgBody, int Msglen, BOOL B2Flag); -BOOL CreateSMTPMessageFile(char * Message, struct MsgInfo * Msg); -SOCKET CreateListeningSocket(int Port); -int TidyString(char * MailFrom); -VOID ProcessPOP3ServerMessage(SocketConn * sockptr, char * Buffer, int Len); -char *str_base64_encode(char *str); -int b64decode(char *str); -SocketConn * SMTPConnect(char * Host, int Port, BOOL AMPR, struct MsgInfo * Msg, char * MsgBody); -BOOL POP3Connect(char * Host, int Port); -VOID ProcessSMTPClientMessage(SocketConn * sockptr, char * Buffer, int Len); -VOID ProcessPOP3ClientMessage(SocketConn * sockptr, char * Buffer, int Len); -int CreatePOP3Message(char * From, char * To, char * MsgTitle, time_t Date, char * MsgBody, int MsgLen, BOOL B2Flag); -void WriteLogLine(CIRCUIT * conn, int Flag, char * Msg, int MsgLen, int Flags); -int SendSock(SocketConn * sockptr, char * msg); -VOID __cdecl sockprintf(SocketConn * sockptr, const char * format, ...); -VOID SendFromQueue(SocketConn * sockptr); -VOID SendMultiPartMessage(SocketConn * sockptr, struct MsgInfo * Msg, UCHAR * msgbytes); -int CountMessagesTo(struct UserInfo * user, int * Unread); - -BOOL SendtoISP(); - -// NNTP ROutines - -VOID InitialiseNNTP(); -VOID BuildNNTPList(struct MsgInfo * Msg); -int NNTP_Data(int sock, int error, int eventcode); -int NNTP_Accept(SOCKET SocketId); - -VOID * GetOverrides(config_setting_t * group, char * ValueName); -VOID * RegGetOverrides(HKEY hKey, char * ValueName); - -VOID DoHouseKeeping(BOOL Mainual); -VOID ExpireMessages(); -VOID KillMsg(struct MsgInfo * Msg); -BOOL RemoveKilledMessages(); -VOID Renumber_Messages(); -BOOL ExpireBIDs(); -VOID MailHousekeepingResults(); -VOID CreateBBSTrafficReport(); -VOID CreateWPReport(); - -// WP Routines - -VOID ProcessWPMsg(char * MailBuffer, int Size, char * FisrtRLine); -VOID GetWPInfoFromRLine(char * From, char * FirstRLine, time_t RLineTime); -VOID UpdateWPWithUserInfo(struct UserInfo * user); -VOID GetWPBBSInfo(char * Rline); - -// UI Routines - -VOID SetupUIInterface(); -VOID Free_UI(); -VOID SendLatestUI(int Port); -VOID SendMsgUI(struct MsgInfo * Msg); -static VOID Send_AX_Datagram(UCHAR * Msg, DWORD Len, UCHAR Port, UCHAR * HWADDR, BOOL Queue); -VOID SeeifBBSUIFrame(struct _MESSAGEX * buff, int len); -struct MsgInfo * FindMessageByNumber(int msgno); -int CountConnectionsOnPort(int CheckPort); - -// Message Routing Routtines - -VOID SetupHAElements(struct BBSForwardingInfo * ForwardingInfo); -VOID SetupHAddreses(struct BBSForwardingInfo * ForwardingInfo); -VOID SetupHAddresesP(struct BBSForwardingInfo * ForwardingInfo); -VOID SetupMyHA(); -VOID SetupFwdAliases(); -struct Continent * FindContinent(char * Name); -int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn); -BOOL CheckABBS(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char * HRoute); -BOOL CheckBBSToList(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo); -BOOL CheckBBSAtList(struct MsgInfo * Msg, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS); -BOOL CheckBBSHList(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char * HRoute); -BOOL CheckBBSHElements(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char ** HElements); -BOOL CheckBBSHElementsFlood(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char ** HElements); -int CheckBBSToForNTS(struct MsgInfo * Msg, struct BBSForwardingInfo * ForwardingInfo); -int CheckBBSATListWildCarded(struct MsgInfo * Msg, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS); - -VOID ReRouteMessages(); - -VOID initUTF8(); -int Is8Bit(unsigned char *cpt, int len); -int IsUTF8(unsigned char *ptr, int len); -int IsUTF8(unsigned char *ptr, int len); -int WebIsUTF8(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); - - -VOID FreeWebMailMallocs(); - -extern int _MYTIMEZONE; - -extern HKEY REGTREE; -extern char * REGTREETEXT; - -extern HBRUSH bgBrush; -extern BOOL cfgMinToTray; - -extern CIRCUIT * Console; - -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 BOOL OnlyKnown; - -extern BOOL AllowAnon; -extern BOOL UserCantKillT; -extern BOOL DontNeedHomeBBS; - -extern int LatestMsg; -extern char BBSName[]; -extern char SYSOPCall[]; -extern char BBSSID[]; -extern char NewUserPrompt[]; - -extern char * WelcomeMsg; -extern char * NewWelcomeMsg; -extern char * ChatWelcomeMsg; -extern char * NewChatWelcomeMsg; -extern char * ExpertWelcomeMsg; - -extern char * Prompt; -extern char * NewPrompt; -extern char * ExpertPrompt; - -// Filter Params - -extern char ** RejFrom; // Reject on FROM Call -extern char ** RejTo; // Reject on TO Call -extern char ** RejAt; // Reject on AT Call -extern char ** RejBID; - -extern char ** HoldFrom; // Hold on FROM Call -extern char ** HoldTo; // Hold on TO Call -extern char ** HoldAt; // Hold on AT Call -extern char ** HoldBID; - -// Send WP Params - -extern BOOL SendWP; -extern char SendWPVIA[81]; -extern char SendWPTO[11]; -extern int SendWPType; - -extern int Ver[4]; - -extern struct MsgInfo ** MsgHddrPtr; - -extern BIDRec ** BIDRecPtr; -extern int NumberofBIDs; - -extern struct NNTPRec * FirstNNTPRec; -//extern int NumberofNNTPRecs; - - -extern int NumberofMessages; -extern int FirstMessageIndextoForward; - -extern WPRec ** WPRecPtr; -extern int NumberofWPrecs; - -extern struct SEM AllocSemaphore; -extern struct SEM ConSemaphore; -extern struct SEM MsgNoSemaphore; - -extern struct MsgInfo * MsgnotoMsg[]; // Message Number to Message Slot List. - - -extern char hostname[]; -extern char RtUsr[]; -extern char RtUsrTemp[]; -extern char RtKnown[]; -extern int AXIPPort; -extern BOOL NeedStatus; - -extern BOOL ISP_Gateway_Enabled; -extern BOOL SMTPAuthNeeded; - - -extern int MaxMsgno; -extern int BidLifetime; -extern int MaxAge; -extern int MaintInterval; -extern int MaintTime; -extern int UserLifetime; - -extern int MaxRXSize; -extern int MaxTXSize; - -extern char OurNode[]; -extern char OurAlias[]; -extern BOOL SMTPMsgCreated; - -extern HINSTANCE hInst; -extern HWND hWnd; -extern RECT MainRect; - -extern char BBSName[]; -extern char HRoute[]; -extern char AMPRDomain[]; -extern BOOL SendAMPRDirect; -extern int BBSApplNum; -extern int SMTPInPort; -extern int POP3InPort; -extern int NNTPInPort; -extern BOOL RemoteEmail; - -extern int MaxStreams; -extern UCHAR * OtherNodes; -extern struct UserInfo * BBSChain; // Chain of users that are BBSes -extern struct UserInfo ** UserRecPtr; -extern int NumberofUsers; -extern struct MsgInfo ** MsgHddrPtr; -extern int NumberofMessages; -extern int HighestBBSNumber; -extern HMENU hFWDMenu; // Forward Menu Handle -extern char zeros[]; // For forward bitmask tests -extern BOOL EnableUI; -extern BOOL RefuseBulls; -extern BOOL SendSYStoSYSOPCall; -extern BOOL SendBBStoSYSOPCall; -extern BOOL DontHoldNewUsers; -extern BOOL DefaultNoWINLINK; -extern BOOL UIEnabled[]; -extern BOOL UINull[]; -extern BOOL UIMF[]; -extern BOOL UIHDDR[]; -extern char * UIDigi[]; -extern int MailForInterval; -extern char MailForText[]; - -extern BOOL ISP_Gateway_Enabled; - -extern char MyDomain[]; // Mail domain for BBS<>Internet Mapping - -extern char ISPSMTPName[]; -extern char ISPEHLOName[]; -extern int ISPSMTPPort; - -extern char ISPPOP3Name[]; -extern int ISPPOP3Port; -extern int ISPPOP3Interval; - -extern char ISPAccountName[]; -extern char ISPAccountPass[]; -extern char EncryptedISPAccountPass[]; -extern int EncryptedPassLen; -extern char *month[]; - -extern HWND hDebug; -extern RECT MonitorRect; -extern RECT DebugRect; -extern HWND hMonitor; -//extern HWND hConsole; -//extern RECT ConsoleRect; -extern int LogAge; -extern BOOL DeletetoRecycleBin; -extern BOOL SuppressMaintEmail; -extern BOOL SaveRegDuringMaint; -extern BOOL SendWP; -extern BOOL OverrideUnsent; -extern BOOL SendNonDeliveryMsgs; -extern BOOL GenerateTrafficReport; - -extern double PR; -extern double PUR; -extern double PF; -extern double PNF; -extern int BF; -extern int BNF; -extern int NTSD; -extern int NTSU; -extern int NTSF; -extern int AP; -extern int AB; - -extern struct Override ** LTFROM; -extern struct Override ** LTTO; -extern struct Override ** LTAT; - -extern time_t LastHouseKeepingTime; -extern time_t LastTrafficTime; - -extern char * MyElements[]; -extern char ** AliasText; -extern struct ALIAS ** Aliases; - -extern BOOL ReaddressLocal; -extern BOOL ReaddressReceived; -extern BOOL WarnNoRoute; -extern BOOL SendPtoMultiple; -extern BOOL Localtime; - -extern struct ConsoleInfo * ConsHeader[2]; - -extern BOOL NeedHomeBBS; -extern char ConfigName[250]; -extern BOOL UsingingRegConfig; - -extern BOOL MulticastRX; - -extern BOOL FilterWPBulls; -extern BOOL NoWPGuesses; -extern char ** SendWPAddrs; // Replacers WP To and VIA - -extern BOOL DontCheckFromCall; - -extern time_t APIClock;; - -// YAPP stuff - -#define SOH 1 -#define STX 2 -#define ETX 3 -#define EOT 4 -#define ENQ 5 -#define ACK 6 -#define DLE 0x10 -#define NAK 0x15 -#define CAN 0x18 diff --git a/.svn/pristine/0e/0e76009e1f1f816128476fe53b8ac9e78d519dea.svn-base b/.svn/pristine/0e/0e76009e1f1f816128476fe53b8ac9e78d519dea.svn-base deleted file mode 100644 index 6755ea9..0000000 --- a/.svn/pristine/0e/0e76009e1f1f816128476fe53b8ac9e78d519dea.svn-base +++ /dev/null @@ -1,6764 +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 end of session code (58) -// 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) -// Fix L4 RTT (66) -// Fix RigConrol with Chanxx but no other settings (66) -// Add option to compress L2 frames (67) -// Sort Routes displays (67) -// Fix Ardop session premature close (70) -// Add timestamps to log entries in Web Driver windows (70) -// Generate stack backtrace if SIGSEGV or SIGABRT occur (Linux) (70) -// Remove some debug logging from L2 code (70) -// Fix compiling LinBPQ with nomqtt option (70) -// Improve handling of binary data in RHP interface (70) -// Fix sending KISS commands to multiport or multidropped TNCs (70) -// Add MHUV and MHLV commands (Verbose listing with timestamps in clock time) (70) - -#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[len], "\\\r\n", RegLine); - strcat(RegLine, "\\\r\n"); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - len = 2; - } - - len += sprintf(&RegLine[len], "%02x,", 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[len], "\\\r\n"); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - len = 2; - } - - len += sprintf(&RegLine[len], "%02x,", Value[k]); - if (len > 76) - { - len += sprintf(&RegLine[len], "\\\r\n"); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - } - len += sprintf(&RegLine[len], "00,"); - } - - 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/.svn/pristine/0e/0e8459408202da08ceff06ab61d9b945a02e38ba.svn-base b/.svn/pristine/0e/0e8459408202da08ceff06ab61d9b945a02e38ba.svn-base deleted file mode 100644 index aa4929c..0000000 --- a/.svn/pristine/0e/0e8459408202da08ceff06ab61d9b945a02e38ba.svn-base +++ /dev/null @@ -1,1638 +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 -*/ - -// -// INP3 Suport Code for BPQ32 Switch -// - -// All code runs from the BPQ32 Received or Timer Routines under Semaphore. - - -#define _CRT_SECURE_NO_DEPRECATE - -#pragma data_seg("_BPQDATA") - -#include "cheaders.h" - -#include "time.h" -#include "stdio.h" -#include -//#include "vmm.h" - -uint64_t timeLoadedMS = 0; - -VOID SendNegativeInfo(); -VOID SortRoutes(struct DEST_LIST * Dest); -VOID SendRTTMsg(struct ROUTE * Route); - -static VOID SendNetFrame(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame) -{ - // INP3 should only ever send over an active link, so just queue the message - - if (Route->NEIGHBOUR_LINK) - C_Q_ADD(&Route->NEIGHBOUR_LINK->TX_Q, Frame); - else - ReleaseBuffer(Frame); -} - - -typedef struct _RTTMSG -{ - UCHAR ID[7]; - UCHAR TXTIME[11]; - UCHAR SMOOTHEDRTT[11]; - UCHAR LASTRTT[11]; - UCHAR POINTER[11]; - UCHAR ALIAS[7]; - UCHAR VERSION[12]; - UCHAR SWVERSION[9]; - UCHAR FLAGS[10]; - UCHAR PADDING[147]; - -} RTTMSG; - -int COUNTNODES(struct ROUTE * ROUTE); - -VOID __cdecl Debugprintf(const char * format, ...); - -VOID SendINP3RIF(struct ROUTE * Route, UCHAR * Call, UCHAR * Alias, int Hops, int RTT); -VOID SendOurRIF(struct ROUTE * Route); -VOID UpdateNode(struct ROUTE * Route, UCHAR * axcall, UCHAR * alias, int hops, int rtt); -VOID UpdateRoute(struct DEST_LIST * Dest, struct INP3_DEST_ROUTE_ENTRY * ROUTEPTR, int hops, int rtt); -VOID KillRoute(struct INP3_DEST_ROUTE_ENTRY * ROUTEPTR); -VOID AddHere(struct INP3_DEST_ROUTE_ENTRY * ROUTEPTR,struct ROUTE * Route , int hops, int rtt); -VOID SendRIPToNeighbour(struct ROUTE * Route); -VOID DecayNETROMRoutes(struct ROUTE * Route); -VOID DeleteINP3Routes(struct ROUTE * Route); -BOOL L2SETUPCROSSLINKEX(PROUTE ROUTE, int Retries); - -//#define NOINP3 - -struct _RTTMSG RTTMsg = {""}; - -//struct ROUTE DummyRoute = {"","",""}; - -int RIPTimerCount = 0; // 1 sec to 10 sec counter -int PosTimerCount = 0; // 1 sec to 5 Mins counter - -// Timer Runs every 10 Secs - -extern int MAXRTT; // 90 secs -extern int MaxHops; - -extern int RTTInterval; // 4 Minutes -int RTTRetries = 2; -int RTTTimeout = 6; // 1 Min (Horizon is 1 min) - -VOID InitialiseRTT() -{ - UCHAR temp[sizeof(RTTMsg.FLAGS) + 4]; - - memset(&RTTMsg, ' ', sizeof(struct _RTTMSG)); - memcpy(RTTMsg.ID, "L3RTT: ", 7); - memcpy(RTTMsg.VERSION, "LEVEL3_V2.1 ", 12); - memcpy(RTTMsg.SWVERSION, "BPQ32001 ", 9); - _snprintf(temp, sizeof(temp), "$M%d $N ", MAXRTT); // trailing spaces extend to ensure padding if the length of characters for MAXRTT changes. - memcpy(RTTMsg.FLAGS, temp, 10); // But still limit the actual characters copied. - memcpy(RTTMsg.ALIAS, &MYALIASTEXT, 6); - RTTMsg.ALIAS[6] = ' '; -} - -VOID TellINP3LinkGone(struct ROUTE * Route) -{ - struct DEST_LIST * Dest = DESTS; - char call[11]=""; - - ConvFromAX25(Route->NEIGHBOUR_CALL, call); - Debugprintf("BPQ32 L2 Link to Neighbour %s lost", call); - - if (Route->NEIGHBOUR_LINK) - Debugprintf("BPQ32 Neighbour_Link not cleared"); - - - if (Route->INP3Node == 0) - DecayNETROMRoutes(Route); - else - DeleteINP3Routes(Route); -} - -VOID DeleteINP3Routes(struct ROUTE * Route) -{ - int i; - struct DEST_LIST * Dest = DESTS; - char Call1[10]; - char Call2[10]; - - Call1[ConvFromAX25(Route->NEIGHBOUR_CALL, Call1)] = 0; - - Debugprintf("Deleting INP3 routes via %s", Call1); - - // Delete any INP3 Dest entries via this Route - - Route->SRTT = 0; - Route->RTT = 0; - Route->BCTimer = 0; - Route->Status = 0; - Route->Timeout = 0; - - Dest--; - - // Delete any Dest entries via this Route - - for (i=0; i < MAXDESTS; i++) - { - Dest++; - - if (Dest->DEST_CALL[0] == 0) - continue; // Spare Entry - - if (Dest->NRROUTE[0].ROUT_OBSCOUNT >= 128) // Not if locked - continue; - - Call2[ConvFromAX25(Dest->DEST_CALL, Call2)] = 0; - - if (Dest->INP3ROUTE[0].ROUT_NEIGHBOUR == Route) - { - // We are deleting the best INP3 route, so need to tell other nodes - // If this is the only one, we need to keep the entry with at 60000 rtt so - // we can send it. Remove when all gone - - // How do we indicate is is dead - Maybe the 60000 is enough! - - // If we are cleaning up after a sabm on an existing link (frmr or other end reloaded) then we don't need to tell anyone - the routes should be reestablished very quickly - - Debugprintf("Deleting First INP3 Route to %s", Call2); - - if (Dest->INP3ROUTE[1].ROUT_NEIGHBOUR == 0) - { - - // Only entry - Dest->INP3ROUTE[0].SRTT = 60000; - Dest->INP3ROUTE[0].Hops = 255; - - Debugprintf("Was the only INP3 route"); - - if (Dest->DEST_ROUTE == 4) // we were using it - Dest->DEST_ROUTE = 0; - - continue; - } - - Dest->INP3ROUTE[1].LastRTT = Dest->INP3ROUTE[0].SRTT; // So next scan will check if rtt has increaced enough to need a RIF - memcpy(&Dest->INP3ROUTE[0], &Dest->INP3ROUTE[1], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memcpy(&Dest->INP3ROUTE[1], &Dest->INP3ROUTE[2], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memset(&Dest->INP3ROUTE[2], 0, sizeof(struct INP3_DEST_ROUTE_ENTRY)); - - continue; - } - - // If we aren't removing the best, we don't need to tell anyone. - - if (Dest->INP3ROUTE[1].ROUT_NEIGHBOUR == Route) - { - Debugprintf("Deleting 2nd INP3 Route to %s", Call2); - memcpy(&Dest->INP3ROUTE[1], &Dest->INP3ROUTE[2], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memset(&Dest->INP3ROUTE[2], 0, sizeof(struct INP3_DEST_ROUTE_ENTRY)); - - continue; - } - - if (Dest->INP3ROUTE[2].ROUT_NEIGHBOUR == Route) - { - Debugprintf("Deleting 3rd INP3 Route to %s", Call2); - memset(&Dest->INP3ROUTE[2], 0, sizeof(struct INP3_DEST_ROUTE_ENTRY)); - continue; - } - } - - // I think we should send Negative info immediately - - SendNegativeInfo(); -} - -VOID DecayNETROMRoutes(struct ROUTE * Route) -{ - int i; - struct DEST_LIST * Dest = DESTS; - - Dest--; - - // Decay any NETROM Dest entries via this Route. If OBS reaches zero, remove - - // OBSINIT is probably too many retries. Try decrementing by 2. - - for (i=0; i < MAXDESTS; i++) - { - Dest++; - - if (Dest->DEST_CALL[0] == 0) - continue; // Spare Entry - - if (Dest->NRROUTE[0].ROUT_NEIGHBOUR == Route) - { - if (Dest->NRROUTE[0].ROUT_OBSCOUNT && Dest->NRROUTE[0].ROUT_OBSCOUNT < 128) // Not if locked - { - Dest->NRROUTE[0].ROUT_OBSCOUNT--; - if (Dest->NRROUTE[0].ROUT_OBSCOUNT) - Dest->NRROUTE[0].ROUT_OBSCOUNT--; - - } - if (Dest->NRROUTE[0].ROUT_OBSCOUNT == 0) - { - // Route expired - - if (Dest->NRROUTE[1].ROUT_NEIGHBOUR == 0) // No more Netrom Routes - { - if (Dest->INP3ROUTE[0].ROUT_NEIGHBOUR == 0) // Any INP3 ROutes? - { - // No More Routes - ZAP Dest - - REMOVENODE(Dest); // Clear buffers, Remove from Sorted Nodes chain, and zap entry - continue; - } - else - { - // Still have an INP3 Route - just zap this entry - - memset(&Dest->NRROUTE[0], 0, sizeof(struct NR_DEST_ROUTE_ENTRY)); - continue; - - } - } - - memcpy(&Dest->NRROUTE[0], &Dest->NRROUTE[1], sizeof(struct NR_DEST_ROUTE_ENTRY)); - memcpy(&Dest->NRROUTE[1], &Dest->NRROUTE[2], sizeof(struct NR_DEST_ROUTE_ENTRY)); - memset(&Dest->NRROUTE[2], 0, sizeof(struct NR_DEST_ROUTE_ENTRY)); - - continue; - } - } - - if (Dest->NRROUTE[1].ROUT_NEIGHBOUR == Route) - { - Dest->NRROUTE[1].ROUT_OBSCOUNT--; - - if (Dest->NRROUTE[1].ROUT_OBSCOUNT == 0) - { - memcpy(&Dest->NRROUTE[1], &Dest->NRROUTE[2], sizeof(struct NR_DEST_ROUTE_ENTRY)); - memset(&Dest->NRROUTE[2], 0, sizeof(struct NR_DEST_ROUTE_ENTRY)); - - continue; - } - } - - if (Dest->NRROUTE[2].ROUT_NEIGHBOUR == Route) - { - Dest->NRROUTE[2].ROUT_OBSCOUNT--; - - if (Dest->NRROUTE[2].ROUT_OBSCOUNT == 0) - { - memset(&Dest->NRROUTE[2], 0, sizeof(struct NR_DEST_ROUTE_ENTRY)); - continue; - } - } - } -} - - -VOID TellINP3LinkSetupFailed(struct ROUTE * Route) -{ - // Attempt to activate Neighbour failed - -// char call[11]=""; - -// ConvFromAX25(Route->NEIGHBOUR_CALL, call); -// Debugprintf("BPQ32 L2 Link to Neighbour %s setup failed", call); - - - if (Route->INP3Node == 0) - DecayNETROMRoutes(Route); - else - DeleteINP3Routes(Route); -} - -VOID ProcessRTTReply(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff) -{ - int RTT; - unsigned int OrigTime; - - char Normcall[10]; - - Normcall[ConvFromAX25(Route->NEIGHBOUR_CALL, Normcall)] = 0; - - Route->Timeout = 0; // Got Response - - sscanf(&Buff->L4DATA[6], "%d", &OrigTime); - RTT = (GetTickCount() - timeLoadedMS) - OrigTime; - - if (RTT > 60000) - return; // Ignore if more than 60 secs - - Route->RTT = RTT; - - if (Route->SRTT == 0) - Route->SRTT = RTT; - else - Route->SRTT = ((Route->SRTT * 80)/100) + ((RTT * 20)/100); - - if ((Route->Status & GotRTTResponse) == 0) - { - // Link is just starting - - Debugprintf("INP3 got first RTT reply from %s - Link is (Re)staring", Normcall); - - Route->Status |= GotRTTResponse; - } - -} - -VOID ProcessINP3RIF(struct ROUTE * Route, UCHAR * ptr1, int msglen, int Port) -{ - unsigned char axcall[7]; - int hops; - unsigned short rtt; - int len; - int opcode; - char alias[6]; - UINT Stamp, HH, MM; - char Normcall[10]; - - Normcall[ConvFromAX25(Route->NEIGHBOUR_LINK->LINKCALL, Normcall)] = 0; - Debugprintf("Processing RIF from %s INP3Node %d Route SRTT %d", Normcall, Route->INP3Node, Route->SRTT); - - if (Route->SRTT == 0) - Debugprintf("INP3 Zero SRTT"); - - -#ifdef NOINP3 - - return; - -#endif - - if (Route->INP3Node == 0) - return; // We don't want to use INP3 - - // Update Timestamp on Route - - Stamp = time(NULL) % 86400; // Secs into day - HH = Stamp / 3600; - - Stamp -= HH * 3600; - MM = Stamp / 60; - - Route->NEIGHBOUR_TIME = 256 * HH + MM; - - while (msglen > 0) - { - if (msglen < 10) - { - Debugprintf("Corrupt INP3 Message"); - return; - } - - memset(alias, ' ', 6); - memcpy(axcall, ptr1, 7); - - if (axcall[0] < 0x60 || (axcall[0] & 1)) // Not valid ax25 callsign - return; // Corrupt RIF - - ptr1+=7; - - hops = *ptr1++; - rtt = (*ptr1++ << 8); - rtt += *ptr1++; - - // rtt is value from remote node. Add our RTT to that node - - rtt += Route->SRTT; - - msglen -= 10; - - while (*ptr1 && msglen > 0) - { - len = *ptr1; - opcode = *(ptr1+1); - - if (len < 2 || len > msglen) - return; // Duff RIF - - if (opcode == 0) - { - if (len > 1 && len < 9) - memcpy(alias, ptr1+2, len-2); - else - { - Debugprintf("Corrupt INP3 Message"); - return; - } - } - ptr1+=len; - msglen -=len; - } - - ptr1++; - msglen--; // EOP - - UpdateNode(Route, axcall, alias, hops, rtt); - } - - return; -} - -VOID KillRoute(struct INP3_DEST_ROUTE_ENTRY * ROUTEPTR) -{ -} - - -VOID UpdateNode(struct ROUTE * Route, UCHAR * axcall, UCHAR * alias, int hops, int rtt) -{ - struct DEST_LIST * Dest; - struct INP3_DEST_ROUTE_ENTRY * ROUTEPTR; - int i; - char call[11]=""; - APPLCALLS * APPL; - int App; - char Normcall[10]; - Normcall[ConvFromAX25(axcall, Normcall)] = 0; - - -// SEE IF any of OUR CALLs - DONT WANT TO PUT IT IN LIST! - - if (CompareCalls(axcall, NETROMCALL)) - { - Debugprintf("INP3 for our Nodecall - discarding"); - return; - } - - if (CheckExcludeList(axcall) == 0) - { - Debugprintf("INP3 excluded - discarding"); - return; - } - - for (App = 0; App < NumberofAppls; App++) - { - APPL=&APPLCALLTABLE[App]; - - if (APPL->APPLHASALIAS == 0 && CompareCalls(axcall, APPL->APPLCALL)) - { - Debugprintf("INP3 for an APPLCALL - discarding"); - return; - } - } - - - if (hops > MaxHops && hops < 255) - { - ConvFromAX25(axcall, call); - Debugprintf("INP3 Node %s Hops %d RTT %d Ignored - Hop Count too high", call, hops, rtt); - return; - } - - if (rtt > MAXRTT && rtt < 60000) - { - ConvFromAX25(axcall, call); - Debugprintf("INP3 Node %s Hops %d RTT %d Ignored - rtt too high", call, hops, rtt); - return; - } - - if (rtt >= 60000) - { - Debugprintf("INP3 RTT > 60000 - discarding"); - return; - } - - if (FindDestination(axcall, &Dest)) - goto Found; - - if (Dest == NULL) - { - Debugprintf("INP3 Table Full - discarding"); - return; // Table Full - } - - - - memset(Dest, 0, sizeof(struct DEST_LIST)); - - memcpy(Dest->DEST_CALL, axcall, 7); - memcpy(Dest->DEST_ALIAS, alias, 6); - -// Set up First Route - - Dest->INP3ROUTE[0].Hops = hops; - Dest->INP3ROUTE[0].SRTT = rtt; - Dest->INP3ROUTE[0].LastRTT = 0; - - Dest->INP3FLAGS = NewNode; - - Dest->INP3ROUTE[0].ROUT_NEIGHBOUR = Route; - - NUMBEROFNODES++; - - ConvFromAX25(Dest->DEST_CALL, call); - Debugprintf("INP3 Adding New Node %s Hops %d RTT %d", call, hops, rtt); - - return; - -Found: - - if (Dest->DEST_STATE & 0x80) // Application Entry - { - Debugprintf("INP3 Application Entry - discarding"); - return; // Tsble Full - } - - // Update ALIAS - - ConvFromAX25(Dest->DEST_CALL, call); - Debugprintf("INP3 Updating Node %s Hops %d RTT %d", call, hops, rtt); - - - if (alias[0] > ' ') - memcpy(Dest->DEST_ALIAS, alias, 6); - - // See if we are known to it, it not add - - ROUTEPTR = &Dest->INP3ROUTE[0]; - - if (ROUTEPTR->ROUT_NEIGHBOUR == Route) - { - Debugprintf("INP3 Already have as route[0] - updating"); - UpdateRoute(Dest, ROUTEPTR, hops, rtt); - return; - } - - ROUTEPTR = &Dest->INP3ROUTE[1]; - - if (ROUTEPTR->ROUT_NEIGHBOUR == Route) - { - Debugprintf("INP3 Already have as route[1] - updating"); - UpdateRoute(Dest, ROUTEPTR, hops, rtt); - return; - } - - ROUTEPTR = &Dest->INP3ROUTE[2]; - - if (ROUTEPTR->ROUT_NEIGHBOUR == Route) - { - Debugprintf("INP3 Already have as route[2] - updating"); - UpdateRoute(Dest, ROUTEPTR, hops, rtt); - return; - } - - // Not in list. If any spare, add. - // If full, see if this is better - - for (i = 0; i < 3; i++) - { - ROUTEPTR = &Dest->INP3ROUTE[i]; - - if (ROUTEPTR->ROUT_NEIGHBOUR == NULL) - { - // Add here - - Debugprintf("INP3 adding as route[%d]", i); - AddHere(ROUTEPTR, Route, hops, rtt); - SortRoutes(Dest); - return; - } - ROUTEPTR++; - } - - Debugprintf("INP3 All entries in use - see if this is better than existing"); - - // Full, see if this is better - - // Note that wont replace any netrom routes with INP3 ones unless we add pseudo rtt values to netrom entries - - if (Dest->INP3ROUTE[0].SRTT > rtt) - { - // We are better. Move others down and add on front - - Debugprintf("INP3 Replacing route 0"); - - memcpy(&Dest->INP3ROUTE[2], &Dest->INP3ROUTE[1], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memcpy(&Dest->INP3ROUTE[1], &Dest->INP3ROUTE[0], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - AddHere(&Dest->INP3ROUTE[0], Route, hops, rtt); - return; - } - - if (Dest->INP3ROUTE[1].SRTT > rtt) - { - // We are better. Move 2nd down and add - - Debugprintf("INP3 Replacing route 1"); - memcpy(&Dest->INP3ROUTE[2], &Dest->INP3ROUTE[1], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - AddHere(&Dest->INP3ROUTE[1], Route, hops, rtt); - return; - } - - if (Dest->INP3ROUTE[2].SRTT > rtt) - { - // We are better. Add here - - Debugprintf("INP3 Replacing route 2"); - AddHere(&Dest->INP3ROUTE[2], Route, hops, rtt); - return; - } - - - Debugprintf("INP3 Worse that any existing route"); - - - // Worse than any - ignore - -} - -VOID AddHere(struct INP3_DEST_ROUTE_ENTRY * ROUTEPTR,struct ROUTE * Route , int hops, int rtt) -{ - ROUTEPTR->Hops = hops; - ROUTEPTR->SRTT = rtt; - ROUTEPTR->LastRTT = 0; - ROUTEPTR->RTT = 0; - ROUTEPTR->ROUT_NEIGHBOUR = Route; - - return; -} - - -/* LEA EDI,DEST_CALL[EBX] - MOV ECX,7 - REP MOVSB - - MOV ECX,6 ; ADD ALIAS - MOV ESI,OFFSET32 TEMPFIELD - REP MOVSB - - POP ESI -; -; GET _NEIGHBOURS FOR THIS DESTINATION -; - CALL CONVTOAX25 - JNZ SHORT BADROUTE -; - CALL GETVALUE - MOV _SAVEPORT,AL ; SET PORT FOR _FINDNEIGHBOUR - - CALL GETVALUE - MOV _ROUTEQUAL,AL -; - MOV ESI,OFFSET32 AX25CALL - - PUSH EBX ; SAVE DEST - CALL _FINDNEIGHBOUR - MOV EAX,EBX ; ROUTE TO AX - POP EBX - - JZ SHORT NOTBADROUTE - - JMP SHORT BADROUTE - -NOTBADROUTE: -; -; UPDATE ROUTE LIST FOR THIS DEST -; - MOV ROUT1_NEIGHBOUR[EBX],EAX - MOV AL,_ROUTEQUAL - MOV ROUT1_QUALITY[EBX],AL - MOV ROUT1_OBSCOUNT[EBX],255 ; LOCKED -; - POP EDI - POP EBX - - INC _NUMBEROFNODES - - JMP SENDOK -*/ - -struct INP3_DEST_ROUTE_ENTRY Temp; - - -VOID SortRoutes(struct DEST_LIST * Dest) -{ - char Call1[10], Call2[10], Call3[10]; - - - // May now be out of order - - if (Dest->INP3ROUTE[1].ROUT_NEIGHBOUR == 0) - { - Call1[ConvFromAX25(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call1)] = 0; - Debugprintf("INP3 1 route %d %s", Dest->INP3ROUTE[0].SRTT, Call1); - return; // Only One, so cant be out of order - } - if (Dest->INP3ROUTE[2].ROUT_NEIGHBOUR == 0) - { - // Only 2 - - Call1[ConvFromAX25(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call1)] = 0; - Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0; - - Debugprintf("INP3 2 routes %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2); - - if (Dest->INP3ROUTE[0].SRTT <= Dest->INP3ROUTE[1].SRTT) - return; - - // Swap one and two - - memcpy(&Temp, &Dest->INP3ROUTE[0], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memcpy(&Dest->INP3ROUTE[0], &Dest->INP3ROUTE[1], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memcpy(&Dest->INP3ROUTE[1], &Temp, sizeof(struct INP3_DEST_ROUTE_ENTRY)); - - Call1[ConvFromAX25(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call1)] = 0; - Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0; - - Debugprintf("INP3 2 routes %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2); - return; - } - - // Have 3 Entries - - - Call1[ConvFromAX25(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call1)] = 0; - Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0; - Call3[ConvFromAX25(Dest->INP3ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call3)] = 0; - - Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3); - - // In order? - - if (Dest->INP3ROUTE[0].SRTT <= Dest->INP3ROUTE[1].SRTT && Dest->INP3ROUTE[1].SRTT <= Dest->INP3ROUTE[2].SRTT)// In order? - return; - - // If second is better that first swap - - if (Dest->INP3ROUTE[0].SRTT > Dest->INP3ROUTE[1].SRTT) - { - memcpy(&Temp, &Dest->INP3ROUTE[0], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memcpy(&Dest->INP3ROUTE[0], &Dest->INP3ROUTE[1], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memcpy(&Dest->INP3ROUTE[1], &Temp, sizeof(struct INP3_DEST_ROUTE_ENTRY)); - } - - - Call1[ConvFromAX25(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call1)] = 0; - Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0; - Call3[ConvFromAX25(Dest->INP3ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call3)] = 0; - - Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3); - - // if 3 is better than 2 swap them. As two is worse than one. three will then be worst - - if (Dest->INP3ROUTE[1].SRTT > Dest->INP3ROUTE[2].SRTT) - { - memcpy(&Temp, &Dest->INP3ROUTE[1], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memcpy(&Dest->INP3ROUTE[1], &Dest->INP3ROUTE[2], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memcpy(&Dest->INP3ROUTE[2], &Temp, sizeof(struct INP3_DEST_ROUTE_ENTRY)); - } - - - Call1[ConvFromAX25(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call1)] = 0; - Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0; - Call3[ConvFromAX25(Dest->INP3ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call3)] = 0; - - Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3); - - // 3 is now slowest. 2 could still be better than 1 - - - if (Dest->INP3ROUTE[0].SRTT > Dest->INP3ROUTE[1].SRTT) - { - memcpy(&Temp, &Dest->INP3ROUTE[0], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memcpy(&Dest->INP3ROUTE[0], &Dest->INP3ROUTE[1], sizeof(struct INP3_DEST_ROUTE_ENTRY)); - memcpy(&Dest->INP3ROUTE[1], &Temp, sizeof(struct INP3_DEST_ROUTE_ENTRY)); - } - - - Call1[ConvFromAX25(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call1)] = 0; - Call2[ConvFromAX25(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call2)] = 0; - Call3[ConvFromAX25(Dest->INP3ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Call3)] = 0; - - Debugprintf("INP3 3 routes %d %s %d %s %d %s", Dest->INP3ROUTE[0].SRTT, Call1, Dest->INP3ROUTE[1].SRTT, Call2, Dest->INP3ROUTE[2].SRTT, Call3); - - if (Dest->INP3ROUTE[0].SRTT <= Dest->INP3ROUTE[1].SRTT && Dest->INP3ROUTE[1].SRTT <= Dest->INP3ROUTE[2].SRTT)// In order? - return; - - // Something went wrong - - Debugprintf("INP3 Sort Failed"); - -} - - - -VOID UpdateRoute(struct DEST_LIST * Dest, struct INP3_DEST_ROUTE_ENTRY * ROUTEPTR, int hops, int rtt) -{ - if (ROUTEPTR->Hops == 0) - { - // This is not a INP3 Route - Convert it - - ROUTEPTR->Hops = hops; - ROUTEPTR->SRTT = rtt; - - SortRoutes(Dest); - return; - } - - if (rtt == 60000) - { - ROUTEPTR->SRTT = rtt; - ROUTEPTR->Hops = hops; - - SortRoutes(Dest); - return; - - } - - ROUTEPTR->SRTT = rtt; - ROUTEPTR->Hops = hops; - - SortRoutes(Dest); - return; -} - -VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len, int Port) -{ - int OtherRTT; - int Dummy; - - char Normcall[10]; - - Normcall[ConvFromAX25(Route->NEIGHBOUR_LINK->LINKCALL, Normcall)] = 0; - - // See if a reply to our message, or a new request - - if (memcmp(Buff->L3SRCE, MYCALL,7) == 0) - { - ProcessRTTReply(Route, Buff); - ReleaseBuffer(Buff); - return; - } - - if (Route->NEIGHBOUR_LINK->LINKPORT->ALLOWINP3) - Route->INP3Node = 1; - - if (Route->INP3Node == 0) - { - Debugprintf("Ignoring RTT Msg from %s - not using INP3", Normcall); - ReleaseBuffer(Buff); - return; // We don't want to use INP3 - } - - // Extract other end's SRTT - - sscanf(&Buff->L4DATA[6], "%d %d", &Dummy, &OtherRTT); - Route->NeighbourSRTT = OtherRTT * 10; // We store in mS - - // Echo Back to sender - - SendNetFrame(Route, Buff); - - if ((Route->Status & GotRTTRequest) == 0) - { - // Link is just starting - - Debugprintf("INP3 Processing first RTT frame from %s - link is (re)starting", Normcall); - Route->Status |= GotRTTRequest; - - // I don't think we should send RIF until we get an RTT response. - - if ((Route->Status & SentRTTRequest) == 0) // Not sent one yet so send it - SendRTTMsg(Route); - - // No, it's the other end that must have an rrt response and we've just sent it - - Route->Status |= SentOurRIF; - SendOurRIF(Route); - SendRIPToNeighbour(Route); - - } -} - - -VOID SendRTTMsg(struct ROUTE * Route) -{ - struct _L3MESSAGEBUFFER * Msg; - char Stamp[50]; - char Normcall[10]; - - Normcall[ConvFromAX25(Route->NEIGHBOUR_CALL, Normcall)] = 0; - - Msg = GetBuff(); - if (Msg == 0) - return; - - Msg->Port = Route->NEIGHBOUR_PORT; - Msg->L3PID = NRPID; - - memcpy(Msg->L3DEST, L3RTT, 7); - memcpy(Msg->L3SRCE, MYCALL, 7); - Msg->L3TTL = 2; - Msg->L4ID = 0; - Msg->L4INDEX = 0; - Msg->L4RXNO = 0; - Msg->L4TXNO = 0; - Msg->L4FLAGS = L4INFO; - - - sprintf(Stamp, "%10llu %10d %10d %10d ", (GetTickCount() - timeLoadedMS), Route->SRTT/10, Route->RTT/10, 0); - memcpy(RTTMsg.TXTIME, Stamp, 44); - - memcpy(Msg->L4DATA, &RTTMsg, 236); - - Msg->LENGTH = 256 + 1 + 7; - - Route->Timeout = RTTTimeout; - - SendNetFrame(Route, Msg); - - if (Route->Status & SentRTTRequest) - return; - - Route->Status |= SentRTTRequest; - - Debugprintf("INP3 Sending first RTT Msg to %s", Normcall); - -} - -VOID SendKeepAlive(struct ROUTE * Route) -{ - struct _L3MESSAGEBUFFER * Msg = GetBuff(); - - if (Msg == 0) - return; - - Msg->L3PID = NRPID; - - memcpy(Msg->L3DEST, L3KEEP, 7); - memcpy(Msg->L3SRCE, MYCALL, 7); - Msg->L3TTL = 1; - Msg->L4ID = 0; - Msg->L4INDEX = 0; - Msg->L4RXNO = 0; - Msg->L4TXNO = 0; - Msg->L4FLAGS = L4INFO; - -// Msg->L3MSG.L4DATA[0] = 'K'; - - Msg->LENGTH = 20 + MSGHDDRLEN + 1; - - SendNetFrame(Route, Msg); -} - -int BuildRIF(UCHAR * RIF, UCHAR * Call, UCHAR * Alias, int Hops, int RTT) -{ - int AliasLen; - int RIFLen; - UCHAR AliasCopy[10] = ""; - UCHAR * ptr; - char Normcall[10]; - - Normcall[ConvFromAX25(Call, Normcall)] = 0; - - if (RTT > 60000) RTT = 60000; // Dont send more than 60000 - - memcpy(&RIF[0], Call, 7); - RIF[7] = Hops; - RIF[8] = RTT >> 8; - RIF[9] = RTT & 0xff; - - if (Alias) - { - // Need to null-terminate Alias - - memcpy(AliasCopy, Alias, 6); - ptr = strchr(AliasCopy, ' '); - - if (ptr) - *ptr = 0; - - AliasLen = (int)strlen(AliasCopy); - - RIF[10] = AliasLen+2; - RIF[11] = 0; - memcpy(&RIF[12], Alias, AliasLen); - RIF[12+AliasLen] = 0; - - RIFLen = 13 + AliasLen; - Debugprintf("INP3 sending RIF Entry %s:%s %d %d", AliasCopy, Normcall, Hops, RTT); - return RIFLen; - } - RIF[10] = 0; - - Debugprintf("INP3 sending RIF Entry %s %d %d", Normcall, Hops, RTT); - - return (11); -} - - -VOID SendOurRIF(struct ROUTE * Route) -{ - struct _L3MESSAGEBUFFER * Msg; - int RIFLen; - int totLen = 1; - int App; - APPLCALLS * APPL; - char Normcall[10]; - - Msg = GetBuff(); - if (Msg == 0) - return; - - - Normcall[ConvFromAX25(Route->NEIGHBOUR_LINK->LINKCALL, Normcall)] = 0; - Debugprintf("INP3 Sending Initial RIF to %s ", Normcall); - - - Msg->L3SRCE[0] = 0xff; - - // send a RIF for our Node and all our APPLCalls - - RIFLen = BuildRIF(&Msg->L3SRCE[totLen], MYCALL, MYALIASTEXT, 1, 0); - totLen += RIFLen; - - for (App = 0; App < NumberofAppls; App++) - { - APPL=&APPLCALLTABLE[App]; - - if (APPL->APPLQUAL > 0) - { - RIFLen = BuildRIF(&Msg->L3SRCE[totLen], APPL->APPLCALL, APPL->APPLALIAS_TEXT, 1, 0); - totLen += RIFLen; - } - } - - Msg->L3PID = NRPID; - Msg->LENGTH = totLen + 1 + MSGHDDRLEN; - - SendNetFrame(Route, Msg); -} - -int SendRIPTimer() -{ - int count, nodes; - struct ROUTE * Route = NEIGHBOURS; - int MaxRoutes = MAXNEIGHBOURS; - int INP3Delay; - char Normcall[10]; - - - for (count=0; countNEIGHBOUR_CALL[0] != 0) - { - if (Route->NoKeepAlive) // Keepalive Disabled - { - Route++; - continue; - } - - if (Route->NEIGHBOUR_LINK == 0 || Route->NEIGHBOUR_LINK->LINKPORT == 0) - { - if (Route->NEIGHBOUR_QUAL == 0) - { - Route++; - continue; // Qual zero is a locked out route - } - - // Dont Activate if link has no nodes unless INP3 - - if (Route->INP3Node == 0) - { - nodes = COUNTNODES(Route); - - if (nodes == 0) - { - Route++; - continue; - } - } - - // Delay more if Locked - they could be retrying for a long time - - if ((Route->NEIGHBOUR_FLAG)) // LOCKED ROUTE - INP3Delay = 1200; - else - INP3Delay = 600; - - if (Route->LastConnectAttempt && - (REALTIMETICKS - Route->LastConnectAttempt) < INP3Delay) - { - Route++; - continue; // No room for link - } - - // Try to activate link - - if (Route->INP3Node) - { - Normcall[ConvFromAX25(Route->NEIGHBOUR_CALL, Normcall)] = 0; - Debugprintf("INP3 Activating link to %s", Normcall); - } - - L2SETUPCROSSLINKEX(Route, 2); // Only try SABM twice - - Route->LastConnectAttempt = REALTIMETICKS; - - if (Route->NEIGHBOUR_LINK == 0) - { - Route++; - continue; // No room for link - } - } - - if (Route->NEIGHBOUR_LINK->L2STATE != 5) // Not up yet - { - Route++; - continue; - } - - if (Route->NEIGHBOUR_LINK->KILLTIMER > ((L4LIMIT - 60) * 3)) // IDLETIME - 1 Minute - { - SendKeepAlive(Route); - Route->NEIGHBOUR_LINK->KILLTIMER = 0; // Keep Open - } - -#ifdef NOINP3 - - Route++; - continue; - -#endif - if (Route->INP3Node) - { - if (Route->Timeout) - { - // Waiting for response - - Route->Timeout--; - - if (Route->Timeout) - { - Route++; - continue; // Wait - } - // No response Try again - - Route->Retries--; - - if (Route->Retries) - { - // More Left - - SendRTTMsg(Route); - } - else - { - // No Response - Kill all Nodes via this link - - if (Route->Status) - { - char Call [11] = ""; - - ConvFromAX25(Route->NEIGHBOUR_CALL, Call); - Debugprintf("BPQ32 INP3 Neighbour %s Lost", Call); - - Route->Status = 0; // Down - } - - Route->BCTimer=5; // Wait a while before retrying - } - } - - if (Route->BCTimer) - { - Route->BCTimer--; - } - else - { - Route->BCTimer = RTTInterval; - Route->Retries = RTTRetries; - SendRTTMsg(Route); - } - } - } - - Route++; - } - - return (0); -} - -// Create an Empty RIF - -struct _L3MESSAGEBUFFER * CreateRIFHeader(struct ROUTE * Route) -{ - struct _L3MESSAGEBUFFER * Msg = GetBuff(); - UCHAR AliasCopy[10] = ""; - - if (Msg) - { - Msg->LENGTH = 1; - Msg->L3SRCE[0] = 0xff; - - Msg->L3PID = NRPID; - } - return Msg; - -} - -VOID SendRIF(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Msg) -{ - char Normcall[10]; - - Normcall[ConvFromAX25(Route->NEIGHBOUR_CALL, Normcall)] = 0; - - Msg->LENGTH += MSGHDDRLEN + 1; // PID - - Debugprintf("Sending INP3 RIF length %d to %s", Msg->LENGTH, Normcall); - SendNetFrame(Route, Msg); -} - -VOID SendRIPToOtherNeighbours(UCHAR * axcall, UCHAR * alias, struct INP3_DEST_ROUTE_ENTRY * Entry) -{ - struct ROUTE * Routes = NEIGHBOURS; - struct _L3MESSAGEBUFFER * Msg; - int count, MaxRoutes = MAXNEIGHBOURS; - char Normcall[10]; - - Normcall[ConvFromAX25(axcall, Normcall)] = 0; - - Debugprintf("INP3 SendRIPToOtherNeighbours for %s", Normcall); - - for (count=0; countINP3Node) && - (Routes->Status) && - (Routes != Entry->ROUT_NEIGHBOUR)) // Dont send to originator of route - { - Msg = Routes->Msg; - - if (Msg == NULL) - { - Normcall[ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall)] = 0; - Debugprintf("INP3 Building RIF to send to %s", Normcall); - Msg = Routes->Msg = CreateRIFHeader(Routes); - } - - if (Msg) - { - - Msg->LENGTH += BuildRIF(&Msg->L3SRCE[Msg->LENGTH], - axcall, alias, Entry->Hops + 1, Entry->SRTT + Entry->ROUT_NEIGHBOUR->SRTT/10); - - if (Msg->LENGTH > 250 - 15) -// if (Msg->LENGTH > Routes->NBOUR_PACLEN - 11) - { - SendRIF(Routes, Msg); - Routes->Msg = NULL; - } - } - } - Routes+=1; - } -} - -VOID SendRIPToNeighbour(struct ROUTE * Route) -{ - int i; - struct DEST_LIST * Dest = DESTS; - struct INP3_DEST_ROUTE_ENTRY * Entry; - struct _L3MESSAGEBUFFER * Msg; - - char Normcall[10]; - - Normcall[ConvFromAX25(Route->NEIGHBOUR_LINK->LINKCALL, Normcall)] = 0; - Debugprintf("INP3 Sending Our Table to %s ", Normcall); - - Dest--; - - // Send all entries not via this Neighbour - used when link starts - - for (i=0; i < MAXDESTS; i++) - { - Dest++; - - Entry = &Dest->INP3ROUTE[0]; - - if (Entry->ROUT_NEIGHBOUR && Entry->Hops && Route != Entry->ROUT_NEIGHBOUR) - { - // Best Route not via this neighbour - send - - Msg = Route->Msg; - - if (Msg == NULL) - Msg = Route->Msg = CreateRIFHeader(Route); - - if (Msg == NULL) - return; - - Msg->LENGTH += BuildRIF(&Msg->L3SRCE[Msg->LENGTH], - Dest->DEST_CALL, Dest->DEST_ALIAS, - Entry->Hops + 1, Entry->SRTT + Entry->ROUT_NEIGHBOUR->SRTT/10); - - if (Msg->LENGTH > 250 - 15) - { - SendRIF(Route, Msg); - Route->Msg = NULL; - } - } - } - if (Route->Msg) - { - SendRIF(Route, Route->Msg); - Route->Msg = NULL; - } -} - -VOID FlushRIFs() -{ - struct ROUTE * Routes = NEIGHBOURS; - int count, MaxRoutes = MAXNEIGHBOURS; - - for (count=0; countMsg) - { - char Normcall[10]; - - Normcall[ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall)] = 0; - SendRIF(Routes, Routes->Msg); - Routes->Msg = NULL; - Debugprintf("INP3 Flushing RIF to %s", Normcall); - } - Routes+=1; - } -} - -VOID SendNegativeInfo() -{ - int i, Preload; - struct DEST_LIST * Dest = DESTS; - struct INP3_DEST_ROUTE_ENTRY * Entry; - - Dest--; - - // Send RIF for any Dests that have got worse - - // ?? Should we send to one Neighbour at a time, or do all in parallel ?? - - // The spec says send Negative info as soon as possible so I'll try building them in parallel - // That will mean building several packets in parallel - - - for (i=0; i < MAXDESTS; i++) - { - Dest++; - - Entry = &Dest->INP3ROUTE[0]; - - if (Entry->SRTT > Entry->LastRTT) - { - if (Entry->LastRTT) // if zero haven't yet reported +ve info - { - if (Entry->LastRTT == 1) // if 1, probably new, so send alias - SendRIPToOtherNeighbours(Dest->DEST_CALL, Dest->DEST_ALIAS, Entry); - else - SendRIPToOtherNeighbours(Dest->DEST_CALL, 0, Entry); - - Preload = Entry->SRTT /10; - if (Entry->SRTT < 60000) - Entry->LastRTT = Entry->SRTT + Preload; //10% Negative Preload - } - } - - if (Entry->SRTT >= 60000) - { - // It is dead, and we have reported it if necessary, so remove if no NETROM Routes - - if (Dest->NRROUTE[0].ROUT_NEIGHBOUR == 0) // No more Netrom Routes - { - char call[11]=""; - ConvFromAX25(Dest->DEST_CALL, call); - Debugprintf("INP3 Deleting Node %s", call); - REMOVENODE(Dest); // Clear buffers, Remove from Sorted Nodes chain, and zap entry - } - else - { - // Have a NETROM route, so zap the INP3 one - - memset(Entry, 0, sizeof(struct INP3_DEST_ROUTE_ENTRY)); - } - - if (Dest->DEST_ROUTE == 4) // we were using it - Dest->DEST_ROUTE = 0; - - } - } -} - -VOID SendPositiveInfo() -{ - int i; - struct DEST_LIST * Dest = DESTS; - struct INP3_DEST_ROUTE_ENTRY * Entry; - - Dest--; - - // Send RIF for any Dests that have got significantly better or are newly discovered - - for (i=0; i < MAXDESTS; i++) - { - Dest++; - - Entry = &Dest->INP3ROUTE[0]; - - if (( (Entry->SRTT) && (Entry->LastRTT == 0) )|| // if zero haven't yet reported +ve info - ((((Entry->SRTT * 125) /100) < Entry->LastRTT) && // Better by 25% - ((Entry->LastRTT - Entry->SRTT) > 10))) // and 100ms - { - SendRIPToOtherNeighbours(Dest->DEST_CALL, 0, Entry); - Dest->INP3ROUTE[0].LastRTT = (Dest->INP3ROUTE[0].SRTT * 11) / 10; //10% Negative Preload - } - } -} - -VOID SendNewInfo() -{ - int i; - unsigned int NewRTT; - struct DEST_LIST * Dest = DESTS; - struct INP3_DEST_ROUTE_ENTRY * Entry; - - Dest--; - - // Send RIF for any Dests that have just been added - - for (i=0; i < MAXDESTS; i++) - { - Dest++; - - if (Dest->INP3FLAGS & NewNode) - { - Dest->INP3FLAGS &= ~NewNode; - - Entry = &Dest->INP3ROUTE[0]; - - SendRIPToOtherNeighbours(Dest->DEST_CALL, Dest->DEST_ALIAS, Entry); - - NewRTT = (Entry->SRTT * 11) / 10; - Entry->LastRTT = NewRTT; //10% Negative Preload - } - } -} - - -VOID INP3TIMER() -{ - if (RTTMsg.ID[0] == 0) - InitialiseRTT(); - - // Called once per second - -#ifdef NOINP3 - - if (RIPTimerCount == 0) - { - RIPTimerCount = 10; - SendRIPTimer(); - } - else - RIPTimerCount--; - - return; - -#endif - - SendNegativeInfo(); // Urgent - - if (RIPTimerCount == 0) - { - RIPTimerCount = 10; - SendNewInfo(); // Not quite so urgent - SendRIPTimer(); - } - else - RIPTimerCount--; - - if (PosTimerCount == 0) - { - PosTimerCount = 300; // 5 mins - SendPositiveInfo(); - } - else - PosTimerCount--; - - FlushRIFs(); - -} - - -UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, unsigned int msglen) -{ - char call[10]; - int calllen; - int hops; - unsigned short rtt; - unsigned int len; - unsigned int opcode; - char alias[10] = ""; - UCHAR IP[6]; - int i; - - ptr2+=sprintf(ptr2, " INP3 RIF:\r Alias Call Hops RTT\r"); - - while (msglen > 0) - { - calllen = ConvFromAX25(ptr1, call); - call[calllen] = 0; - - // Validate the call - - for (i = 0; i < calllen; i++) - { - if (!isupper(call[i]) && !isdigit(call[i]) && call[i] != '-') - { - ptr2+=sprintf(ptr2, " Corrupt RIF\r"); - return ptr2; - } - } - - ptr1+=7; - - hops = *ptr1++; - rtt = (*ptr1++ << 8); - rtt += *ptr1++; - - IP[0] = 0; - strcpy(alias, " "); - - msglen -= 10; - - while (*ptr1 && msglen > 0) - { - len = *ptr1; - opcode = *(ptr1+1); - - if (len < 2 || len > msglen) - { - ptr2+=sprintf(ptr2, " Corrupt RIF\r"); - return ptr2; - } - if (opcode == 0 && len < 9) - { - memcpy(&alias[6 - (len - 2)], ptr1+2, len-2); // Right Justiify - } - else - if (opcode == 1 && len < 8) - { - memcpy(IP, ptr1+2, len-2); - } - ptr2+=sprintf(ptr2, " %s:%s %d %4.2d\r", alias, call, hops, rtt); - - ptr1++; - msglen--; // EOP - } - - return ptr2; - } - return ptr2; -} - -// Paula's conversion of rtt to Quality - -int inp3_tt2qual (int tt, int hops) -{ - int qual; - - if (tt >= 60000 || hops > 30) - return(0); - - qual = 254 - (tt/20); - - if (qual > 254 - hops) - qual = 254 - hops; - - if (qual < 0) - qual=0; - - return(qual); -} - diff --git a/.svn/pristine/0e/0ebfb2fa079aeb6cc3c978273fe57af90ded386a.svn-base b/.svn/pristine/0e/0ebfb2fa079aeb6cc3c978273fe57af90ded386a.svn-base deleted file mode 100644 index a4021bf..0000000 --- a/.svn/pristine/0e/0ebfb2fa079aeb6cc3c978273fe57af90ded386a.svn-base +++ /dev/null @@ -1,1856 +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 provide a basic Gateway between IP over AX.25 and the Internet. - -// Uses WinPcap on Windows, TAP Driver on Linux - -// Basically operates as a mac level bridge, with headers converted between ax.25 and Ethernet. -// ARP frames are also reformatted, and monitored to build a simple routing table. -// Apps may not use ARP (MSYS is configured with an ax.25 default route, rather than an IP one), -// so the default route must be configured. - -// Intended as a gateway for legacy apps, rather than a full function ip over ax.25 router. -// Suggested config is to use the Internet Ethernet Adapter, behind a NAT/PAT Router. -// The ax.25 applications will appear as single addresses on the Ethernet LAN - -// The code can also switch packets between ax.25 interfaces - -// First Version, July 2008 - -// Version 1.2.1 January 2009 - -// Add IP Address Mapping option - -// June 2014. Convert to Router instead of MAC Bridge, and include a RIP44 decoder -// so packets can be routed from RF to/from encapsulated 44 net subnets. -// Routes may also be learned from received RF packets, or added from config file - -/* -TODo ?Multiple Adapters -*/ - - -// ip tuntap add dev bpqtap mode tap -// ifconfig bpqtap 44.131.4.19 mtu 256 up - - - -#pragma data_seg("_BPQDATA") - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include - -#include "cheaders.h" - -#include "ipcode.h" - -#ifdef WIN32 -#include "pcap.h" -#endif - -#ifndef LINBPQ -#include "kernelresource.h" -LRESULT CALLBACK ResWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -#endif - -//#define s_addr S_un.S_addr - -extern BPQVECSTRUC * IPHOSTVECTORPTR; - -BOOL APIENTRY Send_AX(PMESSAGE Block, DWORD Len, UCHAR Port); -VOID SENDSABM(struct _LINKTABLE * LINK); -BOOL FindLink(UCHAR * LinkCall, UCHAR * OurCall, int Port, struct _LINKTABLE ** REQLINK); -BOOL ProcessConfig(); -VOID RemoveARP(PARPDATA Arp); - -VOID ProcessTunnelMsg(PIPMSG IPptr); -VOID ProcessRIP44Message(PIPMSG IPptr); -PROUTEENTRY LookupRoute(uint32_t IPADDR, uint32_t Mask, BOOL Add, BOOL * Found); -BOOL ProcessROUTELine(char * buf, BOOL Locked); -VOID DoRouteTimer(); -PROUTEENTRY FindRoute(uint32_t IPADDR); -VOID SendIPtoEncap(PIPMSG IPptr, uint32_t Encap); -USHORT Generate_CHECKSUM(VOID * ptr1, int Len); - -static VOID MapRouteIPMsg(PIPMSG IPptr); -BOOL Check_Checksum(VOID * ptr1, int Len); - -static BOOL Send_ETH(VOID * Block, DWORD len); - -VOID ProcessEthARPMsg(PETHARP arpptr); -static VOID SendARPMsg(PARPDATA Arp); -VOID SendICMPTimeExceeded(PIPMSG IPptr); - -#define ARPTIMEOUT 3600 - - -// ARP REQUEST/REPLY (Eth) - -static ETHARP ETHARPREQMSG = {0}; - -static ARPDATA ** ARPRecords = NULL; // ARP Table - malloc'ed as needed - -static int NumberofARPEntries = 0; - -static ROUTEENTRY ** RouteRecords = NULL; - -static int NumberofRoutes = 0; - -//HANDLE hBPQNET = INVALID_HANDLE_VALUE; - -static uint32_t OurIPAddr = 0; - -static uint32_t OurIPBroadcast = 0; -static uint32_t OurNetMask = 0xffffffff; - -static BOOL WantTAP = FALSE; -static BOOL WantEncap = 0; // Run RIP44 and Net44 Encap - -static int IPTTL = 128; - -static int FramesForwarded = 0; -static int FramesDropped = 0; -static int ARPTimeouts = 0; -static int SecTimer = 10; - -static BOOL NeedResolver = FALSE; - -static HMENU hMenu; -extern HMENU hWndMenu; -static HMENU hPopMenu; - -extern HKEY REGTREE; - -extern int OffsetH, OffsetW; - -extern HMENU hMainFrameMenu, hBaseMenu; -extern HWND ClientWnd, FrameWnd; - -static int map_table_len = 0; -//int index=0; // pointer for table search -static int ResolveIndex=-1; // pointer to entry being resolved - -static struct map_table_entry map_table[MAX_ENTRIES]; - -static int Windowlength, WindowParam; - - -static time_t ltime,lasttime; - -static char ConfigClassName[]="CONFIG"; - -HWND hIPResWnd = 0; - -BOOL IPMinimized; - -static int baseline=0; - -static unsigned char hostaddr[64]; - - -// Following two fields used by stats to get round shared memmory problem - -static ARPDATA Arp={0}; -static int ARPFlag = -1; - -// Following Buffer is used for msgs from WinPcap. Put the Enet message part way down the buffer, -// so there is room for ax.25 header instead of Enet header when we route the frame to ax.25 -// Enet Header ia 14 bytes, AX.25 UI is 16 - -// Also used to reassemble NOS Fragmented ax.25 packets - -static UCHAR Buffer[4096] = {0}; - -#define EthOffset 30 // Should be plenty - -static DWORD IPLen = 0; - - -#ifdef WIN32 -static UCHAR ourMACAddr[6] = {02,'B','P','Q',3,48}; -#else -UCHAR ourMACAddr[6] = {02,'B','P','Q',0,1}; -#endif - -static LONG DefaultIPAddr = 0; - -static IPSTATS IPStats = {0}; - -static UCHAR BPQDirectory[260]; - -static char ARPFN[MAX_PATH]; - -static HANDLE handle; - -#ifdef WIN32 -static pcap_t *adhandle = 0; -static pcap_t * (FAR * pcap_open_livex)(const char *, int, int, int, char *); - -static int pcap_reopen_delay; -#endif - -static char Adapter[256]; - -static int Promiscuous = 1; // Default to Promiscuous - -#ifdef WIN32 - -static HINSTANCE PcapDriver=0; - -typedef int (FAR *FARPROCX)(); - -static int (FAR * pcap_sendpacketx)(); - -static FARPROCX pcap_compilex; -static FARPROCX pcap_setfilterx; -static FARPROCX pcap_datalinkx; -static FARPROCX pcap_next_exx; -static FARPROCX pcap_geterrx; - - -static char Dllname[6]="wpcap"; - -FARPROCX GetAddress(char * Proc); - -#else - -#define pcap_compilex pcap_compile -#define pcap_open_livex pcap_open_live -#define pcap_setfilterx pcap_setfilter -#define pcap_datalinkx pcap_datalink -#define pcap_next_exx pcap_next_ex -#define pcap_geterrx pcap_geterr -#define pcap_sendpacketx pcap_sendpacket -#endif -VOID __cdecl Debugprintf(const char * format, ...); - -static HANDLE hInstance; - - - - -void OpenTAP(); - -Dll BOOL APIENTRY Init_PM() -{ - ARPDATA * ARPptr; - - if (hIPResWnd) - { - PostMessage(hIPResWnd, WM_CLOSE,0,0); -// DestroyWindow(hIPResWnd); - - Debugprintf("IP Init Destroying IP Resolver"); - } - - hIPResWnd= NULL; - - ARPRecords = NULL; // ARP Table - malloc'ed as needed - NumberofARPEntries=0; - - RouteRecords = NULL; - NumberofRoutes = 0; - - ReadConfigFile(); - - // Clear old packets - - memset(ETHARPREQMSG.MSGHDDR.DEST, 255, 6); - memcpy(ETHARPREQMSG.MSGHDDR.SOURCE, ourMACAddr, 6); - ETHARPREQMSG.MSGHDDR.ETYPE = 0x0608; // ARP - - ETHARPREQMSG.HWTYPE=0x0100; // Eth - ETHARPREQMSG.PID=0x0008; - ETHARPREQMSG.HWADDRLEN = 6; - ETHARPREQMSG.IPADDRLEN = 4; - -#ifdef WIN32 - - // - // Open PCAP Driver - - if (Adapter[0]) // Don't have to have ethernet, if used just as ip over ax.25 switch - { - char buf[80]; - - if (OpenPCAP()) - sprintf(buf,"Portmapper Using %s\n", Adapter); - else - sprintf(buf," Portmapper Unable to open %s\n", Adapter); - - WritetoConsoleLocal(buf); - - if (adhandle == NULL) - { - WritetoConsoleLocal("Failed to open pcap device - Portmapper Disabled\n"); - return FALSE; - } - - // Allocate ARP Entry for Default Gateway, and send ARP for it - - if (DefaultIPAddr) - { - ARPptr = AllocARPEntry(); - - if (ARPptr != NULL) - { - ARPptr->ARPINTERFACE = 255; - ARPptr->ARPTYPE = 'E'; - ARPptr->IPADDR = DefaultIPAddr; - ARPptr->LOCKED = TRUE; - - SendARPMsg(ARPptr); - } - } - } - -#else - - // Linux - if TAP requested, open it -#ifndef MACBPQ - - if (WantTAP) - OpenTAP(); - -#endif -#endif - - -#ifndef LINBPQ - - if (NeedResolver) - { - WNDCLASS wc; - int i; - char WindowTitle[100]; - int retCode, Type, Vallen; - HKEY hKey; - char Size[80]; - RECT Rect = {0,0,0,0}; - - retCode = RegOpenKeyEx (REGTREE, "SOFTWARE\\G8BPQ\\BPQ32", 0, KEY_QUERY_VALUE, &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"IPResSize",0, - (uint32_t *)&Type,(UCHAR *)&Size,(uint32_t *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size,"%d,%d,%d,%d,%d",&Rect.left,&Rect.right,&Rect.top,&Rect.bottom, &IPMinimized); - - if (Rect.top < - 500 || Rect.left < - 500) - { - Rect.left = 0; - Rect.top = 0; - Rect.right = 600; - Rect.bottom = 400; - } - - RegCloseKey(hKey); - } - - // Fill in window class structure with parameters that describe - // the main window. - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)ResWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = NULL ; - wc.lpszClassName = "IPAppName"; - - // Register the window classes - - RegisterClass(&wc); - - i=GetLastError(); - - Windowlength=(map_table_len)*14+100; - WindowParam=WS_OVERLAPPEDWINDOW | WS_VSCROLL; - - sprintf(WindowTitle,"PortM Resolver"); - - hIPResWnd = CreateMDIWindow("IPAppName", WindowTitle, WindowParam, - Rect.left - (OffsetW /2), Rect.top - OffsetH, Rect.right - Rect.left, Rect.bottom - Rect.top, - ClientWnd, hInstance, 1234); - - hPopMenu = CreatePopupMenu(); - AppendMenu(hPopMenu, MF_STRING, BPQREREAD, "ReRead Config"); - - SetScrollRange(hIPResWnd,SB_VERT,0, map_table_len,TRUE); - - if (IPMinimized) - ShowWindow(hIPResWnd, SW_SHOWMINIMIZED); - else - ShowWindow(hIPResWnd, SW_RESTORE); - - _beginthread(IPResolveNames, 0, NULL ); - } -#endif - - WritetoConsoleLocal("Portmapper Enabled\n"); - - return TRUE; - -} - -VOID PMClose() -{ -} - -union -{ - struct sockaddr_in rxaddr; - struct sockaddr_in6 rxaddr6; -} RXaddr; - - -Dll BOOL APIENTRY Poll_PM() -{ - int res; - struct pcap_pkthdr *header; - const u_char *pkt_data; - - // Entered every 100 mS - - // if ARPFlag set, copy requested ARP record (For BPQStatus GUI) - - if (ARPFlag != -1) - { - memcpy(&Arp, ARPRecords[ARPFlag], sizeof (ARPDATA)); - ARPFlag = -1; - } - - SecTimer--; - - if (SecTimer == 0) - { - SecTimer = 10; - DoARPTimer(); - DoRouteTimer(); - } - -Pollloop: - -#ifdef WIN32 - - if (adhandle) - { - res = pcap_next_exx(adhandle, &header, &pkt_data); - - if (res > 0) - { - PETHMSG ethptr = (PETHMSG)&Buffer[EthOffset]; - - if (header->len > 1514) - { -// Debugprintf("Ether Packet Len = %d", header->len); - goto Pollloop; - } - - memcpy(&Buffer[EthOffset],pkt_data, header->len); - - if (ethptr->ETYPE == 0x0008) - { - ProcessEthIPMsg((PETHMSG)&Buffer[EthOffset]); - // PIPMSG ipptr = (PIPMSG)&Buffer[EthOffset+14]; - // ProcessIPMsg(ipptr, ethptr->SOURCE, 'E', 255); - goto Pollloop; - } - - if (ethptr->ETYPE == 0x0608) - { - ProcessEthARPMsg((PETHARP)ethptr); - goto Pollloop; - } - - // Ignore anything else - - goto Pollloop; - } - else - { - if (res < 0) - { - char * error = (char *)pcap_geterrx(adhandle) ; - Debugprintf(error); - if (OpenPCAP() == FALSE) - pcap_reopen_delay = 300; - } - } - } - else - { - // No handle. - - if (Adapter[0]) // Don't have to have ethernet, if used just as ip over ax.25 switch - { - // Try reopening periodically - - pcap_reopen_delay --; - - if (pcap_reopen_delay < 0) - if (OpenPCAP() == FALSE) - pcap_reopen_delay = 300; // Retry every 30 seconds - } - } - -#endif - - - return TRUE; -} - - -static BOOL Send_ETH(VOID * Block, DWORD len) -{ -#ifdef WIN32 - if (adhandle) - { -// if (len < 60) len = 60; - - // Send down the packet - - pcap_sendpacketx(adhandle, // Adapter - Block, // buffer with the packet - len); // size - } -#endif - return TRUE; -} - - -static VOID SendIPtoBPQDEV(PIPMSG IPptr, UCHAR * HWADDR) -{ - // AX.25 headers are bigger, so there will always be room in buffer for enet header - - PETHMSG Ethptr = (PETHMSG)IPptr; - int Len; - - (UCHAR *)Ethptr--; - - Len = ntohs(IPptr->IPLENGTH); - - Len+=14; // Add eth Header - - memcpy(Ethptr->DEST, HWADDR, 6); - memcpy(Ethptr->SOURCE, ourMACAddr, 6); - Ethptr->ETYPE= 0x0008; - - Send_ETH(Ethptr,Len); - - return; -} - -static VOID ProcessEthIPMsg(PETHMSG Buffer) - -{ - PIPMSG ipptr = (PIPMSG)&Buffer[1]; - - if (memcmp(Buffer, ourMACAddr,6 ) != 0) - return; // Not for us - - if (memcmp(&Buffer[6], ourMACAddr,6 ) == 0) - return; // Discard our sends - - // if Checkum offload is active we get the packet before the NIC sees it (from PCAP) - - if (ipptr->IPCHECKSUM == 0) // Windows seems to do this - { - // Generate IP and TCP/UDP checksums - - int Len = ntohs(ipptr->IPLENGTH); - Len-=20; - - ipptr->IPCHECKSUM = Generate_CHECKSUM(ipptr, 20); - - if (ipptr->IPPROTOCOL == 6) // TCP - { - PTCPMSG TCP = (PTCPMSG)&ipptr->Data; - PHEADER PH = {0}; - - PH.IPPROTOCOL = 6; - PH.LENGTH = htons(Len); - memcpy(&PH.IPSOURCE, &ipptr->IPSOURCE, 4); - memcpy(&PH.IPDEST, &ipptr->IPDEST, 4); - - TCP->CHECKSUM = ~Generate_CHECKSUM(&PH, 12); - TCP->CHECKSUM = Generate_CHECKSUM(TCP, Len); - } - } - ProcessIPMsg(ipptr, Buffer->SOURCE, 'E', 255); -} - -static VOID ProcessEthARPMsg(PETHARP arpptr) -{ - int i=0; - PARPDATA Arp; - BOOL Found; - - if (memcmp(&arpptr->MSGHDDR.SOURCE, ourMACAddr,6 ) == 0 ) - return; // Discard our sends - - switch (arpptr->ARPOPCODE) - { - case 0x0100: - - // We should only accept requests from our subnet - we might have more than one net on iterface - - if ((arpptr->SENDIPADDR & OurNetMask) != (OurIPAddr & OurNetMask)) - return; - - if (arpptr->TARGETIPADDR == 0) // Request for 0.0.0.0 - return; - - // Add to our table, as we will almost certainly want to send back to it - - Arp = LookupARP(arpptr->SENDIPADDR, TRUE, &Found); - - if (Found) - goto AlreadyThere; // Already there - - if (Arp == NULL) return; // No point of table full - - Arp->IPADDR = arpptr->SENDIPADDR; - Arp->ARPTYPE = 'E'; - Arp->ARPINTERFACE = 255; - Arp->ARPTIMER = ARPTIMEOUT; - - SaveARP(); - -AlreadyThere: - - memcpy(Arp->HWADDR, arpptr->SENDHWADDR ,6); - Arp->ARPVALID = TRUE; - - if (arpptr->TARGETIPADDR == OurIPAddr) - { - uint32_t Save = arpptr->TARGETIPADDR; - - arpptr->ARPOPCODE = 0x0200; - memcpy(arpptr->TARGETHWADDR, arpptr->SENDHWADDR ,6); - memcpy(arpptr->SENDHWADDR, ourMACAddr ,6); - - arpptr->TARGETIPADDR = arpptr->SENDIPADDR; - arpptr->SENDIPADDR = Save; - - memcpy(arpptr->MSGHDDR.DEST, arpptr->MSGHDDR.SOURCE ,6); - memcpy(arpptr->MSGHDDR.SOURCE, ourMACAddr ,6); - - Send_ETH(arpptr,42); - - return; - - } - - break; - - - case 0x0200: - - if (memcmp(&arpptr->MSGHDDR.DEST, ourMACAddr,6 ) != 0 ) - return; // Not for us - - // Update ARP Cache - - Arp = LookupARP(arpptr->SENDIPADDR, TRUE, &Found); - - if (Found) - goto Update; - - if (Arp == NULL) - goto SendBack; - -Update: - Arp->IPADDR = arpptr->SENDIPADDR; - - memcpy(Arp->HWADDR, arpptr->SENDHWADDR ,6); - Arp->ARPTYPE = 'E'; - Arp->ARPINTERFACE = 255; - Arp->ARPVALID = TRUE; - Arp->ARPTIMER = ARPTIMEOUT; - SaveARP(); - -SendBack: - - // Send Back to Originator of ARP Request - - if (arpptr->TARGETIPADDR == OurIPAddr) // Reply to our request? - break; - - default: - break; - } - return; -} - -static int CheckSumAndSend(PIPMSG IPptr, PTCPMSG TCPmsg, USHORT Len) -{ - struct _IPMSG PH = {0}; - IPptr->IPCHECKSUM = 0; - - PH.IPPROTOCOL = 6; - PH.IPLENGTH = htons(Len); - memcpy(&PH.IPSOURCE, &IPptr->IPSOURCE, 4); - memcpy(&PH.IPDEST, &IPptr->IPDEST, 4); - - TCPmsg->CHECKSUM = ~Generate_CHECKSUM(&PH, 20); - TCPmsg->CHECKSUM = Generate_CHECKSUM(TCPmsg, Len); - - // No need to do IP checksum as RouteIPMessage doesit - -// CHECKSUM IT - -// IPptr->IPCHECKSUM = Generate_CHECKSUM(IPptr, 20); - - MapRouteIPMsg(IPptr); - return 0; -} - - -static VOID ProcessIPMsg(PIPMSG IPptr, UCHAR * MACADDR, char Type, UCHAR Port) -{ - uint32_t Dest; - PARPDATA Arp; - BOOL Found; - int index, Len; - PTCPMSG TCPptr; - PUDPMSG UDPptr; - - - if (IPptr->VERLEN != 0x45) return; // Only support Type = 4, Len = 20 - - if (!CheckIPChecksum(IPptr)) return; - - // Make sure origin ia in ARP Table - - Arp = LookupARP(IPptr->IPSOURCE.addr, TRUE, &Found); - - if (!Found) - { - // Add if possible - - if (Arp != NULL) - { - Arp->IPADDR = IPptr->IPSOURCE.addr; - - if (Type == 'E') - { - memcpy(Arp->HWADDR, MACADDR, 6); - } - else - { - memcpy(Arp->HWADDR, MACADDR, 7); - Arp->HWADDR[6] &= 0x7e; - } - Arp->ARPTYPE = Type; - Arp->ARPINTERFACE = Port; - Arp->ARPVALID = TRUE; - Arp->ARPTIMER = ARPTIMEOUT; - - SaveARP(); - } - } - else - Arp->ARPTIMER = ARPTIMEOUT; // Refresh - - // See if for us - if not pass to router - - Dest = IPptr->IPDEST.addr; - - if (Dest == OurIPAddr || Dest == 0xffffffff || Dest == OurIPBroadcast) - goto ForUs; - - return; - -ForUs: - -// if (IPptr->IPPROTOCOL == 4) // AMPRNET Tunnelled Packet -// { -// ProcessTunnelMsg(IPptr); -// return; -// } - - if (IPptr->IPPROTOCOL == 1) // ICMP - { - ProcessICMPMsg(IPptr); - return; - } - - // Support UDP for SNMP - - if (IPptr->IPPROTOCOL == 17) // UDP - { - UDPptr = (PUDPMSG)&IPptr->Data; - - if (UDPptr->DESTPORT == htons(161)) - { - ProcessSNMPMessage(IPptr); - return; - } - } - - // See if for a mapped Address - - if (IPptr->IPPROTOCOL != 6) return; // Only TCP - - TCPptr = (PTCPMSG)&IPptr->Data; - - Len = ntohs(IPptr->IPLENGTH); - Len-=20; - - for (index=0; index < map_table_len; index++) - { - if ((map_table[index].sourceport == TCPptr->DESTPORT) && - map_table[index].sourceipaddr == IPptr->IPSOURCE.addr) - { - // Outgoing Message - replace Dest IP address and Port. Source Port remains unchanged - - IPptr->IPSOURCE.addr = OurIPAddr; - IPptr->IPDEST.addr = map_table[index].mappedipaddr; - TCPptr->DESTPORT = map_table[index].mappedport; - CheckSumAndSend(IPptr, TCPptr, Len); - return; - } - - if ((map_table[index].mappedport == TCPptr->SOURCEPORT) && - map_table[index].mappedipaddr == IPptr->IPSOURCE.addr) - { - // Incomming Message - replace Dest IP address and Source Port - - IPptr->IPSOURCE.addr = OurIPAddr; - IPptr->IPDEST.addr = map_table[index].sourceipaddr; - TCPptr->SOURCEPORT = map_table[index].sourceport; - CheckSumAndSend(IPptr, TCPptr, Len); - return; - } - } -} - -static VOID ProcessICMPMsg(PIPMSG IPptr) -{ - int Len; - PICMPMSG ICMPptr = (PICMPMSG)&IPptr->Data; - - Len = ntohs(IPptr->IPLENGTH); - Len-=20; - - Check_Checksum(ICMPptr, Len); - - if (ICMPptr->ICMPTYPE == 8) - { - // ICMP_ECHO - - ICMPptr->ICMPTYPE = 0; // Convert to Reply - - // CHECKSUM IT - - ICMPptr->ICMPCHECKSUM = 0; - ICMPptr->ICMPCHECKSUM = Generate_CHECKSUM(ICMPptr, Len); - - // Swap Dest to Origin - - IPptr->IPDEST = IPptr->IPSOURCE; - IPptr->IPSOURCE.addr = OurIPAddr; - IPptr->IPTTL = IPTTL; - -// IPptr->IPCHECKSUM = 0; -// IPptr->IPCHECKSUM = Generate_CHECKSUM(IPptr, 20); // RouteIPMsg redoes checksum - - MapRouteIPMsg(IPptr); // Send Back - } - - if (ICMPptr->ICMPTYPE == 0) - { - // ICMP_REPLY: - - // I don't see how Portmapper should be getting ping responses - -/* - UCHAR * BUFFER = GetBuff(); - UCHAR * ptr1; - struct _MESSAGE * Msg; - TRANSPORTENTRY * Session = L4TABLE; - char IP[20]; - unsigned char work[4]; - - Session += ICMPptr->ICMPID; - - if (BUFFER == NULL) - return; - - ptr1 = &BUFFER[7]; - - memcpy(work, &IPptr->IPSOURCE, 4); - sprintf(IP, "%d.%d.%d.%d", work[0], work[1], work[2], work[3]); - - *ptr1++ = 0xf0; // PID - - ptr1 += sprintf(ptr1, "Ping Response from %s", IP); - - *ptr1++ = 0x0d; // CR - - Len = ptr1 - BUFFER; - - Msg = (struct _MESSAGE *)BUFFER; - Msg->LENGTH = Len; - Msg->CHAIN = NULL; - - C_Q_ADD(&Session->L4TX_Q, (UINT *)BUFFER); - - PostDataAvailable(Session); -*/ - return; - } -} - - -static VOID SendICMPMessage(PIPMSG IPptr, int Type, int Code, int P2) -{ - PICMPMSG ICMPptr = (PICMPMSG)&IPptr->Data; - UCHAR * ptr; - - if (OurIPAddr == 0) - return; // Can't do much without one - - if (IPptr->IPPROTOCOL == ICMP && ICMPptr->ICMPTYPE == 11) - return; // Don't send Time Exceeded for TimeExceded - - // Copy the Original IP Header and first 8 bytes of packet down the buffer - - ptr = (UCHAR *) ICMPptr; - - memmove(ptr + 8, IPptr, 28); // IP header plus 8 data - -// We swap Souce to Dest, Convert to ICMP 11 and send back first 8 bytes of packet after header - - IPptr->IPDEST = IPptr->IPSOURCE; - IPptr->IPSOURCE.addr = OurIPAddr; - IPptr->IPPROTOCOL = ICMP; - IPptr->IPTTL = IPTTL; - IPptr->FRAGWORD = 0; - IPptr->IPLENGTH = htons(56); // IP Header ICMP Header IP Header 8 Data - - memset (ICMPptr, 0, 8); - ICMPptr->ICMPTYPE = Type; - ICMPptr->ICMPCODE = Code; - ICMPptr->ICMPSEQUENCE = htons(P2); - ICMPptr->ICMPCHECKSUM = Generate_CHECKSUM(ICMPptr, 36); - - MapRouteIPMsg(IPptr); -} - -static VOID MapRouteIPMsg(PIPMSG IPptr) -{ - PARPDATA Arp; - BOOL Found; - - // We rely on the ARP messages generated by either end to route frames. - // If address is not in ARP cache (say call originated by MSYS), send to our default route - - // Decremnent TTL and Recalculate header checksum - - IPptr->IPTTL--; - - if (IPptr->IPTTL == 0) - { - SendICMPTimeExceeded(IPptr); - return; // Should we send time exceeded???? - } - - IPptr->IPCHECKSUM = 0; - IPptr->IPCHECKSUM = Generate_CHECKSUM(IPptr, 20); - - // Look up ARP - - Arp = LookupARP(IPptr->IPDEST.addr, FALSE, &Found); - - // If enabled, look in Net44 Encap Routes - - if (!Found && DefaultIPAddr) - Arp = LookupARP(DefaultIPAddr, FALSE, &Found); - - if (!Found) - return; // No route or default - - if (Arp == NULL) - return; // Should we try to ARP it? - - if (Arp->ARPVALID) - { - SendIPtoBPQDEV(IPptr, Arp->HWADDR); - } - - return; -} - -static PROUTEENTRY AllocRouteEntry() -{ - PROUTEENTRY Routeptr; - - if (NumberofRoutes == 0) - - RouteRecords = malloc(sizeof(void *)); - else - RouteRecords = realloc(RouteRecords,(NumberofRoutes + 1) * sizeof(void *)); - - Routeptr = zalloc(sizeof(ROUTEENTRY)); - - if (Routeptr == NULL) return NULL; - - RouteRecords[NumberofRoutes++] = Routeptr; - - return Routeptr; -} - - -static PARPDATA AllocARPEntry() -{ - ARPDATA * ARPptr; - - if (NumberofARPEntries == 0) - - ARPRecords = malloc(sizeof(void *)); - else - ARPRecords = realloc(ARPRecords, (NumberofARPEntries+1)*sizeof(void *)); - - ARPptr = malloc(sizeof(ARPDATA)); - - if (ARPptr == NULL) return NULL; - - memset(ARPptr, 0, sizeof(ARPDATA)); - - ARPRecords[NumberofARPEntries++] = ARPptr; - - return ARPptr; -} - - static VOID SendARPMsg(PARPDATA Arp) - { - // Send ARP. Initially used only to find default gateway - - Arp->ARPTIMER = 5; // Retry periodically - - ETHARPREQMSG.ARPOPCODE = 0x0100; // ; REQUEST - - ETHARPREQMSG.TARGETIPADDR = Arp->IPADDR; - memset(ETHARPREQMSG.TARGETHWADDR, 0, 6); - - ETHARPREQMSG.SENDIPADDR = OurIPAddr; - memcpy(ETHARPREQMSG.SENDHWADDR,ourMACAddr, 6); - - memcpy(ETHARPREQMSG.MSGHDDR.SOURCE, ourMACAddr, 6); - memset(ETHARPREQMSG.MSGHDDR.DEST, 255, 6); - - Send_ETH(ÐARPREQMSG, 42); - - return; - } - -static PROUTEENTRY FindRoute(uint32_t IPADDR) -{ - PROUTEENTRY Route = NULL; - int i; - - for (i = 0; i < NumberofRoutes; i++) - { - Route = RouteRecords[i]; - - if ((IPADDR & Route->SUBNET) == Route->NETWORK) - return Route; - } - return NULL; -} - - - -static PROUTEENTRY LookupRoute(uint32_t IPADDR, uint32_t Mask, BOOL Add, BOOL * Found) -{ - PROUTEENTRY Route = NULL; - int i; - - for (i = 0; i < NumberofRoutes; i++) - { - Route = RouteRecords[i]; - - if (Route->NETWORK == IPADDR && Route->SUBNET == Mask) - { - *Found = TRUE; - return Route; - } - } - - // Not Found - - *Found = FALSE; - - if (Add) - { - Route = AllocRouteEntry(); - return Route; - } - else - return NULL; -} - -static PARPDATA LookupARP(uint32_t IPADDR, BOOL Add, BOOL * Found) -{ - PARPDATA Arp = NULL; - int i; - - for (i=0; i < NumberofARPEntries; i++) - { - Arp = ARPRecords[i]; - - if (Arp->IPADDR == IPADDR) - { - *Found = TRUE; - return Arp; - } - } - - // Not Found - - *Found = FALSE; - - if (Add) - { - Arp = AllocARPEntry(); - return Arp; - } - else - return NULL; -} -static VOID RemoveARP(PARPDATA Arp); - -static VOID RemoveRoute(PROUTEENTRY Route) -{ - int i; - - for (i=0; i < NumberofRoutes; i++) - { - if (Route == RouteRecords[i]) - { - while (i < NumberofRoutes) - { - RouteRecords[i] = RouteRecords[i+1]; - i++; - } - - if (Route->ARP) - { - PARPDATA Arp = Route->ARP; - Route->ARP->ARPROUTE = NULL; // Avoid recursion - RemoveARP(Arp); - } - - free(Route); - NumberofRoutes--; - return; - } - } -} - - -static VOID RemoveARP(PARPDATA Arp) -{ - int i; - - if (Arp->IPADDR == DefaultIPAddr) - { - // Dont remove Default Gateway. Set to re-resolve - - Arp->ARPVALID = FALSE; - Arp->ARPTIMER = 5; - return; - } - - for (i=0; i < NumberofARPEntries; i++) - { - if (Arp == ARPRecords[i]) - { - while (i < NumberofARPEntries) - { - ARPRecords[i] = ARPRecords[i+1]; - i++; - } - - // Remove linked route - - if (Arp->ARPROUTE) - { - PROUTEENTRY Route = Arp->ARPROUTE; - Arp->ARPROUTE->ARP = NULL; // Avoid recursion - RemoveRoute(Route); - } - - free(Arp); - NumberofARPEntries--; - return; - } - } -} - - -static BOOL ReadConfigFile() -{ - -// IPAddr 192.168.0.129 -// IPBroadcast 192.168.0.255 -// IPGateway 192.168.0.1 -// IPPorts 1,4 - -// MAP 192.168.0.100 1001 n9pmo.dyndns.org 1000 - - char * Config; - char * ptr1, * ptr2; - - char buf[256],errbuf[256]; - - map_table_len = 0; // For reread - - Config = PortConfig[PortMapConfigSlot]; // Config from bpq32.cfg - - 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 (!ProcessLine(buf)) - { - WritetoConsoleLocal("PortMapper bad config record "); - strcat(errbuf, "\n"); - WritetoConsoleLocal(errbuf); - } - } - } - return (TRUE); -} - - -static int ProcessLine(char * buf) -{ - char * ptr, * p_value, * p_origport, * p_host, * p_port; - int port, mappedport, ipad; - - ptr = strtok(buf, " \t\n\r"); - p_value = strtok(NULL, " \t\n\r"); - - - if(ptr == NULL) return (TRUE); - - if(*ptr =='#') return (TRUE); // comment - - if(*ptr ==';') return (TRUE); // comment - - if(_stricmp(ptr,"ADAPTER") == 0) - { -#ifndef WIN32 - WritetoConsoleLocal("IPGating to Ethernet is not supported in this build\n"); - return TRUE; -#endif - strcpy(Adapter,p_value); - return (TRUE); - } - - if(_stricmp(ptr,"promiscuous") == 0) - { - Promiscuous = atoi(p_value); - return (TRUE); - } - - if (_stricmp(ptr,"IPAddr") == 0) - { - OurIPAddr = inet_addr(p_value); - - if (OurIPAddr == INADDR_NONE) return (FALSE); - - return (TRUE); - } - if (_stricmp(ptr,"IPBroadcast") == 0) - { - OurIPBroadcast = inet_addr(p_value); - - if (OurIPBroadcast == INADDR_NONE) return (FALSE); - - return (TRUE); - } - - if (_stricmp(ptr,"IPNetMask") == 0) - { - OurNetMask = inet_addr(p_value); - - if (OurNetMask == INADDR_NONE) return (FALSE); - - return (TRUE); - } - - - if (_stricmp(ptr,"IPGateway") == 0) - { - DefaultIPAddr = inet_addr(p_value); - - if (DefaultIPAddr == INADDR_NONE) return (FALSE); - - return (TRUE); - } - -// ARP 44.131.4.18 GM8BPQ-7 1 D - - if (_stricmp(ptr,"MAP") == 0) - { -#ifdef LINBPQ - - WritetoConsoleLocal("MAP not supported in LinBPQ IP Gateway\n"); - return TRUE; -#endif - if (!p_value) return FALSE; - - p_origport = strtok(NULL, " ,\t\n\r"); - if (!p_origport) return FALSE; - - p_host = strtok(NULL, " ,\t\n\r"); - if (!p_host) return FALSE; - - p_port = strtok(NULL, " ,\t\n\r"); - if (!p_port) return FALSE; - - port=atoi(p_origport); - if (port == 0) return FALSE; - - mappedport=atoi(p_port); - if (mappedport == 0) return FALSE; - - ipad = inet_addr(p_value); - - map_table[map_table_len].sourceipaddr = ipad; - strcpy(map_table[map_table_len].hostname, p_host); - map_table[map_table_len].sourceport = ntohs(port); - map_table[map_table_len++].mappedport = ntohs(mappedport); - - NeedResolver = TRUE; - - return (TRUE); - } - - // - // Bad line - // - return (FALSE); - -} - -static VOID DoARPTimer() -{ - PARPDATA Arp = NULL; - int i; - - for (i=0; i < NumberofARPEntries; i++) - { - Arp = ARPRecords[i]; - - if (!Arp->ARPVALID) - { - Arp->ARPTIMER--; - - if (Arp->ARPTIMER == 0) - { - // Retry Request - - SendARPMsg(Arp); - } - continue; - } - - // Time out active entries - - if (Arp->LOCKED == 0) - { - Arp->ARPTIMER--; - - if (Arp->ARPTIMER == 0) - { - // Remove Entry - - RemoveARP(Arp); - SaveARP(); - } - } - } -} - -static VOID DoRouteTimer() -{ - int i; - PROUTEENTRY Route; - - for (i=0; i < NumberofRoutes; i++) - { - Route = RouteRecords[i]; - if (Route->RIPTIMOUT) - Route->RIPTIMOUT--; - } -} - - -// PCAP Support Code - - -#ifdef WIN32 - -static FARPROCX GetAddress(char * Proc) -{ - FARPROCX ProcAddr; - int err=0; - char buf[256]; - int n; - - - ProcAddr=(FARPROCX) GetProcAddress(PcapDriver,Proc); - - if (ProcAddr == 0) - { - err=GetLastError(); - - n=sprintf(buf,"Error finding %s - %d", Proc,err); - WritetoConsoleLocal(buf); - - return(0); - } - - return ProcAddr; -} - - -static void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); - -static int OpenPCAP() -{ - u_long param=1; - BOOL bcopt=TRUE; - int i=0; - char errbuf[PCAP_ERRBUF_SIZE]; - u_int netmask; - char packet_filter[64]; - struct bpf_program fcode; - char buf[256]; - int n; - - - PcapDriver=LoadLibrary(Dllname); - - if (PcapDriver == NULL) return(FALSE); - - if ((pcap_sendpacketx=GetAddress("pcap_sendpacket")) == 0 ) return FALSE; - - if ((pcap_datalinkx=GetAddress("pcap_datalink")) == 0 ) return FALSE; - - if ((pcap_compilex=GetAddress("pcap_compile")) == 0 ) return FALSE; - - if ((pcap_setfilterx=GetAddress("pcap_setfilter")) == 0 ) return FALSE; - - pcap_open_livex = (pcap_t * (__cdecl *)(const char *, int, int, int, char *)) GetProcAddress(PcapDriver,"pcap_open_live"); - - if (pcap_open_livex == NULL) return FALSE; - - if ((pcap_geterrx=GetAddress("pcap_geterr")) == 0 ) return FALSE; - - if ((pcap_next_exx=GetAddress("pcap_next_ex")) == 0 ) return FALSE; - - /* Open the adapter */ - - adhandle = pcap_open_livex(Adapter, // name of the device - 65536, // portion of the packet to capture. - // 65536 grants that the whole packet will be captured on all the MACs. - Promiscuous, // promiscuous mode (nonzero means promiscuous) - 1, // read timeout - errbuf // error buffer - ); - - if (adhandle == NULL) - return FALSE; - - /* Check the link layer. We support only Ethernet for simplicity. */ - - if(pcap_datalinkx(adhandle) != DLT_EN10MB) - { - n=sprintf(buf,"\nThis program works only on Ethernet networks.\n"); - WritetoConsoleLocal(buf); - - adhandle = 0; - return FALSE; - } - - netmask=0xffffff; - -// sprintf(packet_filter,"ether[12:2]=0x0800 or ether[12:2]=0x0806"); - - sprintf(packet_filter,"ether broadcast or ether dst %02x:%02x:%02x:%02x:%02x:%02x", - ourMACAddr[0], ourMACAddr[1], ourMACAddr[2], - ourMACAddr[3], ourMACAddr[4], ourMACAddr[5]); - - //compile the filter - - if (pcap_compilex(adhandle, &fcode, packet_filter, 1, netmask) <0 ) - { - n=sprintf(buf,"\nUnable to compile the packet filter. Check the syntax.\n"); - WritetoConsoleLocal(buf); - - adhandle = 0; - return FALSE; - } - - //set the filter - - if (pcap_setfilterx(adhandle, &fcode)<0) - { - n=sprintf(buf,"\nError setting the filter.\n"); - WritetoConsoleLocal(buf); - - adhandle = 0; - return FALSE; - } - - return TRUE; -} -#endif - - -int CompareMasks (const VOID * a, const VOID * b); - - -#ifndef LINBPQ - -extern HFONT hFont; -struct tagMSG Msg; -char buf[1024]; - -static LRESULT CALLBACK ResWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - PAINTSTRUCT ps; - HDC hdc; - HFONT hOldFont ; - struct hostent * hostptr; - struct in_addr ipad; - char line[100]; - int index,displayline; - MINMAXINFO * mmi; - - int i=1; - - int nScrollCode,nPos; - - switch (message) - { - case WM_GETMINMAXINFO: - - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = 400; - mmi->ptMaxSize.y = Windowlength; - mmi->ptMaxTrackSize.x = 400; - mmi->ptMaxTrackSize.y = Windowlength; - break; - - case WM_USER+199: - - i=WSAGETASYNCERROR(lParam); - - map_table[ResolveIndex].error=i; - - if (i ==0) - { - // resolved ok - - hostptr=(struct hostent *)&buf; - memcpy(&map_table[ResolveIndex].mappedipaddr,hostptr->h_addr,4); - } - - InvalidateRect(hWnd,NULL,FALSE); - - while (ResolveIndex < map_table_len) - { - ResolveIndex++; - - WSAAsyncGetHostByName (hWnd,WM_USER+199, - map_table[ResolveIndex].hostname, - buf,MAXGETHOSTSTRUCT); - - break; - } - 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, (WPARAM)hPopMenu, "Actions"); - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM)hWndMenu); - } - else - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM)hMainFrameMenu, (LPARAM)NULL); - - DrawMenuBar(FrameWnd); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - } - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - - - if (wmId == BPQREREAD) - { - if (ProcessConfig()) - { - FreeConfig(); - - ReadConfigFile(); - PostMessage(hIPResWnd, WM_TIMER,0,0); - InvalidateRect(hWnd,NULL,TRUE); - } - else - Consoleprintf("Failed to reread config file - leaving config unchanged"); - - return 0; - } -/* - if (wmId == BPQADDARP) - { - if (ConfigWnd == 0) - { - ConfigWnd=CreateDialog(hInstance,ConfigClassName,0,NULL); - - if (!ConfigWnd) - { - i=GetLastError(); - return (FALSE); - } - ShowWindow(ConfigWnd, SW_SHOW); - UpdateWindow(ConfigWnd); - } - - SetForegroundWindow(ConfigWnd); - - return(0); - } - return 0; -*/ - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - case SC_RESTORE: - - IPMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - break; - - case SC_MINIMIZE: - - IPMinimized = TRUE; - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_VSCROLL: - - nScrollCode = (int) LOWORD(wParam); // scroll bar value - nPos = (short int) HIWORD(wParam); // scroll box position - - //hwndScrollBar = (HWND) lParam; // handle of scroll bar - - if (nScrollCode == SB_LINEUP || nScrollCode == SB_PAGEUP) - { - baseline--; - if (baseline <0) - baseline=0; - } - - if (nScrollCode == SB_LINEDOWN || nScrollCode == SB_PAGEDOWN) - { - baseline++; - if (baseline > map_table_len) - baseline = map_table_len; - } - - if (nScrollCode == SB_THUMBTRACK) - { - baseline=nPos; - } - - SetScrollPos(hWnd,SB_VERT,baseline,TRUE); - - InvalidateRect(hWnd,NULL,TRUE); - break; - - - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - - hOldFont = SelectObject( hdc, hFont) ; - - index = baseline; - displayline=0; - - while (index < map_table_len) - { - if (map_table[index].ResolveFlag && map_table[index].error != 0) - { - // resolver error - Display Error Code - sprintf(hostaddr,"Error %d",map_table[index].error); - } - else - { - memcpy(&ipad,&map_table[index].mappedipaddr,4); - strncpy(hostaddr,inet_ntoa(ipad),16); - } - - memcpy(&ipad,&map_table[index].mappedipaddr,4); - - i=sprintf(line,"%.64s = %-.30s", - map_table[index].hostname, - hostaddr); - - TextOut(hdc,0,(displayline++)*14+2,line,i); - - index++; - } - - SelectObject( hdc, hOldFont ) ; - EndPaint (hWnd, &ps); - - break; - - case WM_DESTROY: - - -// PostQuitMessage(0); - - break; - - - case WM_TIMER: - - for (ResolveIndex=0; ResolveIndex < map_table_len; ResolveIndex++) - { - WSAAsyncGetHostByName (hWnd,WM_USER+199, - map_table[ResolveIndex].hostname, - buf,MAXGETHOSTSTRUCT); - break; - } - - default: - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); -} - -static void IPResolveNames( void *dummy ) -{ - SetTimer(hIPResWnd,1,15*60*1000,0); - - PostMessage(hIPResWnd, WM_TIMER,0,0); - - while (GetMessage(&Msg, hIPResWnd, 0, 0)) - { - TranslateMessage(&Msg); - DispatchMessage(&Msg); - } -} - -#endif - -/* -; DO PSEUDO HEADER FIRST -; - MOV DX,600H ; PROTOCOL (REVERSED) - MOV AX,TCPLENGTH ; TCP LENGTH - XCHG AH,AL - ADD DX,AX - MOV AX,WORD PTR LOCALADDR[BX] - ADC DX,AX - MOV AX,WORD PTR LOCALADDR+2[BX] - ADC DX,AX - MOV AX,WORD PTR REMOTEADDR[BX] - ADC DX,AX - MOV AX,WORD PTR REMOTEADDR+2[BX] - ADC DX,AX - ADC DX,0 - - MOV PHSUM,DX - - PUSH BX - - MOV BX,TXBUFFER ; HEADER - - MOV CX,TCPLENGTH ; PUT LENGTH INTO HEADER - MOV BUFFLEN[BX],CX -; - MOV SI,BUFFPTR[BX] - - INC CX ; ROUND UP - SHR CX,1 ; WORD COUNT - - CALL DO_CHECKSUM - - ADD DX,PHSUM - ADC DX,0 - NOT DX - - MOV SI,BUFFPTR[BX] - MOV CHECKSUM[SI],DX - - -*/ diff --git a/.svn/pristine/0e/0efb7b73d192e43b1c3e8d52089e20083efa2b19.svn-base b/.svn/pristine/0e/0efb7b73d192e43b1c3e8d52089e20083efa2b19.svn-base deleted file mode 100644 index cae501a..0000000 --- a/.svn/pristine/0e/0efb7b73d192e43b1c3e8d52089e20083efa2b19.svn-base +++ /dev/null @@ -1,161 +0,0 @@ - -/* pngrio.c - functions for data input - * - * libpng 1.2.8 - December 3, 2004 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2004 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all input. Users who need - * special handling are expected to write a function that has the same - * arguments as this and performs a similar function, but that possibly - * has a different input method. Note that you shouldn't change this - * function, but rather write a replacement function and then make - * libpng use it at run time with png_set_read_fn(...). - */ - -#define PNG_INTERNAL -#include "png.h" - -/* Read the data from whatever input you are using. The default routine - reads from a file pointer. Note that this routine sometimes gets called - with very small lengths, so you should implement some kind of simple - buffering if you are using unbuffered reads. This should never be asked - to read more then 64K on a 16 bit machine. */ -void /* PRIVATE */ -png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_debug1(4,"reading %d bytes\n", (int)length); - if (png_ptr->read_data_fn != NULL) - (*(png_ptr->read_data_fn))(png_ptr, data, length); - else - png_error(png_ptr, "Call to NULL read function"); -} - -#if !defined(PNG_NO_STDIO) -/* This is the function that does the actual reading of data. If you are - not reading from a standard C stream, you should create a replacement - read_data function and use it at run time with png_set_read_fn(), rather - than changing the library. */ -#ifndef USE_FAR_KEYWORD -void PNGAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ -#if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; -#else - check = (png_size_t)fread(data, (png_size_t)1, length, - (png_FILE_p)png_ptr->io_ptr); -#endif - - if (check != length) - png_error(png_ptr, "Read Error"); -} -#else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -static void /* PRIVATE */ -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - int check; - png_byte *n_data; - png_FILE_p io_ptr; - - /* Check if data really is near. If so, use usual code. */ - n_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); - if ((png_bytep)n_data == data) - { -#if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; -#else - check = fread(n_data, 1, length, io_ptr); -#endif - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t read, remaining, err; - check = 0; - remaining = length; - do - { - read = MIN(NEAR_BUF_SIZE, remaining); -#if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) - err = 0; -#else - err = fread(buf, (png_size_t)1, read, io_ptr); -#endif - png_memcpy(data, buf, read); /* copy far buffer to near buffer */ - if(err != read) - break; - else - check += err; - data += read; - remaining -= read; - } - while (remaining != 0); - } - if ((png_uint_32)check != (png_uint_32)length) - png_error(png_ptr, "read Error"); -} -#endif -#endif - -/* This function allows the application to supply a new input function - for libpng if standard C streams aren't being used. - - This function takes as its arguments: - png_ptr - pointer to a png input data structure - io_ptr - pointer to user supplied structure containing info about - the input functions. May be NULL. - read_data_fn - pointer to a new input function that takes as its - arguments a pointer to a png_struct, a pointer to - a location where input data can be stored, and a 32-bit - unsigned int that is the number of bytes to be read. - To exit and output any fatal error messages the new write - function should call png_error(png_ptr, "Error msg"). */ -void PNGAPI -png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn) -{ - png_ptr->io_ptr = io_ptr; - -#if !defined(PNG_NO_STDIO) - if (read_data_fn != NULL) - png_ptr->read_data_fn = read_data_fn; - else - png_ptr->read_data_fn = png_default_read_data; -#else - png_ptr->read_data_fn = read_data_fn; -#endif - - /* It is an error to write to a read device */ - if (png_ptr->write_data_fn != NULL) - { - png_ptr->write_data_fn = NULL; - png_warning(png_ptr, - "It's an error to set both read_data_fn and write_data_fn in the "); - png_warning(png_ptr, - "same structure. Resetting write_data_fn to NULL."); - } - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) - png_ptr->output_flush_fn = NULL; -#endif -} diff --git a/.svn/pristine/0f/0f360bb978fa349027d73174ce2a1e0fd2560283.svn-base b/.svn/pristine/0f/0f360bb978fa349027d73174ce2a1e0fd2560283.svn-base deleted file mode 100644 index efbd1a5..0000000 --- a/.svn/pristine/0f/0f360bb978fa349027d73174ce2a1e0fd2560283.svn-base +++ /dev/null @@ -1,964 +0,0 @@ -// -// Common definitons for Pactor-like Modules - -#include "kernelresource.h" - -#include "rigcontrol.h" - -#define MAXBLOCK 4096 - -#define MAXFREQS 20 // RigControl freqs to scan - -extern char HFCTEXT[81]; -extern int HFCTEXTLEN; - -extern HANDLE hInstance; - -extern HMENU hMainFrameMenu; -extern HMENU hWndMenu; - -/* -struct WL2KInfo -{ - struct WL2KInfo * Next; - - char * Host; - short WL2KPort; - - char RMSCall[10]; - char BaseCall[10]; - char GridSquare[7]; - char Times[80]; - char ServiceCode[17]; - - BOOL UseRigCtrlFreqs; - char WL2KFreq[12]; - char WL2KMode; // WL2K reporting mode - char WL2KModeChar; // W or N - BOOL DontReportNarrowOnWideFreqs; - -// char NARROWMODE; -// char WIDEMODE; // Mode numbers to report to WL2K - -// struct WL2KInfo WL2KInfoList[MAXFREQS]; // Freqs for sending to WL2K - - int Freq; - char Bandwidth; -// char * TimeList; // eg 06-10,12-15 - int mode; // see below (an integer) - int baud; // see below (an integer) - int power; // actual power if known, default to 100 for HF, 30 for VHF/UHF (an integer) - int height; // antenna height in feet if known, default to 25 - int gain; // antenna gain if known, default to 0 - int direction; // primary antenna direction in degrees if known, use 000 for omni (an integer) - BOOL RPonPTC; // Set if scanning for Robust Packet on a PTC -}; - -*/ -#pragma pack(1) - -// AGWPE Header Structure - -struct AGWHEADER -{ - UCHAR Port; - UCHAR filler1[3]; - char DataKind; - UCHAR filler2; - unsigned char PID; - UCHAR filler3; - unsigned char callfrom[10]; - unsigned char callto[10]; - int DataLength; - int reserved; -}; - -#pragma pack() - -// Telnet Server User Record - -struct UserRec -{ - char * Callsign; - char * UserName; - char * Password; - char * Appl; // Autoconnect APPL - BOOL Secure; // Authorised User -}; - -struct LOCALNET -{ - struct LOCALNET * Next; - uint32_t Network; - uint32_t Mask; -}; - - -#define MaxCMS 10 // Number of addresses we can keep - currently 4 are used. - -struct TCPINFO -{ - int NumberofUsers; - struct UserRec ** UserRecPtr; - int CurrentConnections; - - struct UserRec RelayUser; - - int CurrentSockets; - - int TCPPort; - int FBBPort[100]; - int RelayPort; - int HTTPPort; - int APIPort; - int TriModePort; - int SyncPort; - int SNMPPort; - int DRATSPort; - int CMDPort[33]; - char RELAYHOST[64]; - char CMSServer[64]; - BOOL FallbacktoRelay; // Use Relsy if can't connect to CMS - - BOOL IPV4; // Allow Connect using IPV4 - BOOL IPV6; // Allow Connect using IPV6 - BOOL CMS; // Allow Connect to CMS - BOOL CMSOK; // Internet link is ok. - BOOL UseCachedCMSAddrs; - struct in_addr CMSAddr[MaxCMS]; - BOOL CMSFailed[MaxCMS]; // Set if connect to CMS failed. - char * CMSName[MaxCMS]; // Reverse DNS Name of Server - int NumberofCMSAddrs; - int NextCMSAddr; // Round Robin Pointer - int CheckCMSTimer; // CMS Poll Timer - - char SecureCMSPassword[80]; // For Secure CMS Signin - char GatewayCall[10]; // Call for CMS access - char GatewayLoc[10]; // Loc - Needed to report Hybrid Mode - int ReportHybrid; // Report as Hybrod Station - char * HybridServiceCode; - char * HybridFrequencies; - char * HybridCoLocatedRMS; - - BOOL DisconnectOnClose; - - char PasswordMsg[100]; - - char cfgHOSTPROMPT[100]; - - char cfgCTEXT[300]; - - char cfgLOCALECHO[100]; - - int MaxSessions; - - char LoginMsg[100]; - - char RelayAPPL[20]; - char SyncAPPL[20]; - - SOCKET TCPSock; - SOCKET FBBsock[100]; - SOCKET Relaysock; - SOCKET HTTPsock; - SOCKET APIsock; - SOCKET TriModeSock; - SOCKET TriModeDataSock; - SOCKET Syncsock; - SOCKET DRATSsock; - SOCKET SNMPsock; - - struct ConnectionInfo * TriModeControlSession; - SOCKET sock6; - SOCKET FBBsock6[100]; - SOCKET Relaysock6; - SOCKET HTTPsock6; - SOCKET APIsock6; - SOCKET Syncsock6; - SOCKET DRATSsock6; - - fd_set ListenSet; - SOCKET maxsock; - - HMENU hActionMenu; - HMENU hLogMenu; - HMENU hDisMenu; // Disconnect Menu Handle - HWND hCMSWnd; - - int SecureTelnet; - int ReportRelayTraffic; // Send WL2K Reports for Relay Traffic - - char * WebTermCSS; // css override for web terminal - struct LOCALNET * LocalNets; - -}; - - -struct STREAMINFO -{ -// TRANSPORTENTRY * AttachedSession; - - void * PACTORtoBPQ_Q; // Frames for BPQ - void * BPQtoPACTOR_Q; // Frames for PACTOR - int FramesOutstanding; // Frames Queued - used for flow control - int FramesQueued; // Frames Queued - used for flow control - BOOL InternalCmd; // Last Command was generated internally - int IntCmdDelay; // To limit internal commands - BOOL CheckingCall; // Set on PTC if waiting for I response after a Connect RXed - - BOOL Attached; // Set what attached to a BPQ32 stream - BOOL Connected; // When set, all data is passed as data instead of commands - BOOL Connecting; // Set when Outward Connect in progress - BOOL Disconnecting; // Set when disconnect in progress - // Used when appplication disconnects the bpq session, and - // prevents new attaches while a dirty disconnect is in progress - int DisconnectingTimeout; // A hard disconnect occurs if this expires before the disconnect complete - int ReportDISC; // Need to report an incoming DISC to kernel - BOOL DiscWhenAllSent; // Close session when all msgs have been sent to node - BOOL ARQENDSent; // Set when V4 ARQEND Sent - - int DEDStream; // Stream number for DED interface (same as index except for pactor) - - char MyCall[10] ; // Call we are using - char RemoteCall[10]; // Callsign - - char callingCall[10]; // for reporting. Link and Our calls depand on which end connected - char receivingCall[10]; // for reporting. Link and Our calls depand on which end connected - char Direction[4]; // In or Out - - - - char AGWKey[21]; // Session Key for AGW Session Based Drivers - - time_t ConnectTime; // Time connection made - time_t AttachTime; - - int bytesTXed; - int BytesAcked; - int bytesRXed; - int PacketsSent; - int BytesResent; - int BytesOutstanding; // For Packet Channels - - UCHAR PTCStatus0; // Status Bytes - UCHAR PTCStatus1; // Status Bytes - UCHAR PTCStatus2; // Status Bytes - UCHAR PTCStatus3; // Status Bytes - - char * CmdSet; // A series of commands to send to the TNC - char * CmdSave; // Base address for free - - struct ConnectionInfo * ConnectionInfo; // TCP Server Connection Info - - int TimeInRX; // Too long in send mode timer - int NeedDisc; // Timer to send DISC if appl not available - - BOOL NoCMSFallback; // Dont use relay if CMS not available - struct ARQINFO * ARQInfo; // FLDIGI/FLARQ Stream Mode Specific Data - - HWND xIDC_MYCALL; - HWND xIDC_DESTCALL; - HWND xIDC_STATUS; - HWND xIDC_SEND; - HWND xIDC_RXED; - HWND xIDC_RESENT; - HWND xIDC_ACKED; - HWND xIDC_DIRN; - - int RelaySyncStream; - int VaraACMode; -}; - -typedef struct AGWINFO -{ - // Fields for AGW Session based Ports (eg UZ7HO Modem) - - struct AGWHEADER TXHeader; - struct AGWHEADER RXHeader; - int MaxSessions; - int ConnTimeOut; - int PollDelay; - time_t LastParamTime; - -#ifdef WIN32 - - // For selecting UZ7HO Mode and Freq - - COMBOBOXINFO cbinfo; // UZ7HO Modem Combo Box info - HWND hFreq; // UZ7HO Frequency Box - HWND hSpin; // UZ7HO Spin Button - -#endif - - int isQTSM; // Flag to Identify QtSM - - int CenterFreq; - int Modem; // Modem number in list - char ModemName[20]; - unsigned char Version[4]; - unsigned char fx25Flags; - unsigned char il2pFlags; - unsigned char il2pcrc; - -} *PAGWINFO; - -typedef struct ARQINFO -{ - // Fields for FLDIGI/FLARQ Ports - - // Max window is 64, though often will use less - - char OurStream; - char FarStream; - - PMSGWITHLEN TXHOLDQ[64]; // Frames waiting ACK - PMSGWITHLEN RXHOLDQ[64]; // Frames waiting missing frames. - - int TXWindow; - int RXWindow; - int MaxBlock; // Max sending block size - - int TXSeq; - int TXLastACK; // Last frame ACK'ed - - int RXHighest; - int RXNext; - int RXNoGaps; - - int Retries; - int NoAckRetries; // Status received but no data acked - int ARQTimer; - int ARQState; - -#define ARQ_ACTIVE 1 // Have a session of some type - - int ARQTimerState; - -#define ARQ_CONNECTING 1 -#define ARQ_CONNECTACK 2 -#define ARQ_DISC 3 -#define ARQ_WAITACK 4 -#define ARQ_WAITDATA 5 // Waiting for more data before polling - - char LastMsg[80]; // Last message sent that expects an ack - int LastLen; - char TXMsg[80]; // Message to aend after TXDELAY - int TXLen; - int TurnroundTimer; // RX to TX delay. - int TXDelay; - -} *ARQINFO; - -typedef struct FLINFO -{ - // Fields for MPSK Session Ports ) - - BOOL TX; // Set when FLDigi is transmitting - char DefaultMode[64]; // Mode to return to after session - int DefaultFreq; // Freq to return to after session - BOOL Beacon; // Use ALE Beacons - char LastXML[128]; // Last XML Request Sent - int XMLControl; // Controlls polling FLDigi by XML - int CmdControl; // Controlls polling FLDigi by KISS Command - BOOL FLARQ; // Connection from FLARQ - BOOL Busy; - BOOL CONOK; // Allow incoming connects - BOOL KISSMODE; // Using KISS instead of socket interface - BOOL RAW; // Raw (ARQ Socket or KISS RAW, depening on above) - int CenterFreq; - char CurrentMode[20]; // Mode to return to after session - int Responding; // If FLDigi is responding to conmands - BOOL MCASTMODE; // If port is in MCAST RX MOde - -} *FLINFO; - -typedef struct MPSKINFO -{ - // Fields for MPSK Session Ports ) - - int ConnTimeOut; - BOOL TX; // Set when Multipsk is transmitting - char DefaultMode[20]; // Mode to return to after session - BOOL Beacon; // Use ALE Beacons - int MaxSessions; -} *MPSKINFO; - -struct FreeDataINFO -{ - int startingTNC; - int TNCRunning; - int Conecting; - int Connected; - char ourCall[10]; - char toCall[10]; - char farCall[10]; // TNC Call - char useBaseCall; // Use base call (without ssid) for TNC Call - char * Capture; // Capture Device Name - char * Playback; // Playback Device Name - char * hamlibHost; - int hamlibPort; - - unsigned char toSendData[8192]; // Buffer data from node for more efficiency - int toSendCount; - int toSendTimeout; - unsigned char toSendMsg[256]; // Buffer data from node for more efficiency - int toSendMsgCount; - int toSendMsgTimeout; - char * RXDir; // Directory for Received Files - int CONOK; // Virtual Lisren Flag - int Chat; // In Chat Mode - char ChatCall[10]; - int needPoll; // Set if get data needed - int arqstate; // 1 = Disc / 2 - connecting 3 - connected - int TuningRange; // Must be 50, 100, 150, 200, 250 - int LimitBandWidth; - int TXLevel; - int Explorer; // Enable reporting to Freedata Explorer - char SSIDList[256]; - char * SSIDS[16]; -}; - -struct sixPackInfo; - -typedef struct TNCINFO -{ - HWND hDlg; // Status Window Handle - int (FAR * WebWindowProc)(struct TNCINFO * TNC, char * Buff, BOOL LOCAL); // Routine to build web status window - int WebWinX; - int WebWinY; // Size of window - char * WebBuffer; // Buffer for logs - int RigControlRow; // Rig Control Line in Dialog - struct _EXTPORTDATA * PortRecord; // BPQ32 port record for this port - struct RIGINFO * RIG; // Pointer to Rig Control RIG record for RX or Both - struct RIGINFO * TXRIG; // Pointer to Rig Control RIG record for TX - char * InitScript; // Initialisation Commands - int InitScriptLen; // Length - time_t SessionTimeLimit; // Optional limit to total session time - time_t DefaultSessionTimeLimit; // Configured value - - time_t AttachTimeLimit; // to trap port left attached for a long time without other activity - time_t AttachTime; - - int Hardware; // Hardware Type - -#define H_WINMOR 1 -#define H_SCS 2 -#define H_KAM 3 -#define H_AEA 4 -#define H_HAL 5 -#define H_TELNET 6 -#define H_TRK 7 -#define H_TRKM 7 -#define H_V4 8 -#define H_UZ7HO 9 -#define H_MPSK 10 -#define H_FLDIGI 11 -#define H_UIARQ 12 -#define H_ARDOP 13 -#define H_VARA 14 -#define H_SERIAL 15 -#define H_KISSHF 16 -#define H_WINRPR 17 -#define H_HSMODEM 18 -#define H_FREEDATA 19 -#define H_SIXPACK 20 - - - int Port; // BPQ Port Number - - struct RIGINFO DummyRig; // Used if not using Rigcontrol - - BOOL Minimized; // Start Minimized flag - - void * WINMORtoBPQ_Q; // Frames for BPQ, indexed by BPQ Port - void * BPQtoWINMOR_Q; // Frames for WINMOR. indexed by WINMOR port. Only used it TCP session is blocked - - SOCKET TCPSock; // Control Socket - SOCKET TCPDataSock; // Data Socket - SOCKET PacketSock; // Packet Over TCP (ARDOP) - - char * WINMORSignon; // Pointer to message for secure signin - char * HostName; // WINMOR Host - may be dotted decimal or DNS Name - int TCPPort; // - int PacketPort; // Packet Over TCP (ARDOP) - char * ApplCmd; // Application to connect to on incoming connect (null = leave at command handler) - BOOL SwallowSignon; // Set to suppress *** connected to APPL - - union - { - UCHAR TCPBuffer[1000]; // For converting byte stream to messages - UCHAR DEDBuffer[1000]; // For converting byte stream to messages - UCHAR KISSBuffer[1000]; // For KISS over Host Mode - }; - - UCHAR * ARDOPBuffer; // Needs to be pretty big, so Malloc - UCHAR * ARDOPDataBuffer; // Needs to be pretty big, so Malloc - - int InputLen; // Data we have already = Offset of end of an incomplete packet; - int DataInputLen; // Data we have already = Offset of end of an incomplete packet; - int KISSInputLen; // Data we have already = Offset of end of an incomplete packet; - int ESCFLAG; // KISS Escape received - - int MSGCOUNT; // DED WORKING FIELD - int MSGLENGTH; // DED Msg Len - int MSGCHANNEL; // DED Msg Channel Number - int MSGTYPE; // DED Msg Type - - int HOSTSTATE; // ded HOST state machine - - - BOOL StartSent; // Codec Start send (so will get a disconnect) - int ConnectPending; // Set if Connect Pending Received. If so, mustn't allow freq change. - BOOL GavePermission; // Set if we allowed freq change - BOOL DiscPending; // Set if Disconnect Pending Received. So we can time out stuck in Disconnecting - BOOL HadConnect; // Flag to say have been in session - BOOL FECMode; // In FEC Mode - BOOL FEC1600; // Use 1600 Hz FEC Mode - int FECIDTimer; // Time in FEC Mode. Used to trigger ID broadcasts - BOOL RestartAfterFailure; - BOOL StartInRobust; // For WINMOR, set to Robust Mode for first few packets - - int Busy; // Channel Busy Timer/Counter . Non-zero = Busy - - int BusyFlags; // Channel Busy Flags - -#define CDBusy 1 // For WINMOR - reported busy (set till reported clear) -#define PTTBusy 2 // PTT Active - - BOOL FECPending; // Need an FEC Send when channel is next idle - - time_t lasttime; - - BOOL CONNECTING; // TCP Session Flags - BOOL CONNECTED; - BOOL Alerted; // Connect Failed Prompt sent - BOOL DATACONNECTING; - BOOL DATACONNECTED; - - BOOL TNCCONNECTING; // For FreeData - BOOL TNCCONNECTED; - - BOOL QtSMConnected; - - char NodeCall[10]; // Call we listen for (PORTCALL or NODECALL - char CurrentMYC[10]; // Save current call so we don't change it unnecessarily - char * LISTENCALLS; // Calls TNC will respond to (currently only for VARA) - - char TargetCall[10]; // Call incoming connect is addressed to (for appl call support) - - struct sockaddr_in destaddr; - struct sockaddr_in Datadestaddr; - - int PTTMode; // PTT Mode Flags - int PTTState; // Current State - uint64_t PTTActivemS; // For Stats - uint64_t PTTonTime; // - - uint64_t BusyActivemS; // For channel busy stats - uint64_t BusyonTime; - - char PTTOn[60]; // Port override of RIGCONTROL config - char PTTOff[60]; - int PTTOnLen; - int PTTOffLen; - - int TXRadio; // Rigcontrol Radio Number for TX - int RXRadio; // Rigcontrol Radio Number for RX - - long long int TXFreq; // Freq to set on tx before ptt - double ActiveTXFreq; // Freq to set on tx after attach - double ActiveRXFreq; // Freq to set on rx after attach - - double DefaultTXFreq; // Freq to set on tx after close - double DefaultRXFreq; // Freq to set on rx after close - - char ** DisconnectScript; // May replace above 2 params - - int TXOffset; // Correction to TXFreq - - int PID; // Process ID for Software TNC - HWND hWnd; // Main window handle for Software TNC - - char * CaptureDevices; - char * PlaybackDevices; - char * ProgramPath; - BOOL WeStartedTNC; - - int Restarts; // TNC Kill/Restarts done - time_t LastRestart; - - int TimeSinceLast; // Time since last message from TNC (10ths of a sec) - int HeartBeat; - -// int Interlock; // Port Interlock Group - - HWND hMonitor; // Handle to Monitor control -// HMENU hPopMenu; // Actions Menu Handle - - int MaxConReq; // For ARDOP - int BusyHold; // Hold Time from SCS reporting channel free till we call - int BusyWait; // Time to wait for clear channel before connect - - BOOL OverrideBusy; - int BusyDelay; // Timer for busy timeout - int AutoStartDelay; // Time to wait for TNC to start - char * ConnectCmd; // Saved command if waiting for busy to clear - BOOL UseAPPLCalls; // Robust Packet to use Applcalls - BOOL UseAPPLCallsforPactor; // Pactor to use Applcalls - - // Fields for reporting to WL2K Map - - struct WL2KInfo * WL2K; - -/* - char * Host; - short WL2KPort; - - int UpdateWL2KTimer; - BOOL UpdateWL2K; - char RMSCall[10]; - char BaseCall[10]; - char GridSquare[7]; - char Comment[80]; - char ServiceCode[17]; - - BOOL UseRigCtrlFreqs; - char WL2KFreq[12]; - char WL2KModeChar; // W or N - BOOL DontReportNarrowOnWideFreqs; - -// char NARROWMODE; -// char WIDEMODE; // Mode numbers to report to WL2K - - struct WL2KInfo WL2KInfoList[MAXFREQS]; // Freqs for sending to WL2K -*/ - char WL2KMode; // WL2K reporting mode - - struct STREAMINFO Streams[27]; // 0 is Pactor 1 - 10 are ax.25. - int LastStream; // Last one polled for status or send - - void * BPQtoRadio_Q; // Frames to Rig Interface - void * RadiotoBPQ_Q; // Frames from Rig Interface - - void * KISSTX_Q; // Frames to Host Mode KISS interface - struct PORTCONTROL * VirtualPORT; // Pointer to Virtual Packet Port of Host Mode KISS - - char * InitPtr; // Next Command - int ReinitState; // Reinit State Machine - int ReinitCount; // Count for DED Recovery - int TermReinitCount; // Count for DED Term Mode Recovery - BOOL TNCOK; // TNC is reponding - int FramesOutstanding; // Frames Queued - used for flow control - BOOL InternalCmd; // Last Command was generated internally - int IntCmdDelay; // To limit internal commands - - - HANDLE hDevice; - int ReopenTimer; // Used to reopen device if failed (eg USB port removed) - BOOL HostMode; // Set if in DED Host Mode -// BOOL CRCMode; // Set if using SCS Extended DED Mode (JHOST4) - BOOL UsingTermMode; // Set if tnc should be left in term mode - int Timeout; // Timeout response counter - int Retries; - int Window; // Window Size for ARQ - UCHAR TXBuffer[500]; // Last message sent - saved for Retry - int TXLen; // Len of last sent - UCHAR RXBuffer[520]; // Message being received - may not arrive all at once - UINT RXLen; // Data in RXBUffer - UCHAR Toggle; // Sequence bit - int Buffers; // Free buffers in TNC - BOOL WantToChangeFreq; // Request from Scanner to Change - int OKToChangeFreq; // 1 = SCS Says OK to change, -1 = Dont Change zero = still waiting - BOOL DontWantToChangeFreq; // Change done - ok to SCS - BOOL DontReleasePermission; // Hold Permission to prevent calls on this frequency - time_t TimeEnteredSYNCMode; // To detect scan lock when using applcalls on PTC - BOOL SyncSupported; // TNC reports sync - time_t TimeScanLocked; // ditto for TNCs that don't report SYNC - int PTCStatus; // Sync, Idle, Traffic, etc - UCHAR NexttoPoll[20]; // Streams with data outstanding (from General Poll) - BOOL PollSent; // Toggle to ensure we issue a general poll regularly - int StreamtoPoll; - - char Bandwidth; // Currently set Mode W or N - - int Mode; // Mode Flag - - BOOL Dragon; // Set if P4Dragon - BOOL DragonSingle; // Set if P4Dragon using Pactor and Packet on same port - BOOL DragonKISS; // Set if P4Dragon supports sending KISS frames in Hostmode - BOOL EnterExit; // Switching to Term mode to change bandwidth - int PktStream; // Stream in use for Packet when in single port mode - BOOL MaxLevel; // Pactor Level to set for Wide Mode (3 or 4) - int MinLevel; // Mimimum accepted Pactor Level - int MinLevelTimer; // Time left to achieve Min Level - int PacketChannels; - int RobustTime; // For PTC, Spend this part of scan cycle (in 10th secs) in Robust Packet Mode - int SwitchToPactor; // Countdown to switch - - BOOL OldMode; // Use PACTOR instead of TOR (for old software) - BOOL VeryOldMode; // Use MYCALL instead of MYPTCALL (for old software) - - int Mem1; // Free Bytes (VHF /HF) - int Mem2; - - BOOL HFPacket; // Set if HF port is in Packet mode instead of Pactor Mode - BOOL Robust; // Set if SCS Tracker is in Robust Packet mode or WINMOR TNC is in Robust Mode - BOOL RobustDefault; // Set if SCS Tracker default is Robust Packet mode - BOOL ForceRobust; // Don't allow Normal Packet even if scan requests it. - BOOL TeensyRPR; // Teensy RPR TNC - don't send %R - char NormSpeed[8]; // Speed Param for Normal Packet on Tracker - char RobustSpeed[8]; // Speed Param for Robust Packet on Tracker - BOOL RPBEACON; // Send Beacon after each session - - int TimeInRX; // Time waiting for ISS before sending - char TXRXState; // Current ISS/IRS State - - BOOL NeedPACTOR; // Set if need to send PACTOR to put into Standby Mode - int CmdStream; // Stream last command was issued on - - union - { - struct TCPINFO * TCPInfo; // Telnet Server Specific Data - struct AGWINFO * AGWInfo; // AGW Stream Mode Specific Data - struct MPSKINFO * MPSKInfo; // MPSK Stream Mode Specific Data - struct FLINFO * FLInfo; // FLDIGI Stream Mode Specific Data - }; - - struct ARQINFO * ARQInfo; // FLDIGI/FLARQ Stream Mode Specific Data - - BOOL DataBusy; // Waiting for Data Ack - Don't send any more data - BOOL CommandBusy; // Waiting for Command ACK - - BOOL TEXTMODE; // Set if AEA in text mode - BOOL NeedTurnRound; // Set if we have sent data, so need to send ctrl/z - BOOL NeedTRANS; // Set if we have to send TRANS when ctrl/z is acked. - - char * CmdSet; // A series of commands to send to the TNC - char * CmdSave; // Base address for free - - BOOL PktUpdateMap; // Set if Packet MH data to be sent to NodeMap - - int DefaultMode; - int CurrentMode; // Used on HAL - - char * DefaultRadioCmd; // RADIO command to send at end of session - char * Frequency; - // For Mode Map if no Rigcontrol - // Mode Equates - - #define Clover 'C' - #define Pactor 'P' - #define AMTOR 'A' - - UCHAR DataBuffer[500]; // Data Chars split from received stream - UCHAR CmdBuffer[500]; // Cmd/Response chars split from received stream - int DataLen; // Data in DataBuffer - int CmdLen; // Data in CmdBuffer - BOOL CmdEsc; // Set if last char rxed was 0x80 - BOOL DataEsc; // Set if last char rxed was 0x81 - int PollDelay; // Don't poll too often; - int InData; // FLDigi - MCAST <....> received - int InPacket; // FLDigi - SOH or < received. - int MCASTLen; // Data still to get - - int DataMode; // How to treat data - -#define RXDATA 0x30 // Switch to Receive Data characters -#define TXDATA 0x31 // Switch to Transmit Data characters -#define SECDATA 0x32 // Switch to RX data from secondary port - - int TXMode; // Where to send data - -#define TXMODEM 0x33 // Send TX data to modem -#define TXSEC 0x34 // Send TX data to secondary port - - BOOL XONXOFF; // Set if hardware is using XON/XOFF - - double LastFreq; // Used by V4 to see if freq has changed - int ModemCentre; // Modem centre frequency - int ClientHeight; - int ClientWidth; - HWND xIDC_TNCSTATE; - HWND xIDC_COMMSSTATE; - HWND xIDC_MODE; - HWND xIDC_LEDS; - HWND xIDC_TRAFFIC; - HWND xIDC_BUFFERS; - HWND xIDC_CHANSTATE; - HWND xIDC_LEVELS; - HWND xIDC_STATE; - HWND xIDC_TXRX; - HWND xIDC_PROTOSTATE; - HWND xIDC_RESTARTTIME; - HWND xIDC_RESTARTS; - HWND xIDC_PACTORLEVEL; - HWND xIDC_TXTUNE; - HWND xIDC_TXTUNEVAL; - - char * WEB_TNCSTATE; - char * WEB_COMMSSTATE; - char * WEB_MODE; - char * WEB_LEDS; - char * WEB_TRAFFIC; - char * WEB_BUFFERS; - char * WEB_CHANSTATE; - char * WEB_STATE; - char * WEB_TXRX; - char * WEB_PROTOSTATE; - char * WEB_RESTARTTIME; - char * WEB_RESTARTS; - char * WEB_PACTORLEVEL; - char * WEB_LEVELS; - int WEB_CHANGED; // Used to speed up refresh when active - - HMENU hMenu; - HMENU hWndMenu; - - VOID (* SuspendPortProc) (struct TNCINFO * TNC, struct TNCINFO * ThisTNC); - VOID (* ReleasePortProc) (struct TNCINFO * TNC); - VOID (* ForcedCloseProc) (struct TNCINFO * TNC, int Stream); - - time_t WinmorRestartCodecTimer; - int WinmorCurrentMode; - char ARDOPCurrentMode[10]; - char ARDOPCommsMode; - char * ARDOPSerialPort; // Have Bus/Device for I2C - int ARDOPSerialSpeed; - BOOL TCPCONNECTED; // ARDOP over TCP Connected - int SlowTimer; - int ARQPorts[32]; // For ARQ over KISS - char * LogPath; - FILE * LogHandle; // Ardop Logging File - FILE * DebugHandle; // Ardop Debug File - char LastLogType; // For split packets - - UCHAR * ARDOPAPRS; // Used to reconstruct APRS datagram from FEC packets - int ARDOPAPRSLen; - - BOOL WRITELOG; // Enable debug logging - int InputLevelMin; // Sound card levels - int InputLevelMax; // Sound card levels - - int DiscardNextOK; // Used by VARA to suppress OK response to LISTEN commands - int SeenCancelPending; // Used by VARA to suppress duplicate cancel pendings - - MESSAGE * Monframe; // Used by DED Host for receiving Packet Monitor Frame - // split over 2 packets - - struct HSMODEMINFO * HSModemInfo; - struct FreeDataINFO * FreeDataInfo; - - int DontRestart; // Don't automatically restart failed TNC - int SendTandRtoRelay; // Send T and R suffix messages to RELAY instead of CMS - - double SNR; // S/N Ratio (VARA) - - int NetRomMode; - unsigned char * NetRomTxBuffer; // For Netrom over VARA - int NetRomTxLen; - char * NRNeighbour; - int NRCloseTimer; - struct _LINKTABLE * DummyLink; // Simulated link to simplify interface to ax,25 netrom code - struct sixPackPortInfo * sixPack; - int VaraACAllowed; // Set by config - int VaraACMode; // Set by first message received - int VaraModeSet; // Have decicded if VarAC mode or not - char * VARACMsg; // to build message from packets - int VarACTimer; // delayed send timer - size_t VARACSize; // malloc'ed size - -} *PTNCINFO; - -VOID * zalloc(int len); - -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(struct TNCINFO * TNC, int Stream)); -char * CheckAppl(struct TNCINFO * TNC, char * Appl); -BOOL SendReporttoWL2K(struct TNCINFO * TNC); -struct WL2KInfo * DecodeWL2KReportLine(char * buf); -VOID UpdateMH(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction); -VOID UpdateMHEx(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction, char * LOC, BOOL Report); -VOID SaveWindowPos(int port); -VOID SaveMDIWindowPos(HWND hWnd, char * RegKey, char * Value, BOOL Minimized); -BOOL ProcessIncommingConnect(struct TNCINFO * TNC, char * Call, int Stream, BOOL SENDCTEXT); -BOOL ProcessIncommingConnectEx(struct TNCINFO * TNC, char * Call, int Stream, BOOL SENDCTEXT, BOOL AllowTR); -VOID ShowTraffic(struct TNCINFO * TNC); -int OpenCOMMPort(struct TNCINFO * conn, char * Port, int Speed, BOOL Quiet); -VOID SendMH(struct TNCINFO * TNC, char * call, char * freq, char * LOC, char * Mode); -VOID MoveWindows(struct TNCINFO * TNC); - -static VOID TidyClose(struct TNCINFO * TNC, int Stream); -static VOID ForcedClose(struct TNCINFO * TNC, int Stream); -static VOID CloseComplete(struct TNCINFO * TNC, int Stream); - -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)); - - -BOOL InterlockedCheckBusy(struct TNCINFO * ThisTNC); - -extern UINT CRCTAB; -int BPQTRACE(MESSAGE * Msg, BOOL TOAPRS); - - -static int ProcessLine(char * buf, int Port); -VOID __cdecl Debugprintf(const char * format, ...); -VOID __cdecl Consoleprintf(const char * format, ...); - -extern BOOL MinimizetoTray; - -int standardParams(struct TNCINFO * TNC, char * buf); -void DecodePTTString(struct TNCINFO * TNC, char * ptr); - -int Rig_Command(TRANSPORTENTRY * Session, char * Command); - -BOOL Rig_Poll(); - -VOID Rig_PTT(struct TNCINFO * TNC, BOOL PTTState); -VOID Rig_PTTEx(struct RIGINFO * RIG, BOOL PTTState, struct TNCINFO * TNC); - -struct RIGINFO * Rig_GETPTTREC(int Port); - -struct ScanEntry ** CheckTimeBands(struct RIGINFO * RIG); - -#ifndef LINBPQ -LRESULT CALLBACK PacWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -#endif - -#define Report_P1 11 -#define Report_P12 12 -#define Report_P123 13 -#define Report_P2 14 -#define Report_P23 15 -#define Report_P3 16 - -#define Report_P1234 17 -#define Report_P234 18 -#define Report_P34 19 -#define Report_P4 20 - -#define Report_WINMOR500 21 -#define Report_WINMOR1600 22 - -#define Report_Robust 30 - -#define IOCTL_SERIAL_IS_COM_OPEN CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GETDATA CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x801,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SETDATA CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x802,METHOD_BUFFERED,FILE_ANY_ACCESS) - -#define IOCTL_SERIAL_SET_CTS CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x803,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_DSR CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x804,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_DCD CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x805,METHOD_BUFFERED,FILE_ANY_ACCESS) - -#define IOCTL_SERIAL_CLR_CTS CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x806,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_CLR_DSR CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x807,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_CLR_DCD CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x808,METHOD_BUFFERED,FILE_ANY_ACCESS) - -#define IOCTL_BPQ_ADD_DEVICE CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x809,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_BPQ_DELETE_DEVICE CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x80a,METHOD_BUFFERED,FILE_ANY_ACCESS) - -#define W98_SERIAL_GETDATA 0x801 -#define W98_SERIAL_SETDATA 0x802 diff --git a/.svn/pristine/10/102d41bc4cd0f242aaba204301966dc699e1ff06.svn-base b/.svn/pristine/10/102d41bc4cd0f242aaba204301966dc699e1ff06.svn-base deleted file mode 100644 index bc0a854..0000000 --- a/.svn/pristine/10/102d41bc4cd0f242aaba204301966dc699e1ff06.svn-base +++ /dev/null @@ -1,2179 +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 -*/ - -// Mail and Chat Server for BPQ32 Packet Switch -// -// FBB Forwarding Routines - -#include "bpqmail.h" - -#define GetSemaphore(Semaphore,ID) _GetSemaphore(Semaphore, ID, __FILE__, __LINE__) -void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line); - - -void DeleteRestartData(CIRCUIT * conn); - -int32_t Encode(char * in, char * out, int32_t inlen, BOOL B1Protocol, int Compress); -void MQTTMessageEvent(void* message); - -int MaxRXSize = 99999; -int MaxTXSize = 99999; - -struct FBBRestartData ** RestartData = NULL; -int RestartCount = 0; - -struct B2RestartData ** B2RestartRecs = NULL; -int B2RestartCount = 0; - -extern char ProperBaseDir[]; - -char RestartDir[MAX_PATH] = ""; - -void GetRestartData() -{ - int i; - struct FBBRestartData Restart; - struct FBBRestartData * RestartRec; - char MsgFile[MAX_PATH]; - FILE * hFile; - int FileSize; - struct stat STAT; - size_t ReadLen = 0; - time_t Age; - - strcpy(RestartDir, MailDir); - strcat(RestartDir, "/Restart"); - - // Make sure RestartDir exists - -#ifdef WIN32 - CreateDirectory(RestartDir, NULL); // Just in case -#else - mkdir(RestartDir, S_IRWXU | S_IRWXG | S_IRWXO); - chmod(RestartDir, S_IRWXU | S_IRWXG | S_IRWXO); -#endif - - // look for restart files. These will be numbered from 1 up - - for (i = 1; 1; i++) - { - sprintf_s(MsgFile, sizeof(MsgFile), "%s/%d", RestartDir, i); - - if (stat(MsgFile, &STAT) == -1) - break; - - FileSize = STAT.st_size; - - Age = time(NULL) - STAT.st_ctime; - - if (Age > 86400 * 2) // Max 2 days - continue; - - hFile = fopen(MsgFile, "rb"); - - if (hFile == NULL) - break; - - // Read Restart Record - - fread(&Restart, 1, sizeof(struct FBBRestartData), hFile); - - if ((Restart.MailBufferSize + sizeof(struct FBBRestartData)) != FileSize) // Duff file - { - fclose(hFile); - break; - } - - RestartRec = zalloc(sizeof (struct FBBRestartData)); - - GetSemaphore(&AllocSemaphore, 0); - - RestartData = realloc(RestartData,(++RestartCount+1) * sizeof(void *)); - RestartData[RestartCount] = RestartRec; - - FreeSemaphore(&AllocSemaphore); - - memcpy(RestartRec, &Restart, sizeof(struct FBBRestartData)); - RestartRec->MailBuffer = malloc(RestartRec->MailBufferSize); - ReadLen = fread(RestartRec->MailBuffer, 1, RestartRec->MailBufferSize, hFile); - - Logprintf(LOG_BBS, 0, '?', "Restart Data for %s %s Len %d Loaded", RestartRec->Call, RestartRec->bid, RestartRec->length); - fclose(hFile); - } -} - - -void SaveRestartData() -{ - // Save restart data to file so we can reload on restart - // Restart data has pointers to buffers so we must save copy of data and reconstitue on restart - - // Delete and resave all restart data to keep restart directory clean - - int i, n = 1; - char MsgFile[MAX_PATH]; - FILE * hFile; - size_t WriteLen=0; - struct FBBRestartData * RestartRec = NULL; - struct stat STAT; - time_t NOW = time(NULL); - - - for (i = 1; 1; i++) - { - sprintf_s(MsgFile, sizeof(MsgFile), "%s/%d", RestartDir, i); - - if (stat(MsgFile, &STAT) == -1) - break; - - DeleteFile(MsgFile); - } - - for (i = 1; i <= RestartCount; i++) - { - RestartRec = RestartData[i]; - - if (RestartRec == 0) - return; // Shouldn't happen! - - if ((NOW - RestartRec->TimeCreated) > 86400 * 2) // Max 2 days - continue; - - sprintf_s(MsgFile, sizeof(MsgFile), "%s/%d", RestartDir, n++); - - hFile = fopen(MsgFile, "wb"); - - if (hFile) - { - WriteLen = fwrite(RestartRec, 1, sizeof(struct FBBRestartData), hFile); // Save Header - WriteLen = fwrite(RestartRec->MailBuffer, 1, RestartRec->MailBufferSize, hFile); // Save Data - fclose(hFile); - } - } -} -VOID FBBputs(CIRCUIT * conn, char * buf) -{ - // Sends to user and logs - - int len = (int)strlen(buf); - - WriteLogLine(conn, '>', buf, len -1, LOG_BBS); - - QueueMsg(conn, buf, len); - - if (conn->BBSFlags & NEEDLF) - QueueMsg(conn, "\n", 1); -} - - -VOID ProcessFBBLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int len) -{ - struct FBBHeaderLine * FBBHeader; // The Headers from an FBB forward block - int i; - int Index = 0; // Message Type Index for Stats - char * ptr; - char * Context; - char seps[] = " \r"; - int RestartPtr; - char * Respptr; - BOOL AllRejected = TRUE; - char * MPS; - char * ROChar; - - if (conn->Flags & GETTINGMESSAGE) - { - ProcessMsgLine(conn, user, Buffer, len); - if (conn->Flags & GETTINGMESSAGE) - - // Still going - return; - - SetupNextFBBMessage(conn); - return; - } - - if (conn->Flags & GETTINGTITLE) - { - ProcessMsgTitle(conn, user, Buffer, len); - return; - } - - // Should be FA FB F> FS FF FQ - - if (Buffer[0] == ';') // winlink comment or BPQ Type Select - { - if (memcmp(Buffer, "; MSGTYPES", 7) == 0) - { - char * ptr; - - conn->SendB = conn->SendP = conn->SendT = FALSE; - - ptr = strchr(&Buffer[10], 'B'); - - if (ptr) - { - conn->SendB = TRUE; - conn->MaxBLen = atoi(++ptr); - if (conn->MaxBLen == 0) conn->MaxBLen = 99999999; - } - - ptr = strchr(&Buffer[10], 'T'); - - if (ptr) - { - conn->SendT = TRUE; - conn->MaxTLen = atoi(++ptr); - if (conn->MaxTLen == 0) conn->MaxTLen = 99999999; - } - ptr = strchr(&Buffer[10], 'P'); - - if (ptr) - { - conn->SendP = TRUE; - conn->MaxPLen = atoi(++ptr); - if (conn->MaxPLen == 0) conn->MaxPLen = 99999999; - } - return; - } - - // Other ; Line - Ignore - - return; - } - - if (Buffer[0] != 'F') - { - if (strstr(Buffer, "*** Profanity detected") || strstr(Buffer, "*** Unknown message sender")) - { - // Winlink Check - hold message - - if (conn->FBBMsgsSent) - HoldSentMessages(conn, user); - } - - if (conn->BBSFlags & DISCONNECTING) - return; // Ignore if disconnect aleady started - - BBSputs(conn, "*** Protocol Error - Line should start with 'F'\r"); - Flush(conn); - Sleep(500); - conn->BBSFlags |= DISCONNECTING; - Disconnect(conn->BPQStream); - - return; - } - - switch (Buffer[1]) - { - case 'F': - - // Request Reverse - - if (conn->FBBMsgsSent) - FlagSentMessages(conn, user); - - if (!FBBDoForward(conn)) // Send proposal if anthing to forward - { - FBBputs(conn, "FQ\r"); - - conn->BBSFlags |= DISCONNECTING; - - // LinFBB needs a Disconnect Here - - if (conn->BPQBBS) - return; // BPQ will close when it sees FQ. Close collisions aren't good! - - if ((conn->SessType & Sess_PACTOR) == 0) - conn->CloseAfterFlush = 20; // 2 Secs - else - conn->CloseAfterFlush = 20; // PACTOR/WINMOR drivers support deferred disc so 5 secs should be enough - } - return; - - case 'S': - - // Proposal response - - Respptr=&Buffer[2]; - - for (i=0; i < conn->FBBIndex; i++) - { - FBBHeader = &conn->FBBHeaders[i]; - - if (FBBHeader->MsgType == 'P') - Index = PMSG; - else if (FBBHeader->MsgType == 'B') - Index = BMSG; - else if (FBBHeader->MsgType == 'T') - Index = TMSG; - - Respptr++; - - if (*Respptr == 'E') - { - // Rejected - - Logprintf(LOG_BBS, conn, '?', "Proposal %d Rejected by far end", i + 1); - } - - if ((*Respptr == '-') || (*Respptr == 'N') || (*Respptr == 'R') || (*Respptr == 'E')) // Not wanted - { - user->Total.MsgsRejectedOut[Index]++; - - // Zap the entry - - if (conn->Paclink || conn->RMSExpress || conn->PAT) // Not using Bit Masks - { - // Kill Messages sent to paclink/RMS Express unless BBS FWD bit set - - // What if WLE retrieves P message that is queued to differnet BBS? - // if we dont kill it will be offered again - - if (FBBHeader->FwdMsg->type == 'P' || (check_fwd_bit(FBBHeader->FwdMsg->fbbs, user->BBSNumber) == 0)) - FlagAsKilled(FBBHeader->FwdMsg, FALSE); - } - - clear_fwd_bit(FBBHeader->FwdMsg->fbbs, user->BBSNumber); - set_fwd_bit(FBBHeader->FwdMsg->forw, user->BBSNumber); - - FBBHeader->FwdMsg->Locked = 0; // Unlock - - // Shouldn't we set P messages as Forwarded - // (or will check above have killed it if it is P with other FWD bits set) - // Maybe better to be safe !! - - if (FBBHeader->FwdMsg->type == 'P' || memcmp(FBBHeader->FwdMsg->fbbs, zeros, NBMASK) == 0) - { - FBBHeader->FwdMsg->status = 'F'; // Mark as forwarded - FBBHeader->FwdMsg->datechanged=time(NULL); - } - - memset(FBBHeader, 0, sizeof(struct FBBHeaderLine)); - - conn->UserPointer->ForwardingInfo->MsgCount--; - - SaveMessageDatabase(); - continue; - } - - // FBB uses H for HOLD, but I've never seen it. RMS Express sends H for Defer. - - - if (*Respptr == '=' || *Respptr == 'L' || (*Respptr == 'H' && conn->RMSExpress)) // Defer - { - // Remove entry from forwarding block - - FBBHeader->FwdMsg->Defered = 4; // Don't retry for the next few forward cycles - memset(FBBHeader, 0, sizeof(struct FBBHeaderLine)); - continue; - } - - conn->RestartFrom = 0; // Assume Restart from - - if ((*Respptr == '!') || (*Respptr == 'A')) - { - // Restart - - char Num[10]; - char *numptr=&Num[0]; - - Respptr++; - - while (isdigit(*Respptr)) - { - *(numptr++) = *(Respptr++); - } - *numptr = 0; - - conn->RestartFrom = atoi(Num); - - *(--Respptr) = '+'; // So can drop through - } - - // FBB uses H for HOLD, but I've never seen it. RMS Express sends H for Defer. RMS use trapped above - - if ((*Respptr == '+') || (*Respptr == 'Y') || (*Respptr == 'H')) - { - struct tm * tm; - time_t now; - char * MsgBytes; - - conn->FBBMsgsSent = TRUE; // Messages to flag as complete when next command received - AllRejected = FALSE; - - if (conn->BBSFlags & FBBForwarding) - { - if (conn->BBSFlags & FBBB2Mode) - SendCompressedB2(conn, FBBHeader); - else - SendCompressed(conn, FBBHeader->FwdMsg); - } - else - { - nodeprintf(conn, "%s\r\n", FBBHeader->FwdMsg->title); - - MsgBytes = ReadMessageFile(FBBHeader->FwdMsg->number); - - if (MsgBytes == 0) - { - MsgBytes = _strdup("Message file not found\r\n"); - FBBHeader->FwdMsg->length = (int)strlen(MsgBytes); - } - - now = time(NULL); - - tm = gmtime(&now); - - nodeprintf(conn, "R:%02d%02d%02d/%02d%02dZ %d@%s.%s %s\r\n", - tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, - FBBHeader->FwdMsg->number, BBSName, HRoute, RlineVer); - - if (memcmp(MsgBytes, "R:", 2) != 0) // No R line, so must be our message - put blank line after header - BBSputs(conn, "\r\n"); - - QueueMsg(conn, MsgBytes, FBBHeader->FwdMsg->length); - free(MsgBytes); - - user->Total.MsgsSent[Index]++; - user->Total.BytesForwardedOut[Index] += FBBHeader->FwdMsg->length; - - nodeprintf(conn, "%c\r\n", 26); - } - continue; - } - BBSputs(conn, "*** Protocol Error - Invalid Proposal Response'\r"); - } - - conn->FBBIndex = 0; // ready for next block; - conn->FBBChecksum = 0; - - - if (AllRejected && (conn->RMSExpress || conn->PAT)) - { - // RMS Express and PAT don't send FF or proposal after rejecting all messages - - FBBputs(conn, "FF\r"); - } - - return; - - case 'Q': - - if (conn->FBBMsgsSent) - FlagSentMessages(conn, user); - - conn->BBSFlags |= DISCONNECTING; - - Disconnect(conn->BPQStream); - return; - - case 'A': // Proposal - case 'B': // Proposal - - if (conn->FBBMsgsSent) - FlagSentMessages(conn, user); // Mark previously sent messages - - if (conn->DoReverse == FALSE) // Dont accept messages - return; - - // Accumulate checksum - - for (i=0; i< len; i++) - { - conn->FBBChecksum+=Buffer[i]; - } - - // Parse Header - - // Find free line - - for (i = 0; i < 5; i++) - { - FBBHeader = &conn->FBBHeaders[i]; - - if (FBBHeader->Format == 0) - break; - } - - if (i == 5) - { - BBSputs(conn, "*** Protocol Error - Too Many Proposals\r"); - Flush(conn); - conn->CloseAfterFlush = 20; // 2 Secs - } - - //FA P GM8BPQ G8BPQ G8BPQ 2209_GM8BPQ 8 - - FBBHeader->Format = Buffer[1]; - - ptr = strtok_s(&Buffer[3], seps, &Context); - - if (ptr == NULL) goto badparam; - - if (strlen(ptr) != 1) goto badparam; - - FBBHeader->MsgType = *ptr; - - if (FBBHeader->MsgType == 'P') - Index = PMSG; - else if (FBBHeader->MsgType == 'B') - Index = BMSG; - else if (FBBHeader->MsgType == 'T') - Index = TMSG; - - - ptr = strtok_s(NULL, seps, &Context); - - if (ptr == NULL) goto badparam; - strlop(ptr, '-'); // Remove any (illegal) ssid - - if (strlen(ptr) > 6 ) goto badparam; - - strcpy(FBBHeader->From, ptr); - - ptr = strtok_s(NULL, seps, &Context); - - if (ptr == NULL) goto badparam; - - if (strlen(ptr) > 40 ) goto badparam; - - strcpy(FBBHeader->ATBBS, ptr); - - ptr = strtok_s(NULL, seps, &Context); - - if (ptr == NULL) goto badparam; - - if (strlen(ptr) > 6) - { - // Temp fix - reject instead of breaking connection - - memset(FBBHeader, 0, sizeof(struct FBBHeaderLine)); // Clear header - conn->FBBReplyChars[conn->FBBReplyIndex++] = '-'; - Logprintf(LOG_BBS, conn, '?', "Message Rejected as TO field too long"); - - user->Total.MsgsRejectedIn[Index]++; - return; - } - - strlop(ptr, '-'); // Remove any (illegal) ssid - - strcpy(FBBHeader->To, ptr); - - ptr = strtok_s(NULL, seps, &Context); - - if (ptr == NULL) goto badparam; - - if (strlen(ptr) > 12 ) goto badparam; - - strcpy(FBBHeader->BID, ptr); - - ptr = strtok_s(NULL, seps, &Context); - - if (ptr == NULL) goto badparam; - - FBBHeader->Size = atoi(ptr); - - goto ok; - -badparam: - - BBSputs(conn, "*** Protocol Error - Proposal format error\r"); - Flush(conn); - conn->CloseAfterFlush = 20; // 2 Secs - return; - -ok: - - // Check Filters - - if (CheckRejFilters(FBBHeader->From, FBBHeader->To, FBBHeader->ATBBS, FBBHeader->BID, FBBHeader->MsgType, FBBHeader->Size)) - { - memset(FBBHeader, 0, sizeof(struct FBBHeaderLine)); // Clear header - conn->FBBReplyChars[conn->FBBReplyIndex++] = '-'; - Logprintf(LOG_BBS, conn, '?', "Message Rejected by Filters"); - - user->Total.MsgsRejectedIn[Index]++; - } - - // If P Message, dont immediately reject on a Duplicate BID. Check if we still have the message - // If we do, reject it. If not, accept it again. (do we need some loop protection ???) - - else if (DoWeWantIt(conn, FBBHeader) == FALSE) - { - memset(FBBHeader, 0, sizeof(struct FBBHeaderLine)); // Clear header - conn->FBBReplyChars[conn->FBBReplyIndex++] = '-'; - user->Total.MsgsRejectedIn[Index]++; - } - else if ((RestartPtr = LookupRestart(conn, FBBHeader)) > 0) - { - conn->FBBReplyIndex += sprintf(&conn->FBBReplyChars[conn->FBBReplyIndex], "!%d", RestartPtr); - } - else if (LookupTempBID(FBBHeader->BID)) - { - memset(FBBHeader, 0, sizeof(struct FBBHeaderLine)); // Clear header - conn->FBBReplyChars[conn->FBBReplyIndex++] = '='; - } - else - { - - // Save BID in temp list in case we are offered it again before completion - - BIDRec * TempBID = AllocateTempBIDRecord(); - strcpy(TempBID->BID, FBBHeader->BID); - TempBID->u.conn = conn; - - conn->FBBReplyChars[conn->FBBReplyIndex++] = '+'; - } - - FBBHeader->B2Message = FALSE; - - return; - - case 'C': // B2 Proposal - - if (conn->FBBMsgsSent) - FlagSentMessages(conn, user); // Mark previously sent messages - - if (conn->DoReverse == FALSE) // Dont accept messages - return; - - // Accumulate checksum - - for (i=0; i< len; i++) - { - conn->FBBChecksum+=Buffer[i]; - } - - // Parse Header - - // Find free line - - for (i = 0; i < 5; i++) - { - FBBHeader = &conn->FBBHeaders[i]; - - if (FBBHeader->Format == 0) - break; - } - - if (i == 5) - { - BBSputs(conn, "*** Protocol Error - Too Many Proposals\r"); - Flush(conn); - conn->CloseAfterFlush = 20; // 2 Secs - } - - - // FC EM A3EDD4P00P55 377 281 0 - - /* - - FC Proposal code. Requires B2 SID feature. - Type Message type ( 1 or 2 alphanumeric characters - - CM WinLink 2000 Control message - EM Encapsulated Message - ID Unique Message Identifier (max length 12 characters) - U-Size Uncompressed size of message - C-size Compressed size of message - - */ - FBBHeader->Format = Buffer[1]; - - ptr = strtok_s(&Buffer[3], seps, &Context); - if (ptr == NULL) goto badparam2; - if (strlen(ptr) != 2) goto badparam2; - FBBHeader->MsgType = 'P'; //ptr[0]; - - ptr = strtok_s(NULL, seps, &Context); - - if (ptr == NULL) goto badparam2; - - // Relay In RO mode adds @MPS@R to the MID. Don't know why (yet!) - - MPS = strlop(ptr, '@'); - if (MPS) - ROChar = strlop(MPS, '@'); - - if (strlen(ptr) > 12 ) goto badparam; - strcpy(FBBHeader->BID, ptr); - - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) goto badparam2; - FBBHeader->Size = atoi(ptr); - - ptr = strtok_s(NULL, seps, &Context); - if (ptr == NULL) goto badparam2; - FBBHeader->CSize = atoi(ptr); - FBBHeader->B2Message = TRUE; - - // If using BPQ Extensions (From To AT in proposal) Check Filters - - Buffer[len - 1] = 0; - - if (conn->BPQBBS) - { - char * From = strtok_s(NULL, seps, &Context); - char * ATBBS = strtok_s(NULL, seps, &Context); - char * To = strtok_s(NULL, seps, &Context); - char * Type = strtok_s(NULL, seps, &Context); - - if (From && To && ATBBS && Type && CheckRejFilters(From, To, ATBBS, NULL, *Type, FBBHeader->Size)) - { - memset(FBBHeader, 0, sizeof(struct FBBHeaderLine)); // Clear header - conn->FBBReplyChars[conn->FBBReplyIndex++] = '-'; - user->Total.MsgsRejectedIn[Index]++; - Logprintf(LOG_BBS, conn, '?', "Message Rejected by Filters"); - - return; - } - } - goto ok2; - -badparam2: - - BBSputs(conn, "*** Protocol Error - Proposal format error\r"); - Flush(conn); - conn->CloseAfterFlush = 20; // 2 Secs - return; - -ok2: - if (LookupBID(FBBHeader->BID)) - { - memset(FBBHeader, 0, sizeof(struct FBBHeaderLine)); // Clear header - conn->FBBReplyChars[conn->FBBReplyIndex++] = '-'; - Logprintf(LOG_BBS, conn, '?', "Message Rejected by BID Check"); - user->Total.MsgsRejectedIn[Index]++; - - } - else if (FBBHeader->Size > MaxRXSize) - { - memset(FBBHeader, 0, sizeof(struct FBBHeaderLine)); // Clear header - conn->FBBReplyChars[conn->FBBReplyIndex++] = '-'; - Logprintf(LOG_BBS, conn, '?', "Message Rejected by Size Limit"); - user->Total.MsgsRejectedIn[Index]++; - - } - else if ((RestartPtr = LookupRestart(conn, FBBHeader)) > 0) - { - conn->FBBReplyIndex += sprintf(&conn->FBBReplyChars[conn->FBBReplyIndex], "!%d", RestartPtr); - } - - else if (LookupTempBID(FBBHeader->BID)) - { - memset(FBBHeader, 0, sizeof(struct FBBHeaderLine)); // Clear header - conn->FBBReplyChars[conn->FBBReplyIndex++] = '='; - } - else - { - // Save BID in temp list in case we are offered it again before completion - - BIDRec * TempBID = AllocateTempBIDRecord(); - strcpy(TempBID->BID, FBBHeader->BID); - TempBID->u.conn = conn; - - conn->FBBReplyChars[conn->FBBReplyIndex++] = 'Y'; - } - - return; - - case '>': - - // Optional Checksum - - if (conn->DoReverse == FALSE) // Dont accept messages - { - Logprintf(LOG_BBS, conn, '?', "Reverse Forwarding not allowed"); - Disconnect(conn->BPQStream); - return; - } - - if (len > 3) - { - int sum; - - sscanf(&Buffer[3], "%x", &sum); - - conn->FBBChecksum+=sum; - - if (conn->FBBChecksum) - { - BBSputs(conn, "*** Proposal Checksum Error\r"); - Flush(conn); - conn->CloseAfterFlush = 20; // 2 Secs - return; - } - } - - // Return "FS ", followed by +-= for each proposal - - conn->FBBReplyChars[conn->FBBReplyIndex] = 0; - conn->FBBReplyIndex = 0; - - nodeprintfEx(conn, "FS %s\r", conn->FBBReplyChars); - - // if all rejected, send proposals or prompt, else set up for first message - - FBBHeader = &conn->FBBHeaders[0]; - - if (FBBHeader->MsgType == 0) - { - conn->FBBIndex = 0; // ready for first block; - memset(&conn->FBBHeaders[0], 0, 5 * sizeof(struct FBBHeaderLine)); - conn->FBBChecksum = 0; - - if (!FBBDoForward(conn)) // Send proposal if anthing to forward - { - conn->InputMode = 0; - - if (conn->DoReverse) - FBBputs(conn, "FF\r"); - else - { - FBBputs(conn, "FQ\r"); - conn->CloseAfterFlush = 20; // 2 Secs - } - } - } - else - { - if (conn->BBSFlags & FBBForwarding) - { - conn->InputMode = 'B'; - } - - CreateMessage(conn, FBBHeader->From, FBBHeader->To, FBBHeader->ATBBS, FBBHeader->MsgType, FBBHeader->BID, NULL); - } - - return; - - } - - return; -} - -VOID HoldSentMessages(CIRCUIT * conn, struct UserInfo * user) -{ - struct FBBHeaderLine * FBBHeader; // The Headers from an FBB forward block - int i; - - conn->FBBMsgsSent = FALSE; - - for (i=0; i < 5; i++) - { - FBBHeader = &conn->FBBHeaders[i]; - - if (FBBHeader && FBBHeader->MsgType) // Not a zapped entry - { - int Length=0; - char * MailBuffer = malloc(100); - char Title[100]; - - Length += sprintf(MailBuffer, "Message %d Held\r\n", FBBHeader->FwdMsg->number); - sprintf(Title, "Message %d Held - Rejected by Winlink", FBBHeader->FwdMsg->number); - SendMessageToSYSOP(Title, MailBuffer, Length); - - FBBHeader->FwdMsg->status = 'H'; // Mark as Held - } - } - memset(&conn->FBBHeaders[0], 0, 5 * sizeof(struct FBBHeaderLine)); - SaveMessageDatabase(); -} - - - -VOID FlagSentMessages(CIRCUIT * conn, struct UserInfo * user) -{ - struct FBBHeaderLine * FBBHeader; // The Headers from an FBB forward block - int i; - - // Called if FBB command received after sending a block of messages . Flag as as sent. - - conn->FBBMsgsSent = FALSE; - - for (i=0; i < 5; i++) - { - FBBHeader = &conn->FBBHeaders[i]; - - if (FBBHeader && FBBHeader->MsgType) // Not a zapped entry - { - if ((conn->Paclink || conn->RMSExpress || conn->PAT) && -// ((conn->UserPointer->flags & F_NTSMPS) == 0) && - (FBBHeader->FwdMsg->type == 'P')) - { - // Kill Messages sent to paclink/RMS Express unless BBS FWD bit set - - if (check_fwd_bit(FBBHeader->FwdMsg->fbbs, user->BBSNumber) == 0) - { - FlagAsKilled(FBBHeader->FwdMsg, FALSE); - continue; - } - } - - clear_fwd_bit(FBBHeader->FwdMsg->fbbs, user->BBSNumber); - set_fwd_bit(FBBHeader->FwdMsg->forw, user->BBSNumber); - - // Only mark as forwarded if sent to all BBSs that should have it - - if (memcmp(FBBHeader->FwdMsg->fbbs, zeros, NBMASK) == 0) - { - FBBHeader->FwdMsg->status = 'F'; // Mark as forwarded - FBBHeader->FwdMsg->datechanged=time(NULL); - } - -#ifndef NOMQTT - if (MQTT) - MQTTMessageEvent(FBBHeader->FwdMsg); -#endif - - FBBHeader->FwdMsg->Locked = 0; // Unlock - conn->UserPointer->ForwardingInfo->MsgCount--; - } - } - memset(&conn->FBBHeaders[0], 0, 5 * sizeof(struct FBBHeaderLine)); - SaveMessageDatabase(); -} - - -VOID SetupNextFBBMessage(CIRCUIT * conn) -{ - struct FBBHeaderLine * FBBHeader; // The Headers from an FBB forward block - - memmove(&conn->FBBHeaders[0], &conn->FBBHeaders[1], 4 * sizeof(struct FBBHeaderLine)); - - memset(&conn->FBBHeaders[4], 0, sizeof(struct FBBHeaderLine)); - - FBBHeader = &conn->FBBHeaders[0]; - - if (FBBHeader->MsgType == 0) - { - conn->FBBIndex = 0; // ready for next block; - memset(&conn->FBBHeaders[0], 0, 5 * sizeof(struct FBBHeaderLine)); - - conn->FBBChecksum = 0; - conn->InputMode = 0; - - if (!FBBDoForward(conn)) // Send proposal if anthing to forward - { - conn->InputMode = 0; - FBBputs(conn, "FF\r"); - } - } - else - { - if (conn->BBSFlags & FBBForwarding) - conn->InputMode = 'B'; - - CreateMessage(conn, FBBHeader->From, FBBHeader->To, FBBHeader->ATBBS, FBBHeader->MsgType, FBBHeader->BID, NULL); - } -} - -BOOL FBBDoForward(CIRCUIT * conn) -{ - int i; - char proposal[100]; - int proplen; - - if (FindMessagestoForward(conn)) - { - // Send Proposal Block - - struct FBBHeaderLine * FBBHeader; - - for (i=0; i < conn->FBBIndex; i++) - { - FBBHeader = &conn->FBBHeaders[i]; - - if (conn->BBSFlags & FBBB2Mode) - - if (conn->BPQBBS) - - // Add From and To Header for Filters - - proplen = sprintf(proposal, "FC EM %s %d %d %s %s %s %c\r", - FBBHeader->BID, - FBBHeader->Size, - FBBHeader->CSize, - FBBHeader->From, - (FBBHeader->ATBBS[0]) ? FBBHeader->ATBBS : conn->UserPointer->Call, - FBBHeader->To, - FBBHeader->MsgType); - - else - - // FC EM A3EDD4P00P55 377 281 0 - - proplen = sprintf(proposal, "FC EM %s %d %d %d\r", - FBBHeader->BID, - FBBHeader->Size, - FBBHeader->CSize, 0); - - else - proplen = sprintf(proposal, "%s %c %s %s %s %s %d\r", - (conn->BBSFlags & FBBCompressed) ? "FA" : "FB", - FBBHeader->MsgType, - FBBHeader->From, - (FBBHeader->ATBBS[0]) ? FBBHeader->ATBBS : conn->UserPointer->Call, - FBBHeader->To, - FBBHeader->BID, - FBBHeader->Size); - - // Accumulate checksum - - while(proplen > 0) - { - conn->FBBChecksum+=proposal[--proplen]; - } - - FBBputs(conn, proposal); - } - - conn->FBBChecksum = - conn->FBBChecksum; - - nodeprintfEx(conn, "F> %02X\r", conn->FBBChecksum); - - return TRUE; - } - - return FALSE; -} - -VOID UnpackFBBBinary(CIRCUIT * conn) -{ - int MsgLen, i, offset, n; - UCHAR * ptr; - -loop: - - if (conn->CloseAfterFlush) // Failed (or complete), so discard rest of input - { - conn->InputLen = 0; - return; - } - - - ptr = conn->InputBuffer; - - if (conn->InputLen < 2) - return; // All formats need at least two bytes - - switch (*ptr) - { - case 1: // Header - - MsgLen = ptr[1] + 2; - - if (conn->InputLen < MsgLen) - return; // Wait for more - - if (strlen(&ptr[2]) > 60) - { - memcpy(conn->TempMsg->title, &ptr[2], 60); - conn->TempMsg->title[60] = 0; - Debugprintf("FBB Subject too long - truncated, %s", &ptr[2]); - } - else - strcpy(conn->TempMsg->title, &ptr[2]); - - offset = atoi(ptr+3+strlen(&ptr[2])); - - ptr += MsgLen; - - memmove(conn->InputBuffer, ptr, conn->InputLen-MsgLen); - - conn->InputLen -= MsgLen; - - conn->FBBChecksum = 0; - - if (offset) - { - struct FBBRestartData * RestartRec; - - // Trying to restart - make sure we have restart data - - for (i = 1; i <= RestartCount; i++) - { - RestartRec = RestartData[i]; - - if ((strcmp(RestartRec->Call, conn->UserPointer->Call) == 0) - && (strcmp(RestartRec->bid, conn->TempMsg->bid) == 0)) - { - if (RestartRec->length <= offset) - { - conn->TempMsg->length = RestartRec->length; - conn->MailBuffer = RestartRec->MailBuffer; - conn->MailBufferSize = RestartRec->MailBufferSize; - - // FBB Seems to insert 6 Byte message - // It looks like the original csum and length - perhaps a a consistancy check - - // But Airmail Sends the Restart Data in the next packet, move the check code. - - conn->NeedRestartHeader = TRUE; - - goto GotRestart; - } - else - { - BBSputs(conn, "*** Trying to restart from invalid position.\r"); - Flush(conn); - conn->CloseAfterFlush = 20; // 2 Secs - - return; - } - - // Remove Restart info - - for (n = i; n < RestartCount; n++) - { - RestartData[n] = RestartData[n+1]; // move down all following entries - } - RestartCount--; - SaveRestartData(); - } - } - - // No Restart Data - - BBSputs(conn, "*** Trying to restart, but no restart data.\r"); - Flush(conn); - conn->CloseAfterFlush = 20; // 2 Secs - - return; - } - - // Create initial buffer of 10K. Expand if needed later - - if (conn->MailBufferSize == 0) - { - // Dont allocate if restarting - - conn->MailBuffer=malloc(10000); - conn->MailBufferSize=10000; - } - - GotRestart: - - if (conn->MailBuffer == NULL) - { - BBSputs(conn, "*** Failed to create Message Buffer\r"); - conn->CloseAfterFlush = 20; // 2 Secs - - return; - } - - goto loop; - - - - case 2: // Data Block - - if (ptr[1] == 0) - MsgLen = 256; - else - MsgLen = ptr[1]; - - if (conn->InputLen < (MsgLen + 2)) - return; // Wait for more - - // If waiting for Restart Header, see if it has arrived - - if (conn->NeedRestartHeader) - { - conn->NeedRestartHeader = FALSE; - - if (MsgLen == 6) - { - ptr = conn->InputBuffer+2; - conn->InputLen -=8; - - for (i=0; i<6; i++) - { - conn->FBBChecksum+=ptr[0]; - ptr++; - } - memmove(conn->InputBuffer, ptr, conn->InputLen); - } - else - { - BBSputs(conn, "*** Restart Header Missing.\r"); - Flush(conn); - conn->CloseAfterFlush = 20; // 2 Secs - } - - goto loop; - - } - // Process it - - ptr+=2; - - for (i=0; i< MsgLen; i++) - { - conn->FBBChecksum+=ptr[i]; - } - - ptr-=2; - - if ((conn->TempMsg->length + MsgLen) > conn->MailBufferSize) - { - conn->MailBufferSize += 10000; - conn->MailBuffer = realloc(conn->MailBuffer, conn->MailBufferSize); - - if (conn->MailBuffer == NULL) - { - BBSputs(conn, "*** Failed to extend Message Buffer\r"); - conn->CloseAfterFlush = 20; // 2 Secs - - return; - } - } - - memcpy(&conn->MailBuffer[conn->TempMsg->length], &ptr[2], MsgLen); - - conn->TempMsg->length += MsgLen; - - MsgLen +=2; - - ptr += MsgLen; - - memmove(conn->InputBuffer, ptr, conn->InputLen-MsgLen); - - conn->InputLen -= MsgLen; - - goto loop; - - - case 4: // EOM - - // Process EOM - - conn->FBBChecksum+=ptr[1]; - - if (conn->FBBChecksum == 0) - { -#ifndef LINBPQ - __try - { -#endif - conn->InputMode = 0; // So we won't save Restart data if decode fails - DeleteRestartData(conn); - Decode(conn, 0); // Setup Next Message will reset InputMode if needed -#ifndef LINBPQ - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - BBSputs(conn, "*** Program Error Decoding Message\r"); - Flush(conn); - conn->CloseAfterFlush = 20; // 2 Secs - return; - } -#endif - } - - else - { - BBSputs(conn, "*** Message Checksum Error\r"); - Flush(conn); - conn->CloseAfterFlush = 20; // 2 Secs - - // Don't allow restart, as saved data is probably duff - - conn->DontSaveRestartData = TRUE; - return; - } - ptr += 2; - - memmove(conn->InputBuffer, ptr, conn->InputLen-2); - - conn->InputLen -= 2; - - goto loop; - - default: - - BBSputs(conn, "*** Protocol Error - Invalid Binary Message Format (Invalid Block Type)\r"); - Flush(conn); - - if (conn->CloseAfterFlush == 0) - { - // Dont do it more than once - - conn->CloseAfterFlush = 20; // 2 Secs - - // Don't allow restart, as saved data is probably duff - - // Actually all but the last block is probably OK, but maybe - // not worth the risk of restarting - - // Actually I think it is - - if (conn->TempMsg->length > 256) - { - conn->TempMsg->length -= 256; - conn->DontSaveRestartData = FALSE; - } - else - conn->DontSaveRestartData = TRUE; - } - return; - } -} - -VOID SendCompressed(CIRCUIT * conn, struct MsgInfo * FwdMsg) -{ - struct tm * tm; - char * MsgBytes, * Save; - UCHAR * Compressed, * Compressedptr; - UCHAR * UnCompressed; - char * Title; - UCHAR * Output, * Outputptr; - int i, OrigLen, MsgLen, CompLen, DataOffset; - char Rline[80]; - int RLineLen; - int Index; - time_t temp; - - if (FwdMsg->type == 'P') - Index = PMSG; - else if (FwdMsg->type == 'B') - Index = BMSG; - else if (FwdMsg->type == 'T') - Index = TMSG; - - MsgBytes = Save = ReadMessageFile(FwdMsg->number); - - if (MsgBytes == 0) - { - MsgBytes = _strdup("Message file not found\r\n"); - FwdMsg->length = (int)strlen(MsgBytes); - } - - OrigLen = FwdMsg->length; - - Title = FwdMsg->title; - - Compressed = Compressedptr = zalloc(2 * OrigLen + 200); - Output = Outputptr = zalloc(2 * OrigLen + 200); - - *Outputptr++ = 1; - *Outputptr++ = (int)strlen(Title) + 8; - strcpy(Outputptr, Title); - Outputptr += strlen(Title) +1; - sprintf(Outputptr, "%6d", conn->RestartFrom); - Outputptr += 7; - - DataOffset = (int)(Outputptr - Output); // Used if restarting - - memcpy(&temp, &FwdMsg->datereceived, sizeof(time_t)); - tm = gmtime(&temp); - - sprintf(Rline, "R:%02d%02d%02d/%02d%02dZ %d@%s.%s %s\r\n", - tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, - FwdMsg->number, BBSName, HRoute, RlineVer); - - if (memcmp(MsgBytes, "R:", 2) != 0) // No R line, so must be our message - strcat(Rline, "\r\n"); - - RLineLen = (int)strlen(Rline); - - MsgLen = OrigLen + RLineLen; - - UnCompressed = zalloc(MsgLen+10); - - strcpy(UnCompressed, Rline); - - // If a B2 Message, Remove B2 Header - - if (FwdMsg->B2Flags & B2Msg) - { - char * ptr; - int BodyLen = OrigLen; - - // Remove all B2 Headers, and all but the first part. - - ptr = strstr(MsgBytes, "Body:"); - - if (ptr) - { - BodyLen = atoi(&ptr[5]); - ptr= strstr(MsgBytes, "\r\n\r\n"); // Blank Line after headers - - if (ptr) - ptr +=4; - else - ptr = MsgBytes; - - } - else - ptr = MsgBytes; - - if (memcmp(ptr, "R:", 2) == 0) // Already have RLines, so remove blank line after new R:line - RLineLen -= 2; - - memcpy(&UnCompressed[RLineLen], ptr, BodyLen); - - MsgLen = BodyLen + RLineLen; - } - else // Not B2 Message - { - memcpy(&UnCompressed[RLineLen], MsgBytes, OrigLen); - } - - CompLen = Encode(UnCompressed, Compressed, MsgLen, conn->BBSFlags & FBBB1Mode, conn->BBSFlags & FBBCompressed); - - conn->FBBChecksum = 0; - - // If restarting, send the checksum and length as a single record, then data from the restart point - // The count includes the header, so adjust count and pointers - - if (conn->RestartFrom) - { - *Outputptr++ = 2; - *Outputptr++ = 6; - - for (i=0; i< 6; i++) - { - conn->FBBChecksum+=Compressed[i]; - *Outputptr++ = Compressed[i]; - } - - for (i=conn->RestartFrom; i< CompLen; i++) - { - conn->FBBChecksum+=Compressed[i]; - } - - Compressedptr += conn->RestartFrom; - CompLen -= conn->RestartFrom; - } - else - { - for (i=0; i< CompLen; i++) - { - conn->FBBChecksum+=Compressed[i]; - } - } - - while (CompLen > 250) - { - *Outputptr++ = 2; - *Outputptr++ = 250; - - memcpy(Outputptr, Compressedptr, 250); - Outputptr += 250; - Compressedptr += 250; - CompLen -= 250; - } - - *Outputptr++ = 2; - *Outputptr++ = CompLen; - - memcpy(Outputptr, Compressedptr, CompLen); - - Outputptr += CompLen; - - *Outputptr++ = 4; - conn->FBBChecksum = - conn->FBBChecksum; - *Outputptr++ = conn->FBBChecksum; - - if (conn->OpenBCM) // Telnet, so escape any 0xFF - { - unsigned char * ptr1 = Output; - unsigned char * ptr2 = Compressed; // Reuse Compressed buffer - size_t Len = Outputptr - Output; - unsigned char c; - - while (Len--) - { - c = *(ptr1++); - *(ptr2++) = c; - if (c == 0xff) // FF becodes FFFF - *(ptr2++) = c; - } - - QueueMsg(conn, Compressed, (int)(ptr2 - Compressed)); - } - else - QueueMsg(conn, Output, (int)(Outputptr - Output)); - - free(Save); - free(Compressed); - free(UnCompressed); - free(Output); - -} - -BOOL CreateB2Message(CIRCUIT * conn, struct FBBHeaderLine * FBBHeader, char * Rline) -{ - char * MsgBytes; - UCHAR * Compressed; - UCHAR * UnCompressed; - int OrigLen, MsgLen, B2HddrLen, CompLen; - char Date[20]; - struct tm * tm; - char B2From[80]; - char B2To[80]; - struct MsgInfo * Msg = FBBHeader->FwdMsg; - struct UserInfo * FromUser; - int BodyLineToBody; - int RlineLen = (int)strlen(Rline) ; - char * TypeString; -#ifndef LINBPQ - struct _EXCEPTION_POINTERS exinfo; - - __try { -#endif - - if (Msg == NULL) - Debugprintf("Msg = NULL"); - - - MsgBytes = ReadMessageFile(Msg->number); - - if (MsgBytes == 0) - { - Debugprintf("B2 Message - Message File not found"); - return FALSE; - } - - UnCompressed = zalloc(Msg->length + 2000); - - if (UnCompressed == NULL) - Debugprintf("B2 Message - zalloc for %d failed", Msg->length + 2000); - - OrigLen = Msg->length; - - // If a B2 Message add R:line at start of Body, but otherwise leave intact. - // Unless a message to Paclink, when we must remove any HA from the TO address - // Or to a CMS, when we remove HA from From or Reply-to - - if (Msg->B2Flags & B2Msg) - { - char * ptr, *ptr2; - int BodyLen; - int BodyLineLen; - int Index; - - MsgLen = OrigLen + RlineLen; - - if (conn->Paclink) - { - // Remove any HA on the TO address - - ptr = strstr(MsgBytes, "To:"); - if (ptr) - { - ptr2 = strstr(ptr, "\r\n"); - if (ptr2) - { - while (ptr < ptr2) - { - if (*ptr == '.' || *ptr == '@') - { - memset(ptr, ' ', ptr2 - ptr); - break; - } - ptr++; - } - } - } - } - - if (conn->WL2K) - { - // Remove any HA on the From or Reply-To address - - ptr = strstr(MsgBytes, "From:"); - if (ptr == NULL) - ptr = strstr(MsgBytes, "Reply-To:"); - - if (ptr) - { - ptr2 = strstr(ptr, "\r\n"); - if (ptr2) - { - while (ptr < ptr2) - { - if (*ptr == '.' || *ptr == '@') - { - memset(ptr, ' ', ptr2 - ptr); - break; - } - ptr++; - } - } - } - } - - - // Add R: Line at start of body. Will Need to Update Body Length - - ptr = strstr(MsgBytes, "Body:"); - - if (ptr == 0) - { - Debugprintf("B2 Messages without Body: Line"); - return FALSE; - } - ptr2 = strstr(ptr, "\r\n"); - - Index = (int)(ptr - MsgBytes); // Bytes Before Body: line - - if (Index <= 0 || Index > MsgLen) - { - Debugprintf("B2 Message Body: line position invalid - %d", Index); - return FALSE; - } - - // If message to saildocs adding an R: line will mess up the message processing, so add as an X header - - if (strstr(MsgBytes, "To: query@saildocs.com")) - { - int x_Len; - - memcpy(UnCompressed, MsgBytes, Index); // Up to Old Body; - x_Len = sprintf(&UnCompressed[Index], "x-R: %s", &Rline[2]); - MsgLen = OrigLen + x_Len; - Index +=x_Len; - goto copyRest; - } - - BodyLen = atoi(&ptr[5]); - - if (BodyLen < 0 || BodyLen > MsgLen) - { - Debugprintf("B2 Message Length from Body: line invalid - Msg len %d From Body %d", MsgLen, BodyLen); - return FALSE; - } - - BodyLineLen = (int)(ptr2 - ptr) + 2; - MsgLen -= BodyLineLen; // Length of Body Line may change - - ptr = strstr(ptr2, "\r\n\r\n"); // Blank line before Body - - if (ptr == 0) - { - Debugprintf("B2 Message - No Blank Line before Body"); - return FALSE; - } - - ptr += 4; - - ptr2 += 2; // Line Following Original Body: Line - - BodyLineToBody = (int)(ptr - ptr2); - - if (memcmp(ptr, "R:", 2) != 0) // No R line, so must be our message - { - strcat(Rline, "\r\n"); - RlineLen += 2; - MsgLen += 2; - } - BodyLen += RlineLen; - - memcpy(UnCompressed, MsgBytes, Index); // Up to Old Body; - BodyLineLen = sprintf(&UnCompressed[Index], "Body: %d\r\n", BodyLen); - - MsgLen += BodyLineLen; // Length of Body Line may have changed - Index += BodyLineLen; - - if (BodyLineToBody < 0 || BodyLineToBody > 1000) - { - Debugprintf("B2 Message - Body too far from Body Line - %d", BodyLineToBody); - return FALSE; - } - memcpy(&UnCompressed[Index], ptr2, BodyLineToBody); // Stuff Between Body: Line and Body - - Index += BodyLineToBody; - - memcpy(&UnCompressed[Index], Rline, RlineLen); - Index += RlineLen; - -copyRest: - - memcpy(&UnCompressed[Index], ptr, MsgLen - Index); // Rest of Message - - FBBHeader->Size = MsgLen; - - Compressed = zalloc(2 * MsgLen + 200); -#ifndef LINBPQ - __try { -#endif - CompLen = Encode(UnCompressed, Compressed, MsgLen, TRUE, conn->BBSFlags & FBBCompressed); - - FBBHeader->CompressedMsg = Compressed; - FBBHeader->CSize = CompLen; - - free(UnCompressed); - return TRUE; -#ifndef LINBPQ - } My__except_Routine("Encode B2Message"); -#endif - return FALSE; - } - - - if (memcmp(MsgBytes, "R:", 2) != 0) // No R line, so must be our message - { - strcat(Rline, "\r\n"); - RlineLen += 2; - } - - MsgLen = OrigLen + RlineLen; - -// if (conn->RestartFrom == 0) -// { -// // save time first sent, or checksum will be wrong when we restart -// -// FwdMsg->datechanged=time(NULL); -// } - - tm = gmtime((time_t *)&Msg->datechanged); - - sprintf(Date, "%04d/%02d/%02d %02d:%02d", - tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); - - // We create the B2 Header -/* - MID: XR88I1J160EB - Date: 2009/07/25 18:17 - Type: Private - From: SMTP:john.wiseman@ntlworld.com - To: G8BPQ - Subject: RE: RMS Test Message - Mbo: SMTP - Body: 213 - -*/ - if (strcmp(Msg->to, "RMS") == 0) // Address is in via - strcpy(B2To, Msg->via); - else - if (Msg->via[0] && (!conn->Paclink)) - sprintf(B2To, "%s@%s", Msg->to, Msg->via); - else - strcpy(B2To, Msg->to); - - // Try to create a full from: addrsss so RMS Express can reply - - strcpy(B2From, Msg->from); - - Logprintf(LOG_BBS, conn, '?', "B2 From %s", B2From); - - if (strcmp(conn->Callsign, "RMS") != 0 && conn->WL2K == 0) // if going to RMS - just send calll - { - if (_stricmp(Msg->from, "SMTP:") == 0) // Address is in via - strcpy(B2From, Msg->emailfrom); - else - { - FromUser = LookupCall(Msg->from); - - if (FromUser) - { - Logprintf(LOG_BBS, conn, '?', "B2 From - Local User"); - - if (FromUser->HomeBBS[0]) - sprintf(B2From, "%s@%s", Msg->from, FromUser->HomeBBS); - else - sprintf(B2From, "%s@%s", Msg->from, BBSName); - } - else - { - WPRecP WP = LookupWP(Msg->from); - - Logprintf(LOG_BBS, conn, '?', "B2 From - not local User"); - - if (WP) - sprintf(B2From, "%s@%s", Msg->from, WP->first_homebbs); - } - } - } - - Logprintf(LOG_BBS, conn, '?', "B2 From Finally %s", B2From); - - if (Msg->type == 'P') - TypeString = "Private" ; - else if (Msg->type == 'B') - TypeString = "Bulletin"; - else if (Msg->type == 'T') - TypeString = "Traffic"; - - B2HddrLen = sprintf(UnCompressed, - "MID: %s\r\nDate: %s\r\nType: %s\r\nFrom: %s\r\nTo: %s\r\nSubject: %s\r\nMbo: %s\r\n" - "Content-Type: text/plain\r\nContent-Transfer-Encoding: 8bit\r\nBody: %d\r\n\r\n", - Msg->bid, Date, TypeString, B2From, B2To, Msg->title, BBSName, MsgLen); - - - memcpy(&UnCompressed[B2HddrLen], Rline, RlineLen); - memcpy(&UnCompressed[B2HddrLen + RlineLen], MsgBytes, OrigLen); // Rest of Message - - MsgLen += B2HddrLen; - - FBBHeader->Size = MsgLen; - - Compressed = zalloc(2 * MsgLen + 200); - - CompLen = Encode(UnCompressed, Compressed, MsgLen, TRUE, conn->BBSFlags & FBBCompressed); - - FBBHeader->CompressedMsg = Compressed; - FBBHeader->CSize = CompLen; - - free(UnCompressed); - - return TRUE; -#ifndef LINBPQ - } My__except_Routine("CreateB2Message"); -#endif - return FALSE; - -} - -VOID SendCompressedB2(CIRCUIT * conn, struct FBBHeaderLine * FBBHeader) -{ - UCHAR * Compressed, * Compressedptr; - UCHAR * Output, * Outputptr; - int i, CompLen; - int Index; - - if (FBBHeader->FwdMsg->type == 'P') - Index = PMSG; - else if (FBBHeader->FwdMsg->type == 'B') - Index = BMSG; - else if (FBBHeader->FwdMsg->type == 'T') - Index = TMSG; - - Compressed = Compressedptr = FBBHeader->CompressedMsg; - - Output = Outputptr = zalloc(FBBHeader->CSize + 10000); - - *Outputptr++ = 1; - *Outputptr++ = (int)strlen(FBBHeader->FwdMsg->title) + 8; - strcpy(Outputptr, FBBHeader->FwdMsg->title); - Outputptr += strlen(FBBHeader->FwdMsg->title) +1; - sprintf(Outputptr, "%06d", conn->RestartFrom); - Outputptr += 7; - - CompLen = FBBHeader->CSize; - - conn->FBBChecksum = 0; - - // If restarting, send the checksum and length as a single record, then data from the restart point - // The count includes the header, so adjust count and pointers - - if (conn->RestartFrom) - { - *Outputptr++ = 2; - *Outputptr++ = 6; - - for (i=0; i< 6; i++) - { - conn->FBBChecksum+=Compressed[i]; - *Outputptr++ = Compressed[i]; - } - - for (i=conn->RestartFrom; i< CompLen; i++) - { - conn->FBBChecksum+=Compressed[i]; - } - - Compressedptr += conn->RestartFrom; - CompLen -= conn->RestartFrom; - } - else - { - for (i=0; i< CompLen; i++) - { - conn->FBBChecksum+=Compressed[i]; - } - conn->UserPointer->Total.MsgsSent[Index]++; - conn->UserPointer->Total.BytesForwardedOut[Index] += FBBHeader->FwdMsg->length; - - } - - while (CompLen > 256) - { - *Outputptr++ = 2; - *Outputptr++ = 0; - - memcpy(Outputptr, Compressedptr, 256); - Outputptr += 256; - Compressedptr += 256; - CompLen -= 256; - } - - *Outputptr++ = 2; - *Outputptr++ = CompLen; - - memcpy(Outputptr, Compressedptr, CompLen); - - Outputptr += CompLen; - - *Outputptr++ = 4; - conn->FBBChecksum = - conn->FBBChecksum; - *Outputptr++ = conn->FBBChecksum; - - if (conn->OpenBCM) // Telnet, so escape any 0xFF - { - unsigned char * ptr1 = Output; - unsigned char * ptr2 = Compressed; // Reuse Compressed buffer - int Len = (int)(Outputptr - Output); - unsigned char c; - - while (Len--) - { - c = *(ptr1++); - *(ptr2++) = c; - if (c == 0xff) // FF becodes FFFF - *(ptr2++) = c; - } - - QueueMsg(conn, Compressed, (int)(ptr2 - Compressed)); - } - else - QueueMsg(conn, Output, (int)(Outputptr - Output)); - - free(Compressed); - free(Output); -} - -// Restart Routines. - -VOID SaveFBBBinary(CIRCUIT * conn) -{ - // Disconnected during binary transfer - - char Msg[120]; - int i, len; - struct FBBRestartData * RestartRec = NULL; - - if (conn->TempMsg == NULL) - return; - - if (conn->TempMsg->length < 256) - return; // Not worth it. - - // If we already have a restart record, reuse it - - for (i = 1; i <= RestartCount; i++) - { - RestartRec = RestartData[i]; - - if ((strcmp(RestartRec->Call, conn->UserPointer->Call) == 0) - && (strcmp(RestartRec->bid, conn->TempMsg->bid) == 0)) - { - // Found it, so reuse - - // If we have more data, reset retry count - - if (RestartRec->length < conn->TempMsg->length) - RestartRec->Count = 0;; - - break; - } - } - - if (RestartRec == NULL) - { - RestartRec = zalloc(sizeof (struct FBBRestartData)); - - GetSemaphore(&AllocSemaphore, 0); - - RestartData=realloc(RestartData,(++RestartCount+1) * sizeof(void *)); - RestartData[RestartCount] = RestartRec; - - FreeSemaphore(&AllocSemaphore); - RestartRec->TimeCreated = time(NULL); - } - - strcpy(RestartRec->Call, conn->UserPointer->Call); - RestartRec->length = conn->TempMsg->length; - strcpy(RestartRec->bid, conn->TempMsg->bid); - RestartRec->MailBuffer = conn->MailBuffer; - RestartRec->MailBufferSize = conn->MailBufferSize; - - len = sprintf_s(Msg, sizeof(Msg), "Disconnect received from %s during Binary Transfer - %d Bytes Saved for restart", - conn->Callsign, conn->TempMsg->length); - - SaveRestartData(); - - WriteLogLine(conn, '|',Msg, len, LOG_BBS); -} - -void DeleteRestartData(CIRCUIT * conn) -{ - struct FBBRestartData * RestartRec = NULL; - int i, n; - - if (conn->TempMsg == NULL) - return; - - for (i = 1; i <= RestartCount; i++) - { - RestartRec = RestartData[i]; - - if ((strcmp(RestartRec->Call, conn->UserPointer->Call) == 0) - && (strcmp(RestartRec->bid, conn->TempMsg->bid) == 0)) - { - // Remove restrt data - - for (n = i; n < RestartCount; n++) - { - RestartData[n] = RestartData[n+1]; // move down all following entries - } - - RestartCount--; - SaveRestartData(); - return; - } - } -} - - -BOOL LookupRestart(CIRCUIT * conn, struct FBBHeaderLine * FBBHeader) -{ - int i, n; - - struct FBBRestartData * RestartRec; - - if ((conn->BBSFlags & FBBB1Mode) == 0) - return FALSE; // Only B1 & B2 support restart - - for (i = 1; i <= RestartCount; i++) - { - RestartRec = RestartData[i]; - - if ((strcmp(RestartRec->Call, conn->UserPointer->Call) == 0) - && (strcmp(RestartRec->bid, FBBHeader->BID) == 0)) - { - char Msg[120]; - int len; - - RestartRec->Count++; - - if (RestartRec->Count > 10) - { - len = sprintf_s(Msg, sizeof(Msg), "Too many restarts for %s - Requesting restart from beginning", - FBBHeader->BID); - - WriteLogLine(conn, '|',Msg, len, LOG_BBS); - - // Remove restrt data - - for (n = i; n < RestartCount; n++) - { - RestartData[n] = RestartData[n+1]; // move down all following entries - } - - RestartCount--; - SaveRestartData(); - return FALSE; - } - - len = sprintf_s(Msg, sizeof(Msg), "Restart Data found for %s - Requesting restart from %d", - FBBHeader->BID, RestartRec->length); - - WriteLogLine(conn, '|',Msg, len, LOG_BBS); - - return (RestartRec->length); - } - } - - return FALSE; // Not Found -} - - - -BOOL DoWeWantIt(CIRCUIT * conn, struct FBBHeaderLine * FBBHeader) -{ - struct MsgInfo * Msg; - BIDRec * BID; - int m; - - if (RefuseBulls && FBBHeader->MsgType == 'B') - { - Logprintf(LOG_BBS, conn, '?', "Message Rejected by RefuseBulls"); - return FALSE; - } - if (FBBHeader->Size > MaxRXSize) - { - Logprintf(LOG_BBS, conn, '?', "Message Rejected by Size Check"); - return FALSE; - } - - BID = LookupBID(FBBHeader->BID); - - if (BID) - { - if (FBBHeader->MsgType == 'B') - { - Logprintf(LOG_BBS, conn, '?', "Message Rejected by BID Check"); - return FALSE; - } - - // Treat P messages to SYSOP@WW as Bulls - - if (strcmp(FBBHeader->To, "SYSOP") == 0 && strcmp(FBBHeader->ATBBS, "WW") == 0) - { - Logprintf(LOG_BBS, conn, '?', "Message Rejected by BID Check"); - return FALSE; - } - - m = NumberofMessages; - - while (m > 0) - { - Msg = MsgHddrPtr[m]; - - if (Msg->number == BID->u.msgno) - { - // if the same TO we will assume the same message - - if (strcmp(Msg->to, FBBHeader->To) == 0) - { - // We have this message. If we have already forwarded it, we should accept it again - - if ((Msg->status == 'N') || (Msg->status == 'Y')|| (Msg->status == 'H')) - { - Logprintf(LOG_BBS, conn, '?', "Message Rejected by BID Check"); - return FALSE; // Dont want it - } - else - return TRUE; // Get it again - } - - // Same number. but different message (why?) Accept for now - - return TRUE; - } - - m--; - } - - return TRUE; // A personal Message we have had before, but don't still have. - } - else - { - // We don't know the BID - - return TRUE; // We want it - } -} - - - - diff --git a/.svn/pristine/10/108655b013214695f1c2c29f5492cd4f17755b62.svn-base b/.svn/pristine/10/108655b013214695f1c2c29f5492cd4f17755b62.svn-base deleted file mode 100644 index 49e3f4e..0000000 --- a/.svn/pristine/10/108655b013214695f1c2c29f5492cd4f17755b62.svn-base +++ /dev/null @@ -1,22 +0,0 @@ -Chat : -{ - ApplNum = 2; - MaxStreams = 11; - OtherChatNodes = "RDGCHT:GB7RDG-1|C STHGTE|C 1 MB7NCR-2|C RDGCHT\r\nRDGCHT:GB7RDG-1|C STHGTE|C 1 MB7NCR-2|C RDGCHT\r\n\r\n"; - ChatWelcomeMsg = "G8BPQ Chat Server.$WType /h for command summary.$WBringing up links to other nodes.$WThis may take a minute or two.$WThe /p command shows what nodes are linked.$W"; - MapPosition = "MapPosition=5259.04N, 00107.01W"; - MapPopup = "MapPopup=G8BPQ Nottingham

BPQ32 Home Page - -#include "cheaders.h" -#include "tncinfo.h" - -int C_Q_COUNT(VOID *PQ); -VOID SENDUIMESSAGE(struct DATAMESSAGE * Msg); - -VOID TNCTimerProc() -{ - // CALLED AT 10 HZ - - int n = BPQHOSTSTREAMS; - PBPQVECSTRUC HOSTSESS = BPQHOSTVECTOR; - TRANSPORTENTRY * Session; - UCHAR DISCFLAG = 0; - - while (n--) - { - // Action any DISC Requests (must be done in timer owning process) - - if (HOSTSESS->HOSTFLAGS & 0x40) // DISC REQUEST - { - if (HOSTSESS->HOSTFLAGS & 0x20) // Stay? - DISCFLAG = 'S'; - - HOSTSESS->HOSTFLAGS &= 0x9F; // Clear Flags - - Session = HOSTSESS->HOSTSESSION; - - if (Session == 0) // Gone?? - { - HOSTSESS->HOSTFLAGS |= 3; // STATE CHANGE -#ifndef LINBPQ - if (HOSTSESS->HOSTHANDLE); - { - PostMessage(HOSTSESS->HOSTHANDLE, BPQMsg, HOSTSESS->HOSTSTREAM, 4); - } -#endif - continue; - } - - if (Session->L4CROSSLINK) - Session->L4CROSSLINK->STAYFLAG = DISCFLAG; - - HOSTSESS->HOSTSESSION = 0; - HOSTSESS->HOSTFLAGS |= 3; // STATE CHANGE - - PostStateChange(Session); - - CloseSessionPartner(Session); // SEND CLOSE TO PARTNER (IF PRESENT) - } - - // Check Trace Q - - if (HOSTSESS->HOSTAPPLFLAGS & 0x80) - { - if (HOSTSESS->HOSTTRACEQ) - { - int Count = C_Q_COUNT(&HOSTSESS->HOSTTRACEQ); - - if (Count > 100) - ReleaseBuffer((void *)Q_REM((void *)&HOSTSESS->HOSTTRACEQ)); - } - } - HOSTSESS++; - } -} - -VOID SendSmartID(struct PORTCONTROL * PORT) -{ - struct _MESSAGE * ID = IDMSG; - struct _MESSAGE * Buffer; - - PORT->SmartIDNeeded = 0; - - Buffer = GetBuff(); - - if (Buffer) - { - memcpy(Buffer, ID, ID->LENGTH); - - Buffer->PORT = PORT->PORTNUMBER; - - // IF PORT HAS A CALLSIGN DEFINED, SEND THAT INSTEAD - - if (PORT->PORTCALL[0] > 0x40) - { - memcpy(Buffer->ORIGIN, PORT->PORTCALL, 7); - Buffer->ORIGIN[6] |= 1; // SET END OF CALL BIT - } - - // If Pactor Style add to UI_Q - - if (PORT->PROTOCOL == 10 && PORT->TNC && PORT->TNC->Hardware != H_KISSHF && PORT->UICAPABLE) - { - EXTPORTDATA * EXTPORT = (EXTPORTDATA *) PORT; - - C_Q_ADD(&EXTPORT->UI_Q, Buffer); - return; - } - - PUT_ON_PORT_Q(PORT, Buffer); - } -} - - -VOID SENDIDMSG() -{ - struct PORTCONTROL * PORT = PORTTABLE; - struct _MESSAGE * ID = IDMSG; - struct _MESSAGE * Buffer; - - while (PORT) - { - if (PORT->PROTOCOL < 10) // Not Pactor-style - { - Buffer = GetBuff(); - - if (Buffer) - { - memcpy(Buffer, ID, ID->LENGTH); - - Buffer->PORT = PORT->PORTNUMBER; - - // IF PORT HAS A CALLSIGN DEFINED, SEND THAT INSTEAD - - if (PORT->PORTCALL[0] > 0x40) - { - memcpy(Buffer->ORIGIN, PORT->PORTCALL, 7); - Buffer->ORIGIN[6] |= 1; // SET END OF CALL BIT - } - C_Q_ADD(&IDMSG_Q, Buffer); - } - } - PORT = PORT->PORTPOINTER; - } -} - - - -VOID SENDBTMSG() -{ - struct PORTCONTROL * PORT = PORTTABLE; - struct _MESSAGE * Buffer; - char * ptr1, * ptr2; - - while (PORT) - { - if (PORT->PROTOCOL >= 10 || PORT->PORTUNPROTO == 0) // Pactor-style or no UNPROTO ADDR? - { - PORT = PORT->PORTPOINTER; - continue; - } - - Buffer = GetBuff(); - - if (Buffer) - { - memcpy(Buffer->DEST, PORT->PORTUNPROTO, 7); - Buffer->DEST[6] |= 0xC0; // Set Command bits - - // Send from BBSCALL unless PORTBCALL defined - - if (PORT->PORTBCALL[0] > 32) - memcpy(Buffer->ORIGIN, PORT->PORTBCALL, 7); - else if (APPLCALLTABLE->APPLCALL[0] > 32) - memcpy(Buffer->ORIGIN, APPLCALLTABLE->APPLCALL, 7); - else - memcpy(Buffer->ORIGIN, MYCALL, 7); - - ptr1 = &PORT->PORTUNPROTO[7]; // First Digi - ptr2 = &Buffer->CTL; // Digi field in buffer - - // Copy any digis - - while (*(ptr1)) - { - memcpy(ptr2, ptr1, 7); - ptr1 += 7; - ptr2 += 7; - } - - *(ptr2 - 1) |= 1; // Set End of Address - *(ptr2++) = UI; - - memcpy(ptr2, &BTHDDR.PID, BTHDDR.LENGTH); - ptr2 += BTHDDR.LENGTH; - Buffer->LENGTH = (int)(ptr2 - (char *)Buffer); - Buffer->PORT = PORT->PORTNUMBER; - - C_Q_ADD(&IDMSG_Q, Buffer); - } - PORT = PORT->PORTPOINTER; - } -} - -VOID SENDUIMESSAGE(struct DATAMESSAGE * Msg) -{ - struct PORTCONTROL * PORT = PORTTABLE; - struct _MESSAGE * Buffer; - char * ptr1, * ptr2; - - Msg->LENGTH -= MSGHDDRLEN; // Remove Header - - while (PORT) - { - if ((PORT->PROTOCOL == 10 && PORT->UICAPABLE == 0) || PORT->PORTUNPROTO == 0) // Pactor-style or no UNPROTO ADDR? - { - PORT = PORT->PORTPOINTER; - continue; - } - - Buffer = GetBuff(); - - if (Buffer) - { - memcpy(Buffer->DEST, PORT->PORTUNPROTO, 7); - Buffer->DEST[6] |= 0xC0; // Set Command bits - - // Send from BBSCALL unless PORTBCALL defined - - if (PORT->PORTBCALL[0] > 32) - memcpy(Buffer->ORIGIN, PORT->PORTBCALL, 7); - else if (APPLCALLTABLE->APPLCALL[0] > 32) - memcpy(Buffer->ORIGIN, APPLCALLTABLE->APPLCALL, 7); - else - memcpy(Buffer->ORIGIN, MYCALL, 7); - - ptr1 = &PORT->PORTUNPROTO[7]; // First Digi - ptr2 = &Buffer->CTL; // Digi field in buffer - - // Copy any digis - - while (*(ptr1)) - { - memcpy(ptr2, ptr1, 7); - ptr1 += 7; - ptr2 += 7; - } - - *(ptr2 - 1) |= 1; // Set End of Address - *(ptr2++) = UI; - - memcpy(ptr2, &Msg->PID, Msg->LENGTH); - ptr2 += Msg->LENGTH; - Buffer->LENGTH = (int)(ptr2 - (char *)Buffer); - Buffer->PORT = PORT->PORTNUMBER; - - if (PORT->PROTOCOL == 10) - { - EXTPORTDATA * EXTPORT = (EXTPORTDATA *) PORT; - C_Q_ADD(&EXTPORT->UI_Q, Buffer); - } - else - C_Q_ADD(&IDMSG_Q, Buffer); - } - PORT = PORT->PORTPOINTER; - } -} - -Dll VOID APIENTRY Send_AX(UCHAR * Block, DWORD Len, UCHAR Port) -{ - // Block included the 7/11 byte header, Len does not - - struct PORTCONTROL * PORT; - PMESSAGE Copy; - - if (Len > 360 - 15) - return; - - if (QCOUNT < 50) - return; // Running low - - PORT = GetPortTableEntryFromPortNum(Port); - - if (PORT == 0) - return; - - Copy = GetBuff(); - - if (Copy == 0) - return; - - memcpy(&Copy->DEST[0], &Block[MSGHDDRLEN], Len); - - Copy->LENGTH = (USHORT)Len + MSGHDDRLEN; - - if (PORT->PROTOCOL == 10 && PORT->TNC && PORT->TNC->Hardware != H_KISSHF) - { - // Pactor Style. Probably will only be used for Tracker uneless we do APRS over V4 or WINMOR - - EXTPORTDATA * EXTPORT = (EXTPORTDATA *) PORT; - - if (EXTPORT->UI_Q) - C_Q_ADD(&EXTPORT->UI_Q, Copy); - else - C_Q_ADD(&EXTPORT->UI_Q, Copy); - return; - } - - Copy->PORT = Port; - - PUT_ON_PORT_Q(PORT, Copy); -} - - -TRANSPORTENTRY * SetupSessionFromHost(PBPQVECSTRUC HOST, UINT ApplMask) -{ - // Create a Transport (L4) session linked to an incoming HOST (API) Session - - TRANSPORTENTRY * NewSess = L4TABLE; - int Index = 0; - - - while (Index < MAXCIRCUITS) - { - if (NewSess->L4USER[0] == 0) - { - // Got One - - UCHAR * ourcall = &MYCALL[0]; - - // IF APPL PORT USE APPL CALL, ELSE NODE CALL - - if (ApplMask) - { - // Circuit for APPL - look for an APPLCALL - - APPLCALLS * APPL = APPLCALLTABLE; - - while ((ApplMask & 1) == 0) - { - ApplMask >>= 1; - APPL++; - } - if (APPL->APPLCALL[0] > 0x40) // We have an applcall - ourcall = &APPL->APPLCALL[0]; - } - - memcpy(NewSess->L4USER, ourcall, 7); - memcpy(NewSess->L4MYCALL, ourcall, 7); - - NewSess->CIRCUITINDEX = Index; //OUR INDEX - NewSess->CIRCUITID = NEXTID; - - NEXTID++; - if (NEXTID == 0) - NEXTID++; // Keep Non-Zero - - NewSess->L4TARGET.HOST = HOST; - NewSess->L4STATE = 5; - - - NewSess->SESSIONT1 = L4T1; - NewSess->L4WINDOW = (UCHAR)L4DEFAULTWINDOW; - NewSess->SESSPACLEN = PACLEN; // Default; - - return NewSess; - } - Index++; - NewSess++; - } - - // Table Full - - return NULL; -} - - - - diff --git a/.svn/pristine/11/11ab65d78680c467536199db5610df554c166f83.svn-base b/.svn/pristine/11/11ab65d78680c467536199db5610df554c166f83.svn-base deleted file mode 100644 index 5331129..0000000 Binary files a/.svn/pristine/11/11ab65d78680c467536199db5610df554c166f83.svn-base and /dev/null differ diff --git a/.svn/pristine/11/11d52b0b03646836ba24c40da664584b044dd1fc.svn-base b/.svn/pristine/11/11d52b0b03646836ba24c40da664584b044dd1fc.svn-base deleted file mode 100644 index 835424a..0000000 --- a/.svn/pristine/11/11d52b0b03646836ba24c40da664584b044dd1fc.svn-base +++ /dev/null @@ -1,82 +0,0 @@ -// -// Standard __except handler to dump stack and code around eip -// - -__except(memcpy(&exinfo, GetExceptionInformation(), sizeof(struct _EXCEPTION_POINTERS)), EXCEPTION_EXECUTE_HANDLER) -{ - unsigned __int32 SPPtr = 0; - unsigned __int32 SPVal = 0; - unsigned __int32 eip = 0; - unsigned __int32 rev = 0; - int i; - - DWORD Stack[16]; - DWORD CodeDump[16]; - -#ifndef _WIN64 - - eip = exinfo.ContextRecord->Eip; - SPPtr = exinfo.ContextRecord->Esp; - - __asm - { - mov eax, SPPtr - mov SPVal,eax - lea edi,Stack - mov esi,eax - mov ecx,64 - rep movsb - - lea edi,CodeDump - mov esi,eip - mov ecx,64 - rep movsb - } - - - - Debugprintf("BPQ32 *** Program Error %x at %x in %s", - exinfo.ExceptionRecord->ExceptionCode, exinfo.ExceptionRecord->ExceptionAddress, EXCEPTMSG); - - Debugprintf("EAX %x EBX %x ECX %x EDX %x ESI %x EDI %x ESP %x", - exinfo.ContextRecord->Eax, exinfo.ContextRecord->Ebx, exinfo.ContextRecord->Ecx, - exinfo.ContextRecord->Edx, exinfo.ContextRecord->Esi, exinfo.ContextRecord->Edi, SPVal); - -#endif - - Debugprintf("Stack:"); - - Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ", - SPVal, Stack[0], Stack[1], Stack[2], Stack[3], Stack[4], Stack[5], Stack[6], Stack[7]); - - Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ", - SPVal+32, Stack[8], Stack[9], Stack[10], Stack[11], Stack[12], Stack[13], Stack[14], Stack[15]); - - Debugprintf("Code:"); - - 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 ", - eip, 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 %08x ", - eip+32, CodeDump[8], CodeDump[9], CodeDump[10], CodeDump[11], CodeDump[12], CodeDump[13], CodeDump[14], CodeDump[15]); - - WriteMiniDump(); - - // Note - no closing } so additional code may be run in the __except block - -#ifdef MDIKERNEL - if (CloseOnError == 1) - CloseAllNeeded = 1; -#endif - -#undef EXCEPTMSG diff --git a/.svn/pristine/11/11df31525d8096af91b6003047c846fb996c508a.svn-base b/.svn/pristine/11/11df31525d8096af91b6003047c846fb996c508a.svn-base deleted file mode 100644 index 1ecd775..0000000 --- a/.svn/pristine/11/11df31525d8096af91b6003047c846fb996c508a.svn-base +++ /dev/null @@ -1,2201 +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 -*/ - - -#pragma data_seg("_BPQDATA") - -#define _CRT_SECURE_NO_DEPRECATE - -#include - -#define SD_RECEIVE 0x00 -#define SD_SEND 0x01 -#define SD_BOTH 0x02 - - -#include "kernelresource.h" -#include "cheaders.h" -#include "tncinfo.h" -#ifndef LINBPQ -#include -#endif -//#include -#include "bpq32.h" -#include "adif.h" - - -HANDLE hInstance; -extern HBRUSH bgBrush; -extern HWND ClientWnd, FrameWnd; -extern int OffsetH, OffsetW; - -extern HMENU hMainFrameMenu; -extern HMENU hBaseMenu; -extern HANDLE hInstance; - -extern HKEY REGTREE; - -extern int Ver[]; - - -int KillTNC(struct TNCINFO * TNC); -int RestartTNC(struct TNCINFO * TNC); - -char * GetChallengeResponse(char * Call, char * ChallengeString); - -VOID __cdecl Debugprintf(const char * format, ...); -int FromLOC(char * Locator, double * pLat, double * pLon); -BOOL ToLOC(double Lat, double Lon , char * Locator); - -int GetPosnFromAPRS(char * Call, double * Lat, double * Lon); -char * stristr (char *ch1, char *ch2); - - -static RECT Rect; - -#define WSA_ACCEPT WM_USER + 1 -#define WSA_DATA WM_USER + 2 -#define WSA_CONNECT WM_USER + 3 - -int Winmor_Socket_Data(int sock, int error, int eventcode); - -struct WL2KInfo * WL2KReports; - -int WL2KTimer = 0; - -int ModetoBaud[31] = {0,0,0,0,0,0,0,0,0,0,0, // 0 = 10 - 200,600,3200,600,3200,3200, // 11 - 16 - 0,0,0,0,0,0,0,0,0,0,0,0,0,600}; // 17 - 30 - -extern char HFCTEXT[]; -extern int HFCTEXTLEN; - - -extern char WL2KCall[10]; -extern char WL2KLoc[7]; - - -VOID MoveWindows(struct TNCINFO * TNC) -{ -#ifndef LINBPQ - RECT rcClient; - int ClientHeight, ClientWidth; - - GetClientRect(TNC->hDlg, &rcClient); - - ClientHeight = rcClient.bottom; - ClientWidth = rcClient.right; - - if (TNC->hMonitor) - MoveWindow(TNC->hMonitor,2 , TNC->RigControlRow + 3, ClientWidth-4, ClientHeight - (TNC->RigControlRow + 3), TRUE); -#endif -} - -char * Config; -static char * ptr1, * ptr2; - -#ifndef LINBPQ - -LRESULT CALLBACK PacWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - MINMAXINFO * mmi; - - int i; - struct TNCINFO * TNC; - - HKEY hKey; - char Key[80]; - int retCode, disp; - - for (i=0; i<41; 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_CREATE: - - break; - - case WM_PAINT: - -// hdc = BeginPaint (hWnd, &ps); - -// SelectObject( hdc, hFont) ; - -// EndPaint (hWnd, &ps); -// -// wParam = hdc; - - break; - - - case WM_GETMINMAXINFO: - - if (TNC->ClientHeight) - { - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = TNC->ClientWidth; - mmi->ptMaxSize.y = TNC->ClientHeight; - mmi->ptMaxTrackSize.x = TNC->ClientWidth; - mmi->ptMaxTrackSize.y = TNC->ClientHeight; - } - - break; - - - case WM_MDIACTIVATE: - { - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - - if (TNC->hMenu) - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)TNC->hMenu, "Actions"); - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - -// SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) TNC->hMenu, (LPARAM) TNC->hWndMenu); - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - // call DrawMenuBar after the menu items are set - DrawMenuBar(FrameWnd); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - } - - - - case WM_INITMENUPOPUP: - - if (wParam == (WPARAM)TNC->hMenu) - { - if (TNC->ProgramPath) - { - if (strstr(TNC->ProgramPath, " TNC") || strstr(TNC->ProgramPath, "ARDOP") - || strstr(TNC->ProgramPath, "VARA") || stristr(TNC->ProgramPath, "FREEDATA")) - { - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_ENABLED); - - break; - } - } - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_GRAYED); - } - - break; - - case WM_COMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - case WINMOR_KILL: - - TNC->DontRestart = TRUE; - KillTNC(TNC); - break; - - case WINMOR_RESTART: - - TNC->DontRestart = FALSE; - KillTNC(TNC); - RestartTNC(TNC); - break; - - case WINMOR_RESTARTAFTERFAILURE: - - TNC->RestartAfterFailure = !TNC->RestartAfterFailure; - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", TNC->Port); - - retCode = RegCreateKeyEx(REGTREE, Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - RegSetValueEx(hKey,"TNC->RestartAfterFailure",0,REG_DWORD,(BYTE *)&TNC->RestartAfterFailure, 4); - RegCloseKey(hKey); - } - break; - - case ARDOP_ABORT: - - if (TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SIZING: - case WM_SIZE: - - MoveWindows(TNC); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - - case SC_RESTORE: - - TNC->Minimized = FALSE; - break; - - case SC_MINIMIZE: - - TNC->Minimized = TRUE; - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - 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_HSCROLL: - { - char value[16]; - - switch (LOWORD(wParam)) - { - case TB_ENDTRACK: - case TB_THUMBTRACK: - - TNC->TXOffset = SendMessage(TNC->xIDC_TXTUNE, TBM_GETPOS, 0, 0); - sprintf(value, "%d", TNC->TXOffset); - MySetWindowText(TNC->xIDC_TXTUNEVAL, value); - - break; - } - - default: - break; - } - case WM_DESTROY: - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); -} -#endif - -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; -#else - WNDCLASS wc; - char Title[80]; - int retCode, Type, Vallen; - HKEY hKey=0; - char Key[80]; - char Size[80]; - int Top, Left; - HANDLE hDlg = 0; - static int LP = 1235; - - if (TNC->hDlg) - { - ShowWindow(TNC->hDlg, SW_SHOWNORMAL); - SetForegroundWindow(TNC->hDlg); - return FALSE; // Already open - } - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = WndProc; - 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 = ClassName; - - RegisterClass(&wc); - -// if (TNC->Hardware == H_WINMOR || TNC->Hardware == H_TELNET ||TNC->Hardware == H_ARDOP || -// TNC->Hardware == H_V4 || TNC->Hardware == H_FLDIGI || TNC->Hardware == H_UIARQ || TNC->Hardware == H_VARA) - if (TNC->PortRecord) - sprintf(Title, "%s Status - Port %d %s", WindowTitle, TNC->Port, TNC->PortRecord->PORTCONTROL.PORTDESCRIPTION); - else - sprintf(Title, "Rigcontrol"); - - if (TNC->Hardware == H_MPSK) - sprintf(Title, "Rigcontrol for MultiPSK Port %d", TNC->Port); - - TNC->hDlg = hDlg = CreateMDIWindow(ClassName, Title, 0, - 0, 0, Width, Height, ClientWnd, hInstance, ++LP); - - // CreateDialog(hInstance,ClassName,0,NULL); - - Rect.top = 100; - Rect.left = 20; - Rect.right = Width + 20; - Rect.bottom = Height + 100; - - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", TNC->Port); - - 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,%d",&Rect.left,&Rect.right,&Rect.top,&Rect.bottom, &TNC->Minimized); - - if (Rect.top < - 500 || Rect.left < - 500) - { - Rect.left = 0; - Rect.top = 0; - Rect.right = 600; - Rect.bottom = 400; - } - - if (Rect.top < OffsetH) - { - int Error = OffsetH - Rect.top; - Rect.top += Error; - Rect.bottom += Error; - } - } - - if (TNC->Hardware == H_WINMOR || TNC->Hardware == H_ARDOP|| TNC->Hardware == H_VARA) - retCode = RegQueryValueEx(hKey,"TNC->RestartAfterFailure",0, - (ULONG *)&Type,(UCHAR *)&TNC->RestartAfterFailure,(ULONG *)&Vallen); - - RegCloseKey(hKey); - } - - Top = Rect.top; - Left = Rect.left; - -// GetWindowRect(hDlg, &Rect); // Get the real size - - MoveWindow(hDlg, Left - (OffsetW /2), Top - OffsetH, Rect.right - Rect.left, Rect.bottom - Rect.top, TRUE); - - if (TNC->Minimized) - ShowWindow(hDlg, SW_SHOWMINIMIZED); - else - ShowWindow(hDlg, SW_RESTORE); - - TNC->RigControlRow = RigControlRow; - - SetWindowText(TNC->xIDC_TNCSTATE, "Free"); - - TNC->ForcedCloseProc = ForcedCloseProc; - - return TRUE; -#endif -} - - -// WL2K Reporting Code. - -static SOCKADDR_IN sinx; - - -VOID SendReporttoWL2KThread(void * unused); -VOID SendHTTPReporttoWL2KThread(void * unused); - -VOID CheckWL2KReportTimer() -{ - if (WL2KReports == NULL) - return; // Shouldn't happen! - - WL2KTimer--; - - if (WL2KTimer != 0) - return; - -#ifdef WIN32 - WL2KTimer = 2 * 32910; // Every 2 Hours - PC Tick is a bit slow -#else - WL2KTimer = 2 * 36000; // Every 2 Hours -#endif - - if (CheckAppl(NULL, "RMS ") == NULL) - if (CheckAppl(NULL, "RELAY ") == NULL) - return; - - _beginthread(SendHTTPReporttoWL2KThread, 0, 0); - - return; -} - -static char HeaderTemplate[] = "POST %s HTTP/1.1\r\n" - "Accept: application/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" - //r\nUser-Agent: BPQ32(G8BPQ)\r\n" -// "Expect: 100-continue\r\n" - "\r\n{%s}"; - -char Missing[] = "** Missing **"; - -VOID GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value) -{ - char * ptr1, * ptr2; - - strcpy(Value, Missing); - - ptr1 = strstr(_REPLYBUFFER, Name); - - if (ptr1 == 0) - return; - - ptr1 += (strlen(Name) + 1); - - ptr2 = strchr(ptr1, '"'); - - if (ptr2) - { - size_t ValLen = ptr2 - ptr1; - memcpy(Value, ptr1, ValLen); - Value[ValLen] = 0; - } - - return; -} - - -// Send Winlink Session Record - -extern char LOC[7]; -extern char TextVerstring[50]; - -double Distance(double laa, double loa, double lah, double loh, BOOL KM); -double Bearing(double lat2, double lon2, double lat1, double lon1); -VOID SendHTTPRequest(SOCKET sock, char * Request, char * Params, int Len, char * Return); -SOCKET OpenWL2KHTTPSock(); - - - -struct WL2KMode -{ - int Mode; - char * WL2KString; - char * ADIFString; - char * BPQString; -}; - -struct WL2KMode WL2KModeList[] = -{ - {0,"Packet 1200"}, - {1,"Packet 2400"}, - {2, "Packet 4800"}, - {3, "Packet 9600"}, - {4, "Packet 19200"}, - {5, "Packet 38400"}, - {11, "Pactor 1"}, - {12, "Pactor 1,2"}, - {13, "Pactor 1,2,3"}, - {14, "Pactor 2"}, - {15, "Pactor 2,3"}, - {16, "Pactor 3"}, - {17, "Pactor 1,2,3,4"}, - {18, "Pactor 2,3,4"}, - {19, "Pactor 3,4"}, - {20, "Pactor 4"}, - {21, "WINMOR 500"}, - {22, "WINMOR 1600"}, - {30, "Robust Packet"}, - {40, "ARDOP 200"}, - {41, "ARDOP 500"}, - {42, "ARDOP 1000"}, - {43, "ARDOP 2000"}, - {44, "ARDOP 2000 FM"}, - {50, "VARA"}, - {51, "VARA FM"}, - {52, "VARA FM WIDE"}, - {53, "VARA 500"} -}; - -char WL2KModes [55][18] = { - "Packet 1200", "Packet 2400", "Packet 4800", "Packet 9600", "Packet 19200", "Packet 38400", "High Speed Packet", "", "", "", "", - "Pactor 1", "Pactor", "Pactor", "Pactor 2", "Pactor", "Pactor 3", "Pactor", "Pactor", "Pactor", "Pactor 4", // 11 - 20 - "Winmor 500", "Winmor 1600", "", "", "", "", "", "", "", // 21 - 29 - "Robust Packet", "", "", "", "", "", "", "", "", "", // 30 - 39 - "ARDOP 200", "ARDOP 500", "ARDOP 1000", "ARDOP 2000", "ARDOP 2000 FM", "", "", "", "", "", // 40 - 49 - "VARA", "VARA FM", "VARA FM WIDE", "VARA 500", "VARA 2750"}; - - -VOID SendWL2KSessionRecordThread(void * param) -{ - SOCKET sock; - char Message[512]; - - strcpy(Message, param); - free(param); - - Debugprintf("Sending %s", Message); - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - SendHTTPRequest(sock, "/session/add", (char *)Message, (int)strlen(Message), NULL); - closesocket(sock); - } - - return; -} - -VOID SendWL2KRegisterHybridThread(void * param) -{ - SOCKET sock; - char Message[512]; - - strcpy(Message, param); - free(param); - - Debugprintf("Sending %s", Message); - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - SendHTTPRequest(sock, "/radioNetwork/params/add", (char *)Message, (int)strlen(Message), NULL); - closesocket(sock); - } - - return; -} - -VOID SendWL2KRegisterHybrid(struct TNCINFO * TNC) -{ - char Message[512]; - char Date[80] ; - int Len; - struct TCPINFO * TCP = TNC->TCPInfo; - time_t T; - struct tm * tm; - char Call[10]; - - if (TCP == NULL || TCP->GatewayLoc[0] == 0) - return; - - strcpy(Call, TCP->GatewayCall); - strlop(Call, '-'); - - T = time(NULL); - tm = gmtime(&T); - - //2021-10-31-14=35=29 - - sprintf(Date, "%04d-%02d-%02d-%02d:%02d:%02d", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - -// "Callsign":"String","Password":"String","Param":"String","Value":"String","Key":"String" - - Len = sprintf(Message, "\"Callsign\":\"%s\",\"Password\":\"%s\",\"Param\":\"RMSRelayVersion\",\"Value\":\"%s|%s|*HARMNNNN|%s|%s|\"", - Call, TCP->SecureCMSPassword, Date, "3.1.11.2", - TCP->HybridServiceCode, TCP->GatewayLoc); - - SendWL2KRegisterHybridThread(_strdup(Message)); - - Len = sprintf(Message, "\"Callsign\":\"%s\",\"Password\":\"%s\",\"Param\":\"CoLocatedRMS\",\"Value\":\"%s\"", - Call, TCP->SecureCMSPassword, TCP->HybridCoLocatedRMS); - - SendWL2KRegisterHybridThread(_strdup(Message)); - - Len = sprintf(Message, "\"Callsign\":\"%s\",\"Password\":\"%s\",\"Param\":\"AllowFreq\",\"Value\":\"%s\"", - Call, TCP->SecureCMSPassword, TCP->HybridFrequencies); - - SendWL2KRegisterHybridThread(_strdup(Message)); - - return; -} - -BOOL NoSessionAccount = FALSE; -BOOL SessionAccountChecked = FALSE; - -BOOL SendWL2KSessionRecord(ADIF * ADIF, int BytesSent, int BytesReceived) -{ -/* -The API is /session/add https://api.winlink.org/json/metadata?op=SessionAdd - -The important parameters are (others can be omitted): - -Application (gateway program name) -Server (gateway callsign) -ServerGrid -Client (client callsign) -ClientGrid -Mode (Pactor, winmor, vara, etc) -Frequency -MessagesSent -MessagesReceived -BytesSent -BytesReceived -HoldingSeconds (duration of connection) -IdTag (random alphanumeric, 12 chars) - -"Application":"RMS Trimode", -"Version":"1.3.25.0", -"Cms":"CMS-A", -"Server":"AB4NX", -"ServerGrid":"EM73WT", -"Client":"VE2SCA","ClientGrid":"", -"Sid":"","Mode":"WINMOR16", -"Frequency":10145000, -"Kilometers":0, -"Degrees":0, -"LastCommand":">", -"MessagesSent":0, -"MessagesReceived":0, -"BytesSent":179, -"BytesReceived":0, -"HoldingSeconds":126, -"IdTag":"ATK9S3QGL2E1"} -*/ - time_t T; - - char Message[4096] = ""; - char * MessagePtr; - int MessageLen; - int Dist = 0; - int intBearing = 0; - - double Lat, Lon; - double myLat, myLon; - - char Tag[32]; - - SOCKET sock; - char Response[1024]; - int Len; - - // Only report if the CMSCall has a WL2KAccount - - if (NoSessionAccount) - return TRUE; - - if (!SessionAccountChecked) - { - // only check once - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - SessionAccountChecked = TRUE; - - Len = sprintf(Message, "\"Callsign\":\"%s\"", ADIF->CMSCall); - - SendHTTPRequest(sock, "/account/exists", Message, Len, Response); - closesocket(sock); - - if (strstr(Response, "\"CallsignExists\":false")) - { - WritetoConsole("WL2K Traffic Reporting disabled - Gateway "); - WritetoConsole(ADIF->CMSCall); - WritetoConsole(" does not have a Winlink Account\r\n"); - Debugprintf("WL2K Traffic Reporting disabled - Gateway %s does not have a Winlink Account", ADIF->CMSCall); - NoSessionAccount = TRUE; - return TRUE; - } - } - } - - if (ADIF == NULL || ADIF->LOC[0] == 0 || ADIF->Call[0] == 0) - return TRUE; - - if (ADIF->StartTime == 0 || ADIF->ServerSID[0] == 0 || ADIF->CMSCall[0] == 0) - return TRUE; - - T = time(NULL); - - // Extract Info we need - - // Distance and Bearing - - if (LOC[0] && ADIF->LOC[0]) - { - if (FromLOC(LOC, &myLat, &myLon) == 0) // Basic checks on LOCs - return TRUE; - if (FromLOC(ADIF->LOC, &Lat, &Lon) == 0) - return TRUE; - - Dist = (int)Distance(myLat, myLon, Lat, Lon, TRUE); - intBearing = (int)Bearing(Lat, Lon, myLat, myLon); - } - - MessageLen = sprintf(Message, "\"Application\":\"%s\",", "BPQ32"); - MessageLen += sprintf(&Message[MessageLen], "\"Version\":\"%s\",", TextVerstring); - MessageLen += sprintf(&Message[MessageLen], "\"Cms\":\"%s\",", "CMS"); - MessageLen += sprintf(&Message[MessageLen], "\"Server\":\"%s\",", ADIF->CMSCall); - MessageLen += sprintf(&Message[MessageLen], "\"ServerGrid\":\"%s\",", LOC); - MessageLen += sprintf(&Message[MessageLen], "\"Client\":\"%s\",", ADIF->Call); - MessageLen += sprintf(&Message[MessageLen], "\"ClientGrid\":\"%s\",", ADIF->LOC); - MessageLen += sprintf(&Message[MessageLen], "\"Sid\":\"%s\",", ADIF->UserSID); - MessageLen += sprintf(&Message[MessageLen], "\"Mode\":\"%s\",", WL2KModes[ADIF->Mode]); - MessageLen += sprintf(&Message[MessageLen], "\"Frequency\":%lld,", ADIF->Freq); - MessageLen += sprintf(&Message[MessageLen], "\"Kilometers\":%d,", Dist); - MessageLen += sprintf(&Message[MessageLen], "\"Degrees\":%d,", intBearing); - MessageLen += sprintf(&Message[MessageLen], "\"LastCommand\":\"%s\",", ADIF->Termination); - MessageLen += sprintf(&Message[MessageLen], "\"MessagesSent\":%d,", ADIF->Sent); - MessageLen += sprintf(&Message[MessageLen], "\"MessagesReceived\":%d,", ADIF->Received); - MessageLen += sprintf(&Message[MessageLen], "\"BytesSent\":%d,", BytesSent); - MessageLen += sprintf(&Message[MessageLen], "\"BytesReceived\":%d,", BytesReceived); - MessageLen += sprintf(&Message[MessageLen], "\"HoldingSeconds\":%d,", (int)(T - ADIF->StartTime)); - sprintf(Tag, "%012X", (int)T * (rand() + 1)); - MessageLen += sprintf(&Message[MessageLen], "\"IdTag\":\"%s\"", Tag); - - MessagePtr = _strdup(Message); - _beginthread(SendWL2KSessionRecordThread, 0, (void *)MessagePtr); - - return TRUE; -} - -char APIKey[] = ",\"Key\":\"0D0C7AD6B38C45A7A9534E67111C38A7\""; - - -VOID SendHTTPRequest(SOCKET sock, char * Request, char * Params, int Len, char * Return) -{ - int InputLen = 0; - int inptr = 0; - char Buffer[2048]; - char Header[2048]; - char * ptr, * ptr1; - int Sent; - - strcat(Params, APIKey); - Len += (int)strlen(APIKey); - - sprintf(Header, HeaderTemplate, Request, "api.winlink.org", 80, Len + 2, Params); - Sent = send(sock, Header, (int)strlen(Header), 0); - - if (Sent == -1) - { - int Err = WSAGetLastError(); - Debugprintf("Error %d from WL2K Update send()", Err); - return; - } - - while (InputLen != -1) - { - InputLen = recv(sock, &Buffer[inptr], 2048 - inptr, 0); - - if (InputLen == -1 || InputLen == 0) - { - int Err = WSAGetLastError(); - Debugprintf("Error %d from WL2K Update recv()", Err); - return; - } - - // As we are using a persistant connection, can't look for close. Check - // for complete message - - 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("WL2K Database update ok"); - - } - else - { - strlop(Buffer, 13); - Debugprintf("WL2K Update Params - %s", Params); - Debugprintf("WL2K Update failed - %s", Buffer); - } - return; - } - } - else - { - ptr1 = strstr(_strlwr(Buffer), "transfer-encoding:"); - - if (ptr1) - { - // Just accept anything until I've sorted things with Lee - Debugprintf("%s", ptr1); - Debugprintf("WL2K Database update ok"); - return; - } - } - } - } -} - -BOOL WL2KAccountChecked = FALSE; -BOOL NoWL2KAccount = FALSE; - -VOID SendHTTPReporttoWL2KThread(void * unused) -{ - // Uses HTTP/JSON Interface - - struct WL2KInfo * WL2KReport = WL2KReports; - char * LastHost = NULL; - char * LastRMSCall = NULL; - char Message[512]; - int LastSocket = 0; - SOCKET sock = 0; - struct sockaddr_in destaddr; - int addrlen=sizeof(sinx); - struct hostent * HostEnt; - int err; - u_long param=1; - BOOL bcopt=TRUE; - int Len; - - // Send all reports in list - - char Response[1024]; - - // Only report if the CMSCall has a WL2KAccount - - if (NoWL2KAccount) - return; - - if (!WL2KAccountChecked) - { - // only check once - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - WL2KAccountChecked = TRUE; - - Len = sprintf(Message, "\"Callsign\":\"%s\"", - WL2KReport->BaseCall); - - SendHTTPRequest(sock, "/account/exists", Message, Len, Response); - closesocket(sock); - - if (strstr(Response, "\"CallsignExists\":false")) - { - WritetoConsole("WL2K Reporting disabled - Gateway "); - WritetoConsole(WL2KReport->BaseCall); - WritetoConsole(" does not have a Winlink Account\r\n"); - NoWL2KAccount = TRUE; - return; - } - } - } - - while (WL2KReport) - { - // Resolve Name if needed - - if (LastHost && strcmp(LastHost, WL2KReport->Host) == 0) // Same host? - goto SameHost; - - // New Host - Connect to it - - LastHost = WL2KReport->Host; - - destaddr.sin_family = AF_INET; - destaddr.sin_addr.s_addr = inet_addr(WL2KReport->Host); - destaddr.sin_port = htons(WL2KReport->WL2KPort); - - if (destaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - Debugprintf("Resolving %s", WL2KReport->Host); - HostEnt = gethostbyname (WL2KReport->Host); - - if (!HostEnt) - { - err = WSAGetLastError(); - - Debugprintf("Resolve Failed for %s %d %x", WL2KReport->Host, err, err); - return; // Resolve failed - } - - memcpy(&destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - - // Allocate a Socket entry - - if (sock) - closesocket(sock); - - sock = socket(AF_INET, SOCK_STREAM, 0); - - if (sock == INVALID_SOCKET) - return; - -// ioctlsocket(sock, FIONBIO, ¶m); - - setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char FAR *)&bcopt, 4); - - destaddr.sin_family = AF_INET; - - if (sock == INVALID_SOCKET) - { - sock = 0; - return; - } - - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); - - // Connect to Host - - if (connect(sock,(LPSOCKADDR) &destaddr, sizeof(destaddr)) != 0) - { - err=WSAGetLastError(); - - // - // Connect failed - // - - Debugprintf("Connect Failed"); - closesocket(sock); - sock = 0; - break; - } - - SameHost: - - Len = sprintf(Message, - "\"Callsign\":\"%s\"," - "\"BaseCallsign\":\"%s\"," - "\"GridSquare\":\"%s\"," - "\"Frequency\":%lld," - "\"Mode\":%d," - "\"Baud\":%d," - "\"Power\":%d," - "\"Height\":%d," - "\"Gain\":%d," - "\"Direction\":%d," - "\"Hours\":\"%s\"," - "\"ServiceCode\":\"%s\"", - - WL2KReport->RMSCall, WL2KReport->BaseCall, WL2KReport->GridSquare, - WL2KReport->Freq, WL2KReport->mode, WL2KReport->baud, WL2KReport->power, - WL2KReport->height, WL2KReport->gain, WL2KReport->direction, - WL2KReport->Times, WL2KReport->ServiceCode); - - Debugprintf("Sending %s", Message); - - SendHTTPRequest(sock, "/channel/add", Message, Len, NULL); - - - // Send Version Message - - - if (LastRMSCall == NULL || strcmp(WL2KReport->RMSCall, LastRMSCall) != 0) - { - int Len; - - LastRMSCall = WL2KReport->RMSCall; - - // "Callsign":"String","Program":"String","Version":"String","Comments":"String" - - Len = sprintf(Message, "\"Callsign\":\"%s\",\"Program\":\"BPQ32\"," - "\"Version\":\"%d.%d.%d.%d\",\"Comments\":\"Test Comment\"", - WL2KReport->RMSCall, Ver[0], Ver[1], Ver[2], Ver[3]); - - Debugprintf("Sending %s", Message); - - SendHTTPRequest(sock, "/version/add", Message, Len, NULL); - } - - WL2KReport = WL2KReport->Next; - } - - Sleep(100); - closesocket(sock); - sock = 0; - -} - -struct WL2KInfo * DecodeWL2KReportLine(char * buf) -{ - //06'', '', '', , , , , - // , , , '', , '' - - // WL2KREPORT service, api.winlink.org, 80, GM8BPQ, IO68VL, 00-23, 144800000, PKT1200, 10, 20, 5, 0, BPQTEST - - char * Context; - char * p_cmd; - char * param; - char errbuf[256]; - struct WL2KInfo * WL2KReport = zalloc(sizeof(struct WL2KInfo)); - char * ptr; - char Param[8][256]; - char * ptr1, * ptr2; - int n = 0; - - memset(Param, 0, 2048); - - strcpy(errbuf, buf); - - p_cmd = strtok_s(&buf[10], ", \t\n\r", &Context); - if (p_cmd == NULL) goto BadLine; - - strcpy(WL2KReport->ServiceCode, p_cmd); - - // Can default Host and Port, so cant use strtok for them - - ptr1 = Context; - - while (ptr1 && *ptr1 && n < 2) - { - while(ptr1 && *ptr1 && *ptr1 == ' ') - ptr1++; - - ptr2 = strchr(ptr1, ','); - if (ptr2) *ptr2++ = 0; - - strcpy(&Param[n][0], ptr1); - strlop(Param[n++], ' '); - ptr1 = ptr2; - - } - - if (n < 2) - goto BadLine; - - if (Param[1][0] == 0) - WL2KReport->WL2KPort = 80; // HTTP Interface - else - WL2KReport->WL2KPort = atoi(&Param[1][0]); - - if (Param[0][0] == 0) - WL2KReport->Host = _strdup("api.winlink.org"); - else - { - _strlwr(&Param[0][0]); - - if (strstr(&Param[0][0], "winlink.org")) - { - WL2KReport->WL2KPort = 80; // HTTP Interface - WL2KReport->Host = _strdup("api.winlink.org"); - } - else - WL2KReport->Host = _strdup(&Param[0][0]); - } - - Context = ptr1; - - p_cmd = strtok_s(NULL, ", \t\n\r", &Context); - if (p_cmd == NULL) goto BadLine; - - if (WL2KReport->WL2KPort == 0) goto BadLine; - - strcpy(WL2KReport->RMSCall, p_cmd); - strcpy(WL2KReport->BaseCall, p_cmd); - strlop(WL2KReport->BaseCall, '-'); // Remove any SSID - - strcpy(WL2KCall, WL2KReport->BaseCall); // For SYSOP Update - - p_cmd = strtok_s(NULL, " ,\t\n\r", &Context); - if (p_cmd == NULL) goto BadLine; - if (strlen(p_cmd) != 6) goto BadLine; - - strcpy(WL2KReport->GridSquare, p_cmd); - strcpy(WL2KLoc, p_cmd); - - p_cmd = strtok_s(NULL, " ,\t\n\r", &Context); - if (p_cmd == NULL) goto BadLine; - if (strlen(p_cmd) > 79) goto BadLine; - - // Convert any : in times to comma - - ptr = strchr(p_cmd, ':'); - - while (ptr) - { - *ptr = ','; - ptr = strchr(p_cmd, ':'); - } - - strcpy(WL2KReport->Times, p_cmd); - - p_cmd = strtok_s(NULL, " ,\t\n\r", &Context); - if (p_cmd == NULL) goto BadLine; - - WL2KReport->Freq = strtoll(p_cmd, NULL, 10); - - if (WL2KReport->Freq == 0) // Invalid - goto BadLine; - - param = strtok_s(NULL, " ,\t\n\r", &Context); - - // Mode Designator - one of - - // PKTnnnnnn - // WINMOR500 - // WINMOR1600 - // ROBUST - // P1 P12 P123 P1234 etc - - if (memcmp(param, "PKT", 3) == 0) - { - int Speed, Mode; - - Speed = atoi(¶m[3]); - - WL2KReport->baud = Speed; - - if (Speed <= 1200) - Mode = 0; // 1200 - else if (Speed <= 2400) - Mode = 1; // 2400 - else if (Speed <= 4800) - Mode = 2; // 4800 - else if (Speed <= 9600) - Mode = 3; // 9600 - else if (Speed <= 19200) - Mode = 4; // 19200 - else if (Speed <= 38400) - Mode = 5; // 38400 - else - Mode = 6; // >38400 - - WL2KReport->mode = Mode; - } - else if (_stricmp(param, "WINMOR500") == 0) - WL2KReport->mode = 21; - else if (_stricmp(param, "WINMOR1600") == 0) - WL2KReport->mode = 22; - else if (_stricmp(param, "ROBUST") == 0) - { - WL2KReport->mode = 30; - WL2KReport->baud = 600; - } - else if (_stricmp(param, "ARDOP200") == 0) - WL2KReport->mode = 40; - else if (_stricmp(param, "ARDOP500") == 0) - WL2KReport->mode = 41; - else if (_stricmp(param, "ARDOP1000") == 0) - WL2KReport->mode = 42; - else if (_stricmp(param, "ARDOP2000") == 0) - WL2KReport->mode = 43; - else if (_stricmp(param, "ARDOP2000FM") == 0) - WL2KReport->mode = 44; - else if (_stricmp(param, "P1") == 0) - WL2KReport->mode = 11; - else if (_stricmp(param, "P12") == 0) - WL2KReport->mode = 12; - else if (_stricmp(param, "P123") == 0) - WL2KReport->mode = 13; - else if (_stricmp(param, "P2") == 0) - WL2KReport->mode = 14; - else if (_stricmp(param, "P23") == 0) - WL2KReport->mode = 15; - else if (_stricmp(param, "P3") == 0) - WL2KReport->mode = 16; - else if (_stricmp(param, "P1234") == 0) - WL2KReport->mode = 17; - else if (_stricmp(param, "P234") == 0) - WL2KReport->mode = 18; - else if (_stricmp(param, "P34") == 0) - WL2KReport->mode = 19; - else if (_stricmp(param, "P4") == 0) - WL2KReport->mode = 20; - else if (_stricmp(param, "VARA") == 0) - WL2KReport->mode = 50; - else if (_stricmp(param, "VARA2300") == 0) - WL2KReport->mode = 50; - else if (_stricmp(param, "VARAFM") == 0) - WL2KReport->mode = 51; - else if (_stricmp(param, "VARAFM12") == 0) - WL2KReport->mode = 51; - else if (_stricmp(param, "VARAFM96") == 0) - WL2KReport->mode = 52; - else if (_stricmp(param, "VARA500") == 0) - WL2KReport->mode = 53; - else if (_stricmp(param, "VARA2750") == 0) - WL2KReport->mode = 54; - else - goto BadLine; - - param = strtok_s(NULL, " ,\t\n\r", &Context); - - // Optional Params - - WL2KReport->power = (param)? atoi(param) : 0; - param = strtok_s(NULL, " ,\t\n\r", &Context); - WL2KReport->height = (param)? atoi(param) : 0; - param = strtok_s(NULL, " ,\t\n\r", &Context); - WL2KReport->gain = (param)? atoi(param) : 0; - param = strtok_s(NULL, " ,\t\n\r", &Context); - WL2KReport->direction = (param)? atoi(param) : 0; - - WL2KTimer = 60; - - WL2KReport->Next = WL2KReports; - WL2KReports = WL2KReport; - - return WL2KReport; - -BadLine: - - WritetoConsole(" Bad config record "); - WritetoConsole(errbuf); - WritetoConsole("\r\n"); - - return 0; -} - -VOID UpdateMHSupport(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction, char * Loc, BOOL Report, BOOL Digis); - -VOID UpdateMHwithDigis(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction) -{ - UpdateMHSupport(TNC, Call, Mode, Direction, NULL, TRUE, TRUE); -} -VOID UpdateMHEx(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction, char * LOC, BOOL Report) -{ - UpdateMHSupport(TNC, Call, Mode, Direction, LOC, Report, FALSE); -} - -VOID UpdateMH(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction) -{ - UpdateMHSupport(TNC, Call, Mode, Direction, NULL, TRUE, FALSE); -} - -VOID UpdateMHSupport(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction, char * Loc, BOOL Report, BOOL Digis) -{ - PMHSTRUC MH = TNC->PortRecord->PORTCONTROL.PORTMHEARD; - PMHSTRUC MHBASE = MH; - UCHAR AXCall[72] = ""; - int i; - char * LOC, * LOCEND; - char ReportMode[20]; - char NoLOC[7] = ""; - double Freq; - char ReportFreq[350] = ""; - int OldCount = 0; - char ReportCall[16]; - - if (MH == 0) return; - - if (Digis) - { - // Call is an ax.25 digi string not a text call - - memcpy(AXCall, Call, 7 * 9); - ReportCall[ConvFromAX25(Call, ReportCall)] = 0; - - // if this is a UI frame with a locator or APRS position - // we could derive a position from it - - } - else - { - strcpy(ReportCall, Call); - ConvToAX25(Call, AXCall); - AXCall[6] |= 1; // Set End of address - } - - // Adjust freq to centre - -// if (Mode != ' ' && TNC->RIG->Valchar[0]) - if (TNC->RIG->Valchar[0]) - { - if (TNC->Hardware == H_UZ7HO) - { - // See if we have Center Freq Info - if (TNC->AGWInfo->CenterFreq) - { - Freq = atof(TNC->RIG->Valchar) + ((TNC->AGWInfo->CenterFreq * 1.0) / 1000000.0); - } -#ifdef WIN32 - else if (TNC->AGWInfo->hFreq) - { - char Centre[16]; - double ModemFreq; - - SendMessage(TNC->AGWInfo->hFreq, WM_GETTEXT, 15, (LPARAM)Centre); - - ModemFreq = atof(Centre); - - Freq = atof(TNC->RIG->Valchar) + (ModemFreq / 1000000); - } -#endif - else - Freq = atof(TNC->RIG->Valchar) + 0.0015; // Assume 1500 - } - else - - // Not UZ7HO or Linux - - Freq = atof(TNC->RIG->Valchar) + 0.0015; - - _gcvt(Freq, 9, ReportFreq); - } - - if (TNC->Hardware == H_ARDOP) - { - LOC = memchr(Call, '[', 20); - - if (LOC) - { - LOCEND = memchr(Call, ']', 30); - if (LOCEND) - { - LOC--; - *(LOC++) = 0; - *(LOCEND) = 0; - LOC++; - if (strlen(LOC) != 6 && strlen(LOC) != 0) - { - Debugprintf("Corrupt LOC %s %s", Call, LOC); - LOC = NoLOC; - } - goto NOLOC; - } - } - } - - else if (TNC->Hardware != H_WINMOR) // Only WINMOR has a locator - { - LOC = NoLOC; - goto NOLOC; - } - - LOC = memchr(Call, '(', 20); - - if (LOC) - { - LOCEND = memchr(Call, ')', 30); - if (LOCEND) - { - LOC--; - *(LOC++) = 0; - *(LOCEND) = 0; - LOC++; - if (strlen(LOC) != 6 && strlen(LOC) != 0) - { - Debugprintf("Corrupt LOC %s %s", Call, LOC); - LOC = NoLOC; - } - } - } - else - LOC = NoLOC; - -NOLOC: - - if (Loc) - LOC = Loc; // Supplied Locator overrides - - for (i = 0; i < MHENTRIES; i++) - { - if (Mode == ' ' || Mode == '*') // Packet - { - if ((MH->MHCALL[0] == 0) || ((memcmp(AXCall, MH->MHCALL, 7) == 0) && MH->MHDIGI == Mode)) // Spare or our entry - { - OldCount = MH->MHCOUNT; - goto DoMove; - } - } - else - { - if ((MH->MHCALL[0] == 0) || ((memcmp(AXCall, MH->MHCALL, 7) == 0) && - MH->MHDIGI == Mode && strcmp(MH->MHFreq, ReportFreq) == 0)) // Spare or our entry - { - OldCount = MH->MHCOUNT; - goto DoMove; - } - } - MH++; - } - - // TABLE FULL AND ENTRY NOT FOUND - MOVE DOWN ONE, AND ADD TO TOP - - i = MHENTRIES - 1; - - // Move others down and add at front -DoMove: - - if (i != 0) // First - memmove(MHBASE + 1, MHBASE, i * sizeof(MHSTRUC)); - -// memcpy (MHBASE->MHCALL, Buffer->ORIGIN, 7 * 9); - memcpy (MHBASE->MHCALL, AXCall, 7 * 9); // Save Digis - MHBASE->MHDIGI = Mode; - MHBASE->MHTIME = time(NULL); - MHBASE->MHCOUNT = ++OldCount; - - memcpy(MHBASE->MHLocator, LOC, 6); - strcpy(MHBASE->MHFreq, ReportFreq); - - // Report to NodeMap - - if (Report == FALSE) - return; - - if (Mode == '*') - return; // Digi'ed Packet - - if (Mode == ' ') // Packet Data - { - if (TNC->PktUpdateMap == 1) - Mode = '!'; - else - return; - } - - ReportMode[0] = TNC->Hardware + '@'; - ReportMode[1] = Mode; - if (TNC->Hardware == H_HAL) - ReportMode[2] = TNC->CurrentMode; - else - ReportMode[2] = (TNC->RIG->CurrentBandWidth) ? TNC->RIG->CurrentBandWidth : '?'; - ReportMode[3] = Direction; - ReportMode[4] = 0; - - // If no position see if we have an APRS posn - - if (LOC[0] == 0) - { - double Lat, Lon; - - if (GetPosnFromAPRS(ReportCall, &Lat, &Lon) && Lat != 0.0) - { - ToLOC(Lat, Lon, LOC); - } - } - - SendMH(TNC, ReportCall, ReportFreq, LOC, ReportMode); - - return; -} - -VOID CloseDriverWindow(int port) -{ -#ifndef LINBPQ - - struct TNCINFO * TNC; - - TNC = TNCInfo[port]; - if (TNC == NULL) - return; - - if (TNC->hDlg == NULL) - return; - - PostMessage(TNC->hDlg, WM_CLOSE,0,0); -// DestroyWindow(TNC->hDlg); - - TNC->hDlg = NULL; -#endif - return; -} - -VOID SaveWindowPos(int port) -{ -#ifndef LINBPQ - - struct TNCINFO * TNC; - char Key[80]; - - TNC = TNCInfo[port]; - - if (TNC == NULL) - return; - - if (TNC->hDlg == NULL) - return; - - sprintf(Key, "PACTOR\\PORT%d", port); - - SaveMDIWindowPos(TNC->hDlg, Key, "Size", TNC->Minimized); - -#endif - return; -} - -VOID ShowTraffic(struct TNCINFO * TNC) -{ - char Status[80]; - - sprintf(Status, "RX %d TX %d ACKED %d ", - TNC->Streams[0].bytesRXed, TNC->Streams[0].bytesTXed, TNC->Streams[0].BytesAcked); -#ifndef LINBPQ - SetDlgItemText(TNC->hDlg, IDC_TRAFFIC, Status); -#endif -} - -BOOL InterlockedCheckBusy(struct TNCINFO * ThisTNC) -{ - // See if this port, or any interlocked ports are reporting channel busy - - struct TNCINFO * TNC; - int i; - int rxInterlock = ThisTNC->RXRadio; - int txInterlock = ThisTNC->TXRadio; - - if (ThisTNC->Busy) - return TRUE; // Our port is busy - - if (rxInterlock == 0 && txInterlock == 0) - return ThisTNC->Busy; // No Interlock - - for (i=1; i <= MAXBPQPORTS; i++) - { - TNC = TNCInfo[i]; - - if (TNC == NULL) - continue; - - if (TNC == ThisTNC) - continue; - - if (rxInterlock == TNC->RXRadio || txInterlock == TNC->TXRadio) // Same Group - if (TNC->Busy) - return TRUE; // Interlocked port is busy - - } - return FALSE; // None Busy -} - -char ChallengeResponse[13]; - -char * GetChallengeResponse(char * Call, char * ChallengeString) -{ - // Generates a response to the CMS challenge string... - - long long Challenge = _atoi64(ChallengeString); - long long CallSum = 0; - long long Mask; - long long Response; - long long XX = 1065484730; - - char CallCopy[10]; - UINT i; - - - if (Challenge == 0) - return "000000000000"; - -// Calculate Mask from Callsign - - memcpy(CallCopy, Call, 10); - strlop(CallCopy, '-'); - strlop(CallCopy, ' '); - - for (i = 0; i < strlen(CallCopy); i++) - { - CallSum += CallCopy[i]; - } - - Mask = CallSum + CallSum * 4963 + CallSum * 782386; - - Response = (Challenge % 930249781); - Response ^= Mask; - - sprintf(ChallengeResponse, "%012lld", Response); - - return ChallengeResponse; -} - -SOCKET OpenWL2KHTTPSock() -{ - 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 ("api.winlink.org"); - - if (!HostEnt) - { - err = WSAGetLastError(); - - Debugprintf("Resolve Failed for %s %d %x", "api.winlink.org", 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; -} - -BOOL GetWL2KSYSOPInfo(char * Call, char * _REPLYBUFFER) -{ - SOCKET sock = 0; - int Len; - char Message[1000]; - - sock = OpenWL2KHTTPSock(); - - if (sock == 0) - return 0; - - // {"Callsign":"String"} - - Len = sprintf(Message, "\"Callsign\":\"%s\"", Call); - - SendHTTPRequest(sock, "/sysop/get", Message, Len, _REPLYBUFFER); - - closesocket(sock); - - return _REPLYBUFFER[0]; -} - -BOOL UpdateWL2KSYSOPInfo(char * Call, char * SQL) -{ - SOCKET sock = 0; - struct sockaddr_in destaddr; - struct sockaddr_in sinx; - int len = 100; - int addrlen=sizeof(sinx); - struct hostent * HostEnt; - int err; - u_long param=1; - BOOL bcopt=TRUE; - char Buffer[1000]; - char SendBuffer[1000]; - - destaddr.sin_family = AF_INET; - destaddr.sin_addr.s_addr = inet_addr("api.winlink.org"); - destaddr.sin_port = htons(80); - - HostEnt = gethostbyname ("api.winlink.org"); - - if (!HostEnt) - { - err = WSAGetLastError(); - - Debugprintf("Resolve Failed for %s %d %x", "api.winlink.org", 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; - } - - len = recv(sock, &Buffer[0], len, 0); - - len = sprintf(SendBuffer, "02%07d%-12s%s%s", (int)strlen(SQL), Call, GetChallengeResponse(Call, Buffer), SQL); - - send(sock, SendBuffer, len, 0); - - len = 1000; - - len = recv(sock, &Buffer[0], len, 0); - - Buffer[len] = 0; - Debugprintf(Buffer); - - closesocket(sock); - - return TRUE; - -} -// http://server.winlink.org:8085/csv/reply/ChannelList?Modes=40,41,42,43,44&ServiceCodes=BPQTEST,PUBLIC - -// Process config lines that are common to a number of HF modes - -static char ** SeparateMultiString(char * MultiString) -{ - char ** Value; - int Count = 0; - char * ptr, * ptr1; - - // Convert to string array - - Value = zalloc(sizeof(void *)); // always NULL entry on end even if no values - Value[0] = NULL; - - strlop(MultiString, 13); - ptr = MultiString; - - while (ptr && strlen(ptr)) - { - ptr1 = strchr(ptr, '|'); - - if (ptr1) - *(ptr1++) = 0; - - if (strlen(ptr)) - { - Value = realloc(Value, (Count+2) * sizeof(void *)); - Value[Count++] = _strdup(ptr); - } - ptr = ptr1; - } - - Value[Count] = NULL; - return Value; -} - - - - -extern int nextDummyInterlock; - -int standardParams(struct TNCINFO * TNC, char * buf) -{ - if (_memicmp(buf, "WL2KREPORT", 10) == 0) - TNC->WL2K = DecodeWL2KReportLine(buf); - else if (_memicmp(buf, "SESSIONTIMELIMIT", 16) == 0) - TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit = atoi(&buf[17]) * 60; - else if (_memicmp(buf, "ATTACHTIMELIMIT", 15) == 0) - TNC->AttachTimeLimit = atoi(&buf[16]) * 60; - else if (_memicmp(buf, "BUSYHOLD", 8) == 0) // Hold Time for Busy Detect - TNC->BusyHold = atoi(&buf[8]); - else if (_memicmp(buf, "BUSYWAIT", 8) == 0) // Wait time before failing connect if busy - TNC->BusyWait = atoi(&buf[8]); - else if (_memicmp(buf, "AUTOSTARTDELAY", 14) == 0) // Time to wait for TNC to start - TNC->AutoStartDelay = atoi(&buf[15]); - else if (_memicmp(buf, "DEFAULTRADIOCOMMAND", 19) == 0) - TNC->DefaultRadioCmd = _strdup(&buf[20]); - else if (_memicmp(buf, "MYCALLS", 7) == 0) - { - TNC->LISTENCALLS = _strdup(&buf[8]); - strlop(TNC->LISTENCALLS, '\r'); - } - else if (_memicmp(buf, "NRNEIGHBOUR", 11) == 0) - TNC->NRNeighbour = _strdup(&buf[12]); - else if (_memicmp(buf, "MAXCONREQ", 9) == 0) // Hold Time for Busy Detect - TNC->MaxConReq = atoi(&buf[9]); - - else if (_memicmp(buf, "FREQUENCY", 9) == 0) - TNC->Frequency = _strdup(&buf[10]); - else if (_memicmp(buf, "SendTandRtoRelay", 16) == 0) - TNC->SendTandRtoRelay = atoi(&buf[17]); - else if (_memicmp(buf, "Radio", 5) == 0) // Rig Control RADIO for TX amd RX (Equiv to INTERLOCK) - TNC->RXRadio = TNC->TXRadio = atoi(&buf[6]); - else if (_memicmp(buf, "TXRadio", 7) == 0) // Rig Control RADIO for TX - TNC->TXRadio = atoi(&buf[8]); - else if (_memicmp(buf, "RXRadio", 7) == 0) // Rig Control RADIO for RXFRETRIES - TNC->RXRadio = atoi(&buf[8]); - else if (_memicmp(buf, "TXFreq", 6) == 0) // For PTT Sets Freq mode - TNC->TXFreq = strtoll(&buf[7], NULL, 10); - else if (_memicmp(buf, "DefaultTXFreq", 13) == 0) // Set at end of session - TNC->DefaultTXFreq = atof(&buf[14]); - else if (_memicmp(buf, "DefaultRXFreq", 13) == 0) // Set at end of session - TNC->DefaultRXFreq = atof(&buf[14]); - else if (_memicmp(buf, "ActiveTXFreq", 12) == 0) // Set at start of session - TNC->ActiveTXFreq = atof(&buf[13]); - else if (_memicmp(buf, "ActiveRXFreq", 12) == 0) // Set at start of session - TNC->ActiveRXFreq = atof(&buf[13]); - else if (_memicmp(buf, "DisconnectScript", 16) == 0) // Set at start of session - TNC->DisconnectScript = SeparateMultiString(&buf[17]); - else if (_memicmp(buf, "PTTONHEX", 8) == 0) - { - // Hex String to use for PTT on for this port - - char * ptr1 = &buf[9]; - char * ptr2 = TNC->PTTOn; - int i, j, len; - - _strupr(ptr1); - - TNC->PTTOnLen = len = strlen(ptr1) / 2; - - if (len < 240) - { - while ((len--) > 0) - { - i = *(ptr1++); - i -= '0'; - if (i > 9) - i -= 7; - - j = i << 4; - - i = *(ptr1++); - i -= '0'; - if (i > 9) - i -= 7; - - *(ptr2++) = j | i; - } - } - } - else if (_memicmp(buf, "PTTOFFHEX", 9) == 0) - { - // Hex String to use for PTT off - - char * ptr = &buf[10]; - char * ptr2 = TNC->PTTOff; - int i, j, len; - - _strupr(ptr); - - TNC->PTTOffLen = len = strlen(ptr) / 2; - - if (len < 240) - { - while ((len--) > 0) - { - i = *(ptr++); - i -= '0'; - if (i > 9) - i -= 7; - - j = i << 4; - - i = *(ptr++); - i -= '0'; - if (i > 9) - i -= 7; - - *(ptr2++) = j | i; - } - } - } - else - return FALSE; - - return TRUE; -} - -void DecodePTTString(struct TNCINFO * TNC, char * ptr) -{ - if (_stricmp(ptr, "CI-V") == 0) - TNC->PTTMode = PTTCI_V; - else if (_stricmp(ptr, "CAT") == 0) - TNC->PTTMode = PTTCI_V; - else if (_stricmp(ptr, "RTS") == 0) - TNC->PTTMode = PTTRTS; - else if (_stricmp(ptr, "DTR") == 0) - TNC->PTTMode = PTTDTR; - else if (_stricmp(ptr, "DTRRTS") == 0) - TNC->PTTMode = PTTDTR | PTTRTS; - else if (_stricmp(ptr, "CM108") == 0) - TNC->PTTMode = PTTCM108; - else if (_stricmp(ptr, "HAMLIB") == 0) - TNC->PTTMode = PTTHAMLIB; - else if (_stricmp(ptr, "FLRIG") == 0) - TNC->PTTMode = PTTFLRIG; -} - -extern SOCKET ReportSocket; -extern char LOCATOR[80]; -extern char ReportDest[7]; -extern int NumberofPorts; -extern struct RIGPORTINFO * PORTInfo[34]; // Records are Malloc'd - -time_t LastModeReportTime; -time_t LastFreqReportTime; - -VOID SendReportMsg(char * buff, int txlen); - -void sendModeReport() -{ - // if TNC is connected send mode and frequencies to Node Map as a MODE record - // Are we better sending scan info as a separate record ?? - - // MODE Port, HWType, Interlock - - struct PORTCONTROL * PORT = PORTTABLE; - - struct TNCINFO * TNC; - MESSAGE AXMSG; - PMESSAGE AXPTR = &AXMSG; - char Msg[300] = "MODE "; - int i, Len = 5; - - if ((CurrentSecs - LastModeReportTime) < 900) // Every 15 Mins - return; - - LastModeReportTime = CurrentSecs; - - for (i = 0; i < NUMBEROFPORTS; i++) - { - if (PORT->PROTOCOL == 10) - { - PEXTPORTDATA PORTVEC = (PEXTPORTDATA)PORT; - TNC = TNCInfo[PORT->PORTNUMBER]; - PORT = PORT->PORTPOINTER; - - if (TNC == NULL) - continue; - - if (TNC->CONNECTED == 0 && TNC->TNCOK == 0) - continue; - - if (ReportSocket == 0 || LOCATOR[0] == 0) - continue; - - if (TNC->Frequency) - Len += sprintf(&Msg[Len], "%d,%d,%d,%.6f/", TNC->Port, TNC->Hardware, TNC->RXRadio, atof(TNC->Frequency)); - else - Len += sprintf(&Msg[Len], "%d,%d,%d/", TNC->Port, TNC->Hardware, TNC->RXRadio); - - if (Len > 240) - break; - } - else - PORT = PORT->PORTPOINTER; - } - - if (Len == 5) - return; // Nothing to send - - // 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) ; -} - -void sendFreqReport(char * From) -{ - // Send info from rig control or Port Frequency info to Node Map for Mode page. - - MESSAGE AXMSG; - PMESSAGE AXPTR = &AXMSG; - char Msg[300] = "FREQ "; - int i, Len = 5, p; - - struct RIGPORTINFO * RIGPORT; - struct RIGINFO * RIG; - struct TimeScan * Band; - struct PORTCONTROL * PORT = PORTTABLE; - struct TNCINFO * TNC; - - if ((CurrentSecs - LastFreqReportTime) < 7200) // Every 2 Hours - return; - - LastFreqReportTime = CurrentSecs; - - for (p = 0; p < NumberofPorts; p++) - { - RIGPORT = PORTInfo[p]; - - for (i = 0; i < RIGPORT->ConfiguredRigs; i++) - { - int j = 1, k = 0; - - RIG = &RIGPORT->Rigs[i]; - - if (RIG->reportFreqs) - { - Len += sprintf(&Msg[Len], "%d/00:00/%s,\\|",RIG->Interlock,RIG->reportFreqs); - } - else - { - if (RIG->TimeBands) - { - Len += sprintf(&Msg[Len], "%d/",RIG->Interlock); - while (RIG->TimeBands[j]) - { - Band = RIG->TimeBands[j]; - k = 0; - - if (Band->Scanlist[0]) - { - Len += sprintf(&Msg[Len], "%02d:%02d/", Band->Start / 3600, Band->Start % 3600); - - while (Band->Scanlist[k]) - { - Len += sprintf(&Msg[Len],"%.0f,", Band->Scanlist[k]->Freq + RIG->rxOffset); - k++; - } - Len += sprintf(&Msg[Len], "\\"); - } - j++; - } - Len += sprintf(&Msg[Len], "|"); - } - } - } - } - - // Look for Port freq info - - for (i = 0; i < NUMBEROFPORTS; i++) - { - if (PORT->PROTOCOL == 10) - { - PEXTPORTDATA PORTVEC = (PEXTPORTDATA)PORT; - TNC = TNCInfo[PORT->PORTNUMBER]; - PORT = PORT->PORTPOINTER; - - if (TNC == NULL) - continue; - - if (TNC->Frequency == NULL) - continue; - - if (TNC->RIG->TimeBands && TNC->RIG->TimeBands[1]->Scanlist) - continue; // Have freq info from Rigcontrol - - if (TNC->RXRadio == 0) // Replace with dummy - TNC->RXRadio = nextDummyInterlock++; - - // Use negative port no instead of interlock group - - Len += sprintf(&Msg[Len], "%d/00:00/%.0f|", TNC->RXRadio, atof(TNC->Frequency) * 1000000.0); - } - else - PORT = PORT->PORTPOINTER; - } - - if (Len == 5) - return; // Nothing to send - - // 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) ; -} - - diff --git a/.svn/pristine/12/129588435d73a332d9a80b3904b723c535bcd9c1.svn-base b/.svn/pristine/12/129588435d73a332d9a80b3904b723c535bcd9c1.svn-base deleted file mode 100644 index 1c3dce1..0000000 --- a/.svn/pristine/12/129588435d73a332d9a80b3904b723c535bcd9c1.svn-base +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.svn/pristine/13/133f0644e7f4f8c80ccfe00872403b0abf4bd029.svn-base b/.svn/pristine/13/133f0644e7f4f8c80ccfe00872403b0abf4bd029.svn-base deleted file mode 100644 index d3caae4..0000000 --- a/.svn/pristine/13/133f0644e7f4f8c80ccfe00872403b0abf4bd029.svn-base +++ /dev/null @@ -1,277 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2020 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v2.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * https://www.eclipse.org/legal/epl-2.0/ - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file - * \brief This structure represents a persistent data store, used to store - * outbound and inbound messages, in order to achieve reliable messaging. - * - * The MQTT Client persists QoS1 and QoS2 messages in order to meet the - * assurances of delivery associated with these @ref qos levels. The messages - * are saved in persistent storage - * The type and context of the persistence implementation are specified when - * the MQTT client is created (see MQTTClient_create()). The default - * persistence type (::MQTTCLIENT_PERSISTENCE_DEFAULT) uses a file system-based - * persistence mechanism. The persistence_context argument passed to - * MQTTClient_create() when using the default peristence is a string - * representing the location of the persistence directory. If the context - * argument is NULL, the working directory will be used. - * - * To use memory-based persistence, an application passes - * ::MQTTCLIENT_PERSISTENCE_NONE as the persistence_type to - * MQTTClient_create(). This can lead to message loss in certain situations, - * but can be appropriate in some cases (see @ref qos). - * - * Client applications can provide their own persistence mechanism by passing - * ::MQTTCLIENT_PERSISTENCE_USER as the persistence_type. To implement a - * custom persistence mechanism, the application must pass an initialized - * ::MQTTClient_persistence structure as the persistence_context - * argument to MQTTClient_create(). - * - * If the functions defined return an ::MQTTCLIENT_PERSISTENCE_ERROR then the - * state of the persisted data should remain as it was prior to the function - * being called. For example, if Persistence_put() returns - * ::MQTTCLIENT_PERSISTENCE_ERROR, then it is assumed tha tthe persistent store - * does not contain the data that was passed to the function. Similarly, if - * Persistence_remove() returns ::MQTTCLIENT_PERSISTENCE_ERROR then it is - * assumed that the data to be removed is still held in the persistent store. - * - * It is up to the persistence implementation to log any error information that - * may be required to diagnose a persistence mechanism failure. - */ - -/* -/// @cond EXCLUDE -*/ -#if !defined(MQTTCLIENTPERSISTENCE_H) -#define MQTTCLIENTPERSISTENCE_H -/* -/// @endcond -*/ - -/** - * This persistence_type value specifies the default file system-based - * persistence mechanism (see MQTTClient_create()). - */ -#define MQTTCLIENT_PERSISTENCE_DEFAULT 0 -/** - * This persistence_type value specifies a memory-based - * persistence mechanism (see MQTTClient_create()). - */ -#define MQTTCLIENT_PERSISTENCE_NONE 1 -/** - * This persistence_type value specifies an application-specific - * persistence mechanism (see MQTTClient_create()). - */ -#define MQTTCLIENT_PERSISTENCE_USER 2 - -/** - * Application-specific persistence functions must return this error code if - * there is a problem executing the function. - */ -#define MQTTCLIENT_PERSISTENCE_ERROR -2 - -/** - * @brief Initialize the persistent store. - * - * Either open the existing persistent store for this client ID or create a new - * one if one doesn't exist. If the persistent store is already open, return - * without taking any action. - * - * An application can use the same client identifier to connect to many - * different servers. The clientid in conjunction with the - * serverURI uniquely identifies the persistence store required. - * - * @param handle The address of a pointer to a handle for this persistence - * implementation. This function must set handle to a valid reference to the - * persistence following a successful return. - * The handle pointer is passed as an argument to all the other - * persistence functions. It may include the context parameter and/or any other - * data for use by the persistence functions. - * @param clientID The client identifier for which the persistent store should - * be opened. - * @param serverURI The connection string specified when the MQTT client was - * created (see MQTTClient_create()). - * @param context A pointer to any data required to initialize the persistent - * store (see ::MQTTClient_persistence). - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_open)(void** handle, const char* clientID, const char* serverURI, void* context); - -/** - * @brief Close the persistent store referred to by the handle. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_close)(void* handle); - -/** - * @brief Put the specified data into the persistent store. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @param key A string used as the key for the data to be put in the store. The - * key is later used to retrieve data from the store with Persistence_get(). - * @param bufcount The number of buffers to write to the persistence store. - * @param buffers An array of pointers to the data buffers associated with - * this key. - * @param buflens An array of lengths of the data buffers. buflen[n] - * gives the length of buffer[n]. - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_put)(void* handle, char* key, int bufcount, char* buffers[], int buflens[]); - -/** - * @brief Retrieve the specified data from the persistent store. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @param key A string that is the key for the data to be retrieved. This is - * the same key used to save the data to the store with Persistence_put(). - * @param buffer The address of a pointer to a buffer. This function sets the - * pointer to point at the retrieved data, if successful. - * @param buflen The address of an int that is set to the length of - * buffer by this function if successful. - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_get)(void* handle, char* key, char** buffer, int* buflen); - -/** - * @brief Remove the data for the specified key from the store. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @param key A string that is the key for the data to be removed from the - * store. This is the same key used to save the data to the store with - * Persistence_put(). - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_remove)(void* handle, char* key); - -/** - * @brief Returns the keys in this persistent data store. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @param keys The address of a pointer to pointers to strings. Assuming - * successful execution, this function allocates memory to hold the returned - * keys (strings used to store the data with Persistence_put()). It also - * allocates memory to hold an array of pointers to these strings. keys - * is set to point to the array of pointers to strings. - * @param nkeys A pointer to the number of keys in this persistent data store. - * This function sets the number of keys, if successful. - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_keys)(void* handle, char*** keys, int* nkeys); - -/** - * @brief Clears the persistence store, so that it no longer contains any - * persisted data. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_clear)(void* handle); - -/** - * @brief Returns whether any data has been persisted using the specified key. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @param key The string to be tested for existence in the store. - * @return Return 0 if the key was found in the store, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_containskey)(void* handle, char* key); - -/** - * @brief A structure containing the function pointers to a persistence - * implementation and the context or state that will be shared across all - * the persistence functions. - */ -typedef struct { - /** - * A pointer to any data required to initialize the persistent store. - */ - void* context; - /** - * A function pointer to an implementation of Persistence_open(). - */ - Persistence_open popen; - /** - * A function pointer to an implementation of Persistence_close(). - */ - Persistence_close pclose; - /** - * A function pointer to an implementation of Persistence_put(). - */ - Persistence_put pput; - /** - * A function pointer to an implementation of Persistence_get(). - */ - Persistence_get pget; - /** - * A function pointer to an implementation of Persistence_remove(). - */ - Persistence_remove premove; - /** - * A function pointer to an implementation of Persistence_keys(). - */ - Persistence_keys pkeys; - /** - * A function pointer to an implementation of Persistence_clear(). - */ - Persistence_clear pclear; - /** - * A function pointer to an implementation of Persistence_containskey(). - */ - Persistence_containskey pcontainskey; -} MQTTClient_persistence; - - -/** - * A callback which is invoked just before a write to persistence. This can be - * used to transform the data, for instance to encrypt it. - * @param context The context as set in ::MQTTAsync_setBeforePersistenceWrite - * @param bufcount The number of buffers to write to the persistence store. - * @param buffers An array of pointers to the data buffers. - * @param buflens An array of lengths of the data buffers. - * @return Return 0 if the function completes successfully, otherwise non 0. - */ -typedef int MQTTPersistence_beforeWrite(void* context, int bufcount, char* buffers[], int buflens[]); - - -/** - * A callback which is invoked just after a read from persistence. This can be - * used to transform the data, for instance to decrypt it. - * @param context The context as set in ::MQTTAsync_setAfterPersistenceRead - * @param buffer The address of a pointer to a buffer. - * @param buflen The address of an int that is the length of the buffer. - * @return Return 0 if the function completes successfully, otherwise non 0. - */ -typedef int MQTTPersistence_afterRead(void* context, char** buffer, int* buflen); - -#endif diff --git a/.svn/pristine/13/1340af3f5aabaa27f5c011eb6fba97496d3ca296.svn-base b/.svn/pristine/13/1340af3f5aabaa27f5c011eb6fba97496d3ca296.svn-base deleted file mode 100644 index 1ceea42..0000000 --- a/.svn/pristine/13/1340af3f5aabaa27f5c011eb6fba97496d3ca296.svn-base +++ /dev/null @@ -1,1329 +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 -*/ - -// Mail and Chat Server for BPQ32 Packet Switch -// -// White Pages Database Support Routines - -#include "bpqmail.h" - -VOID __cdecl Debugprintf(const char * format, ...); -VOID ReleaseSock(SOCKET sock); -void MQTTMessageEvent(void* message); - -#define GetSemaphore(Semaphore,ID) _GetSemaphore(Semaphore, ID, __FILE__, __LINE__) -void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line); - -struct NNTPRec * FirstNNTPRec = NULL; - -//int NumberofNNTPRecs=0; - -SOCKET nntpsock; - -extern SocketConn * Sockets; // Chain of active sockets - -int NNTPInPort = 0; - -char *day[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - - -VOID ReleaseNNTPSock(SOCKET sock); - -int NNTPSendSock(SocketConn * sockptr, char * msg) -{ - int len = (int)strlen(msg); - char * newmsg = malloc(len+10); - - WriteLogLine(NULL, '>',msg, len, LOG_TCP); - - strcpy(newmsg, msg); - - strcat(newmsg, "\r\n"); - - len+=2; - - // Attempt to fix Thunderbird - Queue all and send at end - - if ((sockptr->SendSize + len) > sockptr->SendBufferSize) - { - sockptr->SendBufferSize += (10000 + len); - sockptr->SendBuffer = realloc(sockptr->SendBuffer, sockptr->SendBufferSize); - } - - memcpy(&sockptr->SendBuffer[sockptr->SendSize], newmsg, len); - sockptr->SendSize += len; - free (newmsg); - return len; -} - -void NNTPFlush(SocketConn * sockptr) -{ - int sent; - - sent = send(sockptr->socket, sockptr->SendBuffer, sockptr->SendSize, 0); - - if (sent < sockptr->SendSize) - { - int error, remains; - - // Not all could be sent - queue rest - - if (sent == SOCKET_ERROR) - { - error = WSAGetLastError(); - if (error == WSAEWOULDBLOCK) - sent=0; - - // What else?? - } - - remains = sockptr->SendSize - sent; - - sockptr->SendBufferSize += (10000 + remains); - sockptr->SendBuffer = malloc(sockptr->SendBufferSize); - - memmove(sockptr->SendBuffer, &sockptr->SendBuffer[sent], remains); - - sockptr->SendSize = remains; - sockptr->SendPtr = 0; - - return; - } - - free(sockptr->SendBuffer); - sockptr->SendBuffer = NULL; - sockptr->SendSize = 0; - sockptr->SendBufferSize = 0; - return; -} - -VOID __cdecl NNTPsockprintf(SocketConn * sockptr, const char * format, ...) -{ - // printf to a socket - - char buff[1000]; - va_list(arglist); - - va_start(arglist, format); - vsprintf(buff, format, arglist); - - NNTPSendSock(sockptr, buff); -} - -struct NNTPRec * LookupNNTP(char * Group) -{ - struct NNTPRec * ptr = FirstNNTPRec; - - while (ptr) - { - if (_stricmp(ptr->NewsGroup, Group) == 0) - return ptr; - - ptr = ptr->Next; - } - - return NULL; -} - - -VOID BuildNNTPList(struct MsgInfo * Msg) -{ - struct NNTPRec * REC; - struct NNTPRec * OLDREC; - struct NNTPRec * PREVREC = 0; - - char FullGroup[100]; - - if (Msg->type != 'B' || Msg->status == 'K' || Msg->status == 'H') - return; - - sprintf(FullGroup, "%s.%s", Msg->to, Msg->via); - - REC = LookupNNTP(FullGroup); - - if (REC == NULL) - { - // New Group. Allocate a record, and put at correct place in chain (alpha order) - - GetSemaphore(&AllocSemaphore, 0); - - REC = zalloc(sizeof (struct NNTPRec)); - OLDREC = FirstNNTPRec; - - if (OLDREC == 0) // First record - { - FirstNNTPRec = REC; - goto DoneIt; - } - else - { - // Follow chain till we find one with a later name - - while(OLDREC) - { - if (strcmp(OLDREC->NewsGroup, FullGroup) > 0) - { - // chain in here - - REC->Next = OLDREC; - if (PREVREC) - PREVREC->Next = REC; - else - FirstNNTPRec = REC; - goto DoneIt; - - } - else - { - PREVREC = OLDREC; - OLDREC = OLDREC->Next; - } - } - - // Run off end - chain to PREVREC - - PREVREC->Next = REC; - } -DoneIt: - strcpy(REC->NewsGroup, FullGroup); - REC->FirstMsg = Msg->number; - REC->DateCreated = (time_t)Msg->datecreated; - - FreeSemaphore(&AllocSemaphore); - } - - REC->LastMsg = Msg->number; - REC->Count++; -} - -void RebuildNNTPList() -{ - struct NNTPRec * NNTPREC = FirstNNTPRec; - struct NNTPRec * SaveNNTPREC; - struct MsgInfo * Msg; - int i; - - // Free old list - - while (NNTPREC) - { - SaveNNTPREC = NNTPREC->Next; - free(NNTPREC); - NNTPREC = SaveNNTPREC; - } - - FirstNNTPRec = NULL; - - for (i = 1; i <= NumberofMessages; i++) - { - Msg = MsgHddrPtr[i]; - BuildNNTPList(Msg); - } -} - - - -char * GetPathFromHeaders(char * MsgBytes) -{ - char * Path = zalloc(10000); - char * ptr1; - - ptr1 = MsgBytes; - -nextline: - - if (memcmp(ptr1, "R:", 2) == 0) - { - char * ptr4 = strchr(ptr1, '\r'); - char * ptr5 = strchr(ptr1, '.'); - ptr1 = strchr(ptr1, '@'); - - if (!ptr1) - return Path; - - if (*++ptr1 == ':') - ptr1++; // Format 2 - - *(ptr5) = 0; - - strcat(Path, "|"); - strcat(Path, ptr1); - - *(ptr5) = '.'; - - ptr1 = ptr4; - - ptr1++; - if (*ptr1 == '\n') ptr1++; - - goto nextline; - } - - return Path; -} - -char * FormatNNTPDateAndTime(time_t Datim) -{ - struct tm *tm; - static char Date[30]; - - // Fri, 19 Nov 82 16:14:55 GMT - // A#asctime gives Wed Jan 02 02:03:55 1980\n\0. - - tm = gmtime(&Datim); - - - - if (tm) - sprintf_s(Date, sizeof(Date), "%s, %02d %3s %02d %02d:%02d:%02d Z", - day[tm->tm_wday], tm->tm_mday, month[tm->tm_mon], tm->tm_year - 100, tm->tm_hour, tm->tm_min, tm->tm_sec); - - return Date; -} - -VOID InitialiseNNTP() - -{ - if (NNTPInPort) - nntpsock = CreateListeningSocket(NNTPInPort); -} - -int CreateNNTPMessage(char * From, char * To, char * MsgTitle, time_t Date, char * MsgBody, int MsgLen) -{ - struct MsgInfo * Msg; - BIDRec * BIDRec; - char * Via; - - // Allocate a message Record slot - - Msg = AllocateMsgRecord(); - - // Set number here so they remain in sequence - - Msg->number = ++LatestMsg; - MsgnotoMsg[Msg->number] = Msg; - Msg->length = MsgLen; - - sprintf_s(Msg->bid, sizeof(Msg->bid), "%d_%s", LatestMsg, BBSName); - - Msg->type = 'B'; - Msg->status = 'N'; - Msg->datereceived = Msg->datechanged = Msg->datecreated = time(NULL); - - if (Date) - Msg->datecreated = Date; - - BIDRec = AllocateBIDRecord(); - - strcpy(BIDRec->BID, Msg->bid); - BIDRec->mode = Msg->type; - BIDRec->u.msgno = LOWORD(Msg->number); - BIDRec->u.timestamp = LOWORD(time(NULL)/86400); - - - TidyString(To); - Via = strlop(To, '@'); - - if (strlen(To) > 6) To[6]=0; - - strcpy(Msg->to, To); - strcpy(Msg->from, From); - strcpy(Msg->title, MsgTitle); - strcpy(Msg->via, Via); - - // Set up forwarding bitmap - - MatchMessagetoBBSList(Msg, 0); - - if (memcmp(Msg->fbbs, zeros, NBMASK) != 0) - Msg->status = '$'; // Has forwarding - - BuildNNTPList(Msg); // Build NNTP Groups list - -#ifndef NOMQTT - if (MQTT) - MQTTMessageEvent(Msg); -#endif - - - return CreateSMTPMessageFile(MsgBody, Msg); - -} - - - -VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) -{ - SOCKET sock; - time_t Date = 0; - - sock=sockptr->socket; - - WriteLogLine(NULL, '<',Buffer, Len-2, LOG_TCP); - - if (sockptr->Flags == GETTINGMESSAGE) - { - if(memcmp(Buffer, ".\r\n", 3) == 0) - { - // File Message - - char * ptr1, * ptr2; - int linelen, MsgLen; - char MsgFrom[62], MsgTo[62], Msgtitle[62]; - - // Scan headers for From: To: and Subject: Line (Headers end at blank line) - - ptr1 = sockptr->MailBuffer; - Loop: - ptr2 = strchr(ptr1, '\r'); - - if (ptr2 == NULL) - { - NNTPSendSock(sockptr, "500 Eh"); - return; - } - - linelen = (int)(ptr2 - ptr1); - - // From: "John Wiseman" - // To: - // - - - if (_memicmp(ptr1, "From:", 5) == 0) - { - if (linelen > 65) linelen = 65; - memcpy(MsgFrom, ptr1, linelen); - MsgFrom[linelen]=0; - } - else - if (_memicmp(ptr1, "Newsgroups:", 3) == 0) - { - char * sep = strchr(ptr1, '.'); - - if (sep) - *(sep) = '@'; - - if (linelen > 63) linelen = 63; - memcpy(MsgTo, &ptr1[11], linelen-11); - MsgTo[linelen-11]=0; - } - else - if (_memicmp(ptr1, "Subject:", 8) == 0) - { - if (linelen > 68) linelen = 68; - memcpy(Msgtitle, &ptr1[9], linelen-9); - Msgtitle[linelen-9]=0; - } - else - if (_memicmp(ptr1, "Date:", 5) == 0) - { - struct tm rtime; - char * Context; - char seps[] = " ,\t\r"; - char Offset[10] = ""; - int i, HH, MM; - - memset(&rtime, 0, sizeof(struct tm)); - - // Date: Tue, 9 Jun 2009 20:54:55 +0100 - - ptr1 = strtok_s(&ptr1[5], seps, &Context); // Skip Day - ptr1 = strtok_s(NULL, seps, &Context); // Day - - rtime.tm_mday = atoi(ptr1); - - ptr1 = strtok_s(NULL, seps, &Context); // Month - - for (i=0; i < 12; i++) - { - if (strcmp(month[i], ptr1) == 0) - { - rtime.tm_mon = i; - break; - } - } - - sscanf(Context, "%04d %02d:%02d:%02d%s", - &rtime.tm_year, &rtime.tm_hour, &rtime.tm_min, &rtime.tm_sec, Offset); - - rtime.tm_year -= 1900; - - Date = mktime(&rtime) - (time_t)_MYTIMEZONE; - - if (Date == (time_t)-1) - Date = 0; - else - { - if ((Offset[0] == '+') || (Offset[0] == '-')) - { - MM = atoi(&Offset[3]); - Offset[3] = 0; - HH = atoi(&Offset[1]); - MM = MM + (60 * HH); - - if (Offset[0] == '+') - Date -= (60*MM); - else - Date += (60*MM); - - - } - } - } - - if (linelen) // Not Null line - { - ptr1 = ptr2 + 2; // Skip crlf - goto Loop; - } - - ptr1 = sockptr->MailBuffer; - - MsgLen = sockptr->MailSize - (int)(ptr2 - ptr1); - - ptr1 = strchr(MsgFrom, '<'); - - if (ptr1) - { - char * ptr3 = strchr(ptr1, '@'); - ptr1++; - if (ptr3) - *(ptr3) = 0; - } - else - ptr1 = MsgFrom; - - CreateNNTPMessage(_strupr(ptr1), _strupr(MsgTo), Msgtitle, Date, ptr2, MsgLen); - - free(sockptr->MailBuffer); - sockptr->MailBufferSize=0; - sockptr->MailBuffer=0; - sockptr->MailSize = 0; - - sockptr->Flags &= ~GETTINGMESSAGE; - - NNTPSendSock(sockptr, "240 OK"); - - return; - } - - if ((sockptr->MailSize + Len) > sockptr->MailBufferSize) - { - sockptr->MailBufferSize += 10000; - sockptr->MailBuffer = realloc(sockptr->MailBuffer, sockptr->MailBufferSize); - - if (sockptr->MailBuffer == NULL) - { - CriticalErrorHandler("Failed to extend Message Buffer"); - shutdown(sock, 0); - return; - } - } - - memcpy(&sockptr->MailBuffer[sockptr->MailSize], Buffer, Len); - sockptr->MailSize += Len; - - return; - } - - Buffer[Len-2] = 0; - - if(_memicmp(Buffer, "AUTHINFO USER", 13) == 0) - { - if (Len > 22) Buffer[22]=0; - strcpy(sockptr->CallSign, &Buffer[14]); - sockptr->State = GettingPass; - NNTPsockprintf(sockptr, "381 More authentication information required"); - return; - } - - if (sockptr->State == GettingUser) - { - NNTPsockprintf(sockptr, "480 Authentication required"); - return; - } - - if (sockptr->State == GettingPass) - { - struct UserInfo * user = NULL; - - if(_memicmp(Buffer, "AUTHINFO PASS", 13) == 0) - { - user = LookupCall(sockptr->CallSign); - - if (user) - { - if (strcmp(user->pass, &Buffer[14]) == 0) - { - NNTPsockprintf(sockptr, "281 Authentication accepted"); - - sockptr->State = Authenticated; - sockptr->POP3User = user; - return; - } - } - NNTPSendSock(sockptr, "482 Authentication rejected"); - sockptr->State = GettingUser; - return; - } - - NNTPsockprintf(sockptr, "480 Authentication required"); - return; - } - - - if(_memicmp(Buffer, "GROUP", 5) == 0) - { - struct NNTPRec * REC = FirstNNTPRec; - - while (REC) - { - if (_stricmp(REC->NewsGroup, &Buffer[6]) == 0) - { - NNTPsockprintf(sockptr, "211 %d %d %d %s", REC->Count, REC->FirstMsg, REC->LastMsg, REC->NewsGroup); - sockptr->NNTPNum = 0; - sockptr->NNTPGroup = REC; - return; - } - REC =REC->Next; - } - - NNTPsockprintf(sockptr, "411 no such news group"); - return; - } - - if(_memicmp(Buffer, "LISTGROUP", 9) == 0) - { - struct NNTPRec * REC = sockptr->NNTPGroup; - struct MsgInfo * Msg; - int MsgNo ; - - // Either currently selected, or a param follows - - if (REC == NULL && Buffer[10] == 0) - { - NNTPsockprintf(sockptr, "412 No Group Selected"); - return; - } - - if (Buffer[10] == 0) - goto GotGroup; - - REC = FirstNNTPRec; - - while(REC) - { - if (_stricmp(REC->NewsGroup, &Buffer[10]) == 0) - { - GotGroup: - - NNTPsockprintf(sockptr, "211 Article Numbers Follows"); - sockptr->NNTPNum = 0; - sockptr->NNTPGroup = REC; - - for (MsgNo = REC->FirstMsg; MsgNo <= REC->LastMsg; MsgNo++) - { - Msg=MsgnotoMsg[MsgNo]; - - if (Msg) - { - char FullGroup[100]; - sprintf(FullGroup, "%s.%s", Msg->to, Msg->via ); - if (_stricmp(FullGroup, REC->NewsGroup) == 0) - { - NNTPsockprintf(sockptr, "%d", MsgNo); - } - } - } - NNTPSendSock(sockptr,"."); - return; - } - REC = REC->Next; - } - NNTPsockprintf(sockptr, "411 no such news group"); - return; - } - - if(_memicmp(Buffer, "MODE READER", 11) == 0) - { - NNTPSendSock(sockptr, "200 Hello"); - return; - } - - if(_memicmp(Buffer, "LIST",4) == 0) - { - struct NNTPRec * REC = FirstNNTPRec; - - NNTPSendSock(sockptr, "215 list of newsgroups follows"); - - while (REC) - { - NNTPsockprintf(sockptr, "%s %d %d y", REC->NewsGroup, REC->LastMsg, REC->FirstMsg); - REC = REC->Next; - } - - NNTPSendSock(sockptr,"."); - return; - } - - //NEWGROUPS YYMMDD HHMMSS [GMT] [] - - if(_memicmp(Buffer, "NEWGROUPS", 9) == 0) - { - struct NNTPRec * REC = FirstNNTPRec; - struct tm rtime; - char Offset[20] = ""; - time_t Time; - - memset(&rtime, 0, sizeof(struct tm)); - - sscanf(&Buffer[10], "%02d%02d%02d %02d%02d%02d %s", - &rtime.tm_year, &rtime.tm_mon, &rtime.tm_mday, - &rtime.tm_hour, &rtime.tm_min, &rtime.tm_sec, Offset); - - rtime.tm_year+=100; - rtime.tm_mon--; - - if (_stricmp(Offset, "GMT") == 0) - Time = mktime(&rtime) - (time_t)_MYTIMEZONE; - else - Time = mktime(&rtime); - - NNTPSendSock(sockptr, "231 list of new newsgroups follows"); - - while(REC) - { - if (REC->DateCreated > Time) - NNTPsockprintf(sockptr, "%s %d %d y", REC->NewsGroup, REC->LastMsg, REC->FirstMsg); - REC = REC->Next; - } - - NNTPSendSock(sockptr,"."); - return; - } - - if(_memicmp(Buffer, "HEAD",4) == 0) - { - struct NNTPRec * REC = sockptr->NNTPGroup; - struct MsgInfo * Msg; - int MsgNo = atoi(&Buffer[5]); - - if (REC == NULL) - { - NNTPSendSock(sockptr,"412 no newsgroup has been selected"); - return; - } - - if (MsgNo == 0) - { - MsgNo = sockptr->NNTPNum; - - if (MsgNo == 0) - { - NNTPSendSock(sockptr,"420 no current article has been selected"); - return; - } - } - else - { - sockptr->NNTPNum = MsgNo; - } - - Msg=MsgnotoMsg[MsgNo]; - - if (Msg) - { - NNTPsockprintf(sockptr, "221 %d <%s>", MsgNo, Msg->bid); - - NNTPsockprintf(sockptr, "From: %s", Msg->from); - NNTPsockprintf(sockptr, "Date: %s", FormatNNTPDateAndTime((time_t)Msg->datecreated)); - NNTPsockprintf(sockptr, "Newsgroups: %s.s", Msg->to, Msg->via); - NNTPsockprintf(sockptr, "Subject: %s", Msg->title); - NNTPsockprintf(sockptr, "Message-ID: <%s>", Msg->bid); - NNTPsockprintf(sockptr, "Path: %s", BBSName); - - NNTPSendSock(sockptr,"."); - return; - } - - NNTPSendSock(sockptr,"423 No such article in this newsgroup"); - return; - } - - if(_memicmp(Buffer, "ARTICLE", 7) == 0) - { - struct NNTPRec * REC = sockptr->NNTPGroup; - struct MsgInfo * Msg; - int MsgNo = atoi(&Buffer[8]); - char * msgbytes; - char * Path; - - if (REC == NULL) - { - NNTPSendSock(sockptr,"412 no newsgroup has been selected"); - return; - } - - if (MsgNo == 0) - { - MsgNo = sockptr->NNTPNum; - - if (MsgNo == 0) - { - NNTPSendSock(sockptr,"420 no current article has been selected"); - return; - } - } - else - { - sockptr->NNTPNum = MsgNo; - } - - Msg=MsgnotoMsg[MsgNo]; - - if (Msg) - { - NNTPsockprintf(sockptr, "220 %d <%s>", MsgNo, Msg->bid); - msgbytes = ReadMessageFile(Msg->number); - - Path = GetPathFromHeaders(msgbytes); - - NNTPsockprintf(sockptr, "From: %s", Msg->from); - NNTPsockprintf(sockptr, "Date: %s", FormatNNTPDateAndTime((time_t)Msg->datecreated)); - NNTPsockprintf(sockptr, "Newsgroups: %s.%s", Msg->to, Msg->via); - NNTPsockprintf(sockptr, "Subject: %s", Msg->title); - NNTPsockprintf(sockptr, "Message-ID: <%s>", Msg->bid); - NNTPsockprintf(sockptr, "Path: %s", &Path[1]); - - NNTPSendSock(sockptr,""); - - - NNTPSendSock(sockptr,msgbytes); - NNTPSendSock(sockptr,""); - - NNTPSendSock(sockptr,"."); - - free(msgbytes); - free(Path); - - return; - - } - NNTPSendSock(sockptr,"423 No such article in this newsgroup"); - return; - } - - if(_memicmp(Buffer, "BODY", 4) == 0) - { - struct NNTPRec * REC = sockptr->NNTPGroup; - struct MsgInfo * Msg; - int MsgNo = atoi(&Buffer[8]); - char * msgbytes; - char * Path; - - if (REC == NULL) - { - NNTPSendSock(sockptr,"412 no newsgroup has been selected"); - return; - } - - if (MsgNo == 0) - { - MsgNo = sockptr->NNTPNum; - - if (MsgNo == 0) - { - NNTPSendSock(sockptr,"420 no current article has been selected"); - return; - } - } - else - { - sockptr->NNTPNum = MsgNo; - } - - Msg=MsgnotoMsg[MsgNo]; - - if (Msg) - { - NNTPsockprintf(sockptr, "222 %d <%s>", MsgNo, Msg->bid); - msgbytes = ReadMessageFile(Msg->number); - - Path = GetPathFromHeaders(msgbytes); - - NNTPSendSock(sockptr,msgbytes); - NNTPSendSock(sockptr,""); - - NNTPSendSock(sockptr,"."); - - free(msgbytes); - free(Path); - - return; - - } - NNTPSendSock(sockptr,"423 No such article in this newsgroup"); - return; - } - - if(_memicmp(Buffer, "XHDR",4) == 0) - { - struct NNTPRec * REC = sockptr->NNTPGroup; - struct MsgInfo * Msg; - int MsgStart, MsgEnd, MsgNo, fields; - char Header[100]; - - if (REC == NULL) - { - NNTPSendSock(sockptr,"412 no newsgroup has been selected"); - return; - } - - // XHDR subject nnnn-nnnn - - fields = sscanf(&Buffer[5], "%s %d-%d", &Header[0], &MsgStart, &MsgEnd); - - if (fields > 1) - MsgNo = MsgStart; - - if (fields == 2) - MsgEnd = MsgStart; - - if (MsgNo == 0) - { - MsgStart = MsgEnd = sockptr->NNTPNum; - - if (MsgStart == 0) - { - NNTPSendSock(sockptr,"420 no current article has been selected"); - return; - } - } - else - { - sockptr->NNTPNum = MsgEnd; - } - - NNTPsockprintf(sockptr, "221 "); - - for (MsgNo = MsgStart; MsgNo <= MsgEnd; MsgNo++) - { - Msg=MsgnotoMsg[MsgNo]; - - if (Msg) - { - char FullGroup[100]; - sprintf(FullGroup, "%s.%s", Msg->to, Msg->via ); - if (_stricmp(FullGroup, REC->NewsGroup) == 0) - { - if (_stricmp(Header, "subject") == 0) - NNTPsockprintf(sockptr, "%d Subject: %s", MsgNo, Msg->title); - else if (_stricmp(Header, "from") == 0) - NNTPsockprintf(sockptr, "%d From: %s", MsgNo, Msg->from); - else if (_stricmp(Header, "date") == 0) - NNTPsockprintf(sockptr, "%d Date: %s", MsgNo, FormatNNTPDateAndTime((time_t)Msg->datecreated)); - else if (_stricmp(Header, "message-id") == 0) - NNTPsockprintf(sockptr, "%d Message-ID: <%s>", MsgNo, Msg->bid); - else if (_stricmp(Header, "lines") == 0) - NNTPsockprintf(sockptr, "%d Lines: %d", MsgNo, Msg->length); - } - } - } - - NNTPSendSock(sockptr,"."); - return; - - } - - if(_memicmp(Buffer, "XOVER", 5) == 0) - { - struct NNTPRec * REC = sockptr->NNTPGroup; - struct MsgInfo * Msg; - int MsgStart, MsgEnd, MsgNo, fields; - - if (REC == NULL) - { - NNTPSendSock(sockptr,"412 no newsgroup has been selected"); - return; - } - - fields = sscanf(&Buffer[6], "%d-%d", &MsgStart, &MsgEnd); - - if (fields > 0) - MsgNo = MsgStart; - - if (fields == 1) - MsgEnd = MsgStart; - - if (MsgNo == 0) - { - MsgStart = MsgEnd = sockptr->NNTPNum; - - if (MsgStart == 0) - { - NNTPSendSock(sockptr,"420 no current article has been selected"); - return; - } - } - else - { - sockptr->NNTPNum = MsgEnd; - } - - NNTPsockprintf(sockptr, "224 "); - - for (MsgNo = MsgStart; MsgNo <= MsgEnd; MsgNo++) - { - Msg=MsgnotoMsg[MsgNo]; - - if (Msg) - { - char FullGroup[100]; - sprintf(FullGroup, "%s.%s", Msg->to, Msg->via ); - if (_stricmp(FullGroup, REC->NewsGroup) == 0) - { - // subject, author, date, message-id, references, byte count, and line count. - NNTPsockprintf(sockptr, "%d\t%s\t%s\t%s\t%s\t%s\t%d\t%d", - MsgNo, Msg->title, Msg->from, FormatNNTPDateAndTime((time_t)Msg->datecreated), Msg->bid, - "", Msg->length, Msg->length); - } - } - } - - NNTPSendSock(sockptr,"."); - return; - - } - - - /* - 240 article posted ok - 340 send article to be posted. End with . - 440 posting not allowed - 441 posting failed -*/ - if(_memicmp(Buffer, "POST", 4) == 0) - { - if (sockptr->State != Authenticated) - { - NNTPsockprintf(sockptr, "480 Authentication required"); - return; - } - - sockptr->MailBuffer=malloc(10000); - sockptr->MailBufferSize=10000; - - if (sockptr->MailBuffer == NULL) - { - CriticalErrorHandler("Failed to create POP3 Message Buffer"); - NNTPSendSock(sockptr, "QUIT"); - sockptr->State = WaitingForQUITResponse; - shutdown(sock, 0); - - return; - } - - sockptr->Flags |= GETTINGMESSAGE; - - NNTPSendSock(sockptr, "340 OK"); - return; - } - - - - if(_memicmp(Buffer, "QUIT", 4) == 0) - { - NNTPSendSock(sockptr, "205 OK"); - Sleep(500); - shutdown(sock, 0); - return; - } - -/* if(memcmp(Buffer, "RSET\r\n", 6) == 0) - { - NNTPSendSock(sockptr, "250 Ok"); - sockptr->State = 0; - sockptr->Recipients; - return; - } -*/ - - if(memcmp(Buffer, "DATE", 4) == 0) - { - //This command returns a one-line response code of 111 followed by the - //GMT date and time on the server in the form YYYYMMDDhhmmss. - // 111 YYYYMMDDhhmmss - - struct tm *tm; - char Date[32]; - time_t Time = time(NULL); - - tm = gmtime(&Time); - - if (tm) - { - sprintf_s(Date, sizeof(Date), "111 %04d%02d%02d%02d%02d%02d", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - - NNTPSendSock(sockptr, Date); - } - else - NNTPSendSock(sockptr, "500 command not recognized"); - - return; - } - - NNTPSendSock(sockptr, "500 command not recognized"); - - return; -} - - - - -int NNTP_Read(SocketConn * sockptr, SOCKET sock) -{ - int InputLen, MsgLen; - char * ptr, * ptr2; - char Buffer[2000]; - - // May have several messages per packet, or message split over packets - - if (sockptr->InputLen > 1000) // Shouldnt have lines longer than this in text mode - { - sockptr->InputLen=0; - } - - InputLen=recv(sock, &sockptr->TCPBuffer[sockptr->InputLen], 1000, 0); - - if (InputLen <= 0) - { - int x = WSAGetLastError(); - - closesocket(sock); - ReleaseSock(sock); - - return 0; // Does this mean closed? - } - - sockptr->InputLen += InputLen; - -loop: - - ptr = memchr(sockptr->TCPBuffer, '\n', sockptr->InputLen); - - if (ptr) // CR in buffer - { - ptr2 = &sockptr->TCPBuffer[sockptr->InputLen]; - ptr++; // Assume LF Follows CR - - if (ptr == ptr2) - { - // Usual Case - single meg in buffer - - ProcessNNTPServerMessage(sockptr, sockptr->TCPBuffer, sockptr->InputLen); - sockptr->InputLen=0; - } - else - { - // buffer contains more that 1 message - - MsgLen = sockptr->InputLen - (int)(ptr2-ptr); - - memcpy(Buffer, sockptr->TCPBuffer, MsgLen); - - ProcessNNTPServerMessage(sockptr, Buffer, MsgLen); - - memmove(sockptr->TCPBuffer, ptr, sockptr->InputLen-MsgLen); - - sockptr->InputLen -= MsgLen; - - goto loop; - - } - } - - NNTPFlush(sockptr); - - return 0; -} - - -int NNTP_Accept(SOCKET SocketId) -{ - int addrlen; - SocketConn * sockptr; - u_long param = 1; - - SOCKET sock; - - addrlen=sizeof(struct sockaddr); - - // Allocate a Socket entry - - sockptr=zalloc(sizeof(SocketConn)+100); - - sockptr->Next = Sockets; - Sockets=sockptr; - - sock = accept(SocketId, (struct sockaddr *)&sockptr->sin, &addrlen); - - if (sock == INVALID_SOCKET) - { - Logprintf(LOG_TCP, NULL, '|', "NNTP accept() failed Error %d", WSAGetLastError()); - - // get rid of socket record - - Sockets = sockptr->Next; - free(sockptr); - - return FALSE; - } - - - sockptr->Type = NNTPServer; - - ioctl(sock, FIONBIO, ¶m); - sockptr->socket = sock; - sockptr->State = 0; - - NNTPSendSock(sockptr, "200 BPQMail NNTP Server ready"); - Logprintf(LOG_TCP, NULL, '|', "Incoming NNTP Connect Socket = %d", sock); - - NNTPFlush(sockptr); - - return 0; -} -/* -int NNTP_Data(int sock, int error, int eventcode) -{ - SocketConn * sockptr; - - // Find Connection Record - - sockptr=Sockets; - - while (sockptr) - { - if (sockptr->socket == sock) - { - switch (eventcode) - { - case FD_READ: - - return NNTP_Read(sockptr,sock); - - case FD_WRITE: - - // Either Just connected, or flow contorl cleared - - if (sockptr->SendBuffer) - // Data Queued - - SendFromQueue(sockptr); - else - { - NNTPSendSock(sockptr, "200 BPQMail NNTP Server ready"); -// sockptr->State = GettingUser; - } - - return 0; - - case FD_OOB: - - return 0; - - case FD_ACCEPT: - - return 0; - - case FD_CONNECT: - - return 0; - - case FD_CLOSE: - - closesocket(sock); - ReleaseNNTPSock(sock); - return 0; - } - return 0; - } - else - sockptr=sockptr->Next; - } - - return 0; -} -*/ -VOID ReleaseNNTPSock(SOCKET sock) -{ - // remove and free the socket record - - SocketConn * sockptr, * lastptr; - - sockptr=Sockets; - lastptr=NULL; - - while (sockptr) - { - if (sockptr->socket == sock) - { - if (lastptr) - lastptr->Next=sockptr->Next; - else - Sockets=sockptr->Next; - - free(sockptr); - return; - } - else - { - lastptr=sockptr; - sockptr=sockptr->Next; - } - } - - return; -} - -VOID SendFromQueue(SocketConn * sockptr) -{ - int bytestosend = sockptr->SendSize - sockptr->SendPtr; - int bytessent; - - Debugprintf("TCP - Sending %d bytes from buffer", bytestosend); - - bytessent = send(sockptr->socket, &sockptr->SendBuffer[sockptr->SendPtr], bytestosend, 0); - - if (bytessent == bytestosend) - { - // All Sent - - free(sockptr->SendBuffer); - sockptr->SendBuffer = NULL; - } - else - { - sockptr->SendPtr += bytessent; - } - - return; -} diff --git a/.svn/pristine/13/1368bcb6660d3eb378f376ef8fa9a0acfad8af7a.svn-base b/.svn/pristine/13/1368bcb6660d3eb378f376ef8fa9a0acfad8af7a.svn-base deleted file mode 100644 index 6d5f618..0000000 --- a/.svn/pristine/13/1368bcb6660d3eb378f376ef8fa9a0acfad8af7a.svn-base +++ /dev/null @@ -1,237 +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 - -#include "compatbits.h" -#include -#include "asmstrucs.h" -#include "tncinfo.h" - -VOID __cdecl Debugprintf(const char * format, ...); - -#ifndef WIN32 - -#define APIENTRY -#define DllExport -#define VOID void - -#else -#include -#endif - -extern BOOL EventsEnabled; -void MQTTReportSession(char * Msg); -extern int MQTT; - - -extern char Modenames[19][10]; - -// Runs use specified routine on certain event -#ifndef WIN32 - -void RunEventProgram(char * Program, char * Param) -{ - char * arg_list[] = {Program, NULL, NULL}; - pid_t child_pid; - - if (EventsEnabled == 0) - return; - - signal(SIGCHLD, SIG_IGN); // Silently (and portably) reap children. - - if (Param && Param[0]) - arg_list[1] = Param; - - // Fork and Exec Specified program - - // Duplicate this process. - - child_pid = fork (); - - if (child_pid == -1) - { - printf ("Event fork() Failed\n"); - return; - } - - 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", arg_list[0]); - exit(0); // Kill the new process - } - -#else - -DllExport void APIENTRY RunEventProgram(char * Program, char * Param) -{ - int n = 0; - char cmdLine[256]; - - STARTUPINFO SInfo; // pointer to STARTUPINFO - PROCESS_INFORMATION PInfo; // pointer to PROCESS_INFORMATION - - if (EventsEnabled == 0) - return; - - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - sprintf(cmdLine, "%s %s", Program, Param); - - if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE,0 ,NULL ,NULL, &SInfo, &PInfo)) - Debugprintf("Failed to Start %s Error %d ", Program, GetLastError()); - -#endif - - return; -} - -void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK) -{ - // Incoming SABM - - LINK->ConnectTime = time(NULL); - LINK->bytesTXed = LINK->bytesRXed = 0; - - strcpy(LINK->callingCall, remotecall); - strcpy(LINK->receivingCall, ourcall); - strcpy(LINK->Direction, "In"); -} - -void hookL2SessionDeleted(struct _LINKTABLE * LINK) -{ - // calculate session time and av bytes/min in and out - - if (LINK->ConnectTime) - { - if (LINK->bytesTXed == 0 && LINK->bytesRXed == 0) - { - // assume failed connect and ignore for now - maybe log later - - } - else - { - char Msg[256]; - char timestamp[16]; - time_t sessionTime = time(NULL) - LINK->ConnectTime; - double avBytesSent = LINK->bytesTXed / (sessionTime / 60.0); - double avBytesRXed = LINK->bytesRXed / (sessionTime / 60.0); - time_t Now = time(NULL); - struct tm * TM = localtime(&Now); - - sprintf(timestamp, "%02d:%02d:%02d", TM->tm_hour, TM->tm_min, TM->tm_sec); - - if (sessionTime == 0) - sessionTime = 1; // Or will get divide by zero error - - Debugprintf("KISS Session Stats Port %d %s %s %d secs Bytes Sent %d BPM %4.2f Bytes Received %d %4.2f BPM ", - LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, sessionTime, LINK->bytesTXed, avBytesSent, LINK->bytesRXed, avBytesRXed, timestamp); - - - sprintf(Msg, "{\"mode\": \"%s\", \"direction\": \"%s\", \"port\": %d, \"callfrom\": \"%s\", \"callto\": \"%s\", \"time\": %d, \"bytesSent\": %d," - "\"BPMSent\": %4.2f, \"BytesReceived\": %d, \"BPMReceived\": %4.2f, \"timestamp\": \"%s\"}", - "KISS", LINK->Direction, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, sessionTime, - LINK->bytesTXed, avBytesSent, LINK->bytesRXed, avBytesRXed, timestamp); - - if (MQTT) - MQTTReportSession(Msg); - } - - LINK->ConnectTime = 0; - } -} - -void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK) -{ - LINK->ConnectTime = time(NULL); - LINK->bytesTXed = LINK->bytesRXed = 0; - - strcpy(LINK->callingCall, ourcall); - strcpy(LINK->receivingCall, remotecall); - strcpy(LINK->Direction, "Out"); -} - -void hookL4SessionAttempt(struct STREAMINFO * STREAM, char * remotecall, char * ourcall) -{ - // Outgoing Connect - - STREAM->ConnectTime = time(NULL); - STREAM->bytesTXed = STREAM->bytesRXed = 0; - - strcpy(STREAM->callingCall, ourcall); - strcpy(STREAM->receivingCall, remotecall); - strcpy(STREAM->Direction, "Out"); -} - -void hookL4SessionAccepted(struct STREAMINFO * STREAM, char * remotecall, char * ourcall) -{ - // Incoming Connect - - STREAM->ConnectTime = time(NULL); - STREAM->bytesTXed = STREAM->bytesRXed = 0; - - strcpy(STREAM->callingCall, remotecall); - strcpy(STREAM->receivingCall, ourcall); - strcpy(STREAM->Direction, "In"); -} - -void hookL4SessionDeleted(struct TNCINFO * TNC, struct STREAMINFO * STREAM) -{ - char Msg[256]; - - char timestamp[16]; - - if (STREAM->ConnectTime) - { - time_t sessionTime = time(NULL) - STREAM->ConnectTime; - double avBytesRXed = STREAM->bytesRXed / (sessionTime / 60.0); - double avBytesSent = STREAM->bytesTXed / (sessionTime / 60.0); - time_t Now = time(NULL); - struct tm * TM = localtime(&Now); - sprintf(timestamp, "%02d:%02d:%02d", TM->tm_hour, TM->tm_min, TM->tm_sec); - - if (sessionTime == 0) - sessionTime = 1; // Or will get divide by zero error - - sprintf(Msg, "{\"mode\": \"%s\", \"direction\": \"%s\", \"port\": %d, \"callfrom\": \"%s\", \"callto\": \"%s\", \"time\": %d, \"bytesSent\": %d," - "\"BPMSent\": %4.2f, \"BytesReceived\": %d, \"BPMReceived\": %4.2f, \"timestamp\": \"%s\"}", - Modenames[TNC->Hardware - 1], STREAM->Direction, TNC->Port, STREAM->callingCall, STREAM->receivingCall, sessionTime, - STREAM->bytesTXed, avBytesSent, STREAM->bytesRXed, avBytesRXed, timestamp); - - if (MQTT) - MQTTReportSession(Msg); - - STREAM->ConnectTime = 0; - } -} - - diff --git a/.svn/pristine/13/136e510d90c53fc02930e5a4a63a91f73204a63a.svn-base b/.svn/pristine/13/136e510d90c53fc02930e5a4a63a91f73204a63a.svn-base deleted file mode 100644 index 2d1a74b..0000000 --- a/.svn/pristine/13/136e510d90c53fc02930e5a4a63a91f73204a63a.svn-base +++ /dev/null @@ -1,988 +0,0 @@ - -// Program to Convert RTS changes on Virtual COM Port to hamlib PTT commands - - -// Version 1. 0. 0. 1 December 2020 - -// Version 1. 0. 2. 1 April 2018 - - -#define _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_DEPRECATE - -#include - -#include -#include -#include -#include -#include - -#define LIBCONFIG_STATIC -#include "libconfig.h" - - -#include "BPQRemotePTTRes.h" - -#define BPQICON 400 - -WSADATA WsaData; // receives data from WSAStartup - -#define WSA_READ WM_USER + 1 - -HINSTANCE hInst; -char AppName[] = "BPQRemotePTT"; -char Title[80] = "BPQRemotePTT"; - -TCHAR szTitle[]="GPSMuxPC"; // The title bar text -TCHAR szWindowClass[]="GPSMAINWINDOW"; // the main window class name - - -// Foward declarations of functions included in this code module: - -ATOM MyRegisterClass(HINSTANCE hInstance); -BOOL InitInstance(HINSTANCE, int); -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); -LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); -VOID WINAPI CompletedReadRoutine(DWORD dwErr, DWORD cbBytesRead, LPOVERLAPPED lpOverLap); -VOID WINAPI txCompletedReadRoutine(DWORD dwErr, DWORD cbBytesRead, LPOVERLAPPED lpOverLap); -VOID CATThread(); -VOID runTimer(); - -int TimerHandle = 0; - -LOGFONT LFTTYFONT ; - -HFONT hFont; - -struct sockaddr_in sinx; -struct sockaddr rx; - -int addrlen = sizeof(struct sockaddr_in); - -int HAMLIBPORT; // Port Number for HAMLIB (rigctld) Emulator -char * HAMLIBHOST[128]; - -BOOL MinimizetoTray=FALSE; - -VOID __cdecl Debugprintf(const char * format, ...) -{ - char Mess[255]; - va_list(arglist); - - va_start(arglist, format); - vsprintf(Mess, format, arglist); - strcat(Mess, "\r\n"); - - OutputDebugString(Mess); - - return; -} - - -char * strlop(char * buf, char delim) -{ - // Terminate buf at delim, and return rest of string - - char * ptr = strchr(buf, delim); - - if (ptr == NULL) return NULL; - - *(ptr)++=0; - - return ptr; -} - -char * RigPort = NULL; -char * RigSpeed = NULL; -HANDLE RigHandle = 0; -int RigType = 0; // Flag for possible RTS/DTR - - -char BPQHostIP[128]; - -char PTTCATPort[4][16]; -HANDLE PTTCATHandle[4]; -short HamLibPort[4]; -SOCKET HamLibSock[4]; // rigctld socket - -HWND comWnd[4]; -HWND portWnd[4]; -HWND stateWnd[4]; -int stateCtl[4]; - -struct sockaddr_in remoteDest[4]; - -int RealMux[4]; // BPQ Virtual or Real - -int EndPTTCATThread = 0; - -char ConfigName[256] = "BPQRemotePTT.cfg"; - -BOOL GetStringValue(config_setting_t * group, char * name, char * value) -{ - const char * str; - config_setting_t *setting; - - setting = config_setting_get_member (group, name); - if (setting) - { - str = config_setting_get_string (setting); - strcpy(value, str); - return TRUE; - } - return FALSE; -} - -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; -} - -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); - -} - - -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 GetConfig() -{ - config_setting_t *group; - config_t cfg; - - memset((void *)&cfg, 0, sizeof(config_t)); - - config_init(&cfg); - - if(!config_read_file(&cfg, ConfigName)) - { - fprintf(stderr, "Config read error line %d - %s\n", config_error_line(&cfg), config_error_text(&cfg)); - config_destroy(&cfg); - return; - } - - group = config_lookup(&cfg, "main"); - - if (group == NULL) - { - config_destroy(&cfg); - return; - } - - - GetStringValue(group, "BPQHostIP", BPQHostIP); - - GetStringValue(group, "COM1", PTTCATPort[0]); - GetStringValue(group, "COM2", PTTCATPort[1]); - GetStringValue(group, "COM3", PTTCATPort[2]); - GetStringValue(group, "COM4", PTTCATPort[3]); - - HamLibPort[0] = GetIntValue(group, "HamLibPort1"); - HamLibPort[1] = GetIntValue(group, "HamLibPort2"); - HamLibPort[2] = GetIntValue(group, "HamLibPort3"); - HamLibPort[3] = GetIntValue(group, "HamLibPort4"); - - config_destroy(&cfg); -} - -VOID SaveConfig() -{ - config_setting_t *root, *group; - config_t 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); - - SaveStringValue(group, "BPQHostIP", BPQHostIP); - - SaveStringValue(group, "COM1", PTTCATPort[0]); - SaveStringValue(group, "COM2", PTTCATPort[1]); - SaveStringValue(group, "COM3", PTTCATPort[2]); - SaveStringValue(group, "COM4", PTTCATPort[3]); - - SaveIntValue(group, "HamLibPort1", HamLibPort[0]); - SaveIntValue(group, "HamLibPort2", HamLibPort[1]); - SaveIntValue(group, "HamLibPort3", HamLibPort[2]); - SaveIntValue(group, "HamLibPort4", HamLibPort[3]); - - if(!config_write_file(&cfg, ConfigName)) - { - fprintf(stderr, "Error while writing file.\n"); - config_destroy(&cfg); - return; - } - - config_destroy(&cfg); -} - - - - -int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) -{ - MSG msg; - - if (lpCmdLine[0]) - { - // Port Name and Speed for Remote CAT - - RigPort = _strdup(lpCmdLine); - RigSpeed = strlop(RigPort, ':'); - } - - MyRegisterClass(hInstance); - - GetConfig(); - - if (!InitInstance(hInstance, nCmdShow)) - return (FALSE); - - // Main message loop: - - while (GetMessage(&msg, NULL, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - KillTimer(NULL, TimerHandle); - - return (msg.wParam); -} - -// - -// -// FUNCTION: InitApplication(HANDLE) -// -// PURPOSE: Initializes window data and registers window class -// -// COMMENTS: -// -// In this function, we initialize a window class by filling out a data -// structure of type WNDCLASS and calling either RegisterClass or -// the internal MyRegisterClass. -// - -#define BGCOLOUR RGB(236,233,216) -HBRUSH bgBrush; -HBRUSH RedBrush; -HBRUSH GreenBrush; - -HWND hWnd; - -BOOL InitApplication(HINSTANCE hInstance) -{ - return TRUE; -} - -// -// FUNCTION: InitInstance(HANDLE, int) -// -// PURPOSE: Saves instance handle and creates main window -// -// COMMENTS: -// -// In this function, we save the instance handle in a global variable and -// create and display the main program window. -// - -HFONT FAR PASCAL MyCreateFont( void ) -{ - CHOOSEFONT cf; - LOGFONT lf; - HFONT hfont; - - // Initialize members of the CHOOSEFONT structure. - - cf.lStructSize = sizeof(CHOOSEFONT); - cf.hwndOwner = (HWND)NULL; - cf.hDC = (HDC)NULL; - cf.lpLogFont = &lf; - cf.iPointSize = 0; - cf.Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY; - cf.rgbColors = RGB(0,0,0); - cf.lCustData = 0L; - cf.lpfnHook = (LPCFHOOKPROC)NULL; - cf.lpTemplateName = (LPSTR)NULL; - cf.hInstance = (HINSTANCE) NULL; - cf.lpszStyle = (LPSTR)NULL; - cf.nFontType = SCREEN_FONTTYPE; - cf.nSizeMin = 0; - cf.nSizeMax = 0; - - // Display the CHOOSEFONT common-dialog box. - - ChooseFont(&cf); - - // Create a logical font based on the user's - // selection and return a handle identifying - // that font. - - hfont = CreateFontIndirect(cf.lpLogFont); - return (hfont); -} - -VOID Rig_PTT(int n, BOOL PTTState) -{ - - char Msg[16]; - int Len = sprintf(Msg, "T %d\n", PTTState); - - if (HamLibSock[n]) - { - send(HamLibSock[n], Msg, Len, 0); - - if (PTTState) - SetDlgItemText(hWnd, stateCtl[n], "PTT"); - else - SetDlgItemText(hWnd, stateCtl[n], ""); - } -} - - - -VOID PTTCATThread() -{ - DWORD dwLength = 0; - int Length, ret, i; - UCHAR * ptr1; - UCHAR * ptr2; - UCHAR c; - UCHAR Block[4][80]; - UCHAR CurrentState[4] = {0}; -#define RTS 2 -#define DTR 4 - HANDLE Event; - DWORD EvtMask[4]; - OVERLAPPED Overlapped[4]; - char Port[32]; - int PIndex = 0; - int HIndex = 0; - int rc; - - EndPTTCATThread = FALSE; - - while (PIndex < 4 && PTTCATPort[PIndex][0]) - { - RealMux[HIndex] = 0; - - sprintf(Port, "\\\\.\\pipe\\BPQ%s", PTTCATPort[PIndex]); - - PTTCATHandle[HIndex] = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - - if (PTTCATHandle[HIndex] == INVALID_HANDLE_VALUE) - { - int Err = GetLastError(); -// Consoleprintf("PTTMUX port BPQCOM%s Open failed code %d", RIG->PTTCATPort[PIndex], Err); - - // See if real com port - - sprintf(Port, "\\\\.\\\\%s", PTTCATPort[PIndex]); - - PTTCATHandle[HIndex] = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - - RealMux[HIndex] = 1; - - if (PTTCATHandle[HIndex] == INVALID_HANDLE_VALUE) - { - int Err = GetLastError(); - PTTCATHandle[HIndex] = 0; - Debugprintf("PTTMUX port COM%s Open failed code %d", PTTCATPort[PIndex], Err); - } - else - { - rc = SetCommMask(PTTCATHandle[HIndex], EV_CTS | EV_DSR); // Request notifications - HIndex++; - } - } - else - HIndex++; - - PIndex++; - - } - - if (PIndex == 0) - return; // No ports - - Event = CreateEvent(NULL, TRUE, FALSE, NULL); - - for (i = 0; i < HIndex; i ++) - { - memset(&Overlapped[i], 0, sizeof(OVERLAPPED)); - Overlapped[i].hEvent = Event; - - if (RealMux[i]) - { - // Request Interface change notifications - - rc = WaitCommEvent(PTTCATHandle[i], &EvtMask[i], &Overlapped[i]); - rc = GetLastError(); - - } - else - { - // Prime a read on each PTTCATHandle - - ReadFile(PTTCATHandle[i], Block[i], 80, &Length, &Overlapped[i]); - } - } - - while (EndPTTCATThread == FALSE) - { - -WaitAgain: - - ret = WaitForSingleObject(Event, 1000); - - if (ret == WAIT_TIMEOUT) - { - if (EndPTTCATThread) - { - for (i = 0; i < HIndex; i ++) - { - CancelIo(PTTCATHandle[i]); - CloseHandle(PTTCATHandle[i]); - PTTCATHandle[i] = INVALID_HANDLE_VALUE; - } - CloseHandle(Event); - return; - } - goto WaitAgain; - } - - ResetEvent(Event); - - // See which request(s) have completed - - for (i = 0; i < HIndex; i ++) - { - ret = GetOverlappedResult(PTTCATHandle[i], &Overlapped[i], &Length, FALSE); - - if (ret) - { - if (RealMux[i]) - { - // Request Interface change notifications - - DWORD Mask; - - GetCommModemStatus(PTTCATHandle[i], &Mask); - - if (Mask & MS_CTS_ON) - Rig_PTT(i, TRUE); - else - Rig_PTT(i, FALSE); - - memset(&Overlapped[i], 0, sizeof(OVERLAPPED)); - Overlapped[i].hEvent = Event; - WaitCommEvent(PTTCATHandle[i], &EvtMask[i], &Overlapped[i]); - - } - else - { - - ptr1 = Block[i]; - ptr2 = Block[i]; - - while (Length > 0) - { - c = *(ptr1++); - - Length--; - - if (c == 0xff) - { - c = *(ptr1++); - Length--; - - if (c == 0xff) // ff ff means ff - { - Length--; - } - else - { - // This is connection / RTS/DTR statua from other end - // Convert to CAT Command - - if (c == CurrentState[i]) - continue; - - if (c & RTS) - Rig_PTT(i, TRUE); - else - Rig_PTT(i, FALSE); - - CurrentState[i] = c; - continue; - } - } - } - - memset(&Overlapped[i], 0, sizeof(OVERLAPPED)); - Overlapped[i].hEvent = Event; - - ReadFile(PTTCATHandle[i], Block[i], 80, &Length, &Overlapped[i]); - } - } - } - } - EndPTTCATThread = FALSE; -} - -char ClassName[]="BPQMAIL"; - -ATOM MyRegisterClass(HINSTANCE hInstance) -{ - WNDCLASS wc; - - bgBrush = CreateSolidBrush(BGCOLOUR); - RedBrush = CreateSolidBrush(RGB(255,0,0)); - GreenBrush = CreateSolidBrush(RGB(0,255,0)); -// BlueBrush = CreateSolidBrush(RGB(0,0,255)); - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; - wc.lpfnWndProc = WndProc; - - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = NULL; //LoadIcon( hInstance, MAKEINTRESOURCE(IDI_GPSMUXPC)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = bgBrush; - - wc.lpszMenuName = NULL;//"MENU_1"; - wc.lpszClassName = szWindowClass; - -// RegisterClass(&wc); - - // wc.lpfnWndProc = TraceWndProc; - // wc.lpszClassName = TraceClassName; - -// RegisterClass(&wc); - -// wc.lpfnWndProc = ConfigWndProc; -// wc.lpszClassName = ConfigClassName; - - return (RegisterClass(&wc)); - -} - - -BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) -{ - u_long param=1; - BOOL bcopt=TRUE; - int ret; - WNDCLASS wc = {0}; - int n = 0; - - - hInst = hInstance; // Store instance handle in our global variable - - WSAStartup(MAKEWORD(2, 0), &WsaData); - - - hWnd=CreateDialog(hInst,szWindowClass,0,NULL); - - if (!hWnd) - { - ret=GetLastError(); - return FALSE; - } - - // 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 = OEM_CHARSET ; - LFTTYFONT.lfOutPrecision = OUT_DEFAULT_PRECIS ; - LFTTYFONT.lfClipPrecision = CLIP_DEFAULT_PRECIS ; - LFTTYFONT.lfQuality = DEFAULT_QUALITY ; - LFTTYFONT.lfPitchAndFamily = FIXED_PITCH | FF_MODERN ; - lstrcpy( LFTTYFONT.lfFaceName, "Fixedsys" ) ; - - hFont = CreateFontIndirect(&LFTTYFONT) ; -// hFont = MyCreateFont(); - - SetWindowText(hWnd,Title); - - comWnd[0] = GetDlgItem(hWnd, IDC_COM1); - comWnd[1] = GetDlgItem(hWnd, IDC_COM2); - comWnd[2] = GetDlgItem(hWnd, IDC_COM3); - comWnd[3] = GetDlgItem(hWnd, IDC_COM4); - - portWnd[0] = GetDlgItem(hWnd, IDC_HAMLIBPORT1); - portWnd[1] = GetDlgItem(hWnd, IDC_HAMLIBPORT2); - portWnd[2] = GetDlgItem(hWnd, IDC_HAMLIBPORT3); - portWnd[3] = GetDlgItem(hWnd, IDC_HAMLIBPORT4); - - stateWnd[0] = GetDlgItem(hWnd, IDC_STATE1); - stateWnd[1] = GetDlgItem(hWnd, IDC_STATE2); - stateWnd[2] = GetDlgItem(hWnd, IDC_STATE3); - stateWnd[3] = GetDlgItem(hWnd, IDC_STATE4); - - - stateCtl[0] = IDC_STATE1; - stateCtl[1] = IDC_STATE2; - stateCtl[2] = IDC_STATE3; - stateCtl[3] = IDC_STATE4; - - ShowWindow(hWnd, nCmdShow); - - SetDlgItemText(hWnd, IDC_BPQHOST, BPQHostIP); - - SetDlgItemText(hWnd, IDC_COM1, PTTCATPort[0]); - SetDlgItemText(hWnd, IDC_COM2, PTTCATPort[1]); - SetDlgItemText(hWnd, IDC_COM3, PTTCATPort[2]); - SetDlgItemText(hWnd, IDC_COM4, PTTCATPort[3]); - - SetDlgItemInt(hWnd, IDC_HAMLIBPORT1, HamLibPort[0], 0); - SetDlgItemInt(hWnd, IDC_HAMLIBPORT2, HamLibPort[1], 0); - SetDlgItemInt(hWnd, IDC_HAMLIBPORT3, HamLibPort[2], 0); - SetDlgItemInt(hWnd, IDC_HAMLIBPORT4, HamLibPort[3], 0); - -// ioctlsocket (sock, FIONBIO, ¶m); - - if (RigPort) - { - int Speed = 9600; - - if (RigSpeed) - Speed = atoi(RigSpeed); - } - - TimerHandle = SetTimer(hWnd, 1, 10000, NULL); - - runTimer(); // Open Hamlib connections - - _beginthread(PTTCATThread, 0); - - return TRUE; -} - -VOID ConnecttoHAMLIB(int n); - -VOID runTimer() -{ - int n; - - for (n = 0; n < 4; n++) - { - if (HamLibPort[n] && HamLibSock[n] == 0) - { - // try to connect - - ConnecttoHAMLIB(n); - - } - } -} -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - - switch (message) - { - case WM_TIMER: - - runTimer(); - break; - - case WM_CTLCOLOREDIT: - { - HDC hdc = (HDC) wParam; // handle to display context - HWND hwnd = (HWND) lParam; // handle to control window - int n; - - for (n = 0; n < 4; n++) - { - if (hwnd == comWnd[n] && PTTCATPort[n][0]) - if (PTTCATHandle[n]) - return (INT_PTR)GreenBrush; - else - return (INT_PTR)RedBrush; - - if (hwnd == portWnd[n] && HamLibPort[n]) - if (HamLibSock[n]) - return (INT_PTR)GreenBrush; - else - return (INT_PTR)RedBrush; - } - - //return (INT_PTR)RedBrush; - - return (DefWindowProc(hWnd, message, wParam, lParam)); - } - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - 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: - - PostQuitMessage(0); - break; - - case WM_COMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - int OK; - - case IDC_TEST1: - - Rig_PTT(0, 1); - Sleep(1500); - Rig_PTT(0, 0); - break; - - case IDC_TEST2: - - Rig_PTT(1, 1); - Sleep(1500); - Rig_PTT(1, 0); - break; - - case IDC_TEST3: - - Rig_PTT(2, 1); - Sleep(1500); - Rig_PTT(2, 0); - break; - - case IDC_TEST4: - - Rig_PTT(3, 1); - Sleep(1500); - Rig_PTT(3, 0); - break; - - case IDOK: - - GetDlgItemText(hWnd, IDC_BPQHOST, BPQHostIP, 127); - - GetDlgItemText(hWnd, IDC_COM1, PTTCATPort[0], 15); - GetDlgItemText(hWnd, IDC_COM2, PTTCATPort[1], 15); - GetDlgItemText(hWnd, IDC_COM3, PTTCATPort[2], 15); - GetDlgItemText(hWnd, IDC_COM4, PTTCATPort[3], 15); - - HamLibPort[0] = GetDlgItemInt(hWnd, IDC_HAMLIBPORT1, &OK, 0); - HamLibPort[1] = GetDlgItemInt(hWnd, IDC_HAMLIBPORT2, &OK, 0); - HamLibPort[2] = GetDlgItemInt(hWnd, IDC_HAMLIBPORT3, &OK, 0); - HamLibPort[3] = GetDlgItemInt(hWnd, IDC_HAMLIBPORT4, &OK, 0); - - SaveConfig(); - - // EndPTTCATThread = 1; - - // Sleep(1100); - - // _beginthread(PTTCATThread, 0); - - break; - - default: - return (DefWindowProc(hWnd, message, wParam, lParam)); - } - } - - return (DefWindowProc(hWnd, message, wParam, lParam)); - -} - -void HAMLIBProcessMessage(int n) -{ - char RXBuffer[256]; - - int InputLen = recv(HamLibSock[n], RXBuffer, 256, 0); - - if (InputLen == 0 || InputLen == SOCKET_ERROR) - { - if (HamLibSock[n]) - closesocket(HamLibSock[n]); - - HamLibSock[n] = 0; - RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE); - - return; - } -} - - -VOID HAMLIBThread(int n); - -VOID ConnecttoHAMLIB(int n) -{ - _beginthread(HAMLIBThread, 0, n); - return ; -} - -VOID HAMLIBThread(int n) -{ - // Opens sockets and looks for data - - char Msg[255]; - int err, i, ret; - u_long param=1; - BOOL bcopt=TRUE; - fd_set readfs; - fd_set errorfs; - struct timeval timeout; - - if (HamLibSock[n]) - closesocket(HamLibSock[n]); - - // Param is IPADDR:PORT. Only Allow numeric addresses - - if (HamLibPort[n] == 0) - return; - - remoteDest[n].sin_family = AF_INET; - remoteDest[n].sin_addr.s_addr = inet_addr(BPQHostIP); - remoteDest[n].sin_port = htons(HamLibPort[n]); - - HamLibSock[n] = 0; - HamLibSock[n] = socket(AF_INET,SOCK_STREAM,0); - - if (HamLibSock[n] == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for HAMLIB socket - error code = %d\r\n", WSAGetLastError()); - Debugprintf(Msg); - - return; - } - - setsockopt(HamLibSock[n], SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(HamLibSock[n], IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); - - if (connect(HamLibSock[n],(LPSOCKADDR)&remoteDest[n],sizeof(remoteDest[n])) == 0) - { - // - // Connected successful - // - } - else - { - err=WSAGetLastError(); - i=sprintf(Msg, "Connect Failed for HAMLIB socket %d - error code = %d\r\n", n, err); - Debugprintf(Msg); - - closesocket(HamLibSock[n]); - - HamLibSock[n] = 0; - - RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE); - - return; - } - - RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE); - - ret = GetLastError(); - - while (HamLibSock[n]) - { - FD_ZERO(&readfs); - FD_ZERO(&errorfs); - - FD_SET(HamLibSock[n],&readfs); - FD_SET(HamLibSock[n],&errorfs); - - timeout.tv_sec = 60; - timeout.tv_usec = 0; - - ret = select((int)HamLibSock[n] + 1, &readfs, NULL, &errorfs, &timeout); - - if (ret == SOCKET_ERROR) - { - Debugprintf("HAMLIB Select failed %d ", WSAGetLastError()); - goto Lost; - } - - if (ret > 0) - { - // See what happened - - if (FD_ISSET(HamLibSock[n], &readfs)) - { - HAMLIBProcessMessage(n); - } - - if (FD_ISSET(HamLibSock[n], &errorfs)) - { -Lost: - sprintf(Msg, "HAMLIB Connection lost for Port %d\r\n", n); - Debugprintf(Msg); - - closesocket(HamLibSock[n]); - HamLibSock[n] = 0; - RedrawWindow(hWnd, NULL, NULL, 0); - - return; - } - continue; - } - else - { - } - } - sprintf(Msg, "HAMLIB Thread Terminated Port %d\r\n", n); - Debugprintf(Msg); -} diff --git a/.svn/pristine/14/147067e4beec11a2c197551503067c2e0ff303a1.svn-base b/.svn/pristine/14/147067e4beec11a2c197551503067c2e0ff303a1.svn-base deleted file mode 100644 index 46cb0b7..0000000 --- a/.svn/pristine/14/147067e4beec11a2c197551503067c2e0ff303a1.svn-base +++ /dev/null @@ -1,45 +0,0 @@ -// -// HTTP Session Control. Used In Kernel HTTPCode, BBSHTMLConfig -// and ChatHTMLConfig - -// On Windows changes to layout or length of this struct require rebuilding BPQ32.dll, BPQMail and BPQChat - -struct HTTPConnectionInfo // Used for Web Server for thread-specific stuff -{ - struct HTTPConnectionInfo * Next; - struct STATIONRECORD * SelCall; // Station Record for individual station display - char Callsign[12]; - int WindDirn, WindSpeed, WindGust, Temp, RainLastHour, RainLastDay, RainToday, Humidity, Pressure; //WX Fields - char * ScreenLines[100]; // Screen Image for Teminal access mode - max 100 lines (cyclic buffer) - int ScreenLineLen[100]; // Length of each lime - int LastLine; // Pointer to last line of data - BOOL PartLine; // Last line does not have CR on end - char HTTPCall[10]; // Call of HTTP user - BOOL Changed; // Changed since last poll. If set, reply immediately, else set timer and wait - SOCKET sock; // Socket for pending send - int ResponseTimer; // Timer for delayed response - int KillTimer; // Clean up timer (no activity timeout) - int Stream; // BPQ Stream Number - char Key[20]; // Session Key - BOOL Connected; - // Use by Mail Module -#ifdef MAIL - struct UserInfo * User; // Selected User - struct MsgInfo * Msg; // Selected Message - WPRec * WP; // Selected WP record - WebMailInfo * WebMail; // Webmail Forms Info -#else - VOID * User; // Selected User - VOID * Msg; // Selected Message - VOID * WP; // Selected WP record - VOID * WebMail; // Webmail Forms Info -#endif - struct UserRec * USER; // Telnet Server USER record - int WebMailSkip; // Number to skip at start of list (for paging) - char WebMailTypes[4]; // Types To List - BOOL WebMailMine; // List all meessage to or from me - BOOL WebMailMyTX; // List all meessage from me - BOOL WebMailMyRX; // List all meessage to me - time_t WebMailLastUsed; - struct TNCINFO * TNC; // Session -> TNC link -}; diff --git a/.svn/pristine/14/148f6414536f7829e65ade1ec3c7a09edd84765d.svn-base b/.svn/pristine/14/148f6414536f7829e65ade1ec3c7a09edd84765d.svn-base deleted file mode 100644 index 7c60f9f..0000000 --- a/.svn/pristine/14/148f6414536f7829e65ade1ec3c7a09edd84765d.svn-base +++ /dev/null @@ -1,1907 +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 -*/ - -// -// DLL to inteface HAL Communications Corp Clover/Pacor controllers to BPQ32 switch -// -// Uses BPQ EXTERNAL interface -// - -#define _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_DEPRECATE - -#include "time.h" - -#include "CHeaders.h" -#include "tncinfo.h" - -#include "bpq32.h" - -#define HAL 1 - -#define SetMYCALL 0x13 -#define ConnectEnable 0x52 -#define ConnectDisable 0x42 -#define SetEAS 0x59 // Echo as Sent -#define SetTones 0xec -#define ClearOnDisc 0x57 - -static char ClassName[]="HALSTATUS"; - -static char WindowTitle[] = "HAL"; -static int RigControlRow = 185; - -struct TNCINFO * TNCInfo[34]; // Records are Malloc'd - -#define SOH 0x01 // CONTROL CODES -#define ETB 0x17 -#define DLE 0x10 - -//int MaxStreams = 0; - -#ifndef LINBPQ -extern HFONT hFont; -#endif - -static char status[23][50] = {"IDLE", "TFC", "RQ", "ERR", "PHS", "OVER", "FSK TX", - "FSK RX", "P-MODE100", "P-MODE200", "HUFMAN ON", "HUFMAN OFF", "P-MODE SBY(LISTEN ON)", - "P-MODE SBY(LISTEN OFF)", "ISS", "IRS", - "AMTOR SBY(LISTEN ON)", "AMTOR SBY(LISTEN OFF)", "AMTOR FEC TX", "AMTOR FEC RX", "P-MODE FEC TX", - "FREE SIGNAL TX (AMTOR)", "FREE SIGNAL TX TIMED OUT (AMTOR)"}; - -struct TNCINFO * CreateTTYInfo(int port, int speed); -BOOL OpenConnection(int); -BOOL SetupConnection(int); -static BOOL WriteCommBlock(struct TNCINFO * TNC); -static void CheckRX(struct TNCINFO * TNC); -VOID HALPoll(int Port); -VOID ProcessDEDFrame(struct TNCINFO * TNC, UCHAR * rxbuff, int len); -VOID ProcessTermModeResponse(struct TNCINFO * TNC); -static VOID DoTNCReinit(struct TNCINFO * TNC); -VOID DoTermModeTimeout(struct TNCINFO * TNC); -VOID ProcessHALBuffer(struct TNCINFO * TNC, int Length); -VOID ProcessHALCmd(struct TNCINFO * TNC); -VOID ProcessHALData(struct TNCINFO * TNC); -VOID ProcessKHOSTPacket(struct TNCINFO * TNC, UCHAR * rxbuffer, int Len); -VOID ProcessKNormCommand(struct TNCINFO * TNC, UCHAR * rxbuffer); -VOID ProcessHostFrame(struct TNCINFO * TNC, UCHAR * rxbuffer, int Len); -VOID DoMonitor(struct TNCINFO * TNC, UCHAR * Msg, int Len); - -BOOL HALConnected(struct TNCINFO * TNC, char * Call); -VOID HALDisconnected(struct TNCINFO * TNC); - -static VOID EncodeAndSend(struct TNCINFO * TNC, UCHAR * txbuffer, int Len); -VOID SendCmd(struct TNCINFO * TNC, UCHAR * txbuffer, int Len); -int DLEEncode(UCHAR * inbuff, UCHAR * outbuff, int len); -int DLEDecode(UCHAR * inbuff, UCHAR * outbuff, int len); - -VOID COMClearDTR(HANDLE fd); -VOID COMClearRTS(HANDLE fd); -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); - - - -//static HANDLE LogHandle[4] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; - -//char * Logs[4] = {"1", "2", "3", "4"}; - -//char BaseDir[]="c:"; - -static VOID CloseLogfile(int Flags) -{ -// CloseHandle(LogHandle[Flags]); -// LogHandle[Flags] = INVALID_HANDLE_VALUE; -} - -static VOID OpenLogfile(int Flags) -{ -/* -UCHAR FN[MAX_PATH]; - time_t T; - struct tm * tm; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(FN,"%s\\HALLog_%02d%02d%02d_%s.bin", BaseDir, tm->tm_mday, tm->tm_hour, tm->tm_min, Logs[Flags]); - - LogHandle[Flags] = CreateFile(FN, - GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - SetFilePointer(LogHandle[Flags], 0, 0, FILE_END); - - return (LogHandle[Flags] != INVALID_HANDLE_VALUE); -*/ -} - -static void WriteLogLine(int Flags, char * Msg, int MsgLen) -{ -// int cnt; -// WriteFile(LogHandle[Flags] ,Msg , MsgLen, &cnt, NULL); -} - - - -int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC; - char errbuf[256]; - - strcpy(errbuf, buf); - - ptr = strtok(buf, " \t\n\r"); - - if(ptr == NULL) return (TRUE); - - if(*ptr =='#') return (TRUE); // comment - - if(*ptr ==';') return (TRUE); // comment - - ptr = strtok(NULL, " \t\n\r"); - - if (_stricmp(buf, "APPL") == 0) // Using BPQ32 COnfig - { - BPQport = Port; - p_cmd = ptr; - } - else - if (_stricmp(buf, "PORT") != 0) // Using Old Config - { - // New config without a PORT or APPL - this is a Config Command - - strcpy(buf, errbuf); - strcat(buf, "\r"); - - BPQport = Port; - - TNC = TNCInfo[BPQport] = zalloc(sizeof(struct TNCINFO)); - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - goto ConfigLine; - } - else - - { - - // Old Config from file - - BPQport=0; - BPQport = atoi(ptr); - - p_cmd = strtok(NULL, " \t\n\r"); - - if (Port && Port != BPQport) - { - // Want a particular port, and this isn't it - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - } - } - } - if(BPQport > 0 && BPQport < 33) - { - TNC = TNCInfo[BPQport] = zalloc(sizeof(struct TNCINFO)); - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - if (p_cmd != NULL) - { - if (p_cmd[0] != ';' && p_cmd[0] != '#') - TNC->ApplCmd=_strdup(p_cmd); - } - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; -ConfigLine: - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if (_memicmp(buf, "WL2KREPORT", 10) == 0) - { - TNC->WL2K = DecodeWL2KReportLine(buf); - continue; - } - if (_memicmp(buf, "NEEDXONXOFF", 10) == 0) - { - TNC->XONXOFF = TRUE; - continue; - } - - if (_memicmp(buf, "TONES", 5) == 0) - { - int tone1 = 0, tone2 = 0; - - ptr = strtok(&buf[6], " ,/\t\n\r"); - if (ptr) - { - tone1 = atoi(ptr); - ptr = strtok(NULL, " ,/\t\n\r"); - if (ptr) - { - tone2 = atoi(ptr); - ptr = &TNC->InitScript[TNC->InitScriptLen]; - - // Try putting into FSK mode first - - *(ptr++) = 0x84; - *(ptr++) = SetTones; // Set Tones (Mark, Space HI byte first) - *(ptr++) = tone1 >> 8; - *(ptr++) = tone1 & 0xff; - *(ptr++) = tone2 >> 8; - *(ptr++) = tone2 & 0xff; - - TNC->InitScriptLen += 6; - - continue; - } - } - goto BadLine; - } - if (_memicmp(buf, "DEFAULTMODE ", 12) == 0) - { - - ptr = strtok(&buf[12], " ,\t\n\r"); - if (ptr) - { - if (_stricmp(ptr, "CLOVER") == 0) - TNC->DefaultMode = Clover; - else if (_stricmp(ptr, "PACTOR") == 0) - TNC->DefaultMode = Pactor; - else if (_stricmp(ptr, "AMTOR") == 0) - TNC->DefaultMode = AMTOR; - else goto BadLine; - - continue; - } - goto BadLine; - } - } - BadLine: - WritetoConsole(" Bad config record "); - WritetoConsole(errbuf); - WritetoConsole("\r\n"); - } - - return (TRUE); -} - -static size_t ExtProc(int fn, int port , PDATAMESSAGE buff) -{ - int txlen = 0; - PMSGWITHLEN buffptr; - struct TNCINFO * TNC = TNCInfo[port]; - struct STREAMINFO * STREAM; - int Stream; - - if (TNC == NULL) - return 0; - - if (fn < 4 || fn > 5) - if (TNC->hDevice == 0) - return 0; // Port not open - - STREAM = &TNC->Streams[0]; - - switch (fn) - { - case 1: // poll - - while (TNC->PortRecord->UI_Q) // Release anything accidentally put on UI_Q - { - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - ReleaseBuffer(buffptr); - } - - //for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (STREAM->ReportDISC) - { - STREAM->ReportDISC = FALSE; - buff->PORT = 0; - - return -1; - } - } - - CheckRX(TNC); - HALPoll(port); - - //for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (STREAM->PACTORtoBPQ_Q !=0) - { - int datalen; - - buffptr=Q_REM(&STREAM->PACTORtoBPQ_Q); - - datalen = (int)buffptr->Len; - - buff->PORT = 0; // Compatibility with Kam Driver - 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; - - if (!TNC->TNCOK) - { - // Send Error Response - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = 27; - memcpy(&buffptr->Data[0], "No Connection to PACTOR TNC\r", 27); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - return 0; - } - - txlen = GetLengthfromBuffer(buff) - (sizeof(void *) + 4); - - buffptr->Len = txlen; - memcpy(&buffptr->Data[0], &buff->L2DATA[0], 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; - - if (STREAM->FramesQueued > 4) - return (1 | TNC->HostMode << 8); - - return TNC->HostMode << 8 | STREAM->Disconnecting << 15; // OK, but lock attach if disconnecting - - case 4: // reinit - - return (0); - - case 5: // Close - - CloseCOMPort(TNCInfo[port]->hDevice); - return (0); - - case 6: // Scan Control - - return 0; // None Yet - - } - return 0; - -} - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, "" - "HAL Status

HAL Status

"); - - Len += sprintf(&Buff[Len], ""); - - Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); - Len += sprintf(&Buff[Len], "", TNC->WEB_STATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TXRX); - Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], "", TNC->WEB_LEDS); - Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Status%s
TX/RX State%s
Traffic%s
LEDSSTBY CALL LINK ERROR TX RX
%s
"); - - Len = DoScanLine(TNC, Buff, Len); - - return Len; -} - - -VOID * HALExtInit(EXTPORTDATA * PortEntry) -{ - char msg[500]; - struct TNCINFO * TNC; - int port; - char * ptr; - int len; - char Msg[80]; -#ifndef LINBPQ - HWND x; -#endif - // - // Will be called once for each Pactor Port - // The COM port number is in IOBASE - // - - sprintf(msg,"HAL Driver %s", PortEntry->PORTCONTROL.SerialPortName); - WritetoConsole(msg); - - port=PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - TNC = TNCInfo[port]; - - if (TNC == NULL) - { - // Not defined in Config file - - sprintf(msg," ** Error - no info in BPQ32.cfg for this port"); - WritetoConsole(msg); - - return ExtProc; - } - - TNC->Port = port; - - TNC->Hardware = H_HAL; - - TNC->Interlock = PortEntry->PORTCONTROL.PORTINTERLOCK; - - PortEntry->MAXHOSTMODESESSIONS = 1; // Default - - TNC->PortRecord = PortEntry; - - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) - { - memcpy(TNC->NodeCall, MYNODECALL, 10); - } - else - { - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - } - - PortEntry->PORTCONTROL.PROTOCOL = 10; - PortEntry->PORTCONTROL.PORTQUALITY = 0; - - if (PortEntry->PORTCONTROL.PORTPACLEN == 0) - PortEntry->PORTCONTROL.PORTPACLEN = 100; - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - if (TNC->DefaultMode) - TNC->CurrentMode = TNC->DefaultMode; - else - TNC->CurrentMode = Clover; - - TNC->PollDelay = 999999999; - - // Set Disable +?, ExpandedStatus , Channel Stats Off, ClearOnDisc, EAS and MYCALL - - len = sprintf(Msg, "%c%c%c%c%c%c%s", 0xcc, 0x56, 0x41, ClearOnDisc, SetEAS, SetMYCALL, TNC->NodeCall); - len++; // We include the NULL - - memcpy(&TNC->InitScript[TNC->InitScriptLen], Msg, len); - TNC->InitScriptLen += len; - - PortEntry->PORTCONTROL.TNC = TNC; - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 510; - TNC->WebWinY = 280; - - TNC->WEB_COMMSSTATE = zalloc(100); - TNC->WEB_TNCSTATE = zalloc(100); - strcpy(TNC->WEB_TNCSTATE, "Free"); - TNC->WEB_MODE = zalloc(100); - TNC->WEB_TRAFFIC = zalloc(100); - TNC->WEB_BUFFERS = zalloc(100); - TNC->WEB_STATE = zalloc(100); - TNC->WEB_TXRX = zalloc(100); - TNC->WEB_LEDS = zalloc(100); - strcpy(TNC->WEB_LEDS, " X X X X X X"); - -#ifndef LINBPQ - - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 500, 233, ForcedClose); - - x = CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,6,120,20, TNC->hDlg, NULL, hInstance, NULL); - x = TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,6,386,20, TNC->hDlg, NULL, hInstance, NULL); - - x = CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,28,106,20, TNC->hDlg, NULL, hInstance, NULL); - x = TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,28,520,20, TNC->hDlg, NULL, hInstance, NULL); - - x = CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,50,80,20, TNC->hDlg, NULL, hInstance, NULL); - x = TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,50,200,20, TNC->hDlg, NULL, hInstance, NULL); - - x = CreateWindowEx(0, "STATIC", "Status", WS_CHILD | WS_VISIBLE, 10,72,110,20, TNC->hDlg, NULL, hInstance, NULL); - x = TNC->xIDC_STATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,72,144,20, TNC->hDlg, NULL, hInstance, NULL); - - x = CreateWindowEx(0, "STATIC", "TX/RX State", WS_CHILD | WS_VISIBLE,10,94,80,20, TNC->hDlg, NULL, hInstance, NULL); - x = TNC->xIDC_TXRX = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,94,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - x = CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,116,80,20, TNC->hDlg, NULL, hInstance, NULL); - x = TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "RX 0 TX 0 ACKED 0", WS_CHILD | WS_VISIBLE,116,116,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - x = CreateWindowEx(0, "STATIC", "LEDS", WS_CHILD | WS_VISIBLE,10,138,60,20, TNC->hDlg, NULL, hInstance, NULL); - SendMessage(x, WM_SETFONT, (WPARAM)hFont, 0); - x = CreateWindowEx(0, "STATIC", "STBY CALL LINK ERROR TX RX", WS_CHILD | WS_VISIBLE,116,138,280,20, TNC->hDlg, NULL, hInstance, NULL); - SendMessage(x, WM_SETFONT, (WPARAM)hFont, 0); - x = TNC->xIDC_LEDS = CreateWindowEx(0, "STATIC", " X X X X X X", WS_CHILD | WS_VISIBLE,116,158,280,20 , TNC->hDlg, NULL, hInstance, NULL); - SendMessage(x, WM_SETFONT, (WPARAM)hFont, 0); - - TNC->ClientHeight = 233; - TNC->ClientWidth = 500; - - MoveWindows(TNC); -#endif - - OpenCOMMPort(TNC, PortEntry->PORTCONTROL.SerialPortName, PortEntry->PORTCONTROL.BAUDRATE, FALSE); - - SendCmd(TNC, "\x09" , 1); // Reset - - WritetoConsole("\n"); - - return ExtProc; -} - - - -static VOID KISSCLOSE(int Port) -{ - struct TNCINFO * conn = TNCInfo[Port]; - - // drop DTR and RTS - - COMClearDTR(conn->hDevice); - COMClearRTS(conn->hDevice); - - // purge any outstanding reads/writes and close device handle - - CloseCOMPort(conn->hDevice); - - return; -} - - -static void CheckRX(struct TNCINFO * TNC) -{ - int Length, Len; - UCHAR * Xptr; - - // only try to read number of bytes in queue - - if (TNC->RXLen == 500) - TNC->RXLen = 0; - - Len = ReadCOMBlock(TNC->hDevice, &TNC->RXBuffer[TNC->RXLen], 500 - TNC->RXLen); - - if (Len == 0) - return; - - TNC->RXLen += Len; - - Length = TNC->RXLen; - - // We need to konw whether data is received or echoed, so we can't split commands and data here. - // Pass everything to the Command Handler. It will check that there are enough bytes for the command, - // and wait for more if not. - - // The USB version also uses 0x91 0x31 to eacape 0x11, 0x91 0x33 for 0x13 and 0x91 0xB1 for 0x91 - - // If USB version, we might get unescaped xon and xoff, which we must ignore - - if (TNC->XONXOFF) - { - Xptr = memchr(&TNC->RXBuffer, 0x11, Length); - - while(Xptr) - { - Debugprintf("XON Port %d", TNC->Port); - memmove(Xptr, Xptr + 1, Length-- - (TNC->RXBuffer - Xptr)); - Xptr = memchr(&TNC->RXBuffer, 0x11, Length); - } - - Xptr = memchr(&TNC->RXBuffer, 0x13, Length); - - while(Xptr) - { - Debugprintf("XOFF Port %d", TNC->Port); - memmove(Xptr, Xptr + 1, Length-- - (TNC->RXBuffer - Xptr)); - Xptr = memchr(&TNC->RXBuffer, 0x13, Length); - } - - Xptr = memchr(&TNC->RXBuffer, 0x91, Length); // See if packet contains 0x91 escape - - if (Xptr) - - // Make sure we have the escaped char as well - - if ((Xptr - &TNC->RXBuffer[0]) == Length - 1) // x91 is last char - return; - } - - ProcessHALBuffer(TNC, Length); - - TNC->RXLen = 0; - - return; - -} - - - -static BOOL WriteCommBlock(struct TNCINFO * TNC) -{ - WriteCOMBlock(TNC->hDevice, TNC->TXBuffer, TNC->TXLen); - return TRUE; -} - -VOID HALPoll(int Port) -{ - struct TNCINFO * TNC = TNCInfo[Port]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - UCHAR * Poll = TNC->TXBuffer; - char Status[80]; - UCHAR TXMsg[1000]; - int datalen; - - if (TNC->Timeout) - { - TNC->Timeout--; - - if (TNC->Timeout) // Still waiting - return; - - // Timed Out - - TNC->TNCOK = FALSE; - TNC->HostMode = 0; - - sprintf(TNC->WEB_COMMSSTATE,"%s Open but TNC not responding", TNC->PortRecord->PORTCONTROL.SerialPortName); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - //for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (TNC->PortRecord->ATTACHEDSESSIONS[0]) // Connected - { - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - } - } - - } - - // if we have just restarted or TNC appears to be in terminal mode, run Initialisation Sequence - - if (TNC->TNCOK) - if (!TNC->HostMode) - { - DoTNCReinit(TNC); - return; - } - - if (TNC->PortRecord->ATTACHEDSESSIONS[0] && STREAM->Attached == 0) - { - // New Attach - - int calllen; - char Msg[80]; - - STREAM->Attached = TRUE; - - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->BytesAcked = 0; - - calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4USER, STREAM->MyCall); - STREAM->MyCall[calllen] = 0; - - datalen = sprintf(TXMsg, "%c%s", SetMYCALL, STREAM->MyCall); - SendCmd(TNC, TXMsg, datalen + 1); // Send the NULL - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Stop Scanning - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command(-1, Msg); - - SendCmd(TNC, "\x42", 1); // Connect Enable off - - return; - - } - - //for (Stream = 0; Stream <= MaxStreams; Stream++) - - if (STREAM->Attached) - CheckForDetach(TNC, 0, STREAM, TidyClose, ForcedClose, CloseComplete); - - if (TNC->NeedPACTOR) - { - TNC->NeedPACTOR--; - - if (TNC->NeedPACTOR == 0) - { - int datalen; - - UCHAR TXMsg[80]; - - datalen = sprintf(TXMsg, "%c%s", SetMYCALL, TNC->NodeCall); - SendCmd(TNC, TXMsg, datalen + 1); // Send the NULL - - // Set Listen Mode - - switch (TNC->CurrentMode) - { - case Pactor: - - SendCmd(TNC, "\x84", 1); // FSK - SendCmd(TNC, "\x83", 1); // Select P-MODE Standby - SendCmd(TNC, "\x58", 1); // Listen - - break; - - case Clover: - - SendCmd(TNC, "\x80", 1); // Clover - SendCmd(TNC, "\x54", 1); // Enable adaptive Clover format - SendCmd(TNC, "\x41", 1); // No Statistics - SendCmd(TNC, "\x60\x09", 2); // Robust Retries - SendCmd(TNC, "\x61\x09", 2); // Normal Retries - - break; - } - - SendCmd(TNC, "\x52", 1); // ConnectEnable - - // Restart Scanning - - sprintf(Status, "%d SCANSTART 15", TNC->Port); - - Rig_Command(-1, Status); - - return; - } - } - -#define MAXHALTX 256 - - //for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (TNC->TNCOK && STREAM->BPQtoPACTOR_Q && (STREAM->BytesTXed - STREAM->BytesAcked < 600)) - { - int datalen; - UINT * buffptr; - UCHAR * MsgPtr; - unsigned char TXMsg[500]; - - buffptr = (UINT * )STREAM->BPQtoPACTOR_Q; - datalen=buffptr[1]; - MsgPtr = (UCHAR *)&buffptr[2]; - - if (STREAM->Connected) - { - if (TNC->SwallowSignon) - { - TNC->SwallowSignon = FALSE; - if (strstr(MsgPtr, "Connected")) // Discard *** connected - { - ReleaseBuffer(buffptr); - STREAM->FramesQueued--; - return; - } - } - - // Must send data in small chunks - the Hal has limited buffer space - - // If in IRS force a turnround - - if (TNC->TXRXState == 'R' && TNC->CurrentMode != Clover) - { - if (TNC->TimeInRX++ > 15) - SendCmd(TNC, "\x87", 1); // Changeover to ISS - else - goto Poll; - } - - TNC->TimeInRX = 0; - - EncodeAndSend(TNC, MsgPtr, datalen); - buffptr=Q_REM(&STREAM->BPQtoPACTOR_Q); - ReleaseBuffer(buffptr); - WriteLogLine(2, MsgPtr, datalen); - - STREAM->BytesTXed += datalen; - STREAM->FramesQueued--; - - ShowTraffic(TNC); - - return; - } - else - { - buffptr=Q_REM(&STREAM->BPQtoPACTOR_Q); - STREAM->FramesQueued--; - - // Command. Do some sanity checking and look for things to process locally - - datalen--; // Exclude CR - MsgPtr[datalen] = 0; // Null Terminate - _strupr(MsgPtr); - - if (memcmp(MsgPtr, "RADIO ", 6) == 0) - { - sprintf(&MsgPtr[40], "%d %s", TNC->Port, &MsgPtr[6]); - if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK->CIRCUITINDEX, &MsgPtr[40])) - { - ReleaseBuffer(buffptr); - } - else - { - buffptr[1] = sprintf((UCHAR *)&buffptr[2], "%s", &MsgPtr[40]); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - } - return; - } - - if (memcmp(MsgPtr, "MODE CLOVER", 11) == 0) - { - TNC->CurrentMode = Clover; - buffptr[1] = sprintf((UCHAR *)&buffptr[2],"HAL} Ok\r"); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - - MySetWindowText(TNC->xIDC_MODE, "Clover"); - strcpy(TNC->WEB_MODE, "Clover"); - - SendCmd(TNC, "\x80", 1); // Clover - SendCmd(TNC, "\x54", 1); // Enable adaptive Clover format - SendCmd(TNC, "\x41", 1); // No Statistics - - return; - } - - if (memcmp(MsgPtr, "MODE PACTOR", 11) == 0) - { - TNC->CurrentMode = Pactor; - buffptr[1] = sprintf((UCHAR *)&buffptr[2],"HAL} Ok\r"); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - - SendCmd(TNC, "\x84", 1); // FSK - SendCmd(TNC, "\x83", 1); // Select P-MODE Standby - SendCmd(TNC, "\x48", 1); // Listen Off - - return; - } - if (memcmp(MsgPtr, "MODE AMTOR", 11) == 0) - { - TNC->CurrentMode = AMTOR; - buffptr[1] = sprintf((UCHAR *)&buffptr[2],"HAL} Ok\r"); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - - return; - } - - if (MsgPtr[0] == 'C' && MsgPtr[1] == ' ' && datalen > 2) // Connect - { - memcpy(STREAM->RemoteCall, &MsgPtr[2], 9); - - switch (TNC->CurrentMode) - { - case Pactor: - - SendCmd(TNC, "\x84", 1); // FSK - SendCmd(TNC, "\x83", 1); // Select P-MODE Standby - - datalen = sprintf(TXMsg, "\x19%s", STREAM->RemoteCall); - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s - PACTOR", STREAM->MyCall, STREAM->RemoteCall); - - // DOnt set connecting till we get the 19 response so we can trap listen as a fail - break; - - case Clover: - - SendCmd(TNC, "\x54", 1); // Enable adaptive Clover format - SendCmd(TNC, "\x57", 1); // Enable TX buffer clear on disconnect - - datalen = sprintf(TXMsg, "\x11%s", STREAM->RemoteCall); - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s - CLOVER", STREAM->MyCall, STREAM->RemoteCall); - - break; - } - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - SendCmd(TNC, TXMsg, datalen + 1); // Include NULL - - ReleaseBuffer(buffptr); - - return; - } - - if (memcmp(MsgPtr, "CLOVER ", 7) == 0) - { - memcpy(STREAM->RemoteCall, &MsgPtr[2], 9); - - SendCmd(TNC, "\x54", 1); // Enable adaptive Clover format - SendCmd(TNC, "\x57", 1); // Enable TX buffer clear on disconnect - - datalen = sprintf(TXMsg, "\x11%s", STREAM->RemoteCall); - SendCmd(TNC, TXMsg, datalen + 1); // Include NULL - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s - CLOVER", - STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - ReleaseBuffer(buffptr); - - return; - } - - if (memcmp(MsgPtr, "DISCONNECT", datalen) == 0) // Disconnect - { - SendCmd(TNC, "\x07", 1); // Normal Disconnect - TNC->NeedPACTOR = 50; - - STREAM->Connecting = FALSE; - STREAM->ReportDISC = TRUE; - ReleaseBuffer(buffptr); - - return; - } - - // Other Command ?? Treat as HEX string - - datalen = sscanf(MsgPtr, "%X %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X", - (UINT *)&TXMsg[0], (UINT *)&TXMsg[1], (UINT *)&TXMsg[2], (UINT *)&TXMsg[3], (UINT *)&TXMsg[4], - (UINT *)&TXMsg[5], (UINT *)&TXMsg[6], (UINT *)&TXMsg[7], (UINT *)&TXMsg[8], (UINT *)&TXMsg[9], - (UINT *)&TXMsg[10], (UINT *)&TXMsg[11], (UINT *)&TXMsg[12], (UINT *)&TXMsg[13], - (UINT *)&TXMsg[14], (UINT *)&TXMsg[15]); - -// SendCmd(TNC, TXMsg, datalen); - ReleaseBuffer(buffptr); - TNC->InternalCmd = 0; - } - } - } -Poll: - // Nothing doing - send Poll (but not too often) - - TNC->PollDelay++; - - if (TNC->PollDelay < 20) - return; - - TNC->PollDelay = 0; - - if (TNC->TNCOK) - SendCmd(TNC, "\x7d" , 1); // Use Get LEDS as Poll - else - SendCmd(TNC, "\x09" , 1); // Reset - - TNC->Timeout = 100; - - return; -} - -static VOID DoTNCReinit(struct TNCINFO * TNC) -{ - // TNC Has Restarted, send init commands (can probably send all at once) - -// TNC->TXBuffer[0] = 0x1b; -// TNC->TXLen = 1; - - WriteCommBlock(TNC); - - SendCmd(TNC, TNC->InitScript, TNC->InitScriptLen); - - TNC->HostMode = TRUE; // Should now be in Host Mode - TNC->NeedPACTOR = 20; // Need to set Calls and start scan - - TNC->DataMode = RXDATA; // Start with RX Data - - SendCmd(TNC, "\x7d" , 1); // Use Get LEDS as Poll -// SendCmd(TNC, "\xc9" , 1); // Huffman Off - SendCmd(TNC, "\x57", 1); // Enable TX buffer clear on disconnect - - SendCmd(TNC, "\x60\x06", 2); // Robust Mode Retries - -// SendCmd(TNC, "\x6f\x03" , 2); // Undocumented XON/XOFF On - used to see if old or new style modem - - TNC->Timeout = 50; - - return; - -} - -VOID ProcessHALData(struct TNCINFO * TNC) -{ - // Received Data just pass to Appl - - UINT * buffptr; - int Len = TNC->DataLen; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - TNC->DataLen = 0; - - if (TNC->DataMode == TXDATA) - { - STREAM->BytesAcked += Len; -// Debugprintf("Acked %d", Len); - - if (STREAM->BytesAcked > STREAM->BytesTXed) - Debugprintf("Too Much Acked"); - - if ((STREAM->BPQtoPACTOR_Q == 0) && STREAM->BytesAcked >= STREAM->BytesTXed) - { - // All sent - - if (STREAM->Disconnecting) - TidyClose(TNC, 0); - else - if (TNC->CurrentMode != Clover) - - // turn round link - - SendCmd(TNC, "\x0c" , 1); // Turnround - - } - } - else - { - if (TNC->DataMode == RXDATA) - { -// Debugprintf("RXed %d", Len); - buffptr = GetBuff(); - if (buffptr == NULL) - return; // No buffers, so ignore - - buffptr[1] = Len; // Length - - WriteLogLine(1, TNC->DataBuffer, Len); - - STREAM->BytesRXed += Len; - - memcpy(&buffptr[2], TNC->DataBuffer, Len); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - } - } - - ShowTraffic(TNC); - - return; -} - - - -VOID ProcessHALBuffer(struct TNCINFO * TNC, int Length) -{ - UCHAR Char; - UCHAR * inptr; - UCHAR * cmdptr; - UCHAR * dataptr; - BOOL CmdEsc, DataEsc; - - inptr = TNC->RXBuffer; - - cmdptr = &TNC->CmdBuffer[TNC->CmdLen]; - dataptr = &TNC->DataBuffer[TNC->DataLen]; - CmdEsc = TNC->CmdEsc; - DataEsc = TNC->DataEsc; - - // HAL uses HEX 80 as a command escape, 81 to ESCAPE 80 and 81 - - // The USB version also uses 0x91 0x31 to eacape 0x11, 0x91 0x33 for 0x13 and 0x91 0xB1 for 0x91 - - // Command Responses can be variable length - - // Command Handler will check for each command/response if it has enough - if not it will wait till more arrives - - while(Length--) - { - Char = *(inptr++); - - if (CmdEsc) - { - CmdEsc = FALSE; - - if (TNC->XONXOFF && Char == 0x91) - { - // XON/XOFF escape. We ensured above that data follows so we can process it inline - - Length--; - Char = *(inptr++) - 0x20; - } - *(cmdptr++) = Char; - } - else if (DataEsc) - { - DataEsc = FALSE; - goto DataChar; - } - else -NotData: - if (Char == 0x80) // Next Char is Command - CmdEsc = TRUE; - else if (Char == 0x81) // Next Char is escaped data (80 or 81) - DataEsc = TRUE; - else - { - // This is a Data Char. We must process any Commands received so far, so we know the type of data - - DataChar: - - TNC->CmdLen = (int)(cmdptr - TNC->CmdBuffer); - ProcessHALCmd(TNC); - cmdptr = &TNC->CmdBuffer[TNC->CmdLen]; - dataptr = &TNC->DataBuffer[TNC->DataLen]; - - *(dataptr++) = Char; // Normal Data - - // Now process any other data chars - - while(Length--) - { - Char = *(inptr++); - - if (TNC->XONXOFF && Char == 0x91) - { - // XON/XOFF escape within data. We ensured above that data follows so we - // can process it here - - Length--; - Char = *(inptr++) - 0x20; - } - - if (Char == 0x80 || Char == 0x81) - { - // Process any data we have, then loop back - - TNC->DataLen = (int)(dataptr - TNC->DataBuffer); - ProcessHALData(TNC); - - goto NotData; - } - *(dataptr++) = Char; // Normal Data - } - - // Used all data - - TNC->DataLen = (int)(dataptr - TNC->DataBuffer); - - ProcessHALData(TNC); - TNC->CmdEsc = CmdEsc; - TNC->DataEsc = DataEsc; - - return; - } - } - - // Save State - - TNC->CmdLen = (int)(cmdptr - TNC->CmdBuffer); - - TNC->CmdEsc = CmdEsc; - TNC->DataEsc = DataEsc; - - if (TNC->DataLen) - ProcessHALData(TNC); - - if (TNC->CmdLen) - ProcessHALCmd(TNC); -} - -VOID mySetWindowText(struct TNCINFO * TNC, char * Msg) -{ - MySetWindowText(TNC->xIDC_STATE, Msg); - strcpy(TNC->WEB_STATE, Msg); -} - -VOID ProcessHALCmd(struct TNCINFO * TNC) -{ - char * Call; - int Stream = 0; - int Opcode; - int StatusByte; - int Leds; - int Len; - int Used; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - -CmdLoop: - - Opcode = TNC->CmdBuffer[0]; - Len = TNC->CmdLen; - - if (Len == 0) - return; - - TNC->TNCOK = TRUE; - TNC->Timeout = 0; - - sprintf(TNC->WEB_COMMSSTATE,"%s TNC link OK", TNC->PortRecord->PORTCONTROL.SerialPortName); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - // We may have more than one response in the buffer, and only each cmd/response decoder knows how many it needs - - switch(Opcode) - { - case 0x09: //Hardware Reset - equivalent to power on reset - - // Hardware has reset - need to reinitialise - - TNC->HostMode = 0; // Force Reinit - - Used = 1; - break; - - case 0x7a: // FSK Modes Status - - // Mixture of mode and state - eg listen huffman on/off irs/iss, so cant just display - - if (Len < 2) return; // Wait for more - - StatusByte = TNC->CmdBuffer[1]; - - switch (StatusByte) - { - case 0x06: // FSK TX (RTTY) - case 0x07: // FSK RX (RTTY) - case 0x10: // AMTOR STANDBY (LISTEN ON) - case 0x11: // AMTOR STANDBY (LISTEN OFF) - case 0x12: // AMTOR FEC TX (AMTOR) - case 0x13: // AMTOR FEC RX (AMTOR) - case 0x14: // P-MODE FEC TX (P-MODE) - case 0x15: // FREE SIGNAL TX (AMTOR) - case 0x16: // FREE SIGNAL TX TIMED OUT (AMTOR) - - // Diaplay Linke Status - - MySetWindowText(TNC->xIDC_MODE, status[StatusByte]); - strcpy(TNC->WEB_MODE, status[StatusByte]); - - break; - - case 0x0C: // P-MODE STANDBY (LISTEN ON) - case 0x0D: // P-MODE STANDBY (LISTEN OFF) - - // if we were connecting, this means connect failed. - - MySetWindowText(TNC->xIDC_MODE, status[StatusByte]); - strcpy(TNC->WEB_MODE, status[StatusByte]); - - if (STREAM->Connecting) - HALDisconnected(TNC); - - break; - - case 0x0E: // ISS (AMTOR/P-MODE) - - MySetWindowText(TNC->xIDC_TXRX,"ISS"); - strcpy(TNC->WEB_TXRX, "ISS"); - TNC->TXRXState = 'S'; - break; - - case 0x0F: // IRS (AMTOR/P-MODE) - - MySetWindowText(TNC->xIDC_TXRX,"IRS"); - strcpy(TNC->WEB_TXRX, "IRS"); - TNC->TXRXState = 'R'; - break; - - case 0x00: // IDLE (AMTOR/P-MODE) - case 0x01: // TFC (AMTOR/P-MODE) - case 0x02: // RQ (AMTOR/P-MODE) - case 0x03: // ERR (AMTOR/P-MODE) - case 0x04: // PHS (AMTOR/P-MODE) - case 0x05: // OVER (AMTOR/P-MODE) (not implemented) - - MySetWindowText(TNC->xIDC_STATE, status[StatusByte]); - strcpy(TNC->WEB_MODE, status[StatusByte]); - - - -//$807A $8008 P-MODE100 (P-MODE) -//$807A $8009 P-MODE200 (P-MODE) -//$807A $800A HUFFMAN ON (P-MODE) -//$807A $800B HUFFMAN OFF (P-MODE) - ; - } - Used = 2; - break; - - - case 0x7d: // Get LED Status - - // We use Get LED Status as a Poll - - if (Len < 2) return; // Wait for more - - Leds = TNC->CmdBuffer[1]; - sprintf(TNC->WEB_LEDS," %c %c %c %c %c %c ", - (Leds & 0x20)? 'X' : ' ', - (Leds & 0x10)? 'X' : ' ', - (Leds & 0x08)? 'X' : ' ', - (Leds & 0x04)? 'X' : ' ', - (Leds & 0x02)? 'X' : ' ', - (Leds & 0x01)? 'X' : ' '); - -// STBY CALL LINK ERROR TX RX - MySetWindowText(TNC->xIDC_LEDS, TNC->WEB_LEDS); - - Used = 2; - break; - - case 0x21: // Monitored FEC CCB - case 0x22: // Monitored ARQ CCB - - // As the reply is variable, make sure we have the terminating NULL - - if (memchr(TNC->CmdBuffer, 0, Len) == NULL) - return; // Wait for more - - Call = &TNC->CmdBuffer[1]; - Used = (int)strlen(Call) + 2; // Opcode and Null - - UpdateMH(TNC, Call, '!', 0); - - break; - - case 0x27: // Clover ARQ LINK REQUEST status message - - //indicates an incoming link request to either MYCALL ($8027 $8000), or MYALTCALL ($8027 $8001). - - if (Len < 2) return; // Wait for more - - // Don't need to do anything (but may eventally use ALTCALL as an APPLCALL - Used = 2; - break; - - case 0x2D: // FSK ARQ Link Request status message - - // $802D $8001 $8000 CLOVER Link Request (not implemented) - // $802D $8002 $8000 AMTOR CCIR-476 Link Request - // $802D $8003 $8000 AMTOR CCIR-625 Link Request - // $802D $8004 $8000 P-MODE Link Request - - if (Len < 3) return; // Wait for more - - // Don't need to do anything (but may save Session type later - - Used = 3; - break; - - - case 0x28: // Monitored Call - - // As the reply is variable, make sure we have the terminating NULL - - if (memchr(TNC->CmdBuffer, 0, Len) == NULL) - return; // Wait for more - - Call = &TNC->CmdBuffer[1]; - Used = strlen(Call) + 2; // Opcode and Null - - // Could possibly be used for APPLCALLS by changing MYCALL when we see a call to one of our calls - - break; - - - case 0x20: // Clover Linked with - Call Connected - case 0x29: // The Linked 476 message indicates the start of a CCIR 476 linked session. - case 0x2A: // The Linked 625 message indicates the start of a CCIR 625 linked session to . - case 0x2B: // P-MODE link to - - // As the reply is variable, make sure we have the terminating NULL - - if (memchr(TNC->CmdBuffer, 0, Len) == NULL) - return; // Wait for more - - Call = &TNC->CmdBuffer[1]; - Used = (int)strlen(Call) + 2; // Opcode and Null - - HALConnected(TNC, Call); - - break; - - case 0x23: // Normal Disconnected - followed by $8000 - case 0x24: // Link failed (any of the link errors) - case 0x25: // Signal Lost (LOS) - - if (Len < 2) return; // Wait for more - - HALDisconnected(TNC); - - Used = 2; - break; - - - // Stream Switch Reports - we will need to do something with these if Echo as Sent is set - // or we do something with the secondary port - - case 0x30: // Switch to Receive Data characters - case 0x31: // Switch to Transmit Data characters - case 0x32: // Switch to RX data from secondary port - - TNC->DataMode = Opcode; - Used = 1; - break; - - case 0x33: // Send TX data to modem - case 0x34: // Send TX data to secondary port - - TNC->TXMode = Opcode; - Used = 1; - break; - - case 0x70: // Channel Spectra Data - // $807F $80xx $8030 Invalid or unimplemented command code - if (Len < 9) return; // Wait for more - - Used = 9; - break; - - case 0x71: // SelCall On/Off - - if (Len < 2) return; // Wait for more - - Used = 2; - break; - - case 0x72: // Channel Spectra Data - // $807F $80xx $8030 Invalid or unimplemented command code - if (Len < 15) return; // Wait for more - - Used = 15; - break; - - case 0x73: // Clover Link state - - if (Len < 2) return; // Wait for more - - StatusByte = TNC->CmdBuffer[1]; - - switch (StatusByte) - { - case 0x00: mySetWindowText(TNC, "Channel idle"); break; - case 0x01: mySetWindowText(TNC, "Channel occupied with non-Clover signal"); break; - case 0x42: mySetWindowText(TNC, "Linked stations monitored"); break; - case 0x64: mySetWindowText(TNC, "Attempting normal link"); break; - case 0x65: mySetWindowText(TNC, "Attempting robust link"); break; - case 0x66: mySetWindowText(TNC, "Calling ARQ CQ"); break; - case 0x78: mySetWindowText(TNC, "Clover Control Block (CCB) send retry"); break; - case 0x79: mySetWindowText(TNC, "Clover Control Block (CCB) receive retry"); break; - case 0x7D: mySetWindowText(TNC, "Clover Control Block (CCB) received successfully"); break; - case 0x8A: mySetWindowText(TNC, "TX data block sent"); break; - case 0x8B: mySetWindowText(TNC, "RX data block received ok (precedes data block)"); break; - case 0x8C: mySetWindowText(TNC, "TX data block re-sent"); break; - case 0x8D: mySetWindowText(TNC, "RX data block decode failed (precedes data block)"); break; - case 0x8E: mySetWindowText(TNC, "TX idle"); break; - case 0x8F: mySetWindowText(TNC, "RX idle"); break; - case 0x9C: mySetWindowText(TNC, "Link failed: CCB send retries exceeded"); break; - case 0x9D: mySetWindowText(TNC, "Link failed: CCB receive retries exceeded"); break; - case 0x9E: mySetWindowText(TNC, "Link failed: protocol error"); break; - case 0xA0: mySetWindowText(TNC, "Receiving FEC SYNC sequence"); break; - } - - Used = 2; - break; - - case 0x75: // Clover waveform format - - if (Len < 5) return; // Wait for more - - Used = 5; - break; - - case 0x7F: // Error $80xx $80yy Error in command $80xx of type $80yy - // $807F $80xx $8030 Invalid or unimplemented command code - // $807F $80xx $8031 Invalid parameter value - // $807F $80xx $8032 Not allowed when connected - // $807F $80xx $8033 Not allowed when disconnected - // $807F $80xx $8034 Not valid in this mode - // $807F $80xx $8035 Not valid in this code - // $807F $8096 $8036 EEPROM write error - - if (Len < 3) return; // Wait for more - - if (TNC->CmdBuffer[1] == 0x6f && TNC->CmdBuffer[2] == 0x31) - { - // Reject of XON/XOFF enable - -// TNC->XONXOFF = FALSE; -// Debugprintf("BPQ32 HAL Port %d - Disabling XON/XOFF mode", TNC->Port); - } - else - Debugprintf("HAL Port %d Command Error Cmd %X Error %X", TNC->Port, TNC->CmdBuffer[1], TNC->CmdBuffer[2]); - - Used = 3; - break; - - // Following are all immediate commands - response is echo of command - - case 0x6f: // XON/XOFF on - -// TNC->XONXOFF = TRUE; // And drop through -// Debugprintf("BPQ32 HAL Port %d - Enabling XON/XOFF mode", TNC->Port); - - case 0x19: // Call P-MODE to - case 0x10: // Robust Link to using MYCALL - case 0x11: // Normal Link to using MYCALL - - STREAM->Connecting = TRUE; - - case 0x00: // P Load LOD file - case 0x01: // P Load S28 file - case 0x02: //Check Unit Error Status - case 0x03: //F Check System Clock - case 0x04: //C Close PTT and transmit Clover waveform - case 0x05: //Open PTT and stop transmit test - case 0x06: //Immediate Abort (Panic Kill) - case 0x07: //Normal disconnect (wait for ACK) - case 0x08: //Software reset - restore all program defaults - case 0x0A: //Send CW ID - case 0x0B: //Close PTT and transmit Single Tone - case 0x0C: //F Normal OVER (AMTOR,P-MODE) - case 0x0D: //F Force RTTY TX (Baudot/ASCII) - case 0x0E: //F Go to RTTY RX (Baudot/ASCII) - case 0x0F: //Go to LOD/S28 file loader - case SetMYCALL: // Set MYCALL Response - - case 0x1E: // Set MYALTCALL Response - - case 0x41: - case 0x42: - case 0x46: - case 0x47: - case 0x48: - case 0x4d: - case 0x52: // Enable adaptive Clover format - case 0x54: // Enable adaptive Clover format - - case 0x56: // Expanded Link State Reports OFF/ON - case 0x57: // Clear buffers on disc - case 0x58: - case 0x59: - case 0x60: // Robust Mode Retries - case 0x61: // Normal Mode Retries - case 0x80: //Switch to CLOVER mode - case 0x81: //Select AMTOR Standby - case 0x82: //Select AMTOR FEC - case 0x83: //Select P-MODE Standby - case 0x84: //Switch to FSK modes - case 0x85: //Select Baudot - case 0x86: //Select ASCII - case 0x87: //Forced OVER (AMTOR, P-MODE) - case 0x88: //Forced END (AMTOR, P-MODE) - case 0x89: //Force LTRS shift - case 0x8A: //Force FIGS shift - case 0x8B: //Send MARK tone - case 0x8C: //Send SPACE tone - case 0x8D: //Send MARK/SPACE tones - case 0x8E: //Received first character on line - case 0x8F: //Close PTT only (no tones) - - case 0xC9: //Huffman Off/On - case 0xCC: - case 0xD9: //Close PTT only (no tones) - - case SetTones: - - Used = 1; - break; - - case 0x91: // ???? - -// if (Len < 2) return; // Wait for more - - Used = 1; - break; - - default: - - // We didn't recognise command, so don't know how long it is - disaster! - - Debugprintf("HAL Port %d Unrecognised Command %x", TNC->Port, Opcode); - TNC->CmdLen = 0; - - return; - } - - if (Used == Len) - { - // All used - most likely case - - TNC->CmdLen = 0; - return; - } - - // Move Command Down buffer, and reenter - - TNC->CmdLen -= Used; - - memmove(TNC->CmdBuffer, &TNC->CmdBuffer[Used], TNC->CmdLen); - - goto CmdLoop; - - -} - - -VOID HALDisconnected(struct TNCINFO * TNC) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - CloseLogfile(0); - CloseLogfile(1); - CloseLogfile(2); - - if ((STREAM->Connecting | STREAM->Connected) == 0) - { - // Not connected or Connecting. Probably response to going into Pactor Listen Mode - - return; - } - - if (STREAM->Connecting && STREAM->Disconnecting == FALSE) - { - UINT * buffptr; - - // Connect Failed - actually I think HAL uses another code for connect failed, but leave here for now - - buffptr = GetBuff(); - - if (buffptr) - { - buffptr[1] = sprintf((UCHAR *)&buffptr[2], "*** Failure with %s\r", STREAM->RemoteCall); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - } - - STREAM->Connecting = FALSE; - STREAM->Connected = FALSE; // In case! - STREAM->FramesQueued = 0; - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - return; - } - - // Connected, or Disconnecting - Release Session - - STREAM->Connecting = FALSE; - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->FramesQueued = 0; - - if (STREAM->Disconnecting == FALSE) - STREAM->ReportDISC = TRUE; // Tell Node - - STREAM->Disconnecting = FALSE; - - // Need to reset Pactor Call in case it was changed - - TNC->NeedPACTOR = 20; -} - -BOOL HALConnected(struct TNCINFO * TNC, char * Call) -{ - char Msg[80]; - UINT * buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - char CallCopy[80]; - - strcpy(CallCopy, Call); - strcat(CallCopy, " "); // Some routines expect 10 char calls - - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->BytesAcked = 0; - STREAM->ConnectTime = time(NULL); - - // Stop Scanner - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command(-1, Msg); - - ShowTraffic(TNC); - - TNC->DataMode = RXDATA; - - OpenLogfile(0); - OpenLogfile(1); - OpenLogfile(2); - - if (TNC->PortRecord->ATTACHEDSESSIONS[0] == 0) - { - // Incoming Connect - - ProcessIncommingConnect(TNC, CallCopy, 0, TRUE); - - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", STREAM->RemoteCall, TNC->NodeCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - if (TNC->CurrentMode != Clover) - SendCmd(TNC, "\x87", 1); // Changeover to ISS - - // If an autoconnect APPL is defined, send it - - if (TNC->ApplCmd) - { - buffptr = GetBuff(); - if (buffptr == 0) return TRUE; // No buffers, so ignore - - buffptr[1] = sprintf((UCHAR *)&buffptr[2], "%s\r", TNC->ApplCmd); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - - return TRUE; - } - - if (FULL_CTEXT && HFCTEXTLEN == 0) - { - EncodeAndSend(TNC, CTEXTMSG, CTEXTLEN); - WriteLogLine(2, CTEXTMSG, CTEXTLEN); - - STREAM->BytesTXed += CTEXTLEN; - } - return TRUE; - } - - // Connect Complete - - buffptr = GetBuff(); - if (buffptr == 0) return TRUE; // No buffers, so ignore - - buffptr[1] = sprintf((UCHAR *)&buffptr[2], "*** Connected to %s\r", Call);; - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - - STREAM->Connecting = FALSE; - STREAM->Connected = TRUE; // Subsequent data to data channel - - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound", TNC->NodeCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - UpdateMH(TNC, CallCopy, '+', 'O'); - - - return TRUE; -} - - -static VOID EncodeAndSend(struct TNCINFO * TNC, UCHAR * txbuffer, int Len) -{ - // Send A Packet With DLE Encoding Encoding - - TNC->TXLen = DLEEncode(txbuffer, TNC->TXBuffer, Len); - - WriteCommBlock(TNC); -} - -VOID SendCmd(struct TNCINFO * TNC, UCHAR * txbuffer, int Len) -{ - // Send A Packet With Command Encoding (preceed each with 0x80 - - int i,txptr=0; - UCHAR * outbuff = TNC->TXBuffer; - - for (i=0; iTXLen = txptr; - WriteCommBlock(TNC); -} - -int DLEEncode(UCHAR * inbuff, UCHAR * outbuff, int len) -{ - int i, txptr = 0; - UCHAR c; - - // Escape x80 and x81 with x81 - -// outbuff[0] = 0x80; -// outbuff[1] = 0x33; // Send data to modem - - for (i=0;iNeedPACTOR = 30; -} - - - - diff --git a/.svn/pristine/14/14b226e8aa8a9b46d989b00b887bcc82fd050d7a.svn-base b/.svn/pristine/14/14b226e8aa8a9b46d989b00b887bcc82fd050d7a.svn-base deleted file mode 100644 index 9ecc6b4..0000000 --- a/.svn/pristine/14/14b226e8aa8a9b46d989b00b887bcc82fd050d7a.svn-base +++ /dev/null @@ -1,706 +0,0 @@ -/* -Copyright 2001-2015 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 -*/ - -// -// DLL to provide BPQEther support for G8BPQ switch in a -// 32bit environment, -// -// Uses BPQ EXTERNAL interface -// -// Uses WINPACAP library - -// Version 1.0 December 2005 - -// Version 1.1 January 2006 -// -// Get config file location from Node (will check bpq directory) - -// Version 1.2 October 2006 - -// Write diagnostics to BPQ console window instead of STDOUT - -// Version 1.3 February 2008 - -// Changes for dynamic unload of bpq32.dll - -// Version 1.3.1 Spetmber 2010 - -// Add option to get config from bpq32.dll - - -#define _CRT_SECURE_NO_DEPRECATE - -#include - -//#include - -#include "CHeaders.h" -#include -#include "pcap.h" - -#include "../CommonSource/bpq32.h" - -//#include "packet32.h" -//#include "ntddndis.h" - -extern char * PortConfig[33]; - -typedef struct PCAPStruct -{ - pcap_t *adhandle; - UCHAR EthSource[6]; - UCHAR EthDest[6]; - short EtherType; - BOOL RLITX; - BOOL RLIRX; - BOOL Promiscuous; - int pcap_reopen_delay; - char Adapter[256]; - -} PCAPINFO, *PPCAPINFO ; - -PCAPINFO * PCAPInfo[32]; - -//PPCAPINFO PCAPInfo[16]={0}; - -UCHAR EthDest[7]={01,'B','P','Q',0,0}; - -char EtherType[10]="0x08FF"; - -//pcap_t *adhandle; - -struct tagMSG Msg; - -short udpport=0; - -extern UCHAR BPQDirectory[]; - -unsigned int OurInst = 0; - -HWND hWnd; -BOOL GotMsg; - -DWORD n; - -#ifdef WIN32 - -static HINSTANCE PcapDriver=0; - -typedef int (FAR *FARPROCX)(); - -int (FAR * pcap_sendpacketx)(); - -FARPROCX pcap_compilex; -FARPROCX pcap_setfilterx; -FARPROCX pcap_datalinkx; -FARPROCX pcap_next_exx; -FARPROCX pcap_geterrx; -pcap_t * (FAR * pcap_open_livex)(const char *, int, int, int, char *); - -static char Dllname[6]="wpcap"; - -FARPROCX GetAddress(char * Proc); - -#else - -#define pcap_compilex pcap_compile -#define pcap_open_livex pcap_open_live -#define pcap_setfilterx pcap_setfilter -#define pcap_datalinkx pcap_datalink -#define pcap_next_exx pcap_next_ex -#define pcap_geterrx pcap_geterr -#define pcap_sendpacketx pcap_sendpacket -#endif - -int InitPCAP(void); -static FARPROCX GetAddress(char * Proc); - -static BOOL ReadConfigFile(int Port); -static int ProcessLine(char * buf,int Port, BOOL CheckPort); -static int OpenPCAP(PPCAPINFO PCAP); - - -int ExtProc(int fn, int port,unsigned char * buff) -{ - int len,txlen=0,res; - char txbuff[500]; - struct pcap_pkthdr *header; - u_char *pkt_data; - PPCAPINFO PCAP = PCAPInfo[port]; - - // char dcall[10],scall[10]; - - if (PCAP->adhandle == 0) - { - // No handle. - - if (PCAP->Adapter[0]) - { - // Try reopening periodically - - PCAP->pcap_reopen_delay --; - - if (PCAP->pcap_reopen_delay < 0) - if (OpenPCAP(PCAP) == FALSE) - PCAP->pcap_reopen_delay = 300; // Retry every 30 seconds - } - return 0; - } - switch (fn) - { - case 1: // poll - - res = pcap_next_exx(PCAP->adhandle, &header, &pkt_data); - - if (res == 0) - /* Timeout elapsed */ - return 0; - - if (res == -1) - { - // Failed - try to reopen - - if (OpenPCAP(PCAP) == FALSE) - PCAP->pcap_reopen_delay = 300; - return 0; - } - - if (PCAP->RLIRX) - - // RLI MODE - An extra 3 bytes before len, seem to be 00 00 41 - - { - len=pkt_data[18]*256 + pkt_data[17]; - - if ((len < 16) || (len > 320)) return 0; // Probably BPQ Mode Frame - - len-=3; - - memcpy(&buff[7],&pkt_data[19],len); - - len+=5; - } - else - { - len=pkt_data[15]*256 + pkt_data[14]; - - if ((len < 16) || (len > 320)) return 0; // Probably RLI Mode Frame - - len-=3; - - memcpy(&buff[7],&pkt_data[16],len); - - len+=5; - } - - buff[5]=(len & 0xff); - buff[6]=(len >> 8); - - return 1; - - - case 2: // send - - if (PCAP->RLITX) - - // RLI MODE - An extra 3 bytes before len, seem to be 00 00 41 - - { - txlen=(buff[6]<<8) + buff[5]; // BPQEther is DOS-based - chain word is 2 bytes - - txlen-=2; - txbuff[16]=0x41; - txbuff[17]=(txlen & 0xff); - txbuff[18]=(txlen >> 8); - - if (txlen < 1 || txlen > 400) - return 0; - - memcpy(&txbuff[19],&buff[7],txlen); - - } - else - { - txlen=(buff[6]<<8) + buff[5]; // BPQEther is DOS-based - chain word is 2 bytes - - txlen-=2; - - txbuff[14]=(txlen & 0xff); - txbuff[15]=(txlen >> 8); - - if (txlen < 1 || txlen > 400) - return 0; - - - memcpy(&txbuff[16],&buff[7],txlen); - } - - memcpy(&txbuff[0],&PCAP->EthDest[0],6); - memcpy(&txbuff[6],&PCAP->EthSource[0],6); - memcpy(&txbuff[12],&PCAP->EtherType,2); - - txlen+=14; - - - if (txlen < 60) txlen = 60; - - // Send down the packet - - if (pcap_sendpacketx(PCAP->adhandle, // Adapter - txbuff, // buffer with the packet - txlen // size - ) != 0) - { - - // n=sprintf(buf,"\nError sending the packet: \n", pcap_geterrx(PCAPInfo[port].adhandle)); - // WritetoConsole(buf); - - return 3; - } - - - return (0); - - - case 3: // CHECK IF OK TO SEND - - return (0); // OK - - case 4: // reinit - - return 0; - - case 5: // reinit - - return 0; - } - - return (0); -} - - -UINT ETHERExtInit(struct PORTCONTROL * PortEntry) -{ - // Can have multiple ports, each mapping to a different Ethernet Adapter - - // The Adapter number is in IOADDR - - int Port = PortEntry->PORTNUMBER; - PPCAPINFO PCAP; - char buf[80]; - - if (InitPCAP()) // Make sure pcap is installed - { - WritetoConsole("BPQEther "); - - // - // Read config first, to get UDP info if needed - // - - PCAP = PCAPInfo[Port] = zalloc(sizeof(struct PCAPStruct)); - - if (!ReadConfigFile(Port)) - return (FALSE); - - if (OpenPCAP(PCAP)) - sprintf(buf,"Using %s\n", PCAP->Adapter); - else - sprintf(buf,"Failed to open %s\n", PCAP->Adapter); - - WritetoConsole(buf); - } - return ((int) ExtProc); -} - - -InitPCAP() -{ - char Msg[255]; - int err; - u_long param=1; - BOOL bcopt=TRUE; - -// Use LoadLibrary/GetProcADDR to get round link problem - -#ifndef WIN32 - - return TRUE; - -#endif - - if (PcapDriver) - return TRUE; // Already loaded - - PcapDriver=LoadLibrary(Dllname); - - if (PcapDriver == NULL) - { - err=GetLastError(); - sprintf(Msg,"Error loading Driver %s - Error code %d", Dllname,err); - WritetoConsole(Msg); - return(FALSE); - } - - if ((pcap_sendpacketx=GetAddress("pcap_sendpacket")) == 0 ) return FALSE; - - if ((pcap_datalinkx=GetAddress("pcap_datalink")) == 0 ) return FALSE; - - if ((pcap_compilex=GetAddress("pcap_compile")) == 0 ) return FALSE; - - if ((pcap_setfilterx=GetAddress("pcap_setfilter")) == 0 ) return FALSE; - - if ((pcap_open_livex = (pcap_t * (__cdecl *)()) - GetProcAddress(PcapDriver,"pcap_open_live")) == 0 ) return FALSE; - - if ((pcap_geterrx=GetAddress("pcap_geterr")) == 0 ) return FALSE; - - if ((pcap_next_exx=GetAddress("pcap_next_ex")) == 0 ) return FALSE; - - return (TRUE); -} - -#ifdef WIN32 - -FARPROCX GetAddress(char * Proc) -{ - FARPROCX ProcAddr; - int err=0; - char buf[256]; - int n; - - - ProcAddr=(FARPROCX) GetProcAddress(PcapDriver,Proc); - - if (ProcAddr == 0) - { - err=GetLastError(); - - n=sprintf(buf,"Error finding %s - %d\n", Proc,err); - WritetoConsole(buf); - - return(0); - } - - return ProcAddr; -} -#endif - -#include - -#pragma comment(lib, "IPHLPAPI.lib") - -void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); - -int OpenPCAP(PPCAPINFO PCAP) -{ - int i=0; - char errbuf[PCAP_ERRBUF_SIZE]; - u_int netmask; - char packet_filter[30]; - struct bpf_program fcode; - char buf[256]; - int n; - - /* Open the adapter */ - if ((PCAP->adhandle= pcap_open_livex(PCAP->Adapter, // name of the device - 65536, // portion of the packet to capture. - // 65536 grants that the whole packet will be captured on all the MACs. - PCAP->Promiscuous, // promiscuous mode (nonzero means promiscuous) - 1, // read timeout - errbuf // error buffer - )) == NULL) - { - return FALSE; - } - - /* Check the link layer. We support only Ethernet for simplicity. */ - if(pcap_datalinkx(PCAP->adhandle) != DLT_EN10MB) - { - n=sprintf(buf,"This program works only on Ethernet networks.\n"); - WritetoConsole(buf); - - return FALSE; - } - - netmask=0xffffff; - - sprintf(packet_filter,"ether[12:2]=0x%x", - ntohs(PCAP->EtherType)); - - //compile the filter - if (pcap_compilex(PCAP->adhandle, &fcode, packet_filter, 1, netmask) <0 ) - { - n=sprintf(buf,"Unable to compile the packet filter. Check the syntax.\n"); - WritetoConsole(buf); - - /* Free the device list */ - return FALSE; - } - - //set the filter - - if (pcap_setfilterx(PCAP->adhandle, &fcode)<0) - { - n=sprintf(buf,"Error setting the filter.\n"); - WritetoConsole(buf); - - /* Free the device list */ - return FALSE; - } - - return TRUE; - -} - - -static BOOL ReadConfigFile(int Port) -{ -//TYPE 1 08FF # Ethernet Type -//ETH 1 FF:FF:FF:FF:FF:FF # Target Ethernet AddrMAP G8BPQ-7 10.2.77.1 # IP 93 for compatibility -//ADAPTER 1 \Device\NPF_{21B601E8-8088-4F7D-96 29-EDE2A9243CF4} # Adapter Name - - char buf[256],errbuf[256]; - char * Config; - PPCAPINFO PCAP = PCAPInfo[Port]; - - Config = PortConfig[Port]; - - PCAP->Promiscuous = 1; // Defaults - PCAP->EtherType=htons(0x08FF); - memset(PCAP->EthDest, 0xff, 6); - - if (Config) - { - // Using config from bpq32.cfg - - char * ptr1 = Config, * ptr2; - - 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 (!ProcessLine(buf, Port, FALSE)) - { - WritetoConsole("BPQEther - Bad config record "); - WritetoConsole(errbuf); - WritetoConsole("\n"); - } - } - return (TRUE); - } - - n=sprintf(buf,"No config info found in bpq32.cfg\n"); - WritetoConsole(buf); - - return (FALSE); -} - - -static int ProcessLine(char * buf, int Port, BOOL CheckPort) -{ - char * ptr; - char * p_port; - char * p_mac; - char * p_Adapter; - char * p_type; - - int port; - int a,b,c,d,e,f,num; - - PPCAPINFO PCAP = PCAPInfo[Port]; - - ptr = strtok(buf, " \t\n\r"); - - if(ptr == NULL) return (TRUE); - - if(*ptr =='#') return (TRUE); // comment - - if(*ptr ==';') return (TRUE); // comment - - if (CheckPort) - { - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - port = atoi(p_port); - - if (Port != port) return TRUE; // Not for us - } - - if(_stricmp(ptr,"ADAPTER") == 0) - { - IP_ADAPTER_INFO AdapterInfo[16]; // Allocate information for up to 16 NICs - DWORD dwBufLen = sizeof(AdapterInfo); // Save memory size of buffer - DWORD dwStatus = GetAdaptersInfo(AdapterInfo, &dwBufLen); - - PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo; - - p_Adapter = strtok(NULL, " \t\n\r"); - - strcpy(PCAP->Adapter, p_Adapter); - - // Look for MAC Address - - do - { - if (strcmp(pAdapterInfo->AdapterName, &PCAP->Adapter[12]) == 0) - { - memcpy(PCAP->EthSource, pAdapterInfo->Address, 6); - break; - } - - pAdapterInfo = pAdapterInfo->Next; // Progress through linked list - - } while(pAdapterInfo); // Terminate if last adapter - - return (TRUE); - } - - if(_stricmp(ptr,"TYPE") == 0) - { - p_type = strtok(NULL, " \t\n\r"); - - if (p_type == NULL) return (FALSE); - - num=sscanf(p_type,"%x",&a); - - if (num != 1) return FALSE; - - PCAP->EtherType=htons(a); - return (TRUE); - - } - - if(_stricmp(ptr,"promiscuous") == 0) - { - ptr = strtok(NULL, " \t\n\r"); - - if (ptr == NULL) return (FALSE); - - PCAP->Promiscuous = atoi(ptr); - - return (TRUE); - - } - - if(_stricmp(ptr,"RXMODE") == 0) - { - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - if(_stricmp(p_port,"RLI") == 0) - { - PCAP->RLIRX=TRUE; - return (TRUE); - } - - if(_stricmp(p_port,"BPQ") == 0) - { - PCAP->RLIRX=FALSE; - return (TRUE); - } - - return FALSE; - - } - - if(_stricmp(ptr,"TXMODE") == 0) - { - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - if(_stricmp(p_port,"RLI") == 0) - { - PCAP->RLITX=TRUE; - return (TRUE); - } - - if(_stricmp(p_port,"BPQ") == 0) - { - PCAP->RLITX=FALSE; - return (TRUE); - } - - return FALSE; - - } - - if(_stricmp(ptr,"DEST") == 0) - { - p_mac = strtok(NULL, " \t\n\r"); - - if (p_mac == NULL) return (FALSE); - - num=sscanf(p_mac,"%x-%x-%x-%x-%x-%x",&a,&b,&c,&d,&e,&f); - - if (num != 6) return FALSE; - - PCAP->EthDest[0]=a; - PCAP->EthDest[1]=b; - PCAP->EthDest[2]=c; - PCAP->EthDest[3]=d; - PCAP->EthDest[4]=e; - PCAP->EthDest[5]=f; - - - // strcpy(Adapter,p_Adapter); - - return (TRUE); - } - - if(_stricmp(ptr,"SOURCE") == 0) - { - p_mac = strtok(NULL, " \t\n\r"); - - if (p_mac == NULL) return (FALSE); - - num=sscanf(p_mac,"%x-%x-%x-%x-%x-%x",&a,&b,&c,&d,&e,&f); - - if (num != 6) return FALSE; - - PCAP->EthSource[0]=a; - PCAP->EthSource[1]=b; - PCAP->EthSource[2]=c; - PCAP->EthSource[3]=d; - PCAP->EthSource[4]=e; - PCAP->EthSource[5]=f; - - // strcpy(Adapter,p_Adapter); - - return (TRUE); - - } - // - // Bad line - // - return (FALSE); - -} - - - diff --git a/.svn/pristine/15/151b9ce04ab29bd13f02a3d71b7d4be4b771493b.svn-base b/.svn/pristine/15/151b9ce04ab29bd13f02a3d71b7d4be4b771493b.svn-base deleted file mode 100644 index 2a3d766..0000000 --- a/.svn/pristine/15/151b9ce04ab29bd13f02a3d71b7d4be4b771493b.svn-base +++ /dev/null @@ -1,3137 +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 -*/ - -// -// DLL to provide interface to allow G8BPQ switch to use WINMOR as a Port Driver -// -// Uses BPQ EXTERNAL interface -// - - -// Version 1.0 January 2009 - Initial Version -// - -// March 22 2010 - -// Send FAULTS to Monitor Window -// Force PROTOCOL = WINMOR/PACTOR (to simplifiy Config) - -// July 2010 -// Support up to 32 BPQ Ports -// Support up to 32 Applications - -// Version 1.2.1.2 August 2010 - -// Save Minimized State -// Handle new "BLOCKED by Busy channel" message from TNC - -// Version 1.2.1.4 August 2010 - -// Add Scan control of BW setting -// Reset TNC if stuck in Disconnecting -// Add option to send reports to WL2K -// Disconnect if appl not available - -// Version 1.2.1.5 August 2010 - -// Updates to WL2K Reporting -// Send Watchdog polls every minute and restart if no response. -// Don't connect if channel is busy (unless specifically overridden) - -// Version 1.2.1.6 September 2010 - -// Add option to kill and restart TNC after each transfer -// Fix PTT operation after Node reconfig - -// Version 1.2.2.1 September 2010 - -// Add option to get config from bpq32.cfg -// Merge with BPQ32.dll - - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include - -#include "cheaders.h" - -#ifdef WIN32 -#include -#endif - -extern int (WINAPI FAR *GetModuleFileNameExPtr)(); -extern int (WINAPI FAR *EnumProcessesPtr)(); - - -#define SD_RECEIVE 0x00 -#define SD_SEND 0x01 -#define SD_BOTH 0x02 - -#include "bpq32.h" - -#include "tncinfo.h" - - -#define WSA_ACCEPT WM_USER + 1 -#define WSA_DATA WM_USER + 2 -#define WSA_CONNECT WM_USER + 3 - -static int Socket_Data(int sock, int error, int eventcode); - -int KillTNC(struct TNCINFO * TNC); -int RestartTNC(struct TNCINFO * TNC); -int KillPopups(struct TNCINFO * TNC); -VOID MoveWindows(struct TNCINFO * TNC); -int SendReporttoWL2K(struct TNCINFO * TNC); -char * CheckAppl(struct TNCINFO * TNC, char * Appl); -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); -BOOL KillOldTNC(char * Path); -int standardParams(struct TNCINFO * TNC, char * buf); - -static char ClassName[]="WINMORSTATUS"; -static char WindowTitle[] = "WINMOR"; -static int RigControlRow = 165; - -#define WINMOR -#define NARROWMODE 21 -#define WIDEMODE 22 - -#ifndef LINBPQ -#include -#endif - -extern int SemHeldByAPI; - -static RECT Rect; - -static int ProcessLine(char * buf, int Port); - -// RIGCONTROL COM60 19200 ICOM IC706 5e 4 14.103/U1w 14.112/u1 18.1/U1n 10.12/l1 - -// There seem to be timing issues when calling SendMessage from multiple threads. -// Queue and process in main thread - -UINT * WINMORTraceQ; -UINT * SetWindowTextQ; - -VOID WritetoTraceSupport(struct TNCINFO * TNC, char * Msg, int Len) -{ - int index = 0; - UCHAR * ptr1 = Msg, * ptr2; - UCHAR Line[1000]; - int LineLen, i; - UCHAR Save; - int SaveLen = Len; - char Time[16]; - time_t T; - struct tm * tm; - - if (Len < 0) - return; - - Save = Msg[Len]; - Msg[Len] = 0; - -#ifndef LINBPQ - index=SendMessage(TNC->hMonitor, LB_SETCURSEL, -1, 0); -#endif - -lineloop: - - if (Len > 0) - { - // copy text to control a line at a time - - ptr2 = memchr(ptr1, 13, Len); - - if (ptr2) - { - ptr2++; - LineLen = (int)(ptr2 - ptr1); - Len -= LineLen; - 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] > 126 || Line[i] < 32) - goto Skip; - } - - // We now also pass to Monitor Window - - if (strlen(Line) < 250) - { - MESSAGE Monframe; - memset(&Monframe, 0, sizeof(Monframe)); - - Monframe.PORT = TNC->Port; - Monframe.LENGTH = 12 + strlen(Line); - Monframe.DEST[0] = 1; // Plain Text Monitor - strcpy(&Monframe.DEST[1], Line); - - time(&Monframe.Timestamp); - BPQTRACE((MESSAGE *)&Monframe, FALSE); - } - -#ifdef LINBPQ -#else - index=SendMessage(TNC->hMonitor, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR) Line); -#endif - // Write to Web Buffer - - T = time(NULL); - tm = gmtime(&T); - - sprintf_s(Time, sizeof(Time),"%02d:%02d ", tm->tm_hour, tm->tm_min); - - strcat(TNC->WebBuffer, Time); - strcat(TNC->WebBuffer, Line); - strcat(TNC->WebBuffer, "\r\n"); - if (strlen(TNC->WebBuffer) > 4500) - memmove(TNC->WebBuffer, &TNC->WebBuffer[500], strlen(&TNC->WebBuffer[500]) + 1); // Make sure null is moved - Skip: - ptr1 = ptr2; - - goto lineloop; - - } - - // Process incomplete line - - for (i = 0; i < Len; i++) - { - if (ptr1[i] > 126 || ptr1[i] < 32) - break; - } - - if (i == Len) - { - if (Len < 250) - { - MESSAGE Monframe; - memset(&Monframe, 0, sizeof(Monframe)); - - Monframe.PORT = TNC->Port; - Monframe.LENGTH = 12 + Len; - Monframe.DEST[0] = 1; // Plain Text Monitor - - memcpy(&Monframe.DEST[1], ptr1, Len); - Monframe.DEST[1 + Len] = 0; - - time(&Monframe.Timestamp); - BPQTRACE((MESSAGE *)&Monframe, FALSE); - } - - -#ifdef LINBPQ -#else - index=SendMessage(TNC->hMonitor, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR) ptr1 ); -#endif - T = time(NULL); - tm = gmtime(&T); - - sprintf_s(Time, sizeof(Time),"%02d:%02d ", tm->tm_hour, tm->tm_min); - strcat(TNC->WebBuffer, Time); - - strcat(TNC->WebBuffer, ptr1); - strcat(TNC->WebBuffer, "\r\n"); - if (strlen(TNC->WebBuffer) > 4500) - memmove(TNC->WebBuffer, &TNC->WebBuffer[500], strlen(&TNC->WebBuffer[500]) + 1); // Make sure null is moved - } - } - -#ifdef LINBPQ -#else - - if (index > 1200) - do - index=index=SendMessage(TNC->hMonitor, LB_DELETESTRING, 0, 0); - while (index > 1000); - - if (index > -1) - index=SendMessage(TNC->hMonitor, LB_SETCARETINDEX,(WPARAM) index, MAKELPARAM(FALSE, 0)); -#endif - Msg[SaveLen] = Save; - -} - -VOID MySetWindowTextWithSem(HWND hWnd, char * Msg) -{ -#ifndef LINBPQ - - PMSGWITHLEN buffptr; - - buffptr = GetBuff(); - - if (buffptr) - { - buffptr->Len= (UINT)hWnd; - memcpy(&buffptr->Data[0], Msg, strlen(Msg) + 1); - - C_Q_ADD(&SetWindowTextQ, buffptr); - } - -#endif -} - -int C_Q_ADD_NP(VOID *PQ, VOID *PBUFF); - -struct SEM SetWindTextSem = {0, 0, 0, 0}; - -VOID MySetWindowText(HWND hWnd, char * Msg) -{ -#ifndef LINBPQ - - PMSGWITHLEN buffptr; - - GetSemaphore(&SetWindTextSem, 61); - buffptr = zalloc(400); - - if (buffptr) - { - buffptr->Len= (UINT)hWnd; - memcpy(&buffptr->Data[0], Msg, strlen(Msg) + 1); - - C_Q_ADD_NP(&SetWindowTextQ, buffptr); - } - - FreeSemaphore(&SetWindTextSem); -#endif -} - -VOID SetWindowTextSupport() -{ - PMSGWITHLEN Buffer; - - while (SetWindowTextQ) - { - GetSemaphore(&SetWindTextSem, 61); - Buffer = Q_REM_NP(&SetWindowTextQ); - SetWindowText((HWND)Buffer->Len, Buffer->Data); - FreeSemaphore(&SetWindTextSem); - free(Buffer); - } -} - - -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len) -{ - // It seems writing from multiple threads can cause problems in Windows - // Queue and process in main thread - -#ifdef LINBPQ - WritetoTraceSupport(TNC, Msg, Len); -} -#else - UINT * buffptr; - BOOL Sem = FALSE; - - if (Len < 0) - return; - - // Get semaphore if it isn't set - - if (InterlockedExchange(&Semaphore.Flag, 1) == 0) - { - Sem = TRUE; - Semaphore.Gets++; - } - - buffptr = GetBuff(); - - if (buffptr) - { - if (Len > 340) - Len = 340; - - buffptr[1] = (UINT)TNC; - buffptr[2] = (UINT)Len; - memcpy(&buffptr[3], Msg, Len + 1); - - C_Q_ADD(&WINMORTraceQ, buffptr); - } - - if (Sem) - FreeSemaphore(&Semaphore); - -} -#endif - -static int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC; - char errbuf[256]; - - strcpy(errbuf, buf); - - ptr = strtok(buf, " \t\n\r"); - - if(ptr == NULL) return (TRUE); - - if(*ptr =='#') return (TRUE); // comment - - if(*ptr ==';') return (TRUE); // comment - - if (_stricmp(buf, "ADDR")) - return FALSE; // Must start with ADDR - - ptr = strtok(NULL, " \t\n\r"); - - BPQport = Port; - p_ipad = ptr; - - TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); - memset(TNC, 0, sizeof(struct TNCINFO)); - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - if (p_ipad == NULL) - p_ipad = strtok(NULL, " \t\n\r"); - - if (p_ipad == NULL) return (FALSE); - - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - WINMORport = atoi(p_port); - - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(WINMORport); - TNC->Datadestaddr.sin_family = AF_INET; - TNC->Datadestaddr.sin_port = htons(WINMORport+1); - - TNC->HostName = malloc(strlen(p_ipad)+1); - - if (TNC->HostName == NULL) return TRUE; - - strcpy(TNC->HostName,p_ipad); - - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - DecodePTTString(TNC, ptr); - ptr = strtok(NULL, " \t\n\r"); - } - } - } - - if (ptr) - { - if (_memicmp(ptr, "PATH", 4) == 0) - { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); - } - } - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if ((_memicmp(buf, "CAPTURE", 7) == 0) || (_memicmp(buf, "PLAYBACK", 8) == 0)) - {} // Ignore - else -/* - if (_memicmp(buf, "PATH", 4) == 0) - { - char * Context; - p_cmd = strtok_s(&buf[5], "\n\r", &Context); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); - } - else -*/ - if (_memicmp(buf, "STARTINROBUST", 13) == 0) - TNC->StartInRobust = TRUE; - - else - if (_memicmp(buf, "ROBUST", 6) == 0) - { - if (_memicmp(&buf[7], "TRUE", 4) == 0) - TNC->Robust = TRUE; - - strcat (TNC->InitScript, buf); - } - else if (standardParams(TNC, buf) == FALSE) - strcat (TNC->InitScript, buf); - } - - - return (TRUE); -} - - - -void WINMORThread(void * portptr); -VOID ProcessDataSocketData(int port); -int ConnecttoWINMOR(int port); -static int ProcessReceivedData(struct TNCINFO * TNC); -int V4ProcessReceivedData(struct TNCINFO * TNC); -VOID ReleaseTNC(struct TNCINFO * TNC); -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - -static time_t ltime; - - -static SOCKADDR_IN sinx; -static SOCKADDR_IN rxaddr; - -static int addrlen=sizeof(sinx); - - - -VOID ChangeMYC(struct TNCINFO * TNC, char * Call) -{ - UCHAR TXMsg[100]; - int datalen; - - if (strcmp(Call, TNC->CurrentMYC) == 0) - return; // No Change - - strcpy(TNC->CurrentMYC, Call); - -// send(TNC->TCPSock, "CODEC FALSE\r\n", 13, 0); - - datalen = sprintf(TXMsg, "MYC %s\r\n", Call); - send(TNC->TCPSock,TXMsg, datalen, 0); - -// send(TNC->TCPSock, "CODEC TRUE\r\n", 12, 0); -// TNC->StartSent = TRUE; - - send(TNC->TCPSock, "MYC\r\n", 5, 0); -} - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - int i,winerr; - size_t datalen; - PMSGWITHLEN buffptr; - char txbuff[500]; - unsigned int bytes; - size_t txlen = 0; - char ErrMsg[255]; - size_t Param; - HKEY hKey=0; - struct TNCINFO * TNC = TNCInfo[port]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct ScanEntry * Scan; - fd_set readfs; - fd_set writefs; - fd_set errorfs; - struct timeval timeout; - - if (TNC == NULL) - return 0; // Port not defined - - switch (fn) - { - case 1: // poll - - // Check session limit timer - - if ((STREAM->Connecting || STREAM->Connected) && !STREAM->Disconnecting) - { - if (TNC->SessionTimeLimit && STREAM->ConnectTime && time(NULL) > (TNC->SessionTimeLimit + STREAM->ConnectTime)) - { - send(TNC->TCPSock,"DISCONNECT\r\n", 12, 0); - STREAM->Disconnecting = TRUE; - } - } - - while (TNC->PortRecord->UI_Q) // Release anything accidentally put on UI_Q - { - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - ReleaseBuffer(buffptr); - } - - - if (TNC->Busy) // Count down to clear - { - if ((TNC->BusyFlags & CDBusy) == 0) // TNC Has reported not busy - { - TNC->Busy--; - if (TNC->Busy == 0) - SetWindowText(TNC->xIDC_CHANSTATE, "Clear"); - strcpy(TNC->WEB_CHANSTATE, "Clear"); - } - } - - if (TNC->ConnectCmd && TNC->BusyDelay) - { - // Still Busy? - - if (InterlockedCheckBusy(TNC) == FALSE) - { - // No, so send - - send(TNC->TCPSock, TNC->ConnectCmd, (int)strlen(TNC->ConnectCmd), 0); - TNC->Streams[0].Connecting = TRUE; - - memset(TNC->Streams[0].RemoteCall, 0, 10); - memcpy(TNC->Streams[0].RemoteCall, &TNC->ConnectCmd[8], strlen(TNC->ConnectCmd)-10); - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - free(TNC->ConnectCmd); - TNC->ConnectCmd = 0; - - TNC->BusyDelay = 0; - } - else - { - // Wait Longer - - TNC->BusyDelay--; - - if (TNC->BusyDelay == 0) - { - // Timed out - Send Error Response - - PMSGWITHLEN buffptr = GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = 39; - memcpy(buffptr->Data,"Sorry, Can't Connect - Channel is busy\r", 39); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - free(TNC->ConnectCmd); - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", TNC->Streams[0].MyCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - } - } - } - - if (TNC->HeartBeat++ > 600 || (TNC->Streams[0].Connected && TNC->HeartBeat > 50)) // Every Minute unless connected - { - if (TNC->HeartBeat > 600 && TNC->hWnd) - { - char wtext[100]; - sprintf (wtext, "WINMOR Sound Card TNC - BPQ %s", TNC->PortRecord->PORTCONTROL.PORTDESCRIPTION); - MySetWindowText(TNC->hWnd, wtext); - } - - TNC->HeartBeat = 0; - - if (TNC->CONNECTED) - { - // Probe link - - if (TNC->Streams[0].Connecting || TNC->Streams[0].Connected) - send(TNC->TCPSock, "MODE\r\n", 6, 0); - else - { - if (time(NULL) - TNC->WinmorRestartCodecTimer > 900) // 15 mins - { - send(TNC->TCPSock, "CODEC FALSE\r\n", 13, 0); - send(TNC->TCPSock, "CODEC TRUE\r\n", 12, 0); - } - else - send(TNC->TCPSock, "STATE\r\n", 7, 0); - } - } - } - - if (TNC->FECMode) - { - if (TNC->FECIDTimer++ > 6000) // ID every 10 Mins - { - if (!TNC->Busy) - { - TNC->FECIDTimer = 0; - send(TNC->TCPSock, "SENDID 0\r\n", 10, 0); - } - } - if (TNC->FECPending) // Check if FEC Send needed - { - if (!TNC->Busy) - { - TNC->FECPending = 0; - - if (TNC->FEC1600) - send(TNC->TCPSock,"FECSEND 1600\r\n", 14, 0); - else - send(TNC->TCPSock,"FECSEND 500\r\n", 13, 0); - } - } - } - - if (STREAM->NeedDisc) - { - STREAM->NeedDisc--; - - if (STREAM->NeedDisc == 0) - { - // Send the DISCONNECT - - send(TNC->TCPSock, "DISCONNECT\r\n", 12, 0); - } - } - - if (TNC->DiscPending) - { - TNC->DiscPending--; - - if (TNC->DiscPending == 0) - { - // Too long in Disc Pending - Kill and Restart TNC - - if (TNC->PID) - { - KillTNC(TNC); - RestartTNC(TNC); - } - } - } - - if (TNC->TimeSinceLast++ > 800) // Allow 10 secs for Keepalive - { - // Restart TNC - - if (TNC->ProgramPath && TNC->CONNECTED) - { - if (strstr(TNC->ProgramPath, "WINMOR TNC")) - { - struct tm * tm; - char Time[80]; - - TNC->Restarts++; - TNC->LastRestart = time(NULL); - - tm = gmtime(&TNC->LastRestart); - - sprintf_s(Time, sizeof(Time),"%04d/%02d/%02d %02d:%02dZ", - tm->tm_year +1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); - - SetWindowText(TNC->xIDC_RESTARTTIME, Time); - strcpy(TNC->WEB_RESTARTTIME, Time); - - sprintf_s(Time, sizeof(Time),"%d", TNC->Restarts); - SetWindowText(TNC->xIDC_RESTARTS, Time); - strcpy(TNC->WEB_RESTARTS, Time); - - KillTNC(TNC); - RestartTNC(TNC); - - TNC->TimeSinceLast = 0; - } - } - } - - if (TNC->PortRecord->ATTACHEDSESSIONS[0] && TNC->Streams[0].Attached == 0) - { - // New Attach - - int calllen; - char Msg[80]; - - TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit - - TNC->Streams[0].Attached = TRUE; - - calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4USER, TNC->Streams[0].MyCall); - TNC->Streams[0].MyCall[calllen] = 0; - - // Stop Listening, and set MYCALL to user's call - - send(TNC->TCPSock, "LISTEN FALSE\r\n", 14, 0); - ChangeMYC(TNC, TNC->Streams[0].MyCall); - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", TNC->Streams[0].MyCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Stop Scanning - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command( (TRANSPORTENTRY *) -1, Msg); - - } - - if (TNC->Streams[0].Attached) - CheckForDetach(TNC, 0, &TNC->Streams[0], TidyClose, ForcedClose, CloseComplete); - - if (TNC->Streams[0].ReportDISC) - { - TNC->Streams[0].ReportDISC = FALSE; - buff->PORT = 0; - return -1; - } - - - - if (TNC->CONNECTED == FALSE && TNC->CONNECTING == FALSE) - { - // See if time to reconnect - - time(<ime); - if (ltime - TNC->lasttime > 9 ) - { - ConnecttoWINMOR(port); - TNC->lasttime = ltime; - } - } - - FD_ZERO(&readfs); - - if (TNC->CONNECTED) FD_SET(TNC->TCPDataSock,&readfs); - - FD_ZERO(&writefs); - - if (TNC->BPQtoWINMOR_Q) FD_SET(TNC->TCPDataSock,&writefs); // Need notification of busy clearing - - FD_ZERO(&errorfs); - - if (TNC->CONNECTING || TNC->CONNECTED) FD_SET(TNC->TCPDataSock,&errorfs); - - timeout.tv_sec = 0; - timeout.tv_usec = 0; // poll - - if (select((int)TNC->TCPDataSock + 1, &readfs, &writefs, &errorfs, &timeout) > 0) - { - // See what happened - - if (FD_ISSET(TNC->TCPDataSock, &readfs)) - ProcessDataSocketData(port); - - if (FD_ISSET(TNC->TCPDataSock, &writefs)) - { - // Write block has cleared. Send rest of packet - - buffptr=Q_REM(&TNC->BPQtoWINMOR_Q); - txlen = buffptr->Len; - memcpy(txbuff,buffptr->Data,txlen); - bytes=send(TNC->TCPSock, (const char FAR *)&txbuff, (int)txlen, 0); - ReleaseBuffer(buffptr); - } - - if (FD_ISSET(TNC->TCPDataSock, &errorfs)) - { - i=sprintf(ErrMsg, "WINMOR Data Connection lost for BPQ Port %d\r\n", port); - WritetoConsole(ErrMsg); - TNC->CONNECTING = FALSE; - TNC->CONNECTED = FALSE; - TNC->Streams[0].ReportDISC = TRUE; - } - } - - // See if any frames for this port - - if (TNC->WINMORtoBPQ_Q != 0) - { - buffptr=Q_REM(&TNC->WINMORtoBPQ_Q); - - datalen = buffptr->Len; - - buff->PORT = 0; // Compatibility with Kam Driver - buff->PID = 0xf0; - memcpy(&buff->L2DATA[0], buffptr->Data, datalen); // Data goes to +7, but we have an extra byte - datalen = buffptr->Len; - - datalen += sizeof(void *) + 4; - PutLengthinBuffer(buff, (int)datalen); - - ReleaseBuffer(buffptr); - - return (1); - } - - return (0); - - case 2: // send - - if (!TNC->CONNECTED) - { - // Send Error Response - - PMSGWITHLEN buffptr = GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = 36; - memcpy(buffptr->Data, "No Connection to WINMOR Virtual TNC\r", 36); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - return 0; // Don't try if not connected - } - - if (TNC->Streams[0].BPQtoPACTOR_Q) //Used for CTEXT - { - PMSGWITHLEN buffptr = Q_REM(&TNC->Streams[0].BPQtoPACTOR_Q); - txlen = buffptr->Len; - memcpy(txbuff, buffptr->Data, txlen); - bytes = send(TNC->TCPDataSock, txbuff, (int)txlen, 0); - STREAM->bytesTXed += bytes; - WritetoTrace(TNC, txbuff, (int)txlen); - ReleaseBuffer(buffptr); - } - - if (TNC->SwallowSignon) - { - TNC->SwallowSignon = FALSE; // Discard *** connected - return 0; - } - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - - if (TNC->Streams[0].Connected) - { - STREAM->PacketsSent++; - - if (STREAM->PacketsSent == 3) - { - if (TNC->Robust) - send(TNC->TCPSock, "ROBUST TRUE\r\n", 13, 0); - else - send(TNC->TCPSock, "ROBUST FALSE\r\n", 14, 0); - } - - bytes = send(TNC->TCPDataSock,buff->L2DATA, (int)txlen, 0); - STREAM->bytesTXed += bytes; - WritetoTrace(TNC, &buff->L2DATA[0], (int)txlen); - - } - else - { - if (_memicmp(buff->L2DATA, "D\r", 2) == 0) - { - TNC->Streams[0].ReportDISC = TRUE; // Tell Node - return 0; - } - - if (TNC->FECMode) - { - char Buffer[300]; - int len; - - // Send FEC Data - - buff->L2DATA[txlen] = 0; - len = sprintf(Buffer, "%-9s: %s", TNC->Streams[0].MyCall, &buff->L2DATA); - - send(TNC->TCPDataSock, Buffer, len, 0); - - if (TNC->BusyFlags) - { - TNC->FECPending = 1; - } - else - { - if (TNC->FEC1600) - send(TNC->TCPSock,"FECSEND 1600\r\n", 14, 0); - else - send(TNC->TCPSock,"FECSEND 500\r\n", 13, 0); - } - return 0; - } - - - // See if Local command (eg RADIO) - - if (_memicmp(&buff->L2DATA[0], "RADIO ", 6) == 0) - { - char cmd[56]; - - strcpy(cmd, &buff->L2DATA[6]); - sprintf(&buff->L2DATA[0], "%d %s", TNC->Port, &cmd); - - - if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK, &buff->L2DATA[0])) - { - } - else - { - PMSGWITHLEN buffptr = GetBuff(); - - if (buffptr == 0) return 1; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "%s", &buff->L2DATA[0]); - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - } - return 1; - } - - if (_memicmp(&buff->L2DATA[0], "OVERRIDEBUSY", 12) == 0) - { - PMSGWITHLEN buffptr = GetBuff(); - - TNC->OverrideBusy = TRUE; - - if (buffptr) - { - buffptr->Len = sprintf(&buffptr->Data[0], "Winmor} OK\r"); - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - } - - return 0; - - } - - if (_memicmp(&buff->L2DATA[0], "MAXCONREQ", 9) == 0) - { - if (buff->L2DATA[9] != 13) - { - // Limit connects - - int tries = atoi(&buff->L2DATA[10]); - int len; - - if (tries > 10) tries = 10; - len = sprintf(&buff->L2DATA[0], "MAXCONREQ %d\r\nMAXCONREQ\r\n", tries); - - send(TNC->TCPSock, &buff->L2DATA[0], len, 0); - return 0; - } - } - - if (_memicmp(&buff->L2DATA[0], "SessionTimeLimit", 16) == 0) - { - if (buff->L2DATA[16] != 13) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - TNC->SessionTimeLimit = atoi(&buff->L2DATA[16]) * 60; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "Winmor} OK\r"); - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - } - return 0; - } - } - - if ((_memicmp(buff->L2DATA, "BW 500", 6) == 0) || (_memicmp(buff->L2DATA, "BW 1600", 7) == 0)) - { - // Generate a local response - - PMSGWITHLEN buffptr = GetBuff(); - - if (_memicmp(buff->L2DATA, "BW 500", 6) == 0) - TNC->WL2KMode = 21; - else - TNC->WL2KMode = 22; - - if (buffptr) - { - buffptr->Len = sprintf(&buffptr->Data[0], "Winmor} OK\r"); - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - } - TNC->WinmorCurrentMode = 0; // So scanner will set next value - } - - if (_memicmp(buff->L2DATA, "CODEC TRUE", 9) == 0) - TNC->StartSent = TRUE; - - if (_memicmp(buff->L2DATA, "ROBUST", 6) == 0) - { - if (_memicmp(&buff->L2DATA[7], "TRUE", 4) == 0) - TNC->Robust = TRUE; - else - TNC->Robust = FALSE; - } - - if (_memicmp(buff->L2DATA, "D\r", 2) == 0) - { - TNC->Streams[0].ReportDISC = TRUE; // Tell Node - return 0; - } - - if (_memicmp(buff->L2DATA, "FEC\r", 4) == 0 || _memicmp(buff->L2DATA, "FEC ", 4) == 0) - { - TNC->FECMode = TRUE; - TNC->FECIDTimer = 0; - send(TNC->TCPSock,"FECRCV TRUE\r\nFECRCV\r\n", 21, 0); - - if (_memicmp(buff->L2DATA, "FEC 1600", 8) == 0) - TNC->FEC1600 = TRUE; - else - TNC->FEC1600 = FALSE; - - return 0; - } - - // See if a Connect Command. If so, start codec and set Connecting - - if (toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect - { - char Connect[80] = "CONNECT "; - - memcpy(&Connect[8], &buff->L2DATA[2], txlen); - txlen += 6; - Connect[txlen++] = 0x0a; - Connect[txlen] = 0; - - _strupr(Connect); - - ChangeMYC(TNC, TNC->Streams[0].MyCall); - - // See if Busy - - if (InterlockedCheckBusy(TNC)) - { - // Channel Busy. Unless override set, wait - - if (TNC->OverrideBusy == 0) - { - // Save Command, and wait up to 10 secs - - sprintf(TNC->WEB_TNCSTATE, "Waiting for clear channel"); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - TNC->ConnectCmd = _strdup(Connect); - TNC->BusyDelay = TNC->BusyWait * 10; // BusyWait secs - return 0; - } - } - - TNC->OverrideBusy = FALSE; - - bytes = send(TNC->TCPSock, Connect, (int)txlen, 0); - TNC->Streams[0].Connecting = TRUE; - - memset(TNC->Streams[0].RemoteCall, 0, 10); - memcpy(TNC->Streams[0].RemoteCall, &Connect[8], txlen-10); - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - } - else - { - buff->L2DATA[txlen++] = 0x0a; - bytes = send(TNC->TCPSock, &buff->L2DATA[0], (int)txlen, 0); - } - } - if (bytes != txlen) - { - - // WINMOR doesn't seem to recover from a blocked write. For now just reset - - winerr = WSAGetLastError(); - sprintf(ErrMsg, "WINMOR Write Failed for port %d - error code = %d\r\n", port, winerr); - WritetoConsole(ErrMsg); - closesocket(TNC->TCPSock); - TNC->CONNECTED = FALSE; - - return (0); - } - - return (0); - - case 3: - - // CHECK IF OK TO SEND (And check TNC Status) - - if (TNC->Streams[0].Attached == 0) - return TNC->CONNECTED << 8 | 1; - - return (TNC->CONNECTED << 8 | TNC->Streams[0].Disconnecting << 15); // OK - - break; - - case 4: // reinit - - return (0); - - case 5: // Close - - send(TNC->TCPSock, "CODEC FALSE\r\n", 13, 0); - Sleep(100); - shutdown(TNC->TCPDataSock, SD_BOTH); - shutdown(TNC->TCPSock, SD_BOTH); - Sleep(100); - - closesocket(TNC->TCPDataSock); - closesocket(TNC->TCPSock); - - if (TNC->PID && TNC->WeStartedTNC) - { - KillTNC(TNC); - } - - return (0); - - case 6: // Scan Stop Interface - - Param = (size_t)buff; - - if (Param == 2) // Check Permission (shouldn't happen) - { - Debugprintf("Scan Check Permission called on FLDIGI"); - return 1; // OK to change - } - - if (!TNC->TCPSock) - return 0; // No connection so no interlock - - if (Param == 1) // Request Permission - { - if (TNC->ConnectPending) - return TRUE; // Not OK to Change - - if (TNC->CONNECTED) - { - TNC->GavePermission = TRUE; - send(TNC->TCPSock, "LISTEN FALSE\r\n", 14, 0); - } - return FALSE; - } - - if (Param == 3) // Release Permission - { - if (TNC->CONNECTED) - { - if (TNC->GavePermission) - { - TNC->GavePermission = FALSE; - send(TNC->TCPSock, "LISTEN TRUE\r\n", 13, 0); - } - } - return 0; - } - - // Param is Address of a struct ScanEntry - - Scan = (struct ScanEntry *)buff; - - - if (Scan->Bandwidth == 'W') // Set Wide Mode - { - if (TNC->WinmorCurrentMode != 1600) - { - if (TNC->WinmorCurrentMode == 0) - if (TNC->CONNECTED) - send(TNC->TCPSock, "LISTEN TRUE\r\n", 13, 0); - - if (TNC->CONNECTED) - send(TNC->TCPSock, "BW 1600\r\n", 9, 0); - TNC->WinmorCurrentMode = 1600; - } - TNC->WL2KMode = 22; - return 0; - } - - - if (Scan->Bandwidth == 'N') // Set Narrow Mode - { - if (TNC->WinmorCurrentMode != 500) - { - if (TNC->WinmorCurrentMode == 0) - if (TNC->CONNECTED) - send(TNC->TCPSock, "LISTEN TRUE\r\n", 13, 0); - - TNC->WinmorCurrentMode = 500; - if (TNC->CONNECTED) - send(TNC->TCPSock, "BW 500\r\n", 8, 0); - } - TNC->WL2KMode = 21; - return 0; - } - - if (Scan->Bandwidth == 'X') // Dont Allow Connects - { - if (TNC->WinmorCurrentMode != 0) - { - if (TNC->CONNECTED) - send(TNC->TCPSock, "LISTEN FALSE\r\n", 14, 0); - TNC->WinmorCurrentMode = 0; - } - - TNC->WL2KMode = 0; - return 0; - } - - return 0; - } - return 0; -} - -VOID ReleaseTNC(struct TNCINFO * TNC) -{ - // Set mycall back to Node or Port Call, and Start Scanner - - UCHAR TXMsg[256]; - char wtext[100]; - - ChangeMYC(TNC, TNC->NodeCall); - - if (TNC->CONNECTED) - send(TNC->TCPSock, "LISTEN TRUE\r\nMAXCONREQ 4\r\n", 26, 0); - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - if (TNC->hWnd) - { - sprintf (wtext, "WINMOR Sound Card TNC - BPQ %s", TNC->PortRecord->PORTCONTROL.PORTDESCRIPTION); - MySetWindowText(TNC->hWnd, wtext); - } - - // Start Scanner - - sprintf(TXMsg, "%d SCANSTART 15", TNC->Port); - - Rig_Command( (TRANSPORTENTRY *) -1, TXMsg); - - ReleaseOtherPorts(TNC); - -} - -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC) -{ - // Disable other TNCs in same Interlock Group - - struct TNCINFO * TNC; - int i; - int rxInterlock = ThisTNC->RXRadio; - int txInterlock = ThisTNC->TXRadio; - - if (rxInterlock == 0 || txInterlock == 0) - return; - - for (i = 1; i <= MAXBPQPORTS; i++) - { - TNC = TNCInfo[i]; - if (TNC == NULL) - continue; - - if (TNC == ThisTNC) - continue; - - if (rxInterlock == TNC->RXRadio || txInterlock == TNC->TXRadio) // Same Group - if (TNC->SuspendPortProc) - TNC->SuspendPortProc(TNC, ThisTNC); - } -} - -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC) -{ - // Enable other TNCs in same Interlock Group - - struct TNCINFO * TNC; - int i; - int rxInterlock = ThisTNC->RXRadio; - int txInterlock = ThisTNC->TXRadio; - - if (rxInterlock == 0 && txInterlock == 0) - return; - - for (i=1; i <= MAXBPQPORTS; i++) - { - TNC = TNCInfo[i]; - if (TNC == NULL) - continue; - - if (TNC == ThisTNC) - continue; - - if (rxInterlock == TNC->RXRadio || txInterlock == TNC->TXRadio) // Same Group - if (TNC->ReleasePortProc) - TNC->ReleasePortProc(TNC); - } -} - -VOID WinmorSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC) -{ - if (TNC->CONNECTED) - send(TNC->TCPSock, "CODEC FALSE\r\n", 14, 0); - - if (TNC->Busy) - { - TNC->Busy = FALSE; // Can't clear detector if CODEC off. - MySetWindowText(TNC->xIDC_CHANSTATE, "Clear"); - strcpy(TNC->WEB_CHANSTATE, "Clear"); - } -} - -VOID WinmorReleasePort(struct TNCINFO * TNC) -{ - if (TNC->CONNECTED) - send(TNC->TCPSock, "CODEC TRUE\r\n", 13, 0); -} - -extern char WebProcTemplate[]; -extern char sliderBit[]; - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, WebProcTemplate, TNC->Port, TNC->Port, "WINMOR Status", "WINMOR Status"); - - if (TNC->TXFreq) - Len += sprintf(&Buff[Len], sliderBit, TNC->TXOffset, TNC->TXOffset); - - - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); - Len += sprintf(&Buff[Len], "", TNC->WEB_CHANSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_PROTOSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); -// Len += sprintf(&Buff[Len], "", TNC->WEB_RESTARTS); - Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Channel State%s
Proto State%s
Traffic%s
TNC Restarts
"); - - Len += sprintf(&Buff[Len], "", TNC->WebBuffer); - Len = DoScanLine(TNC, Buff, Len); - - return Len; -} - - -void * WinmorExtInit(EXTPORTDATA * PortEntry) -{ - int i, port; - char Msg[255]; - char * ptr; - APPLCALLS * APPL; - struct TNCINFO * TNC; - char Aux[100] = "MYAUX "; - char Appl[11]; - char * TempScript; - - // - // Will be called once for each WINMOR port - // - // The Socket to connect to is in IOBASE - // - - port = PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - - TNC = TNCInfo[port]; - - if (TNC == NULL) - { - // Not defined in Config file - - sprintf(Msg," ** Error - no info in BPQ32.cfg for this port\n"); - WritetoConsole(Msg); - - return ExtProc; - } - - TNC->Port = port; - TNC->PortRecord = PortEntry; - - if (TNC->ProgramPath) - TNC->WeStartedTNC = RestartTNC(TNC); - - TNC->PortRecord->PORTCONTROL.HWType = TNC->Hardware = H_WINMOR; - - if (TNC->BusyWait == 0) - TNC->BusyWait = 10; - - if (TNC->BusyHold == 0) - TNC->BusyHold = 1; - - - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) - memcpy(TNC->NodeCall, MYNODECALL, 10); - else - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - - if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) - TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; - - PortEntry->PORTCONTROL.PROTOCOL = 10; - PortEntry->PORTCONTROL.PORTQUALITY = 0; - PortEntry->MAXHOSTMODESESSIONS = 1; - PortEntry->SCANCAPABILITIES = SIMPLE; // Scan Control - pending connect only - - if (PortEntry->PORTCONTROL.PORTPACLEN == 0) - PortEntry->PORTCONTROL.PORTPACLEN = 236; - - TNC->SuspendPortProc = WinmorSuspendPort; - TNC->ReleasePortProc = WinmorReleasePort; - - TNC->ModemCentre = 1500; // WINMOR is always 1500 Offset - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - // Set Essential Params and MYCALL - - // Put overridable ones on front, essential ones on end - - TempScript = malloc(1000); - - strcpy(TempScript, "DebugLog True\r\n"); - strcat(TempScript, "CWID False\r\n"); - strcat(TempScript, "BW 1600\r\n"); - strcat(TempScript, "ROBUST False\r\n"); - strcat(TempScript, "MODE AUTO\r\n"); - - strcat(TempScript, TNC->InitScript); - - free(TNC->InitScript); - TNC->InitScript = TempScript; - - TNC->WL2KMode = 22; // in case not scanning - - // Set MYCALL - - strcat(TNC->InitScript,"FECRCV True\r\n"); - strcat(TNC->InitScript,"AUTOBREAK True\r\n"); - - sprintf(Msg, "MYC %s\r\nCODEC TRUE\r\nLISTEN TRUE\r\nMYC\r\n", TNC->NodeCall); - strcat(TNC->InitScript, Msg); - strcat(TNC->InitScript,"PROCESSID\r\n"); - - for (i = 0; i < 32; i++) - { - APPL=&APPLCALLTABLE[i]; - - if (APPL->APPLCALL_TEXT[0] > ' ') - { - char * ptr; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - { - *ptr++ = ','; - *ptr = 0; - } - - strcat(Aux, Appl); - } - } - strcat(TNC->InitScript, Aux); - strcat(TNC->InitScript,"\r\nMYAUX\r\n"); - - strcpy(TNC->CurrentMYC, TNC->NodeCall); - - if (TNC->WL2K == NULL) - if (PortEntry->PORTCONTROL.WL2KInfo.RMSCall[0]) // Alrerady decoded - TNC->WL2K = &PortEntry->PORTCONTROL.WL2KInfo; - - if (TNC->destaddr.sin_family == 0) - { - // not defined in config file, so use localhost and port from IOBASE - - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(PortEntry->PORTCONTROL.IOBASE); - TNC->Datadestaddr.sin_family = AF_INET; - TNC->Datadestaddr.sin_port = htons(PortEntry->PORTCONTROL.IOBASE+1); - - TNC->HostName=malloc(10); - - if (TNC->HostName != NULL) - strcpy(TNC->HostName,"127.0.0.1"); - - } - - PortEntry->PORTCONTROL.TNC = TNC; - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 520; - TNC->WebWinY = 500; - TNC->WebBuffer = zalloc(5000); - - TNC->WEB_COMMSSTATE = zalloc(100); - TNC->WEB_TNCSTATE = zalloc(100); - TNC->WEB_CHANSTATE = zalloc(100); - TNC->WEB_BUFFERS = zalloc(100); - TNC->WEB_PROTOSTATE = zalloc(100); - TNC->WEB_RESTARTTIME = zalloc(100); - TNC->WEB_RESTARTS = zalloc(100); - - TNC->WEB_MODE = zalloc(20); - TNC->WEB_TRAFFIC = zalloc(100); - - -#ifndef LINBPQ - - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 500, 450, ForcedClose); - - CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,6,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,6,386,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,28,106,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,28,520,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,50,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,50,200,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Channel State", WS_CHILD | WS_VISIBLE, 10,72,110,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_CHANSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,72,144,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Proto State", WS_CHILD | WS_VISIBLE,10,94,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_PROTOSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,94,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,116,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "0 0 0 0", WS_CHILD | WS_VISIBLE,116,116,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "TNC Restarts", WS_CHILD | WS_VISIBLE,10,138,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTS = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE,116,138,40,20 , TNC->hDlg, NULL, hInstance, NULL); - CreateWindowEx(0, "STATIC", "Last Restart", WS_CHILD | WS_VISIBLE,140,138,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTTIME = CreateWindowEx(0, "STATIC", "Never", WS_CHILD | WS_VISIBLE,250,138,200,20, TNC->hDlg, NULL, hInstance, NULL); - - TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, - 0,170,250,300, TNC->hDlg, NULL, hInstance, NULL); - - TNC->ClientHeight = 450; - TNC->ClientWidth = 500; - - TNC->hMenu = CreatePopupMenu(); - - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_KILL, "Kill Winmor TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTART, "Kill and Restart Winmor TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTARTAFTERFAILURE, "Restart TNC after failed Connection"); - AppendMenu(TNC->hMenu, MF_STRING, ARDOP_ABORT, "Abort Current Session"); - - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - - MoveWindows(TNC); -#endif - Consoleprintf("WINMOR Host %s %d", TNC->HostName, htons(TNC->destaddr.sin_port)); - - ConnecttoWINMOR(port); - - time(&TNC->lasttime); // Get initial time value - - return ExtProc; -} - -int ConnecttoWINMOR(int port) -{ - _beginthread(WINMORThread, 0, (void *)(size_t)port); - - return 0; -} - -VOID WINMORThread(void * portptr) -{ - // Opens both sockets and looks for data on control socket. Data socket is polled from BG, - // but we need fast response to control messages for PTT porcessing - - int port = (int)(size_t)portptr; - - char Msg[255]; - int err, i, ret; - u_long param=1; - BOOL bcopt=TRUE; - struct hostent * HostEnt; - struct TNCINFO * TNC = TNCInfo[port]; - fd_set readfs; - fd_set errorfs; - struct timeval timeout; - if (TNC->HostName == NULL) - return; - - TNC->CONNECTING = TRUE; - - Sleep(3000); // Allow init to complete - -#ifdef WIN32 - if (strcmp(TNC->HostName, "127.0.0.1") == 0) - { - // can only check if running on local host - - TNC->PID = GetListeningPortsPID(TNC->destaddr.sin_port); - if (TNC->PID == 0) - { - TNC->CONNECTING = FALSE; - return; // Not listening so no point trying to connect - } - } -#endif - -// // If we started the TNC make sure it is still running. - -// if (!IsProcess(TNC->PID)) -// { -// RestartTNC(TNC); -// Sleep(3000); -// } - - - TNC->destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - TNC->Datadestaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - - if (TNC->destaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - HostEnt = gethostbyname (TNC->HostName); - - if (!HostEnt) - { - TNC->CONNECTING = FALSE; - return; // Resolve failed - } - memcpy(&TNC->destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - memcpy(&TNC->Datadestaddr.sin_addr.s_addr,HostEnt->h_addr,4); - - } - - if (TNC->TCPSock) - closesocket(TNC->TCPSock); - - TNC->TCPSock = 0; - - if (TNC->TCPDataSock) - closesocket(TNC->TCPDataSock); - - TNC->TCPDataSock = 0; - - TNC->TCPSock=socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for WINMOR socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->CONNECTING = FALSE; - return; - } - - setsockopt (TNC->TCPSock, 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(TNC->TCPSock, (LPSOCKADDR) &sinx, addrlen) != 0 ) - { - // - // Bind Failed - // - - i=sprintf(Msg, "Bind Failed for WINMOR socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - closesocket(TNC->TCPSock); - TNC->TCPSock = 0; - TNC->CONNECTING = FALSE; - - return; - } - - if (connect(TNC->TCPSock,(LPSOCKADDR) &TNC->destaddr,sizeof(TNC->destaddr)) == 0) - { - // - // Connected successful - // - } - else - { - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - i=sprintf(Msg, "Connect Failed for WINMOR socket - error code = %d\r\n", err); - WritetoConsole(Msg); - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - TNC->Alerted = TRUE; - } - - closesocket(TNC->TCPSock); - TNC->CONNECTING = FALSE; - TNC->TCPSock = 0; - - return; - } - - Sleep(1000); - - TNC->LastFreq = 0; // so V4 display will be updated - - TNC->TCPDataSock=socket(AF_INET,SOCK_STREAM,0); - - setsockopt (TNC->TCPDataSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - - if (TNC->TCPDataSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for WINMOR socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - closesocket(TNC->TCPSock); - TNC->TCPSock = 0; - TNC->CONNECTING = FALSE; - - return; - } - - if (bind(TNC->TCPDataSock, (LPSOCKADDR) &sinx, addrlen) != 0 ) - { - // - // Bind Failed - // - - i=sprintf(Msg, "Bind Failed for WINMOR Data socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - closesocket(TNC->TCPSock); - closesocket(TNC->TCPDataSock); - TNC->TCPSock = 0; - TNC->TCPDataSock = 0; - TNC->CONNECTING = FALSE; - - return; - } - - if (connect(TNC->TCPDataSock,(LPSOCKADDR) &TNC->Datadestaddr,sizeof(TNC->Datadestaddr)) == 0) - { - ioctlsocket (TNC->TCPDataSock,FIONBIO,¶m); // Set nonblocking - TNC->CONNECTED = TRUE; - TNC->CONNECTING = FALSE; - - // Send INIT script - - send(TNC->TCPSock, TNC->InitScript , (int)strlen(TNC->InitScript), 0); - TNC->Alerted = TRUE; - - if (TNC->Hardware == H_V4) - sprintf(TNC->WEB_COMMSSTATE, "Connected to V4 TNC"); - else - sprintf(TNC->WEB_COMMSSTATE, "Connected to WINMOR TNC"); - - GetSemaphore(&Semaphore, 40); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - FreeSemaphore(&Semaphore); - - } - else - { - sprintf(Msg, "Connect Failed for WINMOR Data socket Port %d - error code = %d\r\n", port, WSAGetLastError()); - WritetoConsole(Msg); - - closesocket(TNC->TCPSock); - closesocket(TNC->TCPDataSock); - TNC->TCPSock = 0; - TNC->TCPDataSock = 0; - TNC->CONNECTING = FALSE; - - return; - } - - TNC->HeartBeat = 0; - - while (TRUE) - { - FD_ZERO(&readfs); - FD_ZERO(&errorfs); - - FD_SET(TNC->TCPSock,&readfs); - FD_SET(TNC->TCPSock,&errorfs); - - timeout.tv_sec = 90; - timeout.tv_usec = 0; // We should get messages more frequently that this - - ret = select((int)TNC->TCPSock + 1, &readfs, NULL, &errorfs, &timeout); - - if (ret == SOCKET_ERROR) - { - printf("Select failed %d ", WSAGetLastError()); - goto Lost; - } - if (ret > 0) - { - // See what happened - - if (FD_ISSET(TNC->TCPSock, &readfs)) - { - if (TNC->Hardware == H_V4) - V4ProcessReceivedData(TNC); - else - ProcessReceivedData(TNC); - } - - if (FD_ISSET(TNC->TCPSock, &errorfs)) - { -Lost: - sprintf(Msg, "WINMOR Connection lost for Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - GetSemaphore(&Semaphore, 40); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - FreeSemaphore(&Semaphore); - - TNC->CONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - closesocket(TNC->TCPSock); - closesocket(TNC->TCPDataSock); - - TNC->TCPSock = 0; - TNC->TCPDataSock = 0; - - return; - } - } - else - { - // 90 secs without data. Shouldn't happen - - sprintf(Msg, "WINMOR Connection Timeout Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - GetSemaphore(&Semaphore, 40); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - FreeSemaphore(&Semaphore); - - TNC->CONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - send(TNC->TCPSock, "CODEC FALSE\r\n", 13, 0); - - Sleep(100); - shutdown(TNC->TCPDataSock, SD_BOTH); - shutdown(TNC->TCPSock, SD_BOTH); - Sleep(100); - - closesocket(TNC->TCPDataSock); - closesocket(TNC->TCPSock); - TNC->TCPDataSock = 0; - TNC->TCPSock= 0; - - if (TNC->PID && TNC->WeStartedTNC) - { - KillTNC(TNC); - RestartTNC(TNC); - } - return; - } - } -} - -#ifdef WIN32 - -BOOL CALLBACK EnumTNCWindowsProc(HWND hwnd, LPARAM lParam) -{ - char wtext[100]; - struct TNCINFO * TNC = (struct TNCINFO *)lParam; - UINT ProcessId; - - GetWindowText(hwnd,wtext,99); - - if (memcmp(wtext,"WINMOR Sound Card TNC", 21) == 0) - { - GetWindowThreadProcessId(hwnd, &ProcessId); - - if (TNC->PID == ProcessId) - { - // Our Process - - TNC->hWnd = hwnd; // save so we can reset title when sessicn closes - sprintf (wtext, "WINMOR Sound Card TNC - BPQ %s", TNC->PortRecord->PORTCONTROL.PORTDESCRIPTION); - SetWindowText(hwnd, wtext); - return FALSE; - } - } - - return (TRUE); -} -#endif - -VOID ProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) -{ - // Response on WINMOR control channel. Could be a reply to a command, or - // an Async Response - - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - Buffer[MsgLen - 2] = 0; - - if (_memicmp(Buffer, "FAULT failure to Restart Sound card", 20) == 0) - { - Debugprintf(Buffer); - - // Force a restart - - send(TNC->TCPSock, "CODEC FALSE\r\n", 13, 0); - send(TNC->TCPSock, "CODEC TRUE\r\n", 12, 0); - } - else - { - TNC->TimeSinceLast = 0; - } - - - if (_memicmp(Buffer, "STATE ", 6) == 0) - { - Debugprintf(Buffer); - - if (_memicmp(&Buffer[6], "OFFLINE", 7) == 0) - { - // Force a restart - - send(TNC->TCPSock, "CODEC FALSE\r\n", 13, 0); - send(TNC->TCPSock, "CODEC TRUE\r\n", 12, 0); - } - return; - } - - Buffer[MsgLen - 2] = 0; // Remove CRLF - - if (_memicmp(Buffer, "PTT T", 5) == 0) - { - TNC->Busy = TNC->BusyHold * 10; // BusyHold delay - - if (TNC->PTTMode) - Rig_PTT(TNC, TRUE); - return; - } - if (_memicmp(Buffer, "PTT F", 5) == 0) - { - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); - return; - } - - if (_memicmp(Buffer, "BUSY TRUE", 9) == 0) - { - TNC->BusyFlags |= CDBusy; - TNC->Busy = TNC->BusyHold * 10; // BusyHold delay - - SetWindowText(TNC->xIDC_CHANSTATE, "Busy"); - strcpy(TNC->WEB_CHANSTATE, "Busy"); - - TNC->WinmorRestartCodecTimer = time(NULL); - return; - } - - if (_memicmp(Buffer, "BUSY FALSE", 10) == 0) - { - TNC->BusyFlags &= ~CDBusy; - if (TNC->BusyHold) - strcpy(TNC->WEB_CHANSTATE, "BusyHold"); - else - strcpy(TNC->WEB_CHANSTATE, "Clear"); - - SetWindowText(TNC->xIDC_CHANSTATE, TNC->WEB_CHANSTATE); - TNC->WinmorRestartCodecTimer = time(NULL); - return; - } - - if (_memicmp(Buffer, "TARGET", 6) == 0) - { - Debugprintf(Buffer); - GetSemaphore(&Semaphore, 50); - WritetoTrace(TNC, Buffer, MsgLen - 2); - FreeSemaphore(&Semaphore); - memcpy(TNC->TargetCall, &Buffer[7], 10); - return; - } - - if (_memicmp(Buffer, "OFFSET", 6) == 0) - { -// WritetoTrace(TNC, Buffer, MsgLen - 2); -// memcpy(TNC->TargetCall, &Buffer[7], 10); - return; - } - - if (_memicmp(Buffer, "CONNECTED", 9) == 0) - { - char Call[11]; - char * ptr; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - - Debugprintf(Buffer); - - GetSemaphore(&Semaphore, 50); - WritetoTrace(TNC, Buffer, MsgLen - 2); - FreeSemaphore(&Semaphore); - - STREAM->ConnectTime = time(NULL); - STREAM->bytesRXed = STREAM->bytesTXed = STREAM->PacketsSent = 0; - - if (TNC->StartInRobust) - send(TNC->TCPSock, "ROBUST TRUE\r\n", 13, 0); - - memcpy(Call, &Buffer[10], 10); - - ptr = strchr(Call, ' '); - if (ptr) *ptr = 0; - - TNC->HadConnect = TRUE; - - if (TNC->PortRecord->ATTACHEDSESSIONS[0] == 0) - { - TRANSPORTENTRY * SESS; - - // Incomming Connect - - TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - GetSemaphore(&Semaphore, 50); - - ProcessIncommingConnectEx(TNC, Call, 0, TRUE, TRUE); - FreeSemaphore(&Semaphore); - - SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - SESS->Mode = TNC->WL2KMode; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, TNC->TargetCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - SESS->Mode = TNC->WL2KMode; - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, TNC->TargetCall); - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - SESS->Mode = WL2K->mode; - } - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Check for ExcludeList - - if (ExcludeList[0]) - { - if (CheckExcludeList(SESS->L4USER) == FALSE) - { - char Status[64]; - - TidyClose(TNC, 0); - sprintf(Status, "%d SCANSTART 15", TNC->Port); - Rig_Command( (TRANSPORTENTRY *) -1, Status); - Debugprintf("WINMOR Call from %s rejected", Call); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(SESS->L4USER, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - char Status[64]; - - TidyClose(TNC, 0); - sprintf(Status, "%d SCANSTART 15", TNC->Port); - Rig_Command( (TRANSPORTENTRY *) -1, Status); - Debugprintf("WINMOR Call from %s not in ValidCalls - rejected", Call); - return; - } - } - } - - if (STREAM->BPQtoPACTOR_Q) //Used for CTEXT - { - PMSGWITHLEN buffptr = Q_REM(&STREAM->BPQtoPACTOR_Q); - - send(TNC->TCPDataSock, buffptr->Data, (int)buffptr->Len, 0); - STREAM->bytesTXed += (int)buffptr->Len; - WritetoTrace(TNC, buffptr->Data, (int)buffptr->Len); - ReleaseBuffer(buffptr); - } - - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(TNC->TargetCall, Appl) == 0) - break; - } - - if (App < 32) - { - char AppName[13]; - - memcpy(AppName, &ApplPtr[App * sizeof(struct CMDX)], 12); - AppName[12] = 0; - - // Make sure app is available - - if (CheckAppl(TNC, AppName)) - { - MsgLen = sprintf(Buffer, "%s\r", AppName); - - GetSemaphore(&Semaphore, 50); - - buffptr = GetBuff(); - - if (buffptr == 0) - { - FreeSemaphore(&Semaphore); - return; // No buffers, so ignore - } - - buffptr->Len = MsgLen; - memcpy(buffptr->Data, Buffer, MsgLen); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - FreeSemaphore(&Semaphore); - - TNC->SwallowSignon = TRUE; - - // Save Appl Call in case needed for - - } - else - { - char Msg[] = "Application not available\r\n"; - - // Send a Message, then a disconenct - - send(TNC->TCPDataSock, Msg, (int)strlen(Msg), 0); - STREAM->NeedDisc = 100; // 10 secs - } - } - - return; - } - else - { - // Connect Complete - - char Reply[80]; - int ReplyLen; - - GetSemaphore(&Semaphore, 50); - - buffptr = GetBuff(); - - if (buffptr == 0) - { - FreeSemaphore(&Semaphore); - return; // No buffers, so ignore - } - ReplyLen = sprintf(Reply, "*** Connected to %s\r", &Buffer[10]); - - buffptr->Len = ReplyLen; - memcpy(buffptr->Data, Reply, ReplyLen); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - FreeSemaphore(&Semaphore); - - TNC->Streams[0].Connecting = FALSE; - TNC->Streams[0].Connected = TRUE; // Subsequent data to data channel - - - if (TNC->RIG) - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound Freq %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall, TNC->RIG->Valchar); - else - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall); - - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - UpdateMH(TNC, Call, '+', 'O'); - return; - } - } - - if (_memicmp(Buffer, "DISCONNECTED", 12) == 0) - { - Debugprintf(Buffer); - - if (TNC->FECMode) - return; - - if (TNC->StartSent) - { - TNC->StartSent = FALSE; // Disconnect reported following start codec - return; - } - - if (TNC->Streams[0].Connecting) - { - // Report Connect Failed, and drop back to command mode - - TNC->Streams[0].Connecting = FALSE; - - GetSemaphore(&Semaphore, 50); - - buffptr = GetBuff(); - - if (buffptr == 0) - { - FreeSemaphore(&Semaphore); - return; // No buffers, so ignore - } - - buffptr->Len = sprintf(buffptr->Data, "Winmor} Failure with %s\r", TNC->Streams[0].RemoteCall); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - FreeSemaphore(&Semaphore); - - if (TNC->RestartAfterFailure) - { - if (TNC->PID) - { - KillTNC(TNC); - RestartTNC(TNC); - } - } - - return; - } - - - // Release Session - - if (TNC->Streams[0].Connected) - { - hookL4SessionDeleted(TNC, STREAM); - - GetSemaphore(&Semaphore, 50); - WritetoTrace(TNC, Buffer, MsgLen - 2); - FreeSemaphore(&Semaphore); - } - - - TNC->Streams[0].Connecting = FALSE; - TNC->Streams[0].Connected = FALSE; // Back to Command Mode - TNC->Streams[0].ReportDISC = TRUE; // Tell Node - - if (TNC->Streams[0].Disconnecting) // - ReleaseTNC(TNC); - - TNC->Streams[0].Disconnecting = FALSE; - - return; - } - - if (_memicmp(Buffer, "MONCALL", 7) == 0) - { - Debugprintf(Buffer); - - // Add to MHEARD - - GetSemaphore(&Semaphore, 50); - WritetoTrace(TNC, Buffer, MsgLen - 2); - FreeSemaphore(&Semaphore); - UpdateMH(TNC, &Buffer[8], '!', 0); - - if (!TNC->FECMode) - return; // If in FEC mode pass ID messages to user. - } - - if (_memicmp(Buffer, "CMD", 3) == 0) - { - return; - } - - if (_memicmp(Buffer, "BUFFERS", 7) == 0) - { - int inq, inrx, Sent, BPM; - - sscanf(&Buffer[8], "%d%d%d%d%d", &inq, &inrx, &TNC->Streams[0].BytesOutstanding, &Sent, &BPM); - - if (TNC->Streams[0].BytesOutstanding == 0) - { - // all sent - - if (TNC->Streams[0].Disconnecting) // Disconnect when all sent - { - if (STREAM->NeedDisc == 0) - STREAM->NeedDisc = 60; // 6 secs - } -// else -// if (TNC->TXRXState == 'S') -// send(TNC->TCPSock,"OVER\r\n", 6, 0); - - } - else - { - // Make sure Node Keepalive doesn't kill session. - - TRANSPORTENTRY * SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - if (SESS) - { - SESS->L4KILLTIMER = 0; - SESS = SESS->L4CROSSLINK; - if (SESS) - SESS->L4KILLTIMER = 0; - } - } - - SetWindowText(TNC->xIDC_TRAFFIC, &Buffer[8]); - strcpy(TNC->WEB_TRAFFIC, &Buffer[8]); - return; - } - - Debugprintf(Buffer); - - if (_memicmp(Buffer, "MODE", 4) == 0) - { - // Debugprintf("WINMOR RX: %s", Buffer); - - strcpy(TNC->WEB_MODE, &Buffer[5]); - GetSemaphore(&Semaphore, 50); - MySetWindowText(TNC->xIDC_MODE, &Buffer[5]); - FreeSemaphore(&Semaphore); - return; - } - - if (_memicmp(Buffer, "PENDING", 6) == 0) - return; - - if (_memicmp(Buffer, "FAULT", 5) == 0) - { - WritetoTrace(TNC, Buffer, MsgLen - 2); - return; - } - - if (_memicmp(Buffer, "NEWSTATE", 8) == 0) - { - TNC->WinmorRestartCodecTimer = time(NULL); - - SetWindowText(TNC->xIDC_PROTOSTATE, &Buffer[9]); - strcpy(TNC->WEB_PROTOSTATE, &Buffer[9]); - - if (_memicmp(&Buffer[9], "CONNECTPENDING", 14) == 0) // Save Pending state for scan control - TNC->ConnectPending = TRUE; - else - TNC->ConnectPending = FALSE; - - if (_memicmp(&Buffer[9], "DISCONNECTING", 13) == 0) // So we can timout stuck discpending - { - TNC->DiscPending = 600; - return; - } - if (_memicmp(&Buffer[9], "DISCONNECTED", 12) == 0) - { - TNC->DiscPending = FALSE; - return; - } - - if (strcmp(&Buffer[9], "ISS") == 0) // Save Pending state for scan control - TNC->TXRXState = 'S'; - else if (strcmp(&Buffer[9], "IRS") == 0) - TNC->TXRXState = 'R'; - - return; - } - - - if (_memicmp(Buffer, "PROCESSID", 9) == 0) - { - HANDLE hProc; - char ExeName[256] = ""; - - TNC->PID = atoi(&Buffer[10]); - -#ifdef WIN32 - - // Get the File Name in case we want to restart it. - - if (TNC->ProgramPath == NULL) - { - if (GetModuleFileNameExPtr) - { - hProc = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, TNC->PID); - - if (hProc) - { - GetModuleFileNameExPtr(hProc, 0, ExeName, 255); - CloseHandle(hProc); - - TNC->ProgramPath = _strdup(ExeName); - } - } - } - - // Set Window Title to reflect BPQ Port Description - - EnumWindows(EnumTNCWindowsProc, (LPARAM)TNC); -#endif - } - - if ((_memicmp(Buffer, "FAULT Not from state FEC", 24) == 0) || (_memicmp(Buffer, "FAULT Blocked by Busy Lock", 24) == 0)) - { - if (TNC->FECMode) - { - Sleep(1000); - - if (TNC->FEC1600) - send(TNC->TCPSock,"FECSEND 1600\r\n", 14, 0); - else - send(TNC->TCPSock,"FECSEND 500\r\n", 13, 0); - return; - } - } - - if (_memicmp(Buffer, "PLAYBACKDEVICES", 15) == 0) - { - TNC->PlaybackDevices = _strdup(&Buffer[16]); - } - // Others should be responses to commands - - if (_memicmp(Buffer, "BLOCKED", 6) == 0) - { - WritetoTrace(TNC, Buffer, MsgLen - 2); - return; - } - - if (_memicmp(Buffer, "OVER", 4) == 0) - { - WritetoTrace(TNC, Buffer, MsgLen - 2); - return; - } - - GetSemaphore(&Semaphore, 50); - - buffptr = GetBuff(); - - if (buffptr == 0) - { - FreeSemaphore(&Semaphore); - return; // No buffers, so ignore - } - - buffptr->Len = sprintf(buffptr->Data, "Winmor} %s\r", Buffer); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - FreeSemaphore(&Semaphore); -} - -static int ProcessReceivedData(struct TNCINFO * TNC) -{ - int InputLen, MsgLen; - char * ptr, * ptr2; - char Buffer[2000]; - - // May have several messages per packet, or message split over packets - - if (TNC->InputLen > 1000) // Shouldnt have lines longer than this on command connection - TNC->InputLen=0; - - InputLen=recv(TNC->TCPSock, &TNC->TCPBuffer[TNC->InputLen], 1000 - TNC->InputLen, 0); - - if (InputLen == 0 || InputLen == SOCKET_ERROR) - { - // Does this mean closed? - - closesocket(TNC->TCPSock); - closesocket(TNC->TCPDataSock); - - TNC->TCPSock = 0; - TNC->TCPDataSock = 0; - - TNC->CONNECTED = FALSE; - TNC->Streams[0].ReportDISC = TRUE; - - return 0; - } - - TNC->InputLen += InputLen; - -loop: - - ptr = memchr(TNC->TCPBuffer, '\n', TNC->InputLen); - - if (ptr) // CR in buffer - { - ptr2 = &TNC->TCPBuffer[TNC->InputLen]; - ptr++; // Assume LF Follows CR - - if (ptr == ptr2) - { - // Usual Case - single meg in buffer - - ProcessResponse(TNC, TNC->TCPBuffer, TNC->InputLen); - TNC->InputLen=0; - } - else - { - // buffer contains more that 1 message - - MsgLen = TNC->InputLen - (int)(ptr2-ptr); - - memcpy(Buffer, TNC->TCPBuffer, MsgLen); - - ProcessResponse(TNC, Buffer, MsgLen); - memmove(TNC->TCPBuffer, ptr, TNC->InputLen-MsgLen); - - TNC->InputLen -= MsgLen; - goto loop; - } - } - return 0; -} - - -VOID ProcessDataSocketData(int port) -{ - // Info on Data Socket - just packetize and send on - - struct TNCINFO * TNC = TNCInfo[port]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - int InputLen, PacLen = 236; - PMSGWITHLEN buffptr; - char * msg; - - TNC->TimeSinceLast = 0; - -loop: - buffptr = GetBuff(); - - if (buffptr == NULL) return; // No buffers, so ignore - - InputLen = recv(TNC->TCPDataSock, buffptr->Data, PacLen, 0); - - if (InputLen == -1) - { - ReleaseBuffer(buffptr); - return; - } - - - //Debugprintf("Winmor: RXD %d bytes", InputLen); - - if (InputLen == 0) - { - // Does this mean closed? - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - TNC->CONNECTING = FALSE; - TNC->CONNECTED = FALSE; - TNC->Streams[0].ReportDISC = TRUE; - - ReleaseBuffer(buffptr); - return; - } - - STREAM->bytesRXed += InputLen; - - msg = &buffptr->Data[0]; - msg[InputLen] = 0; - - WritetoTrace(TNC, msg, InputLen); - - if (TNC->FECMode) - { - InputLen = (int)strlen(&buffptr->Data[0]); - - if (msg[InputLen - 1] == 3) // End of errored block - msg[InputLen++] = 13; // Add CR - - } - buffptr->Len = InputLen; - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - goto loop; -} - -/* -INT_PTR CALLBACK ConfigDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - int Cmd = LOWORD(wParam); - - switch (message) - { - case WM_INITDIALOG: - { - struct TNCINFO * TNC = (struct TNCINFO * )lParam; - char * ptr1, *ptr2; - int ptr3 = 0; - char Line[1000]; - int len; - - ptr1 = TNC->CaptureDevices; - - if (!ptr1) - return 0; // No Devices - - - while (ptr2 = strchr(ptr1, ',')) - { - len = ptr2 - ptr1; - memcpy(&Line[ptr3], ptr1, len); - ptr3 += len; - Line[ptr3++] = '\r'; - Line[ptr3++] = '\n'; - - ptr1 = ++ptr2; - } - Line[ptr3] = 0; - strcat(Line, ptr1); - - SetDlgItemText(hDlg, IDC_CAPTURE, Line); - - ptr3 = 0; - - ptr1 = TNC->PlaybackDevices; - - if (!ptr1) - return 0; // No Devices - - - while (ptr2 = strchr(ptr1, ',')) - { - len = ptr2 - ptr1; - memcpy(&Line[ptr3], ptr1, len); - ptr3 += len; - Line[ptr3++] = '\r'; - Line[ptr3++] = '\n'; - - ptr1 = ++ptr2; - } - Line[ptr3] = 0; - strcat(Line, ptr1); - - SetDlgItemText(hDlg, IDC_PLAYBACK, Line); - - SendDlgItemMessage(hDlg, IDC_PLAYBACK, EM_SETSEL, -1, 0); - -// KillTNC(TNC); - - return TRUE; - } - - case WM_SIZING: - { - return TRUE; - } - - case WM_ACTIVATE: - -// SendDlgItemMessage(hDlg, IDC_MESSAGE, EM_SETSEL, -1, 0); - - break; - - - case WM_COMMAND: - - - if (Cmd == IDCANCEL) - { - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - } - - return (INT_PTR)TRUE; - - break; - } - return (INT_PTR)FALSE; -} -*/ - -#ifdef LINBPQ -#include -#include -#endif - - -int KillTNC(struct TNCINFO * TNC) -{ - if (TNC->ProgramPath && _memicmp(TNC->ProgramPath, "REMOTE:", 7) == 0) - { - // Try to Kill TNC on a remote host - - SOCKET sock = socket(AF_INET,SOCK_DGRAM,0); - struct sockaddr_in destaddr; - char Msg[256]; - int Len; - - if (sock == INVALID_SOCKET) - return 0; - - destaddr.sin_family = AF_INET; - destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - destaddr.sin_port = htons(8500); - - if (destaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - struct hostent * HostEnt = gethostbyname (TNC->HostName); - - if (!HostEnt) - return 0; // Resolve failed - - memcpy(&destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - - if (TNC->PID) - Len = sprintf(Msg, "KILL %d", TNC->PID); - else - Len = sprintf(Msg, "KILLBYNAME %s", &TNC->ProgramPath[7]); - - sendto(sock, Msg, Len, 0, (struct sockaddr *)&destaddr, sizeof(destaddr)); - Sleep(100); - closesocket(sock); - - TNC->PID = 0; // So we don't try again - return 1; // Cant tell if it worked, but assume ok - } - - if (TNC->PID == 0) - return 0; - -#ifdef WIN32 - { - HANDLE hProc; - - Debugprintf("KillTNC Called for Pid %d", TNC->PID); - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, TNC->PID); - - if (hProc) - { - TerminateProcess(hProc, 0); - CloseHandle(hProc); - } - } -#else - - printf("KillTNC Called for Pid %d Returned %d\n", TNC->PID, kill(TNC->PID, SIGTERM)); - -#endif - TNC->PID = 0; // So we don't try again - - return 0; -} - -BOOL RestartTNC(struct TNCINFO * TNC) -{ - if (TNC->ProgramPath == NULL || TNC->DontRestart) - return 0; - - if (_memicmp(TNC->ProgramPath, "REMOTE:", 7) == 0) - { - int n; - - // Try to start TNC on a remote host - - SOCKET sock = socket(AF_INET,SOCK_DGRAM,0); - struct sockaddr_in destaddr; - - Debugprintf("trying to restart TNC %s", TNC->ProgramPath); - - if (sock == INVALID_SOCKET) - return 0; - - destaddr.sin_family = AF_INET; - destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - destaddr.sin_port = htons(8500); - - if (destaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - struct hostent * HostEnt = gethostbyname (TNC->HostName); - - if (!HostEnt) - return 0; // Resolve failed - - memcpy(&destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - - n = sendto(sock, TNC->ProgramPath, (int)strlen(TNC->ProgramPath), 0, (struct sockaddr *)&destaddr, sizeof(destaddr)); - - Debugprintf("Restart TNC - sendto returned %d", n); - - Sleep(100); - closesocket(sock); - - return 1; // Cant tell if it worked, but assume ok - } - - // Not Remote - - // Extract any parameters from command string - -#ifndef WIN32 - { - char * arg_list[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - pid_t child_pid; - char * Copy, * Context; - signal(SIGCHLD, SIG_IGN); // Silently (and portably) reap children. - - Copy = _strdup(TNC->ProgramPath); // Save as strtok mangles it - - arg_list[0] = strtok_s(Copy, " \n\r", &Context); - if (arg_list[0]) - arg_list[1] = strtok_s(NULL, " \n\r", &Context); - if (arg_list[1]) - arg_list[2] = strtok_s(NULL, " \n\r", &Context); - if (arg_list[2]) - arg_list[3] = strtok_s(NULL, " \n\r", &Context); - if (arg_list[3]) - arg_list[4] = strtok_s(NULL, " \n\r", &Context); - if (arg_list[4]) - arg_list[5] = strtok_s(NULL, " \n\r", &Context); - if (arg_list[5]) - arg_list[6] = strtok_s(NULL, " \n\r", &Context); - if (arg_list[6]) - arg_list[7] = strtok_s(NULL, " \n\r", &Context); - - // Fork and Exec TNC - - printf("Trying to start %s\n", TNC->ProgramPath); - - /* Duplicate this process. */ - - child_pid = fork (); - - if (child_pid == -1) - { - printf ("StartTNC fork() Failed\n"); - free(Copy); - return 0; - } - - if (child_pid == 0) - { - execvp (arg_list[0], arg_list); - - /* The execvp function returns only if an error occurs. */ - - printf ("Failed to start TNC\n"); - exit(0); // Kill the new process - } - else - { - TNC->PID = child_pid; - printf("Started TNC, Process ID = %d\n", TNC->PID); - } - free(Copy); - return TRUE; - } -#else - { - int n = 0; - - STARTUPINFO SInfo; // pointer to STARTUPINFO - PROCESS_INFORMATION PInfo; // pointer to PROCESS_INFORMATION - char workingDirectory[256]; - int i = strlen(TNC->ProgramPath); - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - Debugprintf("RestartTNC Called for %s", TNC->ProgramPath); - - strcpy(workingDirectory, TNC->ProgramPath); - - while (i--) - { - if (workingDirectory[i] == '\\' || workingDirectory[i] == '/') - { - workingDirectory[i] = 0; - break; - } - } - - while (KillOldTNC(TNC->ProgramPath) && n++ < 100) - { - Sleep(100); - } - - if (CreateProcess(NULL, TNC->ProgramPath, NULL, NULL, FALSE,0, NULL, workingDirectory, &SInfo, &PInfo)) - { - Debugprintf("Restart TNC OK"); - TNC->PID = PInfo.dwProcessId; - return TRUE; - } - else - { - Debugprintf("Restart TNC Failed %d ", GetLastError()); - return FALSE; - } - } -#endif - return 0; -} - -VOID TidyClose(struct TNCINFO * TNC, int Stream) -{ - // If all acked, send disc - - if (TNC->Streams[0].BytesOutstanding == 0) - send(TNC->TCPSock,"DISCONNECT\r\n", 12, 0); -} - -VOID ForcedClose(struct TNCINFO * TNC, int Stream) -{ - send(TNC->TCPSock,"DIRTYDISCONNECT\r\n", 17, 0); -} - -VOID CloseComplete(struct TNCINFO * TNC, int Stream) -{ - ReleaseTNC(TNC); - - if (TNC->FECMode) - { - TNC->FECMode = FALSE; - send(TNC->TCPSock,"SENDID 0\r\n", 10, 0); - } -} - -BOOL KillOldTNC(char * Path) -{ -#ifdef WIN32 - HANDLE hProc; - char ExeName[256] = ""; - DWORD Pid = 0; - - DWORD Processes[1024], Needed, Count; - unsigned int i; - - if (EnumProcessesPtr == NULL) - return FALSE; - - if (!EnumProcessesPtr(Processes, sizeof(Processes), &Needed)) - return FALSE; - - // Calculate how many process identifiers were returned. - - Count = Needed / sizeof(DWORD); - - for (i = 0; i < Count; i++) - { - if (Processes[i] != 0) - { - hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, Processes[i]); - - if (hProc) - { - GetModuleFileNameExPtr(hProc, 0, ExeName, 255); - - // Path could have parameters, so use memcmp - - if (_memicmp(ExeName, Path, strlen(ExeName)) == 0) - { - Debugprintf("Killing Pid %d %s", Processes[i], ExeName); - TerminateProcess(hProc, 0); - CloseHandle(hProc); - return TRUE; - } - CloseHandle(hProc); - } - } - } -#endif - return FALSE; -} diff --git a/.svn/pristine/15/1557275e0b72cb1376626ed0c9e0e37f9edb65c4.svn-base b/.svn/pristine/15/1557275e0b72cb1376626ed0c9e0e37f9edb65c4.svn-base deleted file mode 100644 index 90ae26a..0000000 --- a/.svn/pristine/15/1557275e0b72cb1376626ed0c9e0e37f9edb65c4.svn-base +++ /dev/null @@ -1,6465 +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 -*/ - -#define _CRT_SECURE_NO_DEPRECATE - -#include "cheaders.h" -#include "bpqmail.h" - -#define MAIL -#include "httpconnectioninfo.h" - -#ifdef WIN32 -//#include "C:\Program Files (x86)\GnuWin32\include\iconv.h" -#else -#include -#include -#endif - -static struct HTTPConnectionInfo * FindSession(char * Key); -int APIENTRY SessionControl(int stream, int command, int param); -int SetupNodeMenu(char * Buff); -VOID SetMultiStringValue(char ** values, char * Multi); -char * GetTemplateFromFile(int Version, char * FN); -VOID FormatTime(char * Time, time_t cTime); -struct MsgInfo * GetMsgFromNumber(int msgno); -BOOL CheckUserMsg(struct MsgInfo * Msg, char * Call, BOOL SYSOP); -BOOL OkToKillMessage(BOOL SYSOP, char * Call, struct MsgInfo * Msg); -int DisplayWebForm(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, char * FileName, char * XML, char * Reply, char * RawMessage, int RawLen); -struct HTTPConnectionInfo * AllocateWebMailSession(); -VOID SaveNewMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest, int InputLen); -void ConvertTitletoUTF8(WebMailInfo * WebMail, char * Title, char * UTF8Title, int Len); -char *stristr (char *ch1, char *ch2); -char * ReadTemplate(char * FormSet, char * DirName, char * FileName); -VOID DoStandardTemplateSubsitutions(struct HTTPConnectionInfo * Session, char * txtFile); -BOOL CheckifPacket(char * Via); -int GetHTMLFormSet(char * FormSet); -void ProcessFormInput(struct HTTPConnectionInfo * Session, char * input, char * Reply, int * RLen, int InputLen); -char * WebFindPart(char ** Msg, char * Boundary, int * PartLen, char * End); -struct HTTPConnectionInfo * FindWMSession(char * Key); -int SendWebMailHeaderEx(char * Reply, char * Key, struct HTTPConnectionInfo * Session, char * Alert); -char * BuildFormMessage(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, char * Keys[1000], char * Values[1000], int NumKeys); -char * FindXMLVariable(WebMailInfo * WebMail, char * Var); -int ReplyToFormsMessage(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, char * Reply, BOOL Reenter); -BOOL ParsetxtTemplate(struct HTTPConnectionInfo * Session, struct HtmlFormDir * Dir, char * FN, BOOL isReply); -VOID UpdateFormAction(char * Template, char * Key); -BOOL APIENTRY GetAPRSLatLon(double * PLat, double * PLon); -BOOL APIENTRY GetAPRSLatLonString(char * PLat, char * PLon); -void FreeWebMailFields(WebMailInfo * WebMail); -VOID BuildXMLAttachment(struct HTTPConnectionInfo * Session, char * Keys[1000], char * Values[1000], int NumKeys); -VOID SaveTemplateMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest); -VOID DownloadAttachments(struct HTTPConnectionInfo * Session, char * Reply, int * RLen, char * Rest); -VOID getAttachmentList(struct HTTPConnectionInfo * Session, char * Reply, int * RLen, char * Rest); -char * BuildB2Header(WebMailInfo * WebMail, struct MsgInfo * Msg, char ** ToCalls, int Calls); -VOID FormatTime2(char * Time, time_t cTime); -VOID ProcessSelectResponse(struct HTTPConnectionInfo * Session, char * URLParams); -VOID ProcessAskResponse(struct HTTPConnectionInfo * Session, char * URLParams); -char * CheckFile(struct HtmlFormDir * Dir, char * FN); -VOID GetPage(struct HTTPConnectionInfo * Session, char * NodeURL); -VOID SendTemplateSelectScreen(struct HTTPConnectionInfo * Session, char *URLParams, int InputLen); -BOOL isAMPRMsg(char * Addr); -char * doXMLTransparency(char * string); -Dll BOOL APIENTRY APISendAPRSMessage(char * Text, char * ToCall); -void SendMessageReadEvent(char * Call, struct MsgInfo * Msg); -void SendNewMessageEvent(char * call, struct MsgInfo * Msg); -void MQTTMessageEvent(void* message); - -extern char NodeTail[]; -extern char BBSName[10]; - -extern char LTFROMString[2048]; -extern char LTTOString[2048]; -extern char LTATString[2048]; - - UCHAR BPQDirectory[260]; - -int LineCount = 35; // Lines per page on message list - -// Forms - -struct HtmlFormDir ** HtmlFormDirs = NULL; -int FormDirCount = 0; - -struct HtmlForm -{ - char * FileName; - BOOL HasInitial; - BOOL HasViewer; - BOOL HasReply; - BOOL HasReplyViewer; -}; - -struct HtmlFormDir -{ - char * FormSet; - char * DirName; - struct HtmlForm ** Forms; - int FormCount; - struct HtmlFormDir ** Dirs; // Nested Directories - int DirCount; -}; - - -char FormDirList[4][MAX_PATH] = {"Standard_Templates", "Standard Templates", "Local_Templates"}; - -static char PassError[] = "

Sorry, User or Password is invalid - please try again

"; -static char BusyError[] = "

Sorry, No sessions available - please try later

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

BPQ32 Mail Server %s Access

" - "

Please enter Callsign and Password to access WebMail

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

"; - -static char MsgInputPage[] = "" - "" - "" - "" - "" - "

Webmail Interface - Message Input Form

" - "
" - "
" - "To      %s
" - "Subject      " -// "" -// "
" - "" - "
Type    " - "" - " BID
" - "" - "" - "
" - "
" - "
"; - -static char CheckFormMsgPage[] = "" - "" - "" - "

Webmail Forms Interface - Check Message

" - "
" - - "
" - "To      
" - "CC      
" - "Subject " -//"" - "
Type    " - "" - " BID

" - "
" - - "
" - "
"; - - -extern char * WebMailTemplate; -extern char * WebMailMsgTemplate; -extern char * jsTemplate; - -static char *dat[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; -char *longday[] = {"Sunday", "Monday", "Tusday", "Wednesday", "Thusday", "Friday", "Saturday"}; - -static struct HTTPConnectionInfo * WebSessionList = NULL; // active WebMail sessions - -#ifdef LINBPQ -UCHAR * GetBPQDirectory(); -#endif - -void UndoTransparency(char * input); - -#ifndef LINBPQ - -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; -} -#endif - -void ReleaseWebMailStruct(WebMailInfo * WebMail) -{ - // release any malloc'ed resources - - if (WebMail == NULL) - return; - - FreeWebMailFields(WebMail); - free(WebMail); - return; -} - -VOID FreeWebMailMallocs() -{ - // called when closing. Not really needed, but simplifies tracking down real memory leaks - - struct HTTPConnectionInfo * Session, * SaveNext; - int i; - Session = WebSessionList; - - while (Session) - { - SaveNext = Session->Next; - - // Release amy malloc'ed resouces - - ReleaseWebMailStruct(Session->WebMail); - free(Session); - Session = SaveNext; - } - - for (i = 0; i < FormDirCount; i++) - { - struct HtmlFormDir * Dir = HtmlFormDirs[i]; - - int j; - - for (j = 0; j < Dir->FormCount; j++) - { - free(Dir->Forms[j]->FileName); - free(Dir->Forms[j]); - } - - if (Dir->DirCount) - { - struct HtmlFormDir * SubDir; - - int k, l; - - for (l = 0; l < Dir->DirCount; l++) - { - SubDir = Dir->Dirs[l]; - - for (k = 0; k < Dir->Dirs[l]->FormCount; k++) - { - free(SubDir->Forms[k]->FileName); - free(SubDir->Forms[k]); - } - free(SubDir->DirName); - free(SubDir->Forms); - free(SubDir->FormSet); - - free(Dir->Dirs[l]); - } - } - free(Dir->DirName); - free(Dir->Forms); - free(Dir->FormSet); - free(Dir); - } - - free(HtmlFormDirs); - return; -} - -char * initMultipartUnpack(char ** Input) -{ - // Check if Multipart and return Boundary. Update Input to first part - - // look through header for Content-Type line, and if multipart - // find boundary string. - - char * ptr, * ptr2; - char Boundary[128]; - BOOL Multipart = FALSE; - - ptr = *Input; - - while(*ptr != 13) - { - ptr2 = strchr(ptr, 10); // Find CR - - while(ptr2[1] == ' ' || ptr2[1] == 9) // Whitespace - continuation line - ptr2 = strchr(&ptr2[1], 10); // Find CR - - if (_memicmp(ptr, "Content-Type: ", 14) == 0) - { - char Line[256] = ""; - char * ptr3; - size_t len = ptr2-ptr-14; - - if (len >255) - return NULL; - - memcpy(Line, &ptr[14], len); - - if (_memicmp(Line, "Multipart/", 10) == 0) - { - ptr3 = stristr(Line, "boundary"); - if (ptr3) - { - ptr3+=9; - - if ((*ptr3) == '"') - ptr3++; - - strcpy(Boundary, ptr3); - ptr3 = strchr(Boundary, '"'); - if (ptr3) *ptr3 = 0; - ptr3 = strchr(Boundary, 13); // CR - if (ptr3) *ptr3 = 0; - break; - } - else - return NULL; // Can't do anything without a boundary ?? - } - } - ptr = ptr2; - ptr++; - } - - // Find First part - there is a boundary before it - - ptr = strstr(ptr2, Boundary); - - // Next should be crlf then part - - ptr = strstr(ptr, "\r\n"); - - if (ptr) - ptr += 2; // Over CRLF - - *Input = ptr; // Return first part or NULL - return _strdup(Boundary); -} - -BOOL unpackPart(char * Boundary, char ** Input, char ** Name, char ** Value, int * ValLen, char * End) -{ - // Format seems to be -/* - ------WebKitFormBoundaryABJaEbBWB5SuAHmq - Content-Disposition: form-data; name="Subj" - - subj - ------WebKitFormBoundaryABJaEbBWB5SuAHmq - Content-Disposition: form-data; name="myFile[]"; filename="exiftool.txt" - Content-Type: text/plain - - c:\exiftool "-filenameTo = _strdup(Value); - else if (strcmp(Name, "CC") == 0) - WebMail->CC = _strdup(Value); - else if (strcmp(Name, "Subj") == 0) - WebMail->Subject = _strdup(Value); - else if (strcmp(Name, "Type") == 0) - WebMail->Type = Value[0]; - else if (strcmp(Name, "BID") == 0) - WebMail->BID = _strdup(Value); - else if (strcmp(Name, "Msg") == 0) - WebMail->Body = _strdup(Value); - - else if (_memicmp(Name, "myFile[]", 8) == 0) - { - // Get File Name from param string - myFile[]"; filename="exiftool.txt" \r\nContent-Type: text/plain - - char * fn = strstr(Name, "filename="); - char * endfn; - if (fn) - { - fn += 10; - - endfn = strchr(fn, '"'); - if (endfn) - { - *endfn = 0; - - if (strlen(fn)) - { - WebMail->FileName[WebMail->Files] = _strdup(fn); - WebMail->FileBody[WebMail->Files] = malloc(ValLength); - memcpy(WebMail->FileBody[WebMail->Files], Value, ValLength); - WebMail->FileLen[WebMail->Files++] = ValLength; - } - } - } - } - - else if (_memicmp(Name, "myFile2[]", 8) == 0) - { - // Get File Name from param string - myFile[]"; filename="exiftool.txt" \r\nContent-Type: text/plain - - char * fn = strstr(Name, "filename="); - char * endfn; - if (fn) - { - fn += 10; - - endfn = strchr(fn, '"'); - if (endfn) - { - *endfn = 0; - - if (strlen(fn)) - { - WebMail->Header = malloc(ValLength + 1); - memcpy(WebMail->Header, Value, ValLength + 1); - WebMail->HeaderLen = RemoveLF(WebMail->Header, ValLength); - } - } - } - } - - else if (_memicmp(Name, "myFile3[]", 8) == 0) - { - // Get File Name from param string - myFile[]"; filename="exiftool.txt" \r\nContent-Type: text/plain - - char * fn = strstr(Name, "filename="); - char * endfn; - if (fn) - { - fn += 10; - - endfn = strchr(fn, '"'); - if (endfn) - { - *endfn = 0; - - if (strlen(fn)) - { - WebMail->Footer = malloc(ValLength + 1); - memcpy(WebMail->Footer, Value, ValLength + 1); - WebMail->FooterLen = RemoveLF(WebMail->Footer, ValLength); - } - } - } - } - - return TRUE; -} - - -struct HTTPConnectionInfo * AllocateWebMailSession() -{ - int KeyVal; - struct HTTPConnectionInfo * Session, * SaveNext; - time_t NOW = time(NULL); - - // First see if any session records havent been used for a while - - Session = WebSessionList; - - while (Session) - { - if (NOW - Session->WebMailLastUsed > 1200) // 20 Mins - { - SaveNext = Session->Next; - - // Release amy malloc'ed resouces - - ReleaseWebMailStruct(Session->WebMail); - - memset(Session, 0, sizeof(struct HTTPConnectionInfo)); - - Session->Next = SaveNext; - goto UseThis; - } - Session = Session->Next; - } - - Session = zalloc(sizeof(struct HTTPConnectionInfo)); - - if (Session == NULL) - return NULL; - - if (WebSessionList) - Session->Next = WebSessionList; - - WebSessionList = Session; - -UseThis: - - Session->WebMail = zalloc(sizeof(WebMailInfo)); - - KeyVal = ((rand() % 100) + 1); - - KeyVal *= (int)time(NULL); - - sprintf(Session->Key, "%c%08X", 'W', KeyVal); - - return Session; -} - -struct HTTPConnectionInfo * FindWMSession(char * Key) -{ - struct HTTPConnectionInfo * Session = WebSessionList; - - while (Session) - { - if (strcmp(Session->Key, Key) == 0) - { - Session->WebMailLastUsed = time(NULL); - return Session; - } - Session = Session->Next; - } - - return NULL; -} - - -// Build list of available forms - -VOID ProcessFormDir(char * FormSet, char * DirName, struct HtmlFormDir *** xxx, int * DirCount) -{ - struct HtmlFormDir * FormDir; - struct HtmlFormDir ** FormDirs = *xxx; - struct HtmlForm * Form; - char Search[MAX_PATH]; - int count = *DirCount; - -#ifdef WIN32 - HANDLE hFind = INVALID_HANDLE_VALUE; - WIN32_FIND_DATA ffd; -#else - DIR *dir; - struct dirent *entry; - char name[256]; -#endif - - FormDir = zalloc(sizeof (struct HtmlFormDir)); - - FormDir->DirName = _strdup(DirName); - FormDir->FormSet = _strdup(FormSet); - FormDirs=realloc(FormDirs, (count + 1) * sizeof(void *)); - FormDirs[count++] = FormDir; - - *DirCount = count; - *xxx = FormDirs; - - - // Scan Directory for .txt files - - sprintf(Search, "%s/%s/%s/*", GetBPQDirectory(), FormSet, DirName); - - // Find the first file in the directory. - -#ifdef WIN32 - - hFind = FindFirstFile(Search, &ffd); - - if (INVALID_HANDLE_VALUE == hFind) - return; - - do - { - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - char Dir[MAX_PATH]; - - if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0) - continue; - - // Recurse in subdir - - sprintf(Dir, "%s/%s", DirName, ffd.cFileName); - - ProcessFormDir(FormSet, Dir, &FormDir->Dirs, &FormDir->DirCount); - - continue; - - } - - // Add to list - - Form = zalloc(sizeof (struct HtmlForm)); - - Form->FileName = _strdup(ffd.cFileName); - - FormDir->Forms=realloc(FormDir->Forms, (FormDir->FormCount + 1) * sizeof(void *)); - FormDir->Forms[FormDir->FormCount++] = Form; - } - - while (FindNextFile(hFind, &ffd) != 0); - - FindClose(hFind); - -#else - - sprintf(Search, "%s/%s/%s", GetBPQDirectory(), FormSet, DirName); - - if (!(dir = opendir(Search))) - { - Debugprintf("%s %d %d", "cant open forms dir", errno, dir); - return ; - } - while ((entry = readdir(dir)) != NULL) - { - if (entry->d_type == DT_DIR) - { - char Dir[MAX_PATH]; - - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - // Recurse in subdir - - sprintf(Dir, "%s/%s", DirName, entry->d_name); - - ProcessFormDir(FormSet, Dir, &FormDir->Dirs, &FormDir->DirCount); - continue; - } - - // Add to list - - Form = zalloc(sizeof (struct HtmlForm)); - - Form->FileName = _strdup(entry->d_name); - - FormDir->Forms=realloc(FormDir->Forms, (FormDir->FormCount + 1) * sizeof(void *)); - FormDir->Forms[FormDir->FormCount++] = Form; - } - closedir(dir); -#endif - return; -} - -int GetHTMLForms() -{ - int n = 0; - - while (FormDirList[n][0]) - GetHTMLFormSet(FormDirList[n++]); - - return 0; -} - -int GetHTMLFormSet(char * FormSet) -{ - int i; - -#ifdef WIN32 - - WIN32_FIND_DATA ffd; - char szDir[MAX_PATH]; - HANDLE hFind = INVALID_HANDLE_VALUE; - DWORD dwError=0; - - sprintf(szDir, "%s/%s/*", BPQDirectory, FormSet); - - // Find the first file in the directory. - - hFind = FindFirstFile(szDir, &ffd); - - if (INVALID_HANDLE_VALUE == hFind) - { - // Accept either - return 0; - } - - // Scan all directories looking for file - - do - { - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0) - continue; - - // Add to Directory List - - ProcessFormDir(FormSet, ffd.cFileName, &HtmlFormDirs, &FormDirCount); - } - } - - while (FindNextFile(hFind, &ffd) != 0); - - FindClose(hFind); - -#else - - DIR *dir; - struct dirent *entry; - char name[256]; - - sprintf(name, "%s/%s", BPQDirectory, FormSet); - - if (!(dir = opendir(name))) - { - Debugprintf("cant open forms dir %s %d %d", name, errno, dir); - } - else - { - while ((entry = readdir(dir)) != NULL) - { - if (entry->d_type == DT_DIR) - { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - // Add to Directory List - - ProcessFormDir(FormSet, entry->d_name, &HtmlFormDirs, &FormDirCount); - } - } - closedir(dir); - } -#endif - - // List for testing - - return 0; - - Debugprintf("%d form dirs", FormDirCount); - - for (i = 0; i < FormDirCount; i++) - { - struct HtmlFormDir * Dir = HtmlFormDirs[i]; - - int j; - Debugprintf("%3d %s", Dir->FormCount, Dir->DirName); - - for (j = 0; j < Dir->FormCount; j++) - Debugprintf(" %s", Dir->Forms[j]->FileName); - - if (Dir->DirCount) - { - int k, l; - - for (l = 0; l < Dir->DirCount; l++) - { - Debugprintf("Subdir %3d %s", Dir->Dirs[l]->DirCount, Dir->Dirs[l]->DirName); - for (k = 0; k < Dir->Dirs[l]->FormCount; k++) - Debugprintf(" %s", Dir->Dirs[l]->Forms[k]->FileName); - } - } - } - - - return 0; -} - - -static int compare(const void *arg1, const void *arg2) -{ - // Compare Calls. Fortunately call is at start of stuct - - return _stricmp(*(char**)arg1 , *(char**)arg2); -} - - -int SendWebMailHeader(char * Reply, char * Key, struct HTTPConnectionInfo * Session) -{ - return SendWebMailHeaderEx(Reply, Key, Session, NULL); -} - - -int SendWebMailHeaderEx(char * Reply, char * Key, struct HTTPConnectionInfo * Session, char * Alert) -{ - // Ex includes an alert string to be sent before message - - struct UserInfo * User = Session->User; - char Messages[245000]; - int m; - struct MsgInfo * Msg; - char * ptr = Messages; - int n = NumberofMessages; //LineCount; - char Via[64]; - int Count = 0; - - Messages[0] = 0; - - if (Alert && Alert[0]) - ptr += sprintf(Messages, "", Alert, Key); - - ptr += sprintf(ptr, "%s", " # Date XX Len To @ From Subject\r\n\r\n"); - - for (m = LatestMsg; m >= 1; m--) - { - if (ptr > &Messages[244000]) - break; // protect buffer - - Msg = GetMsgFromNumber(m); - - if (Msg == 0 || Msg->type == 0 || Msg->status == 0) - continue; // Protect against corrupt messages - - if (Msg && CheckUserMsg(Msg, User->Call, User->flags & F_SYSOP)) - { - char UTF8Title[4096]; - char * EncodedTitle; - - // List if it is the right type and in the page range we want - - if (Session->WebMailTypes[0] && strchr(Session->WebMailTypes, Msg->type) == 0) - continue; - - // All Types or right Type. Check Mine Flag - - if (Session->WebMailMine) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->to) != 0 && strcmp(User->Call, Msg->from) != 0) - continue; - } - - if (Session->WebMailMyTX) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->from) != 0) - continue; - } - - if (Session->WebMailMyRX) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->to)!= 0) - continue; - } - - if (Count++ < Session->WebMailSkip) - continue; - - strcpy(Via, Msg->via); - strlop(Via, '.'); - - // make sure title is HTML safe (no < > etc) and UTF 8 encoded - - EncodedTitle = doXMLTransparency(Msg->title); - - memset(UTF8Title, 0, 4096); // In case convert fails part way through - ConvertTitletoUTF8(Session->WebMail, EncodedTitle, UTF8Title, 4095); - - free(EncodedTitle); - - ptr += sprintf(ptr, "
%6d %s %c%c %5d %-8s%-8s%-8s%s\r\n", - Key, Msg->number, Msg->number, - FormatDateAndTime((time_t)Msg->datecreated, TRUE), Msg->type, - Msg->status, Msg->length, Msg->to, Via, - Msg->from, UTF8Title); - - n--; - - if (n == 0) - break; - } - } - - if (WebMailTemplate == NULL) - WebMailTemplate = GetTemplateFromFile(6, "WebMailPage.txt"); - - return sprintf(Reply, WebMailTemplate, BBSName, User->Call, Key, Key, Key, Key, Key, Key, Key, Key, Key, Key, Messages); -} - -int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Number, BOOL DisplayHTML) -{ - char * Key = Session->Key; - struct UserInfo * User = Session->User; - WebMailInfo * WebMail = Session->WebMail; - char * DisplayStyle; - - char Message[200000] = ""; - struct MsgInfo * Msg; - char * ptr = Message; - char * MsgBytes, * Save; - int msgLen; - - char FullTo[100]; - char UTF8Title[4096]; - int Index; - char * crcrptr; - char DownLoad[256] = ""; - - DisplayStyle = "textarea"; // Prevents interpretation of html and xml - - Msg = GetMsgFromNumber(Number); - - if (Msg == NULL) - { - ptr += sprintf(ptr, "Message %d not found\r\n", Number); - return sprintf(Reply, WebMailTemplate, BBSName, User->Call, Key, Key, Key, Key, Key, Key, Key, Message); - } - - // New Display so free any old values - - FreeWebMailFields(WebMail); - - WebMail->CurrentMessageIndex = Number; - - - if (!CheckUserMsg(Msg, User->Call, User->flags & F_SYSOP)) - { - ptr += sprintf(ptr, "Message %d not for you\r", Number); - return sprintf(Reply, WebMailTemplate, BBSName, User->Call, Key, Key, Key, Key, Key, Key, Key, Message); - } - - if (_stricmp(Msg->to, "RMS") == 0) - sprintf(FullTo, "RMS:%s", Msg->via); - else - if (Msg->to[0] == 0) - sprintf(FullTo, "smtp:%s", Msg->via); - else - strcpy(FullTo, Msg->to); - - // make sure title is UTF 8 encoded - - memset(UTF8Title, 0, 4096); // In case convert fails part way through - ConvertTitletoUTF8(Session->WebMail, Msg->title, UTF8Title, 4095); - - // if a B2 message diplay B2 Header instead of a locally generated one - - if ((Msg->B2Flags & B2Msg) == 0) - { - ptr += sprintf(ptr, "From: %s%s\nTo: %s\nType/Status: %c%c\nDate/Time: %s\nBid: %s\nTitle: %s\n\n", - Msg->from, Msg->emailfrom, FullTo, Msg->type, Msg->status, FormatDateAndTime((time_t)Msg->datecreated, FALSE), Msg->bid, UTF8Title); - } - - MsgBytes = Save = ReadMessageFile(Number); - - msgLen = Msg->length; - - if (Msg->type == 'P') - Index = PMSG; - else if (Msg->type == 'B') - Index = BMSG; - else - Index = TMSG; - - if (MsgBytes) - { - if (Msg->B2Flags & B2Msg) - { - char * ptr1; - - // if message has attachments, display them if plain text - - if (Msg->B2Flags & Attachments) - { - int BodyLen, NewLen; - int i; - char *ptr2, *attptr; - - sprintf(DownLoad, "Save Attachments", Key, Msg->number); - - WebMail->Files = 0; - - ptr1 = MsgBytes; - - // ptr += sprintf(ptr, "Message has Attachments\r\n\r\n"); - - while(*ptr1 != 13) - { - ptr2 = strchr(ptr1, 10); // Find CR - - if (memcmp(ptr1, "Body: ", 6) == 0) - { - BodyLen = atoi(&ptr1[6]); - } - - if (memcmp(ptr1, "File: ", 6) == 0) - { - char * ptr3 = strchr(&ptr1[6], ' '); // Find Space - *(ptr2 - 1) = 0; - - WebMail->FileLen[WebMail->Files] = atoi(&ptr1[6]); - WebMail->FileName[WebMail->Files++] = _strdup(&ptr3[1]); - *(ptr2 - 1) = ' '; // put space back - } - - ptr1 = ptr2; - ptr1++; - } - - ptr1 += 2; // Over Blank Line and Separator - - // ptr1 is pointing to body. Save for possible reply - - WebMail->Body = malloc(BodyLen + 2); - memcpy(WebMail->Body, ptr1, BodyLen); - WebMail->Body[BodyLen] = 0; - - *(ptr1 + BodyLen) = 0; - - ptr += sprintf(ptr, "%s", MsgBytes); // B2 Header and Body - - ptr1 += BodyLen + 2; // to first file - - // Save pointers to file - - attptr = ptr1; - - for (i = 0; i < WebMail->Files; i++) - { - WebMail->FileBody[i] = malloc(WebMail->FileLen[i]); - memcpy(WebMail->FileBody[i], attptr, WebMail->FileLen[i]); - attptr += (WebMail->FileLen[i] + 2); - } - - // if first (only??) attachment is XML and filename - // starts "RMS_Express_Form" process as HTML Form - - if (DisplayHTML && _memicmp(ptr1, "FileName[0], "RMS_Express_Form_", 16) == 0) - { - int Len = DisplayWebForm(Session, Msg, WebMail->FileName[0], ptr1, Reply, MsgBytes, BodyLen + 32); // 32 for added "has attachments" - free(MsgBytes); - - // Flag as read - - if ((_stricmp(Msg->to, User->Call) == 0) || ((User->flags & F_SYSOP) && (_stricmp(Msg->to, "SYSOP") == 0))) - { - if ((Msg->status != 'K') && (Msg->status != 'H') && (Msg->status != 'F') && (Msg->status != 'D')) - { - if (Msg->status != 'Y') - { - Msg->status = 'Y'; - Msg->datechanged=time(NULL); - SaveMessageDatabase(); - SendMessageReadEvent(Session->Callsign, Msg); - } - } - } - - return Len; - } - - for (i = 0; i < WebMail->Files; i++) - { - int n; - char * p = ptr1; - char c; - - // Check if message is probably binary - - int BinCount = 0; - - NewLen = WebMail->FileLen[i]; - - for (n = 0; n < NewLen; n++) - { - c = *p; - - if (c==0 || (c & 128)) - BinCount++; - - p++; - - } - - if (BinCount > NewLen/10) - { - // File is probably Binary - - ptr += sprintf(ptr, "\rAttachment %s is a binary file\r", WebMail->FileName[i]); - } - else - { - *(ptr1 + NewLen) = 0; - ptr += sprintf(ptr, "\rAttachment %s\r\r", WebMail->FileName[i]); - RemoveLF(ptr1, NewLen + 1); // Removes LF after CR but not on its own - - ptr += sprintf(ptr, "%s\r\r", ptr1); - - User->Total.MsgsSent[Index] ++; - User->Total.BytesForwardedOut[Index] += NewLen; - } - - ptr1 += WebMail->FileLen[i]; - ptr1 +=2; // Over separator - } - - free(Save); - - ptr += sprintf(ptr, "\r\r[End of Message #%d from %s]\r", Number, Msg->from); - - RemoveLF(Message, (int)strlen(Message) + 1); // Removes LF after CR but not on its own - - if ((_stricmp(Msg->to, User->Call) == 0) || ((User->flags & F_SYSOP) && (_stricmp(Msg->to, "SYSOP") == 0))) - { - if ((Msg->status != 'K') && (Msg->status != 'H') && (Msg->status != 'F') && (Msg->status != 'D')) - { - if (Msg->status != 'Y') - { - Msg->status = 'Y'; - Msg->datechanged=time(NULL); - SaveMessageDatabase(); - SendMessageReadEvent(Session->Callsign, Msg); - } - } - } - - if (DisplayHTML && stristr(Message, "")) - DisplayStyle = "div"; // Use div so HTML and XML are interpreted - - return sprintf(Reply, WebMailMsgTemplate, BBSName, User->Call, Msg->number, Msg->number, Key, Msg->number, Key, DownLoad, Key, Key, Key, DisplayStyle, Message, DisplayStyle); - } - - // Remove B2 Headers (up to the File: Line) - - // ptr1 = strstr(MsgBytes, "Body:"); - - // if (ptr1) - // MsgBytes = ptr1; - } - - // Body may have cr cr lf which causes double space - - crcrptr = strstr(MsgBytes, "\r\r\n"); - - while (crcrptr) - { - *crcrptr = ' '; - crcrptr = strstr(crcrptr, "\r\r\n"); - } - - // Remove lf chars - - msgLen = RemoveLF(MsgBytes, msgLen); - - User->Total.MsgsSent[Index] ++; - // User->Total.BytesForwardedOut[Index] += Length; - - // if body not UTF-8, convert it - - if (WebIsUTF8(MsgBytes, msgLen) == FALSE) - { - int code = TrytoGuessCode(MsgBytes, msgLen); - - UCHAR * UTF = malloc(msgLen * 3); - - if (code == 437) - msgLen = Convert437toUTF8(MsgBytes, msgLen, UTF); - else if (code == 1251) - msgLen = Convert1251toUTF8(MsgBytes, msgLen, UTF); - else - msgLen = Convert1252toUTF8(MsgBytes, msgLen, UTF); - - free(MsgBytes); - Save = MsgBytes = UTF; - - MsgBytes[msgLen] = 0; - } - - // ptr += sprintf(ptr, "%s", MsgBytes); - - memcpy(ptr, MsgBytes, msgLen); - ptr += msgLen; - ptr[0] = 0; - - free(Save); - - ptr += sprintf(ptr, "\r\r[End of Message #%d from %s]\r", Number, Msg->from); - - if ((_stricmp(Msg->to, User->Call) == 0) || ((User->flags & F_SYSOP) && (_stricmp(Msg->to, "SYSOP") == 0))) - { - if ((Msg->status != 'K') && (Msg->status != 'H') && (Msg->status != 'F') && (Msg->status != 'D')) - { - if (Msg->status != 'Y') - { - Msg->status = 'Y'; - Msg->datechanged=time(NULL); - SaveMessageDatabase(); - SendMessageReadEvent(Session->Callsign, Msg); - } - } - } - } - else - { - ptr += sprintf(ptr, "File for Message %d not found\r", Number); - } - - if (DisplayHTML && stristr(Message, "")) - DisplayStyle = "div"; // Use div so HTML and XML are interpreted - - - return sprintf(Reply, WebMailMsgTemplate, BBSName, User->Call, Msg->number, Msg->number, Key, Msg->number, Key, DownLoad, Key, Key, Key, DisplayStyle, Message, DisplayStyle); -} - -int KillWebMailMessage(char * Reply, char * Key, struct UserInfo * User, int Number) -{ - struct MsgInfo * Msg; - char Message[100] = ""; - - Msg = GetMsgFromNumber(Number); - - if (Msg == NULL) - { - sprintf(Message, "Message %d not found", Number); - goto returnit; - } - - if (OkToKillMessage(User->flags & F_SYSOP, User->Call, Msg)) - { - FlagAsKilled(Msg, TRUE); - sprintf(Message, "Message #%d Killed\r", Number); - goto returnit; - } - - sprintf(Message, "Not your message\r"); - -returnit: - return sprintf(Reply, WebMailMsgTemplate, BBSName, User->Call, Msg->number, Msg->number, Key, Msg->number, Key, "", Key, Key, Key, "div", Message, "div"); -} - -void freeKeys(KeyValues * Keys) -{ - while (Keys->Key) - { - free(Keys->Key); - free(Keys->Value); - Keys++; - } -} - -void FreeWebMailFields(WebMailInfo * WebMail) -{ - // release any malloc'ed resources - - int i; - char * SaveReply; - int * SaveRlen; - - if (WebMail == NULL) - return; - - if (WebMail->txtFile) - free(WebMail->txtFile); - - if (WebMail->txtFileName) - free(WebMail->txtFileName); - - if (WebMail->InputHTMLName) - free(WebMail->InputHTMLName); - - if (WebMail->DisplayHTMLName) - free(WebMail->DisplayHTMLName); - - if (WebMail->ReplyHTMLName) - free(WebMail->ReplyHTMLName); - - if (WebMail->To) - free(WebMail->To); - if (WebMail->CC) - free(WebMail->CC); - if (WebMail->Subject) - free(WebMail->Subject); - if (WebMail->BID) - free(WebMail->BID); - if (WebMail->Body) - free(WebMail->Body); - if (WebMail->XML) - free(WebMail->XML); - if (WebMail->XMLName) - free(WebMail->XMLName); - - if (WebMail->OrigTo) - free(WebMail->OrigTo); - if (WebMail->OrigSubject) - free(WebMail->OrigSubject); - if (WebMail->OrigBID) - free(WebMail->OrigBID); - if (WebMail->OrigBody) - free(WebMail->OrigBody); - - freeKeys(WebMail->txtKeys); - freeKeys(WebMail->XMLKeys); - - for (i = 0; i < WebMail->Files; i++) - { - free(WebMail->FileBody[i]); - free(WebMail->FileName[i]); - } - - if (WebMail->Header) - free(WebMail->Header); - if (WebMail->Footer) - free(WebMail->Footer); - - SaveReply = WebMail->Reply; - SaveRlen = WebMail->RLen; - -#ifndef WIN32 - if (WebMail->iconv_toUTF8) - iconv_close(WebMail->iconv_toUTF8); -#endif - - memset(WebMail, 0, sizeof(WebMailInfo)); - - WebMail->Reply = SaveReply; - WebMail->RLen = SaveRlen; - - return; -} - - -void ProcessWebMailMessage(struct HTTPConnectionInfo * Session, char * Key, BOOL LOCAL, char * Method, char * NodeURL, char * input, char * Reply, int * RLen, int InputLen) -{ - char * URLParams = strlop(Key, '&'); - int ReplyLen; - char Appl = 'M'; - - // Webmail doesn't use the normal Mail Key. - - // webscript.js doesn't need a key - - if (_stricmp(NodeURL, "/WebMail/webscript.js") == 0) - { - if (jsTemplate) - free(jsTemplate); - - jsTemplate = GetTemplateFromFile(2, "webscript.js"); - - ReplyLen = sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n" - "Cache-Control: max-age=60\r\nContent-Type: text/javascript\r\n\r\n%s", (int)strlen(jsTemplate), jsTemplate); - *RLen = ReplyLen; - return; - } - - // Neither do js or file downloads - - // This could be a request for a Template file - // WebMail/Local_Templates/My Forms/inc/logo_ad63.png - // WebMail/Standard Templates/ - - - if (_memicmp(NodeURL, "/WebMail/Local", 14) == 0 || (_memicmp(NodeURL, "/WebMail/Standard", 17) == 0)) - { - int FileSize; - char * MsgBytes; - char MsgFile[512]; - FILE * hFile; - size_t ReadLen; - char TimeString[64]; - char FileTimeString[64]; - struct stat STAT; - char * FN = &NodeURL[9]; - char * fileBit = FN; - char * ext; - char Type[64] = "Content-Type: text/html\r\n"; - - UndoTransparency(FN); - ext = strchr(FN, '.'); - - sprintf(MsgFile, "%s/%s", BPQDirectory, FN); - - while (strchr(fileBit, '/')) - fileBit = strlop(fileBit, '/'); - - if (stat(MsgFile, &STAT) == -1) - { - *RLen = sprintf(Reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 16\r\n\r\nPage not found\r\n"); - return; - } - - hFile = fopen(MsgFile, "rb"); - - if (hFile == 0) - { - *RLen = sprintf(Reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 16\r\n\r\nPage not found\r\n"); - return; - } - - FileSize = STAT.st_size; - MsgBytes = malloc(FileSize + 1); - ReadLen = fread(MsgBytes, 1, FileSize, hFile); - - fclose(hFile); - - FormatTime2(FileTimeString, STAT.st_ctime); - FormatTime2(TimeString, time(NULL)); - - ext++; - - if (_stricmp(ext, "js") == 0) - strcpy(Type, "Content-Type: text/javascript\r\n"); - - if (_stricmp(ext, "css") == 0) - strcpy(Type, "Content-Type: text/css\r\n"); - - if (_stricmp(ext, "pdf") == 0) - strcpy(Type, "Content-Type: application/pdf\r\n"); - - if (_stricmp(ext, "jpg") == 0 || _stricmp(ext, "jpeg") == 0 || _stricmp(ext, "png") == 0 || - _stricmp(ext, "gif") == 0 || _stricmp(ext, "bmp") == 0 || _stricmp(ext, "ico") == 0) - strcpy(Type, "Content-Type: image\r\n"); - - // File may be binary so output header then copy in message - - *RLen = sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n" - "%s" - "Date: %s\r\n" - "Last-Modified: %s\r\n" - "\r\n", FileSize, Type,TimeString, FileTimeString); - - memcpy(&Reply[*RLen], MsgBytes, FileSize); - *RLen += FileSize; - free (MsgBytes); - return; - } - - // - - if (_memicmp(NodeURL, "/WebMail/WMFile/", 16) == 0) - { - int FileSize; - char * MsgBytes; - char MsgFile[512]; - FILE * hFile; - size_t ReadLen; - char TimeString[64]; - char FileTimeString[64]; - struct stat STAT; - char * FN = &NodeURL[16]; - char * fileBit = FN; - char * ext; - char Type[64] = "Content-Type: text/html\r\n"; - - - UndoTransparency(FN); - ext = strchr(FN, '.'); - - sprintf(MsgFile, "%s/%s", BPQDirectory, FN); - - while (strchr(fileBit, '/')) - fileBit = strlop(fileBit, '/'); - - if (stat(MsgFile, &STAT) == -1) - { - *RLen = sprintf(Reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 16\r\n\r\nPage not found\r\n"); - return; - } - - hFile = fopen(MsgFile, "rb"); - - if (hFile == 0) - { - *RLen = sprintf(Reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 16\r\n\r\nPage not found\r\n"); - return; - } - - FileSize = STAT.st_size; - MsgBytes = malloc(FileSize + 1); - ReadLen = fread(MsgBytes, 1, FileSize, hFile); - - fclose(hFile); - - FormatTime2(FileTimeString, STAT.st_ctime); - FormatTime2(TimeString, time(NULL)); - - ext++; - - if (_stricmp(ext, "js") == 0) - strcpy(Type, "Content-Type: text/javascript\r\n"); - - if (_stricmp(ext, "css") == 0) - strcpy(Type, "Content-Type: text/css\r\n"); - - if (_stricmp(ext, "pdf") == 0) - strcpy(Type, "Content-Type: application/pdf\r\n"); - - if (_stricmp(ext, "jpg") == 0 || _stricmp(ext, "jpeg") == 0 || _stricmp(ext, "png") == 0 || - _stricmp(ext, "gif") == 0 || _stricmp(ext, "bmp") == 0 || _stricmp(ext, "ico") == 0) - strcpy(Type, "Content-Type: image\r\n"); - - // File may be binary so output header then copy in message - - *RLen = sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n" - "%s" - "Date: %s\r\n" - "Last-Modified: %s\r\n" - "\r\n", FileSize, Type,TimeString, FileTimeString); - - memcpy(&Reply[*RLen], MsgBytes, FileSize); - *RLen += FileSize; - free (MsgBytes); - return; - } - - Session = NULL; - - if (Key && Key[0]) - Session = FindWMSession(Key); - - if (Session == NULL) - { - // Lost Session - - if (LOCAL) - { - Session = AllocateWebMailSession(); - - Key = Session->Key; - - if (SYSOPCall[0]) - Session->User = LookupCall(SYSOPCall); - else - Session->User = LookupCall(BBSName); - - if (Session->User) - { - strcpy(NodeURL, "/WebMail/WebMail"); - Session->WebMailSkip = 0; - Session->WebMailLastUsed = time(NULL); - } - } - else - { - // Send Login Page unless Signon request - - if (_stricmp(NodeURL, "/WebMail/Signon") != 0 || strcmp(Method, "POST") != 0) - { - ReplyLen = sprintf(Reply, WebMailSignon, BBSName, BBSName); - *RLen = ReplyLen; - return; - } - } - } - - if (strcmp(Method, "POST") == 0) - { - if (_stricmp(NodeURL, "/WebMail/Signon") == 0) - { - char * msg = strstr(input, "\r\n\r\n"); // End of headers - char * user, * password, * Key; - char Msg[128]; - int n; - - if (msg) - { - struct UserInfo * User; - - if (strstr(msg, "Cancel=Cancel")) - { - *RLen = sprintf(Reply, ""); - return; - } - // Webmail Gets Here with a dummy Session - - Session = AllocateWebMailSession(); - Session->WebMail->Reply = Reply; - Session->WebMail->RLen = RLen; - - - Key = Session->Key; - - user = strtok_s(&msg[9], "&", &Key); - password = strtok_s(NULL, "=", &Key); - password = Key; - - Session->User = User = LookupCall(user); - - if (User) - { - // Check Password - - if (password[0] && strcmp(User->pass, password) == 0) - { - // send Message Index - - Session->WebMailLastUsed = time(NULL); - Session->WebMailSkip = 0; - Session->WebMailMyTX = FALSE; - Session->WebMailMyRX = FALSE; - Session->WebMailMine = FALSE; - - if (WebMailTemplate) - { - free(WebMailTemplate); - WebMailTemplate = NULL; - } - - if (User->flags & F_Excluded) - { - n = sprintf_s(Msg, sizeof(Msg), "Webmail Connect from %s Rejected by Exclude Flag", _strupr(user)); - WriteLogLine(NULL, '|',Msg, n, LOG_BBS); - ReplyLen = sprintf(Reply, WebMailSignon, BBSName, BBSName); - *RLen = ReplyLen; - return; - } - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - n=sprintf_s(Msg, sizeof(Msg), "Webmail Connect from %s", _strupr(user)); - WriteLogLine(NULL, '|',Msg, n, LOG_BBS); - - return; - } - - } - - // Bad User or Pass - - ReplyLen = sprintf(Reply, WebMailSignon, BBSName, BBSName); - *RLen = ReplyLen; - return; - } - } - - Session->WebMail->Reply = Reply; - Session->WebMail->RLen = RLen; - - if (_stricmp(NodeURL, "/WebMail/EMSave") == 0) - { - // Save New Message - - SaveNewMessage(Session, input, Reply, RLen, Key, InputLen); - return; - } - - if (_stricmp(NodeURL, "/WebMail/Submit") == 0) - { - // Get the POST data from the page and place in message - - char * param = strstr(input, "\r\n\r\n"); // End of headers - WebMailInfo * WebMail = Session->WebMail; - - if (WebMail == NULL) - return; // Can't proceed if we have no info on form - - ProcessFormInput(Session, input, Reply, RLen, InputLen); - return; - } - - if (_stricmp(NodeURL, "/WebMail/FormMsgSave") == 0) - { - // Save New Message - - SaveTemplateMessage(Session, input, Reply, RLen, Key); - return; - } - - if (_stricmp(NodeURL, "/WebMail/GetTemplates") == 0) - { - SendTemplateSelectScreen(Session, input, InputLen); - return; - } - - // End of POST section - } - - if (_stricmp(NodeURL, "/WebMail/WMLogout") == 0) - { - Session->Key[0] = 0; - Session->WebMailLastUsed = 0; - ReplyLen = sprintf(Reply, WebMailSignon, BBSName, BBSName); - *RLen = ReplyLen; - return; - } - - if ((_stricmp(NodeURL, "/WebMail/MailEntry") == 0) || - (_stricmp(NodeURL, "/WebMail") == 0) || - (_stricmp(NodeURL, "/WebMail/") == 0)) - { - // Entry from Menu if signed in, continue. If not and Localhost - // signin as sysop. - - if (Session->User == NULL) - { - // Not yet signed in - - if (LOCAL) - { - // Webmail Gets Here with a dummy Session - - Session = AllocateWebMailSession(); - Session->WebMail->Reply = Reply; - Session->WebMail->RLen = RLen; - - Key = Session->Key; - - if (SYSOPCall[0]) - Session->User = LookupCall(SYSOPCall); - else - Session->User = LookupCall(BBSName); - - if (Session->User) - { - strcpy(NodeURL, "/WebMail/WebMail"); - Session->WebMailSkip = 0; - Session->WebMailLastUsed = time(NULL); - } - } - else - { - // Send Login Page - - ReplyLen = sprintf(Reply, WebMailSignon, BBSName, BBSName); - *RLen = ReplyLen; - return; - } - } - } - - Session->WebMail->Reply = Reply; - Session->WebMail->RLen = RLen; - - if (_stricmp(NodeURL, "/WebMail/WebMail") == 0) - { - if (WebMailTemplate) - { - free(WebMailTemplate); - WebMailTemplate = NULL; - } - - Session->WebMailSkip = 0; - Session->WebMailMine = FALSE; - Session->WebMailMyTX = FALSE; - Session->WebMailMyRX = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMAll") == 0) - { - Session->WebMailSkip = 0; - Session->WebMailTypes[0] = 0; - Session->WebMailMine = FALSE; - Session->WebMailMyTX = FALSE; - Session->WebMailMyRX = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMB") == 0) - { - Session->WebMailSkip = 0; - strcpy(Session->WebMailTypes, "B"); - Session->WebMailMine = FALSE; - Session->WebMailMyTX = FALSE; - Session->WebMailMyRX = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMP") == 0) - { - Session->WebMailSkip = 0; - strcpy(Session->WebMailTypes, "P"); - Session->WebMailMine = FALSE; - Session->WebMailMyTX = FALSE; - Session->WebMailMyRX = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMT") == 0) - { - Session->WebMailSkip = 0; - strcpy(Session->WebMailTypes, "T"); - Session->WebMailMine = FALSE; - Session->WebMailMyTX = FALSE; - Session->WebMailMyRX = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMMine") == 0) - { - Session->WebMailSkip = 0; - Session->WebMailTypes[0] = 0; - Session->WebMailMine = TRUE; - Session->WebMailMyTX = FALSE; - Session->WebMailMyRX = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMtoMe") == 0) - { - Session->WebMailSkip = 0; - Session->WebMailTypes[0] = 0; - Session->WebMailMine = FALSE; - Session->WebMailMyTX = FALSE; - Session->WebMailMyRX = TRUE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMfromMe") == 0) - { - Session->WebMailSkip = 0; - Session->WebMailTypes[0] = 0; - Session->WebMailMine = TRUE; - Session->WebMailMyTX = TRUE; - Session->WebMailMyRX = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - - if (_stricmp(NodeURL, "/WebMail/WMSame") == 0) - { - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMAuto") == 0) - { - // Auto Refresh Version of index page. Uses Web Sockets - - char Page[4096]; - - char WebSockPage[] = - "\r\n" - " \r\n" - " \r\n" - " \r\n" - " \r\n" - "\r\n" - "\r\n" - - "\r\n" - "WebMail \r\n" - "\r\n" - - "\r\n" - "

%s Webmail Interface - User %s - Message List

\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "
BullsPersonalNTSAll TypesMineMy SentMy RxedAuto RefreshSend MessageLogoutNode Menu
\r\n" - "
\r\n" - - "
Waiting for data...
\r\n" - "\r\n"; - - sprintf(Page, WebSockPage, Key, Key ,BBSName, Session->User->Call, Key, Key, Key, Key, Key, Key, Key, Key, Key, Key); - - *RLen = sprintf(Reply, "%s", Page); - return; - } - - - if (memcmp(NodeURL, "/WebMail/QuoteOriginal/", 15) == 0) - { - // Reply to Message - - int n, len; - struct MsgInfo * Msg; - char Message[100] = ""; - char Title[100]; - char * MsgBytes, * Save, * NewBytes; - char * ptr; - char * ptr1, * ptr2; - char * EncodedTitle; - - n = Session->WebMail->CurrentMessageIndex; - - Msg = GetMsgFromNumber(n); - - if (Msg == NULL) - { - sprintf(Message, "Message %d not found", n); - *RLen = sprintf(Reply, "%s", Message); - return; - } - - Session->WebMail->Msg = Msg; - - if (stristr(Msg->title, "Re:") == 0) - sprintf(Title, "Re:%s", Msg->title); - else - sprintf(Title, "%s", Msg->title); - - MsgBytes = Save = ReadMessageFile(n); - - - ptr = NewBytes = malloc((Msg->length * 2) + 256); - - // Copy a line at a time with "> " in front of each - - ptr += sprintf(ptr, "%s", "\r\n\r\n\r\n\r\n\r\nOriginal Message\r\n\r\n> "); - - ptr1 = ptr2 = MsgBytes; - len = (int)strlen(MsgBytes); - - while (len-- > 0) - { - *ptr++ = *ptr1; - - if (*(ptr1) == '\n') - { - *ptr++ = '>'; - *ptr++ = ' '; - } - - ptr1++; - } - - *ptr++ = 0; - - EncodedTitle = doXMLTransparency(Msg->title); - - *RLen = sprintf(Reply, MsgInputPage, Key, Msg->from, "", EncodedTitle , NewBytes); - - free(EncodedTitle); - - free(MsgBytes); - free(NewBytes); - - return; - } - - - - if (memcmp(NodeURL, "/WebMail/Reply/", 15) == 0) - { - // Reply to Message - - int n = atoi(&NodeURL[15]); - struct MsgInfo * Msg; - char Message[100] = ""; - char Title[100]; - char * EncodedTitle; - - // Quote Original - - char Button[] = - "      " - ""; - - char Temp[1024]; - char ReplyAddr[128]; - - Msg = GetMsgFromNumber(n); - - if (Msg == NULL) - { - sprintf(Message, "Message %d not found", n); - *RLen = sprintf(Reply, "%s", Message); - return; - } - - Session->WebMail->Msg = Msg; - - // See if the message was displayed in an HTML form with a reply template - - *RLen = ReplyToFormsMessage(Session, Msg, Reply, FALSE); - - // If couldn't build reply form use normal text reply - - if (*RLen) - return; - - - sprintf(Temp, Button, Key); - - if (stristr(Msg->title, "Re:") == 0) - sprintf(Title, "Re:%s", Msg->title); - else - sprintf(Title, "%s", Msg->title); - - strcpy(ReplyAddr, Msg->from); - strcat(ReplyAddr, Msg->emailfrom); - - EncodedTitle = doXMLTransparency(Msg->title); - - *RLen = sprintf(Reply, MsgInputPage, Key, Msg->from, Temp, EncodedTitle , ""); - - free(EncodedTitle); - return; - } - - if (strcmp(NodeURL, "/WebMail/WM") == 0) - { - // Read Message - - int n = 0; - - if (URLParams) - n = atoi(URLParams); - - if (WebMailMsgTemplate) - free(WebMailMsgTemplate); - - WebMailMsgTemplate = GetTemplateFromFile(5, "WebMailMsg.txt"); - - *RLen = ViewWebMailMessage(Session, Reply, n, TRUE); - - return; - } - - if (strcmp(NodeURL, "/WebMail/WMPrev") == 0) - { - // Read Previous Message - - int m; - struct MsgInfo * Msg; - struct UserInfo * User = Session->User; - - - for (m = Session->WebMail->CurrentMessageIndex - 1; m >= 1; m--) - { - - Msg = GetMsgFromNumber(m); - - if (Msg == 0 || Msg->type == 0 || Msg->status == 0) - continue; // Protect against corrupt messages - - if (Msg && CheckUserMsg(Msg, User->Call, User->flags & F_SYSOP)) - { - // Display if it is the right type and in the page range we want - - if (Session->WebMailTypes[0] && strchr(Session->WebMailTypes, Msg->type) == 0) - continue; - - // All Types or right Type. Check Mine Flag - - if (Session->WebMailMine) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->to) != 0 && strcmp(User->Call, Msg->from) != 0) - continue; - } - - if (Session->WebMailMyTX) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->from) != 0) - continue; - } - - if (Session->WebMailMyRX) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->to) != 0) - continue; - } - *RLen = ViewWebMailMessage(Session, Reply, m, TRUE); - - return; - } - } - - // No More - - *RLen = sprintf(Reply, "", Session->Key); - return; - - } - - if (strcmp(NodeURL, "/WebMail/WMNext") == 0) - { - // Read Previous Message - - int m; - struct MsgInfo * Msg; - struct UserInfo * User = Session->User; - - for (m = Session->WebMail->CurrentMessageIndex + 1; m <= LatestMsg; m++) - { - Msg = GetMsgFromNumber(m); - - if (Msg == 0 || Msg->type == 0 || Msg->status == 0) - continue; // Protect against corrupt messages - - if (Msg && CheckUserMsg(Msg, User->Call, User->flags & F_SYSOP)) - { - // Display if it is the right type and in the page range we want - - if (Session->WebMailTypes[0] && strchr(Session->WebMailTypes, Msg->type) == 0) - continue; - - // All Types or right Type. Check Mine Flag - - if (Session->WebMailMine) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->to) != 0 && strcmp(User->Call, Msg->from) != 0) - continue; - } - - if (Session->WebMailMyTX) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->from) != 0) - continue; - } - - if (Session->WebMailMyRX) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->to) != 0) - continue; - } - *RLen = ViewWebMailMessage(Session, Reply, m, TRUE); - - return; - } - } - - // No More - - *RLen = sprintf(Reply, "", Session->Key); - return; - - } - - - if (strcmp(NodeURL, "/WebMail/DisplayText") == 0) - { - // Read Message - - int n = 0; - - if (URLParams) - n = atoi(URLParams); - - if (WebMailMsgTemplate) - free(WebMailMsgTemplate); - - WebMailMsgTemplate = GetTemplateFromFile(5, "WebMailMsg.txt"); - - *RLen = ViewWebMailMessage(Session, Reply, n, FALSE); - - return; - } - if (memcmp(NodeURL, "/WebMail/WMDel/", 15) == 0) - { - // Kill Message - - int n = atoi(&NodeURL[15]); - - *RLen = KillWebMailMessage(Reply, Session->Key, Session->User, n); - - return; - } - - if (_stricmp(NodeURL, "/WebMail/NewMsg") == 0) - { - // Add HTML Template Button if we have any HTML Form - - char Button[] = - "      " - ""; - - char Temp[1024]; - - FreeWebMailFields(Session->WebMail); // Tidy up for new message - - sprintf(Temp, Button, Key); - - if (FormDirCount == 0) - *RLen = sprintf(Reply, MsgInputPage, Key, "", "", "", ""); - else - *RLen = sprintf(Reply, MsgInputPage, Key, "", Temp, "", ""); - - return; - } - - if (_memicmp(NodeURL, "/WebMail/GetPage/", 17) == 0) - { - // Read and Parse Template File - - GetPage(Session, NodeURL); - return; - } - - if (_memicmp(NodeURL, "/WebMail/GetList/", 17) == 0) - { - // Send Select Template Popup - - char * SubDir; - int DirNo = 0; - int SubDirNo = 0; - char popup[10000]; - - char popuphddr[] = - - "" - "" - "

" - "Select Required Template from %s

" - "

"); - - *RLen = sprintf(Reply, "%s", popup); - return; - } - - if (_stricmp(NodeURL, "/WebMail/DL") == 0) - { - getAttachmentList(Session, Reply, RLen, URLParams); - return; - } - - if (_stricmp(NodeURL, "/WebMail/GetDownLoad") == 0) - { - DownloadAttachments(Session, Reply, RLen, URLParams); - return; - } - - if (_stricmp(NodeURL, "/WebMail/DoSelect") == 0) - { - // User has selected item from Template "; - - char NewGroup [] = - "" - "

"); - - *WebMail->RLen = sprintf(WebMail->Reply, "%s", popup); - - free(Boundary); - return; -} - -static char WinlinkAddr[] = "WINLINK.ORG"; - -VOID SaveNewMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest, int InputLen) -{ - int i, ReplyLen = 0; - struct MsgInfo * Msg; - FILE * hFile; - int Template=0; - char * via = NULL; - BIDRec * BIDRec; - char MsgFile[MAX_PATH]; - size_t WriteLen=0; - char * HDest; - char * HDestCopy; - char * HDestRest; - char * Vptr = NULL; - char * FileList = NULL; - char Prompt[256] = "Message Saved"; - char OrigTo[256]; - WebMailInfo * WebMail = Session->WebMail; - struct UserInfo * user; - CIRCUIT conn; - - // So we can have attachments input is now Content-Type: multipart/form-data; - - char * Input; - size_t MsgLen = 0; - char * Boundary; - - strcpy(conn.Callsign, Session->User->Call); - - Input = MsgPtr; - - Boundary = initMultipartUnpack(&Input); - - if (Boundary == NULL) - return; // Can't work without one - - // Input points to start of part. Normally preceeded by \r\n which is Boundary Terminator. If preceeded by -- we have used last part - - while(Input && Input[-1] != '-') - { - char * Name, * Value; - int ValLen; - - if (unpackPart(Boundary, &Input, &Name, &Value, &ValLen, MsgPtr + InputLen) == FALSE) - { - // ReportCorrupt(WebMail); - free(Boundary); - return; - } - if (SaveInputValue(WebMail, Name, Value, ValLen) == FALSE) - { - *RLen = sprintf(Reply, "", Session->Key); - return; - } - } - - - if (WebMail->txtFileName) - { - // Processing Form Input - - SaveTemplateMessage(Session, MsgPtr, Reply, RLen, Rest); - - // Prevent re-entry - - free(WebMail->txtFileName); - WebMail->txtFileName = NULL; - - return; - } - - // If we aren't using a template then all the information is in the WebMail fields, as we haven't been here before. - - strlop(WebMail->BID, ' '); - if (strlen(WebMail->BID) > 12) - WebMail->BID[12] = 0; - - UndoTransparency(WebMail->BID); - UndoTransparency(WebMail->To); - UndoTransparency(WebMail->Subject); - UndoTransparency(WebMail->Body); - - MsgLen = strlen(WebMail->Body); - - // We will need to mess about with To field. Create a copy so the original can go in B2 header if we use one - - if (WebMail->To[0] == 0) - { - *RLen = sprintf(Reply, "%s", ""); - FreeWebMailFields(WebMail); // We will reprocess message and attachments so reinitialise - return; - } - - if (strlen(WebMail->To) > 255) - { - *RLen = sprintf(Reply, "%s", ""); - FreeWebMailFields(WebMail); // We will reprocess message and attachments so reinitialise - return; - } - - HDest = _strdup(WebMail->To); - - if (strlen(WebMail->BID)) - { - if (LookupBID(WebMail->BID)) - { - // Duplicate bid - *RLen = sprintf(Reply, "%s", ""); - FreeWebMailFields(WebMail); // We will reprocess message and attachments so reinitialise - return; - } - } - - if (WebMail->Type == 'B') - { - if (RefuseBulls) - { - *RLen = sprintf(Reply, "%s", ""); - FreeWebMailFields(WebMail); // We will reprocess message and attachments so reinitialise - return; - } - } - - // ?? Can we just loop though the rest of the code to allow multiple dests ?? - - HDestCopy = HDest; - - while (HDest && HDest[0]) - { - HDestRest = strlop(HDest, ';'); - - Msg = AllocateMsgRecord(); - - // Set number here so they remain in sequence - - Msg->number = ++LatestMsg; - MsgnotoMsg[Msg->number] = Msg; - - strcpy(Msg->from, Session->User->Call); - - if (_memicmp(HDest, "rms:", 4) == 0 || _memicmp(HDest, "rms/", 4) == 0) - { - Vptr=&HDest[4]; - strcpy(Msg->to, "RMS"); - } - else if (_memicmp(HDest, "smtp:", 5) == 0) - { - if (ISP_Gateway_Enabled) - { - Vptr=&HDest[5]; - Msg->to[0] = 0; - } - } - else if (strchr(HDest, '@')) - { - strcpy(OrigTo, HDest); - - Vptr = strlop(HDest, '@'); - - if (Vptr) - { - // If looks like a valid email address, treat as such - - if (strlen(HDest) > 6 || !CheckifPacket(Vptr)) - { - // Assume Email address - - Vptr = OrigTo; - - if (FindRMS() || strchr(Vptr, '!')) // have RMS or source route - strcpy(Msg->to, "RMS"); - else if (ISP_Gateway_Enabled) - Msg->to[0] = 0; - else if (isAMPRMsg(OrigTo)) - strcpy(Msg->to, "RMS"); // Routing will redirect it - else - { - *RLen = sprintf(Reply, "%s", ""); - FreeWebMailFields(WebMail); // We will reprocess message and attachments so reinitialise - return; - - } - } - else - strcpy(Msg->to, _strupr(HDest)); - } - } - else - { - // No @ - - if (strlen(HDest) > 6) - HDest[6] = 0; - - strcpy(Msg->to, _strupr(HDest)); - } - - if (SendBBStoSYSOPCall) - if (_stricmp(HDest, BBSName) == 0) - strcpy(Msg->to, SYSOPCall); - - if (Vptr) - { - if (strlen(Vptr) > 40) - Vptr[40] = 0; - - strcpy(Msg->via, _strupr(Vptr)); - } - else - { - // No via. If not local user try to add BBS - - struct UserInfo * ToUser = LookupCall(Msg->to); - - if (ToUser) - { - // Local User. If Home BBS is specified, use it - - if (ToUser->flags & F_RMSREDIRECT) - { - // sent to Winlink - - strcpy(Msg->via, WinlinkAddr); - sprintf(Prompt, "Redirecting to winlink.org\r"); - } - else if (ToUser->HomeBBS[0]) - { - strcpy(Msg->via, ToUser->HomeBBS); - sprintf(Prompt, "%s added from HomeBBS. Message Saved", Msg->via); - } - } - else - { - // Not local user - Check WP - - WPRecP WP = LookupWP(Msg->to); - - if (WP) - { - strcpy(Msg->via, WP->first_homebbs); - sprintf(Prompt, "%s added from WP", Msg->via); - } - } - } - - if (strlen(WebMail->Subject) > 60) - WebMail->Subject[60] = 0; - - strcpy(Msg->title, WebMail->Subject); - Msg->type = WebMail->Type; - - if (Session->User->flags & F_HOLDMAIL) - { - int Length=0; - char * MailBuffer = malloc(100); - char Title[100]; - - Msg->status = 'H'; - - Length = sprintf(MailBuffer, "Message %d Held\r\n", Msg->number); - sprintf(Title, "Message %d Held - %s", Msg->number, "User has Hold Messages flag set"); - SendMessageToSYSOP(Title, MailBuffer, Length); - } - else - Msg->status = 'N'; - - if (strlen(WebMail->BID) == 0) - sprintf(Msg->bid, "%d_%s", LatestMsg, BBSName); - else - strcpy(Msg->bid, WebMail->BID); - - Msg->datereceived = Msg->datechanged = Msg->datecreated = time(NULL); - - BIDRec = AllocateBIDRecord(); - - strcpy(BIDRec->BID, Msg->bid); - BIDRec->mode = Msg->type; - BIDRec->u.msgno = LOWORD(Msg->number); - BIDRec->u.timestamp = LOWORD(time(NULL)/86400); - - Msg->length = (int)MsgLen + WebMail->HeaderLen + WebMail->FooterLen; - - sprintf_s(MsgFile, sizeof(MsgFile), "%s/m_%06d.mes", MailDir, Msg->number); - - // BuildFormMessage(Session, Msg); - - if (WebMail->Files) - { - // Send as B2 - - char * B2Header = BuildB2Header(WebMail, Msg, NULL, 0); - - hFile = fopen(MsgFile, "wb"); - - if (hFile) - { - WriteLen = fwrite(B2Header, 1, strlen(B2Header), hFile); - WriteLen += fwrite(WebMail->Header, 1, WebMail->HeaderLen, hFile); - WriteLen += fwrite(WebMail->Body, 1, MsgLen, hFile); - WriteLen += fwrite(WebMail->Footer, 1, WebMail->FooterLen, hFile); - WriteLen += fwrite("\r\n", 1, 2, hFile); - - for (i = 0; i < WebMail->Files; i++) - { - WriteLen += fwrite(WebMail->FileBody[i], 1, WebMail->FileLen[i], hFile); - WriteLen += fwrite("\r\n", 1, 2, hFile); - } - fclose(hFile); - free(B2Header); - - Msg->length = (int)WriteLen; - } - } - else - { - hFile = fopen(MsgFile, "wb"); - - if (hFile) - { - WriteLen += fwrite(WebMail->Header, 1, WebMail->HeaderLen, hFile); - WriteLen += fwrite(WebMail->Body, 1, MsgLen, hFile); - WriteLen += fwrite(WebMail->Footer, 1, WebMail->FooterLen, hFile); - fclose(hFile); - } - } - MatchMessagetoBBSList(Msg, &conn); - - BuildNNTPList(Msg); // Build NNTP Groups list - - if (Msg->status != 'H' && Msg->type == 'B' && memcmp(Msg->fbbs, zeros, NBMASK) != 0) - Msg->status = '$'; // Has forwarding - - - if (EnableUI) - SendMsgUI(Msg); - - user = LookupCall(Msg->to); - - // If Event Notifications enabled report a new message event - - SendNewMessageEvent(user->Call, Msg); - -#ifndef NOMQTT - if (MQTT) - MQTTMessageEvent(Msg); -#endif - - if (user && (user->flags & F_APRSMFOR)) - { - char APRS[128]; - char Call[16]; - int SSID = user->flags >> 28; - - if (SSID) - sprintf(Call, "%s-%d", Msg->to, SSID); - else - strcpy(Call, Msg->to); - - sprintf(APRS, "New BBS Message %s From %s", Msg->title, Msg->from); - APISendAPRSMessage(APRS, Call); - } - - HDest = HDestRest; - } - - *RLen = SendWebMailHeaderEx(Reply, Session->Key, Session, Prompt); - - SaveMessageDatabase(); - SaveBIDDatabase(); - FreeWebMailFields(WebMail); - free(HDestCopy); - - return; -} - - - - - - -// RMS Express Forms Support - -char * GetHTMLViewerTemplate(char * FN, struct HtmlFormDir ** FormDir) -{ - int i, j, k, l; - - // Seach list of forms for base file (without .html) - - for (i = 0; i < FormDirCount; i++) - { - struct HtmlFormDir * Dir = HtmlFormDirs[i]; - - for (j = 0; j < Dir->FormCount; j++) - { - if (strcmp(FN, Dir->Forms[j]->FileName) == 0) - { - *FormDir = Dir; - return CheckFile(Dir, FN); - } - } - - if (Dir->DirCount) - { - for (l = 0; l < Dir->DirCount; l++) - { - struct HtmlFormDir * SDir = Dir->Dirs[l]; - - if (SDir->DirCount) - { - struct HtmlFormDir * SSDir = SDir->Dirs[0]; - int x = 1; - } - - for (k = 0; k < SDir->FormCount; k++) - { - if (_stricmp(FN, SDir->Forms[k]->FileName) == 0) - { - *FormDir = SDir; - return CheckFile(SDir, SDir->Forms[k]->FileName); - } - } - if (SDir->DirCount) - { - struct HtmlFormDir * SSDir = SDir->Dirs[0]; - int x = 1; - } - } - } - } - - return NULL; -} -VOID GetReply(struct HTTPConnectionInfo * Session, char * NodeURL) -{ -} - -VOID GetPage(struct HTTPConnectionInfo * Session, char * NodeURL) -{ - // Read the HTML Template file and do any needed substitutions - - WebMailInfo * WebMail = Session->WebMail; - KeyValues * txtKey = WebMail->txtKeys; - - int DirNo; - char * ptr; - int FileNo = 0; - char * SubDir; - int SubDirNo; - int i; - struct HtmlFormDir * Dir; - char * Template; - char * inptr; - char FormDir[MAX_PATH] = ""; - char FN[MAX_PATH] = ""; - char * InputName = NULL; // HTML to input message - char * ReplyName = NULL; - char * To = NULL; - char * CC = NULL; - char * BID = NULL; - char Type = 0; - char * Subject = NULL; - char * MsgBody = NULL; - char * varptr; - char * endptr; - size_t varlen, vallen = 0; - char val[256]=""; // replacement text - char var[100] = "\""; - char * MsgBytes; - char Submit[64]; - - if (NodeURL == NULL) - { - //rentry after processing or substitutions - - // if Dir not specified search all for Filename - - if (Dir == NULL) - { - for (i = 0; i < FormDirCount; i++) - { - int n; - - Dir = HtmlFormDirs[i]; - - MsgBytes = CheckFile(Dir, WebMail->txtFileName); - if (MsgBytes) - goto gotFile; - - // Recurse any Subdirs - - n = 0; - while (n < Dir->DirCount) - { - MsgBytes = CheckFile(Dir->Dirs[n], FN); - if (MsgBytes) - { - Dir = Dir->Dirs[n]; - goto gotFile; - } - n++; - } - } - return; - } - else - MsgBytes = CheckFile(Dir, WebMail->txtFileName); - -gotFile: - - WebMail->Dir = Dir; - - if (WebMail->txtFile) - free(WebMail->txtFile); - - WebMail->txtFile = MsgBytes; - -reEnter: - - if (ParsetxtTemplate(Session, Dir, WebMail->txtFileName, FALSE) == FALSE) - { - // Template has or - - if (WebMail->InputHTMLName == NULL) - { - // This is a plain text template without HTML -/* - if (To == NULL) - To = ""; - - if (To[0] == 0 && WebMail->To && WebMail->To[0]) - To = WebMail->To; - - if (CC == NULL) - CC = ""; - - if (CC[0] == 0 && WebMail->CC && WebMail->CC[0]) - CC = WebMail->CC; - - if (Subject == NULL) - Subject = ""; - - if (Subject[0] == 0 && WebMail->Subject && WebMail->Subject[0]) - Subject = WebMail->Subject; - - if (MsgBody == NULL) - MsgBody = ""; - - if (MsgBody[0] == 0 && WebMail->Body && WebMail->Body[0]) - MsgBody = WebMail->Body; - - *WebMail->RLen = sprintf(WebMail->Reply, CheckFormMsgPage, Session->Key, To, CC, Subject, MsgBody); - */ - return *WebMail->RLen; - } - - Template = CheckFile(WebMail->Dir, WebMail->InputHTMLName); - - if (Template == NULL) - { - // Missing HTML - - *WebMail->RLen = sprintf(WebMail->Reply, "", WebMail->InputHTMLName); - return *WebMail->RLen; - } - - // I've going to update the template in situ, as I can't see a better way - // of making sure all occurances of variables in any order are substituted. - // The space allocated to Template is twice the size of the file - // to allow for insertions - - UpdateFormAction(Template, Session->Key); // Update "Submit" Action - - // Search for "{var }" strings in form and replace with - // corresponding variable from XML - - while (txtKey->Key) - { - char Key[256] = "{var "; - - strcpy(&Key[5], txtKey->Key); - strcat(Key, "}"); - - inptr = Template; - varptr = stristr(inptr, Key); - - while (varptr) - { - // Move the remaining message up/down the buffer to make space for substitution - - varlen = (int)strlen(Key); - if (txtKey->Value) - vallen = (int)strlen(txtKey->Value); - else vallen = 0; - - endptr = varptr + varlen; - - memmove(varptr + vallen, endptr, strlen(endptr) + 1); // copy null on end - memcpy(varptr, txtKey->Value, vallen); - - inptr = endptr + 1; - - varptr = stristr(inptr, Key); - } - txtKey++; - } - - // Remove from end as we add it on later - - ptr = stristr(Template, ""); - - if (ptr) - *ptr = 0; - - Len = sprintf(Reply, "%s", Template); - free(Template); - return Len; -} - -char * CheckFile(struct HtmlFormDir * Dir, char * FN) -{ - struct stat STAT; - FILE * hFile; - char MsgFile[MAX_PATH]; - char * MsgBytes; - int ReadLen; - int FileSize; - -#ifndef WIN32 - - // Need to do case insensitive file search - - DIR *dir; - struct dirent *entry; - char name[256]; - - sprintf(name, "%s/%s/%s", BPQDirectory, Dir->FormSet, Dir->DirName); - - if (!(dir = opendir(name))) - { - Debugprintf("cant open forms dir %s %s %d", Dir->DirName, name, errno); - return 0; - } - - while ((entry = readdir(dir)) != NULL) - { - if (entry->d_type == DT_DIR) - continue; - - if (stricmp(entry->d_name, FN) == 0) - { - sprintf(MsgFile, "%s/%s/%s/%s", GetBPQDirectory(), Dir->FormSet, Dir->DirName, entry->d_name); - break; - } - } - closedir(dir); - -#else - - sprintf(MsgFile, "%s/%s/%s/%s", GetBPQDirectory(), Dir->FormSet, Dir->DirName, FN); - -#endif - - if (stat(MsgFile, &STAT) != -1) - { - hFile = fopen(MsgFile, "rb"); - - if (hFile == 0) - { - MsgBytes = _strdup("File is missing"); - return MsgBytes; - } - - FileSize = STAT.st_size; - MsgBytes = malloc(FileSize * 10); // Allow plenty of room for template substitution - ReadLen = (int)fread(MsgBytes, 1, FileSize, hFile); - MsgBytes[FileSize] = 0; - fclose(hFile); - - return MsgBytes; - } - return NULL; -} - -BOOL DoSelectPrompt(struct HTTPConnectionInfo * Session, char * Select) -{ - // Send a Popup window to select value. Reply handling code will update template then reenter ParsetxtTemplate - - char popuphddr[] = - - "" - "" - "
%s

" - "" - "
'); - - if (ptr) - *ptr = 0; - - ptr = SelCopy; - - if (*ptr == '"') - { - // String has " " round it - - ptr++; - - ptr1 = strchr(ptr, '"'); - if (ptr1 == NULL) - goto returnDuff; - - *(ptr1++) = 0; - prompt = ptr; - } - else - { - // Normal comma terminated - - ptr1 = strchr(ptr, ','); - if (ptr1 == NULL) - goto returnDuff; - - *(ptr1++) = 0; - prompt = ptr; - } - - ptr = ptr1; - - while (ptr && ptr[0]) - { - if (*ptr == '"') - { - // String has " " round it - - ptr++; - - ptr1 = strchr(ptr, '"'); - if (ptr1 == NULL) - goto returnDuff; - - *(ptr1++) = 0; - while(ptr1 && *ptr1 == ',') - ptr1++; - } - else - { - // Normal comma terminated - - ptr1 = strchr(ptr, ','); - if (ptr1) - *(ptr1++) = 0; - } - - var[vars++] = ptr; - - ptr = ptr1; - } - - len = sprintf(popup, popuphddr, Session->Key, prompt, vars + 1); - - for (i = 0; i < vars; i++) - { - char * key = strlop(var[i], '='); - - if (key == NULL) - key = var[i]; - - len += sprintf(&popup[len], "

"); - - *WebMail->RLen = sprintf(WebMail->Reply, "%s", popup); - free(SelCopy); - return TRUE; - -returnDuff: - *WebMail->RLen = sprintf(WebMail->Reply, "", Session->Key); - free(SelCopy); - return TRUE; - -} - -BOOL DoAskPrompt(struct HTTPConnectionInfo * Session, char * Select) -{ - return TRUE; -} - -VOID ProcessSelectResponse(struct HTTPConnectionInfo * Session, char * URLParams) -{ - // User has entered a response for a Template RLen = sprintf(WebMail->Reply, "", Session->Key); - return; - } - - varptr = Select; - endptr = strchr(Select, '>'); - - if (endptr == NULL) - { - *WebMail->RLen = sprintf(WebMail->Reply, "", Session->Key); - return; - } - - *endptr = 0; - varlen = endptr - varptr; - - - valptr = URLParams; - - // Move the remaining message up/down the buffer to make space for substitution - - vallen = strlen(valptr); - - endptr = varptr + varlen; - - memcpy(varptr, valptr, vallen); - memmove(varptr + vallen, endptr + 1, strlen(endptr + 1) + 1); // copy null on end - - if (WebMail->isReply) - *WebMail->RLen = ReplyToFormsMessage(Session, Session->Msg, WebMail->Reply, TRUE); - else - GetPage(Session, NULL); - - return ; -} - -BOOL ParsetxtTemplate(struct HTTPConnectionInfo * Session, struct HtmlFormDir * Dir, char * FN, BOOL isReply) -{ - WebMailInfo * WebMail = Session->WebMail; - KeyValues * txtKey = WebMail->txtKeys; - - char * MsgBytes; - - char * txtFile; - char * ptr, *ptr1; - char * InputName = NULL; // HTML to input message - char * ReplyName = NULL; - char * To = NULL; - char * Subject = NULL; - char * MsgBody = NULL; - char * Select = NULL; - char * Ask = NULL; - - char Date[16]; - char UDate[16]; - char DateTime[32]; - char UDateTime[32]; - char Day[16]; - char UDay[16]; - char UDTG[32]; - char Seq[16]; - char FormDir[MAX_PATH]; - double Lat; - double Lon; - char LatString[32], LonString[32], GPSString[32]; - BOOL GPSOK; - - struct tm * tm; - time_t NOW; - - // Template is now read before entering here - - MsgBytes = WebMail->txtFile; - - // if Template uses tm_year + 1900,tm->tm_mon + 1, tm->tm_mday); - - sprintf(DateTime, "%04d-%02d-%02d %02d:%02d:%02d", - tm->tm_year + 1900,tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - - strcpy(Day, longday[tm->tm_wday]); - - tm = gmtime(&NOW); - - sprintf(UDate, "%04d-%02d-%02dZ", - tm->tm_year + 1900,tm->tm_mon + 1, tm->tm_mday); - - sprintf(UDateTime, "%04d-%02d-%02d %02d:%02d:%02dZ", - tm->tm_year + 100,tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - - sprintf(UDTG, "%02d%02d%02dZ %s %04d", - tm->tm_mday, tm->tm_hour, tm->tm_min, month[tm->tm_mon], tm->tm_year + 1900); - - strcpy(UDay, longday[tm->tm_wday]); - - sprintf(Seq, "%d", Session->User->WebSeqNo); - sprintf(FormDir, "/WebMail/WMFile/%s/%s/", WebMail->Dir->FormSet, WebMail->Dir->DirName); - - // Keep SeqNo at front - - txtKey->Key = _strdup(""); - txtKey++->Value = _strdup(Seq); - - txtKey->Key = _strdup(""); - txtKey++->Value = _strdup(DateTime); - txtKey->Key = _strdup(""); - txtKey++->Value = _strdup(UDateTime); - txtKey->Key = _strdup(""); - txtKey++->Value = _strdup(Date); - txtKey->Key = _strdup(""); - txtKey++->Value = _strdup(UDate); - txtKey->Key = _strdup("