diff --git a/BBSUtilities.c b/BBSUtilities.c index 2cbbafc..4a21033 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -11323,7 +11323,7 @@ VOID ProcessTextFwdLine(ConnectionInfo * conn, struct UserInfo * user, char * Bu MsgPtr = MsgBytes; } - memcpy(&temp, &conn->FwdMsg->datereceived, 4); + memcpy(&temp, &conn->FwdMsg->datereceived, sizeof(time_t)); tm = gmtime(&temp); nodeprintf(conn, "R:%02d%02d%02d/%02d%02dZ %d@%s.%s %s\r", diff --git a/BPQMail.c b/BPQMail.c index f5319f9..954b0d7 100644 --- a/BPQMail.c +++ b/BPQMail.c @@ -1109,7 +1109,7 @@ // Fix BID Hold and Reject filters // Fix Webmail auto-refresh when page exceeds 64K bytes (54) // Fix Webmail send when using both headers/footers and attachmonts (55) - +// Fix R: line corruption on some 64 bit builds #include "bpqmail.h" #define MAIL diff --git a/Bpq32.c b/Bpq32.c index a322966..73e29d3 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1152,6 +1152,8 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // 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) + #define CKernel diff --git a/FBBRoutines.c b/FBBRoutines.c index 84b09d6..2fae431 100644 --- a/FBBRoutines.c +++ b/FBBRoutines.c @@ -1244,7 +1244,7 @@ VOID SendCompressed(CIRCUIT * conn, struct MsgInfo * FwdMsg) DataOffset = (int)(Outputptr - Output); // Used if restarting - memcpy(&temp, &FwdMsg->datereceived, 4); + memcpy(&temp, &FwdMsg->datereceived, sizeof(time_t)); tm = gmtime(&temp); sprintf(Rline, "R:%02d%02d%02d/%02d%02dZ %d@%s.%s %s\r\n", diff --git a/UZ7HODrv.c b/UZ7HODrv.c index 0f8e6b9..f81294c 100644 --- a/UZ7HODrv.c +++ b/UZ7HODrv.c @@ -1340,9 +1340,11 @@ void * UZ7HOExtInit(EXTPORTDATA * PortEntry) MoveWindows(TNC); +#endif + if (MasterPort[port] == port) { - // First port for this TNC - start TNC if sonfigured and connect + // First port for this TNC - start TNC if configured and connect #ifndef LINBPQ if (EnumWindows(EnumTNCWindowsProc, (LPARAM)TNC)) @@ -1362,10 +1364,8 @@ void * UZ7HOExtInit(EXTPORTDATA * PortEntry) MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); } - time(&lasttime[port]); // Get initial time value -#endif return ExtProc; } diff --git a/Versions.h b/Versions.h index cdd51ef..14d05be 100644 --- a/Versions.h +++ b/Versions.h @@ -10,14 +10,14 @@ #endif -#define KVers 6,0,23,56 -#define KVerstring "6.0.23.56\0" +#define KVers 6,0,23,58 +#define KVerstring "6.0.23.58\0" #ifdef CKernel #define Vers KVers #define Verstring KVerstring -#define Datestring "March 2023" +#define Datestring "April 2023" #define VerComments "G8BPQ Packet Switch (C Version)" KVerstring #define VerCopyright "Copyright © 2001-2023 John Wiseman G8BPQ\0" #define VerDesc "BPQ32 Switch\0" diff --git a/WINMOR.c b/WINMOR.c index e09accb..e84d200 100644 --- a/WINMOR.c +++ b/WINMOR.c @@ -2844,7 +2844,7 @@ int KillTNC(struct TNCINFO * TNC) SOCKET sock = socket(AF_INET,SOCK_DGRAM,0); struct sockaddr_in destaddr; - char Msg[80]; + char Msg[256]; int Len; if (sock == INVALID_SOCKET) diff --git a/WinRPR.c b/WinRPR.c index 25609c1..a7f22f1 100644 --- a/WinRPR.c +++ b/WinRPR.c @@ -39,6 +39,12 @@ extern int (WINAPI FAR *EnumProcessesPtr)(); #include "tncinfo.h" + +#define SD_RECEIVE 0x00 +#define SD_SEND 0x01 +#define SD_BOTH 0x02 + + //#include "bpq32.h" static char ClassName[]="TRACKERSTATUS"; @@ -106,6 +112,7 @@ VOID TrkExitHost(struct TNCINFO * TNC); int ConnecttoWinRPR(int port); BOOL KillOldTNC(char * Path); +int KillTNC(struct TNCINFO * TNC); static BOOL RestartTNC(struct TNCINFO * TNC) { @@ -605,12 +612,19 @@ ok: TrkExitHost(TNC); Sleep(50); - CloseCOMPort(TNC->hDevice); - TNC->hDevice =(HANDLE)0; TNC->ReopenTimer = 250; TNC->HostMode = FALSE; - return (0); + shutdown(TNC->TCPSock, SD_BOTH); + Sleep(100); + closesocket(TNC->TCPSock); + + if (TNC->WeStartedTNC) + { + KillTNC(TNC); + RestartTNC(TNC); + } + return 0; case 5: // Close @@ -620,7 +634,14 @@ ok: Sleep(25); - CloseCOMPort(TNC->hDevice); + shutdown(TNC->TCPSock, SD_BOTH); + Sleep(100); + closesocket(TNC->TCPSock); + if (TNC->WeStartedTNC) + KillTNC(TNC); + + + return (0); case 6: // Scan Interface diff --git a/WinRPRHelper.c b/WinRPRHelper.c new file mode 100644 index 0000000..af978e1 --- /dev/null +++ b/WinRPRHelper.c @@ -0,0 +1,486 @@ + +#define _CRT_SECURE_NO_DEPRECATE +#include +#include + + +struct RIGPORTINFO +{ + char IOBASE[80]; + char PTTIOBASE[80]; // Port for Hardware PTT - may be same as control port. + int SPEED; + + HANDLE hDevice; // COM device Handle + int ReopenDelay; + SOCKET remoteSock; // Socket for use with WINMORCONROL + struct sockaddr remoteDest; // Dest for above + UCHAR TXBuffer[500]; // Last message sent - saved for Retry + int TXLen; // Len of last sent + int CONNECTED; // for HAMLIB + int CONNECTING; + int Alerted; +}; + +struct RIGPORTINFO PORTS[4]; + +char PTTCATPort[4][64] = {"", "", "", ""}; +HANDLE PTTCATHandles[4] = {0, 0, 0, 0}; +int RealMux[4] = {0, 0, 0, 0}; // BPQ Virtual or Real + + +VOID PTTCATThread(); +VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT); + +char * strlop(char * buf, char delim) +{ + // Terminate buf at delim, and return rest of string + + char * ptr; + + if (buf == NULL) return NULL; // Protect + + ptr = strchr(buf, delim); + + if (ptr == NULL) return NULL; + + *(ptr)++=0; + + return ptr; +} + + +void SendHamLib(struct RIGPORTINFO * PORT, int PTTState) +{ + char cmd[32]; + int Len = sprintf(cmd, "T %d\n", PTTState); + + Len = send(PORT->remoteSock, cmd, Len, 0); + Len = GetLastError(); + +} + +int DecodeHAMLIBAddr(struct RIGPORTINFO * PORT, char * ptr) +{ + // Param is IPADDR:PORT. Only Allow numeric addresses + + struct sockaddr_in * destaddr = (SOCKADDR_IN *)&PORT->remoteDest; + char * port; + + strcpy(PORT->IOBASE, ptr); + + port = strlop(ptr, ':'); + + if (port == NULL) + return 0; + + destaddr->sin_family = AF_INET; + destaddr->sin_addr.s_addr = inet_addr(ptr); + destaddr->sin_port = htons(atoi(port)); + + return 1; +} + + +void HAMLIBProcessMessage(struct RIGPORTINFO * PORT) +{ + // Called from Background thread. I think we just need to read and discard + + char RXBuffer[512]; + + int InputLen = recv(PORT->remoteSock, RXBuffer, 500, 0); + + if (InputLen == 0 || InputLen == SOCKET_ERROR) + { + if (PORT->remoteSock) + closesocket(PORT->remoteSock); + + PORT->remoteSock = 0; + + PORT->CONNECTED = FALSE; + PORT->hDevice = 0; + return; + } +} + + +int main(int argc, char ** argv) +{ + struct RIGPORTINFO * PORT; + int n = 0; + WSADATA WsaData; // receives data from WSAStartup + + if (argc < 3) + { + printf ("Missing paramters - you need COM port and IP Address and rigctl port of BPQ, eg \r\n" + " WinRPRHelper com10 192.168.1.64:4532\r\n\r\n" + "Press any key to exit\r\n"); + + getchar(); + + exit (0); + } + + WSAStartup(MAKEWORD(2, 0), &WsaData); + + while (argc > 2) + { + PORT = &PORTS[n]; + strcpy(PTTCATPort[n], argv[n + n +1]); + DecodeHAMLIBAddr(PORT, argv[n + n + 2]); + n++; + argc -= 2; + } + + _beginthread(PTTCATThread, 0, 0); + + for (n = 0; n < 4; n++) + { + if (PTTCATPort[n][0]) // Serial port RTS to HAMLIB PTT + { + PORT = &PORTS[n]; + ConnecttoHAMLIB(PORT); + } + } + + Sleep(2000); + + printf("WinRPRHelper running - Press ctrl/c to exit\r\n"); + fflush(stdout); + + while(1) + { + Sleep(1000); + + for (n = 0; n < 4; n++) + { + if (PTTCATPort[n][0]) // Serial port RTS to HAMLIB PTT + { + PORT = &PORTS[n]; + + if (PORT->hDevice == 0) + { + // Try to reopen every 15 secs + + PORT->ReopenDelay++; + + if (PORT->ReopenDelay > 15) + { + PORT->ReopenDelay = 0; + + ConnecttoHAMLIB(PORT); + } + } + } + } + } +} +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; + HANDLE Handle[4]; + DWORD EvtMask[4]; + OVERLAPPED Overlapped[4]; + char Port[32]; + int PIndex = 0; + int HIndex = 0; + int rc; + + while (PIndex < 4 && PTTCATPort[PIndex][0]) + { + RealMux[HIndex] = 0; + + sprintf(Port, "\\\\.\\pipe\\BPQ%s", PTTCATPort[PIndex]); + + Handle[HIndex] = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); + + if (Handle[HIndex] == (HANDLE) -1) + { + int Err = GetLastError(); + printf("PTTMUX port BPQ%s Open failed code %d - trying real com port\r\n", PTTCATPort[PIndex], Err); + + // See if real com port + + sprintf(Port, "\\\\.\\\\%s", PTTCATPort[PIndex]); + + Handle[HIndex] = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + + RealMux[HIndex] = 1; + + if (Handle[HIndex] == (HANDLE) -1) + { + int Err = GetLastError(); + printf("PTTMUX port %s Open failed code %d\r\n", PTTCATPort[PIndex], Err); + } + else + { + rc = SetCommMask(Handle[HIndex], EV_CTS | EV_DSR); // Request notifications + HIndex++; + printf("PTTMUX port %s Opened\r\n", PTTCATPort[PIndex]); + } + } + 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(Handle[i], &EvtMask[i], &Overlapped[i]); + rc = GetLastError(); + + } + else + { + + // Prime a read on each handle + + ReadFile(Handle[i], Block[i], 80, &Length, &Overlapped[i]); + } + } + + while (1) + { + +WaitAgain: + + ret = WaitForSingleObject(Event, 1000); + + if (ret == WAIT_TIMEOUT) + goto WaitAgain; + + ResetEvent(Event); + + // See which request(s) have completed + + for (i = 0; i < HIndex; i ++) + { + ret = GetOverlappedResult(Handle[i], &Overlapped[i], &Length, FALSE); + + if (ret) + { + if (RealMux[i]) + { + // Request Interface change notifications + + DWORD Mask; + + GetCommModemStatus(Handle[i], &Mask); + + if (Mask & MS_CTS_ON) + SendHamLib(&PORTS[i], TRUE); + else + SendHamLib(&PORTS[i], FALSE); + + memset(&Overlapped[i], 0, sizeof(OVERLAPPED)); + Overlapped[i].hEvent = Event; + WaitCommEvent(Handle[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) + SendHamLib(&PORTS[i], TRUE); + else + SendHamLib(&PORTS[i], FALSE); + + CurrentState[i] = c; + continue; + } + } + } + + memset(&Overlapped[i], 0, sizeof(OVERLAPPED)); + Overlapped[i].hEvent = Event; + + ReadFile(Handle[i], Block[i], 80, &Length, &Overlapped[i]); + } + } + } + } + +} + + + +VOID HAMLIBThread(struct RIGPORTINFO * PORT); + +VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT) +{ + _beginthread(HAMLIBThread, 0, (void *)PORT); + return ; +} + +VOID HAMLIBThread(struct RIGPORTINFO * PORT) +{ + // 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 (PORT->remoteSock) + { + closesocket(PORT->remoteSock); + } + + PORT->remoteSock = 0; + PORT->remoteSock = socket(AF_INET,SOCK_STREAM,0); + + if (PORT->remoteSock == INVALID_SOCKET) + { + i=sprintf(Msg, "Socket Failed for HAMLIB socket - error code = %d\r\n", WSAGetLastError()); + printf(Msg); + + PORT->CONNECTING = FALSE; + return; + } + + setsockopt(PORT->remoteSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); + setsockopt(PORT->remoteSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); + + if (connect(PORT->remoteSock,(LPSOCKADDR) &PORT->remoteDest,sizeof(PORT->remoteDest)) == 0) + { + // + // Connected successful + // + + ioctlsocket(PORT->remoteSock, FIONBIO, ¶m); + printf("Connected to HAMLIB socket Addr %s\r\n", PORT->IOBASE); + } + else + { + if (PORT->Alerted == FALSE) + { + struct sockaddr_in * destaddr = (SOCKADDR_IN * )&PORT->remoteDest; + + err = WSAGetLastError(); + + sprintf(Msg, "Connect Failed for HAMLIB socket - error code = %d Addr %s\r\n", err, PORT->IOBASE); + + printf(Msg); + PORT->Alerted = TRUE; + } + + closesocket(PORT->remoteSock); + + PORT->remoteSock = 0; + PORT->CONNECTING = FALSE; + return; + } + + PORT->CONNECTED = TRUE; + PORT->hDevice = (HANDLE)1; // simplifies check code + + PORT->Alerted = TRUE; + + while (PORT->CONNECTED) + { + FD_ZERO(&readfs); + FD_ZERO(&errorfs); + + FD_SET(PORT->remoteSock,&readfs); + FD_SET(PORT->remoteSock,&errorfs); + + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + ret = select((int)PORT->remoteSock + 1, &readfs, NULL, &errorfs, &timeout); + + if (ret == SOCKET_ERROR) + { + printf("HAMLIB Select failed %d r\n", WSAGetLastError()); + goto Lost; + } + + if (ret > 0) + { + // See what happened + + if (FD_ISSET(PORT->remoteSock, &readfs)) + { + HAMLIBProcessMessage(PORT); + } + + if (FD_ISSET(PORT->remoteSock, &errorfs)) + { +Lost: + sprintf(Msg, "HAMLIB Connection lost for Addr %s\r\n", PORT->IOBASE); + printf(Msg); + + PORT->CONNECTED = FALSE; + PORT->Alerted = FALSE; + PORT->hDevice = 0; // simplifies check code + + closesocket(PORT->remoteSock); + PORT->remoteSock = 0; + return; + } + + + continue; + } + else + { + } + } + sprintf(Msg, "HAMLIB Thread Terminated Addr %s\r\n", PORT->IOBASE); + printf(Msg); +} + + diff --git a/WinRPRHelper.vcproj b/WinRPRHelper.vcproj new file mode 100644 index 0000000..20f185d --- /dev/null +++ b/WinRPRHelper.vcproj @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user b/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user new file mode 100644 index 0000000..d4a1f25 --- /dev/null +++ b/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/WinmorControl.c b/WinmorControl.c index e808ce6..da24ff6 100644 --- a/WinmorControl.c +++ b/WinmorControl.c @@ -39,8 +39,6 @@ #define BPQICON 400 -WSADATA WsaData; // receives data from WSAStartup - #define WSA_READ WM_USER + 1 HINSTANCE hInst; @@ -569,6 +567,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) BOOL bcopt=TRUE; char Msg[255]; int ret, err; + WSADATA WsaData; // receives data from WSAStartup hInst = hInstance; // Store instance handle in our global variable diff --git a/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user b/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user new file mode 100644 index 0000000..40182c4 --- /dev/null +++ b/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/debug/bpq32.pdb b/debug/bpq32.pdb new file mode 100644 index 0000000..b9c56d4 Binary files /dev/null and b/debug/bpq32.pdb differ