From 9aad97786d945165530dcac2216c5b75e4632f82 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Tue, 11 Nov 2025 21:42:35 +0000 Subject: [PATCH] 6.0.25.9 --- APRSCode.c | 30 +- ARDOP.c | 170 +++++----- BBSUtilities.c | 8 +- BPQINP3.c | 3 + Bpq32.c | 115 +++++++ Cmd.c | 51 +++ CommonCode.c | 22 ++ DRATS.c | 21 +- Events.c | 862 +++++++++++++++++++++++++++++++++++++++++++++++ KernelScript1.rc | 13 + L2Code.c | 25 ++ L3Code.c | 13 +- L4Code.c | 14 +- LinBPQ.c | 9 + MailTCP.c | 23 +- NETROMTCP.c | 589 ++++++++++++++++++++++++++++++++ TelnetV6.c | 43 +-- UZ7HODrv.c | 116 +++---- VARA.c | 3 +- Versions.h | 8 + WINMOR.c | 2 + WebMail.c | 4 +- asmstrucs.h | 19 ++ bpqaxip.c | 4 +- cMain.c | 27 +- config.c | 7 + lzhuf32.c | 152 ++++----- pngwutil.c | 5 +- 28 files changed, 2064 insertions(+), 294 deletions(-) diff --git a/APRSCode.c b/APRSCode.c index 2ee3b5f..6e65001 100644 --- a/APRSCode.c +++ b/APRSCode.c @@ -7693,7 +7693,7 @@ VOID APRSProcessHTTPMessage(SOCKET sock, char * MsgPtr, BOOL LOCAL, BOOL COOKIE) while (ptr) { char ToLopped[11] = ""; - + if (ptr->Acked) strcpy(Retries, "A"); else if (ptr->Retries == 0) @@ -7701,26 +7701,26 @@ VOID APRSProcessHTTPMessage(SOCKET sock, char * MsgPtr, BOOL LOCAL, BOOL COOKIE) else sprintf(Retries, "%d", ptr->Retries); - memcpy(ToLopped, ptr->ToCall, 10); - strlop(ToLopped, ' '); + memcpy(ToLopped, ptr->ToCall, 10); + strlop(ToLopped, ' '); - OutputLen += sprintf(&OutBuffer[OutputLen], WebTXLine, - ptr->ToCall, ptr->Seq, ptr->Time, Retries, ptr->Text); - ptr = ptr->Next; + OutputLen += sprintf(&OutBuffer[OutputLen], WebTXLine, + ptr->ToCall, ptr->Seq, ptr->Time, Retries, ptr->Text); + ptr = ptr->Next; - if (OutputLen > 99000) - break; + if (OutputLen > 99000) + break; - } + } - OutputLen += sprintf(&OutBuffer[OutputLen], "%s", WebTrailer); + OutputLen += sprintf(&OutBuffer[OutputLen], "%s", WebTrailer); - HeaderLen = sprintf(Header, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, OutBuffer, OutputLen); + HeaderLen = sprintf(Header, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); + sendandcheck(sock, Header, HeaderLen); + sendandcheck(sock, OutBuffer, OutputLen); + + return; - return; - } diff --git a/ARDOP.c b/ARDOP.c index 5832c44..ef92fad 100644 --- a/ARDOP.c +++ b/ARDOP.c @@ -466,107 +466,107 @@ static int ProcessLine(char * buf, int Port) else return FALSE; // Must start with ADDR - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; + TNC->InitScript = malloc(1000); + TNC->InitScript[0] = 0; - ptr = strtok(NULL, " \t\n\r"); + ptr = strtok(NULL, " \t\n\r"); - if (ptr) + if (ptr) + { + if (_stricmp(ptr, "PTT") == 0) { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); + 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); - } - } - - TNC->MaxConReq = 10; // Default - TNC->OldMode = FALSE; // Default - - // 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; + DecodePTTString(TNC, ptr); + ptr = strtok(NULL, " \t\n\r"); } - - if ((_memicmp(buf, "CAPTURE", 7) == 0) || (_memicmp(buf, "PLAYBACK", 8) == 0)) - {} // Ignore - else -/* + } + } + + if (ptr) + { + if (_memicmp(ptr, "PATH", 4) == 0) + { + p_cmd = strtok(NULL, "\n\r"); + if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); + } + } + + TNC->MaxConReq = 10; // Default + TNC->OldMode = FALSE; // Default + + // 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); + char * Context; + p_cmd = strtok_s(&buf[5], "\n\r", &Context); + if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); } else -*/ + */ if (_memicmp(buf, "PACKETCHANNELS", 14) == 0) // Packet Channels TNC->PacketChannels = atoi(&buf[14]); else - if (_memicmp(buf, "MAXCONREQ", 9) == 0) // Hold Time for Busy Detect - TNC->MaxConReq = atoi(&buf[9]); + if (_memicmp(buf, "MAXCONREQ", 9) == 0) // Hold Time for Busy Detect + TNC->MaxConReq = atoi(&buf[9]); - 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 (_memicmp(buf, "LOGDIR ", 7) == 0) - TNC->LogPath = _strdup(&buf[7]); - else - if (_memicmp(buf, "ENABLEPACKET", 12) == 0) - { - if (TNC->PacketChannels == 0) - TNC->PacketChannels = 5; - // AddVirtualKISSPort(TNC, Port, buf); - } + else + if (_memicmp(buf, "STARTINROBUST", 13) == 0) + TNC->StartInRobust = TRUE; -// else if (_memicmp(buf, "PAC ", 4) == 0 && _memicmp(buf, "PAC MODE", 8) != 0) -// { - // PAC MODE goes to TNC, others are parsed locally -// -// ConfigVirtualKISSPort(TNC, buf); -// } - else if (standardParams(TNC, buf) == FALSE) - strcat(TNC->InitScript, buf); - } + else + if (_memicmp(buf, "ROBUST", 6) == 0) + { + if (_memicmp(&buf[7], "TRUE", 4) == 0) + TNC->Robust = TRUE; + + strcat (TNC->InitScript, buf); + } + else + if (_memicmp(buf, "LOGDIR ", 7) == 0) + TNC->LogPath = _strdup(&buf[7]); + else + if (_memicmp(buf, "ENABLEPACKET", 12) == 0) + { + if (TNC->PacketChannels == 0) + TNC->PacketChannels = 5; + // AddVirtualKISSPort(TNC, Port, buf); + } + + // else if (_memicmp(buf, "PAC ", 4) == 0 && _memicmp(buf, "PAC MODE", 8) != 0) + // { + // PAC MODE goes to TNC, others are parsed locally + // + // ConfigVirtualKISSPort(TNC, buf); + // } + else if (standardParams(TNC, buf) == FALSE) + strcat(TNC->InitScript, buf); + } return (TRUE); @@ -1041,8 +1041,10 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) { TNC->Busy--; if (TNC->Busy == 0) + { MySetWindowText(TNC->xIDC_CHANSTATE, "Clear"); strcpy(TNC->WEB_CHANSTATE, "Clear"); + } } } diff --git a/BBSUtilities.c b/BBSUtilities.c index e803500..e6f7ade 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -3701,10 +3701,10 @@ void DoKillCommand(CIRCUIT * conn, struct UserInfo * user, char * Cmd, char * Ar if (conn->sysop) { if (Arg1) - if (KillMessagesFrom(conn, user, Arg1) == 0); + if (KillMessagesFrom(conn, user, Arg1) == 0) BBSputs(conn, "No Messages found\r"); - return; + return; } } @@ -6556,7 +6556,7 @@ nextline: { char APRS[128]; char Call[16]; - int SSID = user->flags >> 28; + int SSID = (user->flags >> 28) & 15; // on some platforms this is treated as signed ?? if (SSID) sprintf(Call, "%s-%d", Msg->to, SSID); @@ -13395,7 +13395,7 @@ int DeleteRedundantMessages() { while(n--) { - if (stat(namelist[n]->d_name, &STAT) == 0); + if (stat(namelist[n]->d_name, &STAT) == 0) { Msgno = atoi(&namelist[n]->d_name[2]); diff --git a/BPQINP3.c b/BPQINP3.c index 872496b..de4bf76 100644 --- a/BPQINP3.c +++ b/BPQINP3.c @@ -747,6 +747,9 @@ VOID SortRoutes(struct DEST_LIST * Dest) { char Call1[10], Call2[10], Call3[10]; + // force route re-evaluation + + Dest->DEST_ROUTE = 0; // May now be out of order diff --git a/Bpq32.c b/Bpq32.c index 41d4e64..3c5801f 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1406,6 +1406,11 @@ void initAIS(); void initADSB(); int CloseAllSessions(); int CloseAllLinks(); +<<<<<<< Updated upstream +||||||| Stash base +======= +void NETROMTCPResolve(); +>>>>>>> Stashed changes extern BOOL ADIFLogEnabled; @@ -1413,6 +1418,8 @@ int CloseOnError = 0; char UIClassName[]="UIMAINWINDOW"; // the main window class name +char ClosingClassName[]="CLOSING"; // the main window class name + HWND UIhWnd; extern char AUTOSAVE; @@ -2216,6 +2223,8 @@ VOID TimerProcX() Start(); + NETROMTCPResolve(); + INITIALISEPORTS(); // Restart Ports SetApplPorts(); @@ -2398,7 +2407,12 @@ VOID TimerProcX() if (CloseAllSessions() == 0) { if (CloseAllLinks() == 0) // No sessions closed so close links now +<<<<<<< Updated upstream CloseAllTimer = 0; // No Links so close now +||||||| Stash base +======= + CloseAllTimer = 1; // No Links so close now +>>>>>>> Stashed changes else CloseAllTimer = 39; // ~4 secs for links to close } @@ -2632,6 +2646,7 @@ Check_Timer() WSAStartup(MAKEWORD(2, 0), &WsaData); + // Load Psapi.dll if possible ExtDriver = LoadLibrary("Psapi.dll"); @@ -2646,6 +2661,8 @@ Check_Timer() Start(); + NETROMTCPResolve(); + INITIALISEPORTS(); OpenReportingSockets(); @@ -2969,6 +2986,8 @@ BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReser } else { + NETROMTCPResolve(); + SetApplPorts(); GetUIConfig(); @@ -5967,14 +5986,110 @@ DllExport VOID APIENTRY CreateNewTrayIcon() void hookNodeClosing(char * Reason); +<<<<<<< Updated upstream +||||||| Stash base +======= +BOOL CALLBACK ClosaAllProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + + switch (message) + { + case WM_INITDIALOG: + 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: + + return 0; + + case WM_SYSCOMMAND: + + wmId = LOWORD(wParam); // Remember, these are... + wmEvent = HIWORD(wParam); // ...different for Win32! + + switch (wmId) + { + case SC_RESTORE: + + return (DefWindowProc(hWnd, message, wParam, lParam)); + + case SC_MINIMIZE: + + if (MinimizetoTray) + return ShowWindow(hWnd, SW_HIDE); + else + return (DefWindowProc(hWnd, message, wParam, lParam)); + + break; + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + + case WM_CLOSE: + return(DestroyWindow(hWnd)); + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + + } + + return (0); +} + + +HWND hwndClosing = NULL; // Window handle of dialog box + +>>>>>>> Stashed changes DllExport VOID APIENTRY CloseAllPrograms() { +<<<<<<< Updated upstream +||||||| Stash base +// HANDLE hProc; +======= + WNDCLASS wc; +>>>>>>> Stashed changes CLOSING = TRUE; // Tell BG to shut when all links are gone or after 5 secs CloseAllTimer = 50; +<<<<<<< Updated upstream +||||||| Stash base + Closing = TRUE; +======= + + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = ClosaAllProc; + 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 = ClosingClassName; + + RegisterClass(&wc); + + hwndClosing = CreateDialog(hInstance, ClosingClassName, NULL, (DLGPROC)ClosaAllProc); + ShowWindow(hwndClosing, SW_SHOW); +>>>>>>> Stashed changes } VOID RealCloseAllPrograms() diff --git a/Cmd.c b/Cmd.c index 605ccd1..7eb6061 100644 --- a/Cmd.c +++ b/Cmd.c @@ -130,6 +130,8 @@ int NOBUFFCOUNT = 0; int BUFFERWAITS = 0; int MAXDESTS = 0; int NUMBEROFNODES = 0; +int L2CONNECTSOUT = 0; +int L2CONNECTSIN = 0; int L4CONNECTSOUT = 0; int L4CONNECTSIN = 0; int L4FRAMESTX = 0; @@ -903,8 +905,18 @@ int checkifService(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, s BOOL Stay = FALSE; char * ptr, *Context; int i; +<<<<<<< Updated upstream ptr = strtok_s(CmdTail, " ", &Context); +||||||| Stash base +======= + char TailCopy[256]; + + strcpy(TailCopy, CmdTail); + + + ptr = strtok_s(TailCopy, " ", &Context); +>>>>>>> Stashed changes // see if any param. if longer than two chars treat as remote node @@ -2665,7 +2677,14 @@ NoPort: // SEE IF CALL TO ANY OF OUR HOST SESSIONS - UNLESS DIGIS SPECIFIED +<<<<<<< Updated upstream if (axcalls[7] == 0 && axcalls[9] ) +||||||| Stash base + if (axcalls[7] == 0) +======= +// if (axcalls[7] == 0 && axcalls[9]) + if (axcalls[7] == 0) +>>>>>>> Stashed changes { // If this connect is as a result of a command alias, don't check appls or we will loop @@ -2716,6 +2735,7 @@ NoPort: } } +<<<<<<< Updated upstream // if no digis see if connect to known node. But now could have a single numeric param as a service number (Paula's Netromx) // cmdCopy is command tail (after call) @@ -2729,11 +2749,42 @@ NoPort: if (cmdCopy[i] != ' ') goto Downlink; else +||||||| Stash base + if (axcalls[7] == 0) +======= + // if no digis see if connect to known node. + + // But now could have a single numeric param as a service number (Paula's Netromx) + // cmdCopy is command tail (after call) + + // Make sure field is numeric + + if (cmdCopy[0] != ' ') +>>>>>>> Stashed changes { +<<<<<<< Updated upstream if (i > 0) // Some digits { haveService = 1; Service = atoi(cmdCopy); +||||||| Stash base + // SEE IF CALL TO ANOTHER NODE +======= + i = 0; + + while (cmdCopy[i] >= '0' && cmdCopy[i]<= '9') + i++; + + if (cmdCopy[i] != ' ') + goto Downlink; + else + { + if (i > 0) // Some digits + { + haveService = 1; + Service = atoi(cmdCopy); + } +>>>>>>> Stashed changes } } diff --git a/CommonCode.c b/CommonCode.c index cffbdb7..09690ae 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -75,6 +75,7 @@ void printStack(void); char * FormatMH(PMHSTRUC MH, char Format); void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode); void SendDataToPktMap(); +void NETROMTCPResolve(); extern BOOL LogAllConnects; extern BOOL M0LTEMap; @@ -3738,16 +3739,37 @@ VOID ResolveUpdateThread(void * Unused) nodeStartedSent = 1; LastNodeStatus = time(NULL); } +<<<<<<< Updated upstream } if (HostEnt1 && HostEnt2) { Sleep(1000 * 60 * 30); continue; +||||||| Stash base + Sleep(1000 * 60 * 30); + continue; +======= +>>>>>>> Stashed changes } +<<<<<<< Updated upstream Debugprintf("Resolve Failed for update.g8bpq.net or chatmap.g8bpq.net"); Sleep(1000 * 60 * 5); +||||||| Stash base + + Debugprintf("Resolve Failed for update.g8bpq.net or chatmap.g8bpq.net"); + Sleep(1000 * 60 * 5); +======= + + NETROMTCPResolve(); + + if (HostEnt1 && HostEnt2) + { + Sleep(1000 * 60 * 15); + continue; + } +>>>>>>> Stashed changes } } diff --git a/DRATS.c b/DRATS.c index c7b6b83..7fd85cf 100644 --- a/DRATS.c +++ b/DRATS.c @@ -568,18 +568,19 @@ void DRATSConnectionLost(struct ConnectionInfo * sockptr) int doinflate(unsigned char * source, unsigned char * dest, int Len, int destlen, int * outLen) { - int ret; - z_stream strm; + int ret; + z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; - ret = inflateInit(&strm); - if (ret != Z_OK) - return ret; + ret = inflateInit(&strm); + + if (ret != Z_OK) + return ret; strm.avail_in = Len; strm.next_in = source; diff --git a/Events.c b/Events.c index 2030929..1a64b3b 100644 --- a/Events.c +++ b/Events.c @@ -57,6 +57,7 @@ extern char LOC[7]; extern char VersionString[50]; extern double LatFromLOC; extern double LonFromLOC; +<<<<<<< Updated upstream void hookL2SessionClosed(struct _LINKTABLE * LINK, char * Reason, char * Direction); int ConvFromAX25(unsigned char * incall, unsigned char * outcall); @@ -66,6 +67,21 @@ int decodeNETROMUIMsg(unsigned char * Msg, int iLen, char * Buffer, int BufferLe int decodeNETROMIFrame(unsigned char * Msg, int iLen, char * Buffer, int BufferLen); int decodeINP3RIF(unsigned char * Msg, int iLen, char * Buffer, int BufferLen); int decodeRecordRoute(L3MESSAGE * L3, int iLen, char * Buffer, int BufferLen); +||||||| Stash base +======= +extern int NUMBEROFNODES, MAXDESTS, L4CONNECTSOUT, L4CONNECTSIN, L4FRAMESTX, L4FRAMESRX, L4FRAMESRETRIED, OLDFRAMES; +extern int L2CONNECTSOUT, L2CONNECTSIN; + +void hookL2SessionClosed(struct _LINKTABLE * LINK, char * Reason, char * Direction); +int ConvFromAX25(unsigned char * incall, unsigned char * outcall); +int COUNT_AT_L2(struct _LINKTABLE * LINK); +int CountFramesQueuedOnSession(TRANSPORTENTRY * Session); +int decodeNETROMUIMsg(unsigned char * Msg, int iLen, char * Buffer, int BufferLen); +int decodeNETROMIFrame(unsigned char * Msg, int iLen, char * Buffer, int BufferLen); +int decodeINP3RIF(unsigned char * Msg, int iLen, char * Buffer, int BufferLen); +int decodeRecordRoute(L3MESSAGE * L3, int iLen, char * Buffer, int BufferLen); +char * byte_base64_encode(char *str, int len); +>>>>>>> Stashed changes // Runs use specified routine on certain event @@ -141,13 +157,31 @@ DllExport void APIENTRY RunEventProgram(char * Program, char * Param) void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK) { // Incoming SABM accepted +<<<<<<< Updated upstream char UDPMsg[1024]; int udplen; +||||||| Stash base + // Incoming SABM +======= +>>>>>>> Stashed changes +<<<<<<< Updated upstream LINK->ConnectTime = time(NULL); LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; +||||||| Stash base + LINK->ConnectTime = time(NULL); + LINK->bytesTXed = LINK->bytesRXed = 0; +======= + char UDPMsg[1024]; + int udplen; +>>>>>>> Stashed changes + L2CONNECTSIN++; + + LINK->lastStatusSentTime = LINK->ConnectTime = time(NULL); + LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; + LINK->LastStatusbytesTXed = LINK->LastStatusbytesRXed = 0; strcpy(LINK->callingCall, remotecall); strcpy(LINK->receivingCall, ourcall); strcpy(LINK->Direction, "In"); @@ -217,9 +251,19 @@ void hookL2SessionDeleted(struct _LINKTABLE * LINK) void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK) { +<<<<<<< Updated upstream LINK->ConnectTime = time(NULL); LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; +||||||| Stash base + LINK->ConnectTime = time(NULL); + LINK->bytesTXed = LINK->bytesRXed = 0; + +======= + LINK->lastStatusSentTime = LINK->ConnectTime = time(NULL); + LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; + LINK->LastStatusbytesTXed = LINK->LastStatusbytesRXed = 0; +>>>>>>> Stashed changes strcpy(LINK->callingCall, ourcall); strcpy(LINK->receivingCall, remotecall); strcpy(LINK->Direction, "Out"); @@ -232,6 +276,7 @@ void hookL2SessionConnected(struct _LINKTABLE * LINK) char UDPMsg[1024]; int udplen; +<<<<<<< Updated upstream if (NodeAPISocket) { LINK->lastStatusSentTime = time(NULL); @@ -297,6 +342,96 @@ void hookL2SessionStatus(struct _LINKTABLE * LINK) LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent); // Debugprintf(UDPMsg); +||||||| Stash base +======= + L2CONNECTSOUT++; + + if (NodeAPISocket) + { + LINK->lastStatusSentTime = time(NULL); + + udplen = sprintf(UDPMsg, "{\"@type\":\"LinkUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}", + NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall); + +// Debugprintf(UDPMsg); + + sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); + } +} + +void hookL2SessionClosed(struct _LINKTABLE * LINK, char * Reason, char * Direction) +{ + // Link closed. Could be normal, ie disc send/received or restried out etc + + char UDPMsg[1024]; + int udplen; + time_t Now = time(NULL); + + if (NodeAPISocket) + { + if (LINK->receivingCall[0] == 0 || LINK->callingCall[0] == 0) + return; + + if (strcmp(Direction, "Out") == 0) + udplen = sprintf(UDPMsg, "{\"@type\":\"LinkDownEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"," + "\"bytesSent\": %d, \"bytesRcvd\": %d, \"frmsSent\": %d, \"frmsRcvd\": %d, \"frmsQueued\": %d, \"frmsResent\": %d, \"reason\": \"%s\"," + " \"time\": %d, \"upForSecs\": %d, \"frmsQdPeak\": %d}", + NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall, + LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent, Reason, + (int)Now, (int)Now - LINK->ConnectTime, LINK->maxQueued); + else + udplen = sprintf(UDPMsg, "{\"@type\":\"LinkDownEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"," + "\"bytesSent\": %d, \"bytesRcvd\": %d, \"frmsSent\": %d, \"frmsRcvd\": %d, \"frmsQueued\": %d, \"frmsResent\": %d, \"reason\": \"%s\"," + " \"time\": %d, \"upForSecs\": %d, \"frmsQdPeak\": %d}", + NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, + LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent, Reason, + (int)Now, (int)Now - LINK->ConnectTime, LINK->maxQueued); + + + Debugprintf(UDPMsg); + + sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); + } +} + +void hookL2SessionStatus(struct _LINKTABLE * LINK) +{ + // Send at regular intervals on open links + + char UDPMsg[1024]; + int udplen; + time_t Now = time(NULL); + int bpsTx, bpsRx, interval; + + if (NodeAPISocket) + { + interval = Now - (int)LINK->lastStatusSentTime; + bpsTx = (LINK->bytesTXed - LINK->LastStatusbytesTXed) / interval; + bpsRx = (LINK->bytesRXed - LINK->LastStatusbytesRXed) / interval; + + LINK->lastStatusSentTime = Now; + LINK->LastStatusbytesTXed = LINK->bytesTXed; + LINK->LastStatusbytesRXed = LINK->bytesRXed; + + if (strcmp(LINK->Direction, "Out") == 0) + udplen = sprintf(UDPMsg, "{\"@type\":\"LinkStatus\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"," + "\"bytesSent\": %d, \"bytesRcvd\": %d, \"frmsSent\": %d, \"frmsRcvd\": %d, \"frmsQueued\": %d, \"frmsResent\": %d," + "\"upForSecs\": %d, \"frmsQdPeak\": %d, \"bpsTxMean\": %d, \"bpsRxMean\": %d, \"frmQMax\": %d, \"l2rttMs\": %d}", + NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall, + LINK->bytesTXed, LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, 0, LINK->framesResent, + (int)Now - LINK->ConnectTime, LINK->maxQueued, bpsTx, bpsRx, LINK->intervalMaxQueued, LINK->RTT); + else + udplen = sprintf(UDPMsg, "{\"@type\":\"LinkStatus\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"," + "\"bytesSent\": %d, \"bytesRcvd\": %d, \"frmsSent\": %d, \"frmsRcvd\": %d, \"frmsQueued\": %d, \"frmsResent\": %d," + "\"upForSecs\": %d, \"frmsQdPeak\": %d, \"bpsTxMean\": %d, \"bpsRxMean\": %d, \"frmQMax\": %d, \"l2rttMs\": %d}", + NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, + LINK->bytesTXed, LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, 0, LINK->framesResent, + (int)Now - LINK->ConnectTime, LINK->maxQueued, bpsTx, bpsRx, LINK->intervalMaxQueued, LINK->RTT); + + LINK->intervalMaxQueued = 0; + + Debugprintf(UDPMsg); +>>>>>>> Stashed changes sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); } @@ -412,6 +547,7 @@ void hookNodeClosing(char * Reason) if (NodeAPISocket) { +<<<<<<< Updated upstream udplen = sprintf(UDPMsg, "{\"@type\": \"NodeDownEvent\", \"nodeCall\": \"%s\", \"nodeAlias\": \"%s\", \"reason\": \"%s\"}", NODECALLLOPPED, MYALIASLOPPED, Reason); @@ -1074,6 +1210,732 @@ int decodeRecordRoute(L3MESSAGE * L3, int iLen, char * Buffer, int BufferLen) (L3->L4TXNO << 8) | L3->L4RXNO, callList); Debugprintf(Buffer); +||||||| Stash base +======= + udplen = sprintf(UDPMsg, "{\"@type\": \"NodeDownEvent\", \"nodeCall\": \"%s\", \"nodeAlias\": \"%s\", \"reason\": \"%s\", \"uptimeSecs\": %d," + "\"linksIn\": %d, \"linksOut\": %d, \"cctsIn\": %d, \"cctsOut\": %d, \"l3Relayed\": %d}", + NODECALLLOPPED, MYALIASLOPPED, Reason, time(NULL) - TimeLoaded, L2CONNECTSIN, L2CONNECTSOUT, L4CONNECTSIN, L4CONNECTSOUT, L3FRAMES); + +// Debugprintf(UDPMsg); + + sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); + } +} + +void hookNodeRunning() +{ + char UDPMsg[1024]; + int udplen; +#ifdef LINBPQ + char Software[80] = "LinBPQ"; + + if (sizeof(void *) == 4) + strcat(Software, "(32 bit)"); +#else + char Software[80] = "BPQ32"; +#endif + + if (NodeAPISocket) + { + + udplen = sprintf(UDPMsg, "{\"@type\": \"NodeStatus\", \"nodeCall\": \"%s\", \"nodeAlias\": \"%s\", \"locator\": \"%s\"," + "\"latitude\": %f, \"longitude\": %f, \"software\": \"%s\", \"version\": \"%s\", \"uptimeSecs\": %d," + "\"linksIn\": %d, \"linksOut\": %d, \"cctsIn\": %d, \"cctsOut\": %d, \"l3Relayed\": %d}", + NODECALLLOPPED, MYALIASLOPPED, LOC, LatFromLOC, LonFromLOC, Software, VersionString, time(NULL) - TimeLoaded, + L2CONNECTSIN, L2CONNECTSOUT, L4CONNECTSIN, L4CONNECTSOUT, L3FRAMES); + +// Debugprintf(UDPMsg); + + sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); + } +} + +void IncomingL4ConnectionEvent(TRANSPORTENTRY * L4) +{ + char UDPMsg[1024]; + int udplen; + + char remotecall[64]; + char ourcall[64]; + char circuitinfo[32]; + + // CACK sent to CREQ + + if (NodeAPISocket) + { + remotecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, remotecall)] = 0; + // remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0; + ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0; + + sprintf(circuitinfo, ":%02x%02x", L4->FARINDEX, L4->FARID); + strcat(remotecall, circuitinfo); + + sprintf(circuitinfo, ":%02x%02x", L4->CIRCUITINDEX, L4->CIRCUITID); + strcat(ourcall, circuitinfo); + + udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\"," + "\"service\": %d, \"remote\": \"%s\", \"local\": \"%s\"}", + NODECALLLOPPED, UDPSeq++, L4->Service, remotecall, ourcall); + +// Debugprintf(UDPMsg); + sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); + } +} + + +void OutgoingL4ConnectionEvent(TRANSPORTENTRY * L4) +{ + char UDPMsg[1024]; + int udplen; + char remotecall[64]; + char ourcall[64]; + char circuitinfo[32]; + + // CACK received + + if (NodeAPISocket) + { + remotecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, remotecall)] = 0; + // remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0; + ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0; + + sprintf(circuitinfo, ":%02x%02x", L4->FARID, L4->FARINDEX); + strcat(remotecall, circuitinfo); + + sprintf(circuitinfo, ":%02x%02x", L4->CIRCUITID, L4->CIRCUITINDEX); + strcat(ourcall, circuitinfo); + + udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\"," + "\"service\": %d, \"remote\": \"%s\", \"local\": \"%s\"}", + NODECALLLOPPED, UDPSeq++, L4->Service, remotecall, ourcall); + +// Debugprintf(UDPMsg); + sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); + } +} + +/* + { + "@type": "CircuitUpEvent", + "node": "G8PZT" + "id": 1, + "direction": "incoming", + "service": 0, + "remote": "G8PZT@G8PZT:14c0", + "local": "G8PZT-4:0001" + } + + + "segsSent": 5, + "segsRcvd": 27, + "segsResent": 0, + "segsQueued": 0, + "reason": "rcvd DREQ" + +*/ + +void L4DisconnectEvent(TRANSPORTENTRY * L4, char * Direction, char * Reason) +{ + char UDPMsg[1024]; + int udplen; + char remotecall[64]; + char ourcall[64]; + char circuitinfo[32]; + int Count; + + // CACK received + + if (NodeAPISocket) + { + remotecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, remotecall)] = 0; +// remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0; + ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0; + + sprintf(circuitinfo, ":%02x%02x", L4->FARINDEX, L4->FARID); + strcat(remotecall, circuitinfo); + + sprintf(circuitinfo, ":%02x%02x", L4->CIRCUITINDEX, L4->CIRCUITID); + strcat(ourcall, circuitinfo); + + + if (L4->L4CROSSLINK) // CONNECTED? + Count = CountFramesQueuedOnSession(L4->L4CROSSLINK); + else + Count = CountFramesQueuedOnSession(L4); + + udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitDownEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"%s\"," + "\"service\": %d, \"remote\": \"%s\", \"local\": \"%s\", \"segsSent\": %d, \"segsRcvd\": %d, \"segsResent\": %d, \"segsQueued\": %d, \"reason\": \"%s\"}", + NODECALLLOPPED, UDPSeq++, Direction, 0, remotecall, ourcall,L4->segsSent, L4->segsRcvd, L4->segsResent, Count, Reason); + +// Debugprintf(UDPMsg); + sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); + } +} + +void L4StatusSeport(TRANSPORTENTRY * L4) +{ + char UDPMsg[1024]; + int udplen; + char remotecall[64]; + char ourcall[64]; + char nodecall[16]; + char circuitinfo[32]; + int Count; + + // CACK received + + if (NodeAPISocket) + { + nodecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, nodecall)] = 0; + remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0; + ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0; + + sprintf(circuitinfo, ":%02x%02x", L4->FARINDEX, L4->FARID); + strcat(remotecall, circuitinfo); + + sprintf(circuitinfo, ":%02x%02x", L4->CIRCUITINDEX, L4->CIRCUITID); + strcat(ourcall, circuitinfo); + + + if (L4->L4CROSSLINK) // CONNECTED? + Count = CountFramesQueuedOnSession(L4->L4CROSSLINK); + else + Count = CountFramesQueuedOnSession(L4); + + udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitStatus\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\"," + "\"service\": %d, \"remote\": %s, \"local\": \"%s\", \"segsSent\": %d, \"segsRcvd\": %d, \"segsResent\": %d, \"segsQueued\": %d}", + NODECALLLOPPED, UDPSeq++, 0, remotecall, ourcall,L4->segsSent, L4->segsRcvd, L4->segsResent, Count); + +// Debugprintf(UDPMsg); + sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); + } +} + + +// L2/3/4 Tracing + +#define PFBIT 0x10 // POLL/FINAL BIT IN CONTROL BYTE +#define NETROM_PID 0xCF +#define IP_PID 0xCC +#define ARP_PID 0xCD + +char * PIDtoText(int PID) +{ + switch (PID) + { + case 240: + return "DATA"; + case NETROM_PID: + return "NET/ROM"; + case IP_PID: + return "IP"; + case ARP_PID: + return "ARP"; + } + return "?"; +} + +void dumpDuffPacket(char * call, char * Buffer, int Len) +{ + // log to syslog in base64 + + char * Base64; + + Base64 = byte_base64_encode(Buffer, Len); + + Debugprintf("Trace Error %s %s", call, Base64); + free(Base64); +} + +int checkCall(char * call, unsigned char * Buffer, int Len) +{ + char c; + int i; + + // Validate source and dest calls - if duff, dump packet + + for (i = 0; i < strlen(call); i++) + { + c = call[i]; + + if (isalnum(c) || c == '-' || c == '@') + continue; + + dumpDuffPacket(call, Buffer, Len); + return 0; + } + + return 1; +} + + + +void APIL2Trace(struct _MESSAGE * Message, char * Dirn) +{ + char UDPMsg[2048]; + int udplen; + char srcecall[64]; + char destcall[16]; + char CR[3] = ""; + char PF[2] = ""; + int iLen = 0; + int CTL = Message->CTL; + char Type[16] = "Unknown"; + int UIFlag = 0; + int IFlag = 0; + int UFlag = 0; + int NS; + int NR; + + + if ((Message->ORIGIN[6] & 1) == 0) // Digis + return; + + destcall[ConvFromAX25(Message->DEST, destcall)] = 0; + srcecall[ConvFromAX25(Message->ORIGIN, srcecall)] = 0; + + // Validate source and dest calls - if duff, dump packet + + if (!checkCall(destcall,(char *) Message, Message->LENGTH)) + return; + + if (!checkCall(srcecall, (char *) Message, Message->LENGTH)) + return; + + // see if any Digis + + if ((Message->ORIGIN[6] & 1) == 0) // Digis - ignore for now + return; + + + if ((Message->DEST[6] & 0x80) == 0 && (Message->ORIGIN[6] & 0x80) == 0) + strcpy(CR, "V1"); + else if ((Message->DEST[6] & 0x80)) + strcpy(CR, "C"); + else if (Message->ORIGIN[6] & 0x80) + strcpy(CR, "R"); + else + strcpy(CR, "V1"); + + if (CTL & PFBIT) + { + if (CR[0] == 'C') + PF[0] = 'P'; + else if (CR[0] == 'R') + PF[0] = 'F'; + } + + CTL &= ~PFBIT; + + if ((CTL & 1) == 0) // I frame + { + NS = (CTL >> 1) & 7; // ISOLATE RECEIVED N(S) + NR = (CTL >> 5) & 7; + + IFlag = 1; + iLen = Message->LENGTH - (MSGHDDRLEN + 16); // Dest origin ctl pid + + strcpy(Type, "I"); + } + else if (CTL == 3) + { + // Un-numbered Information Frame + + strcpy(Type, "UI"); + UIFlag = 1; + iLen = Message->LENGTH - (MSGHDDRLEN + 16); // Dest origin ctl pid + } + + if (CTL & 2) + { + // UnNumbered + + UFlag = 1; + + switch (CTL) + { + case SABM: + + strcpy(Type, "C"); + break; + + case SABME: + + strcpy(Type, "SABME"); + break; + + case XID: + + strcpy(Type, "XID"); + break; + + case TEST: + + strcpy(Type, "TEST"); + break; + + case DISC: + + strcpy(Type, "D"); + break; + + case DM: + + strcpy(Type, "DM"); + break; + + case UA: + + strcpy(Type, "UA"); + break; + + + case FRMR: + + strcpy(Type, "FRMR"); + break; + } + } + else + { + // Super + + NR = (CTL >> 5) & 7; + NS = (CTL >> 1) & 7; // ISOLATE RECEIVED N(S) + + switch (CTL & 0x0F) + { + case RR: + + strcpy(Type, "RR"); + break; + + case RNR: + + strcpy(Type, "RNR"); + break; + + case REJ: + + strcpy(Type, "REJ"); + break; + + case SREJ: + + strcpy(Type, "SREJ"); + break; + } + } + + // Common to all frame types + + udplen = snprintf(UDPMsg, 2048, + "{\"@type\": \"L2Trace\", \"dirn\": \"%s\", \"reportFrom\": \"%s\", \"port\": \"%d\", \"srce\": \"%s\", \"dest\": \"%s\", \"ctrl\": %d," + "\"l2Type\": \"%s\", \"modulo\": 8, \"cr\": \"%s\"", + Dirn, NODECALLLOPPED, Message->PORT, srcecall, destcall, Message->CTL, Type, CR); + + if (UIFlag) + { + udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, + ", \"ilen\": %d, \"pid\": %d, \"ptcl\": \"%s\"", iLen, Message->PID, PIDtoText(Message->PID)); + + if (Message->PID == NETROM_PID) + { + udplen += decodeNETROMUIMsg(Message->L2DATA, iLen, &UDPMsg[udplen], 2048 - udplen); + } + } + else if (IFlag) + { + if (PF[0]) + udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, + ", \"ilen\": %d, \"pid\": %d, \"ptcl\": \"%s\", \"pf\": \"%s\", \"rseq\": %d, \"tseq\": %d", + iLen, Message->PID, PIDtoText(Message->PID), PF, NR, NS); + else + udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, + ", \"ilen\": %d, \"pid\": %d, \"ptcl\": \"%s\", \"rseq\": %d, \"tseq\": %d", + iLen, Message->PID, PIDtoText(Message->PID), NR, NS); + + if (Message->PID == NETROM_PID) + { + int n = decodeNETROMIFrame(Message->L2DATA, iLen, &UDPMsg[udplen], 2048 - udplen); + + if (n == 0) + return; // Can't decode so don't trace anything; + + udplen += n; + } + + } + else if (UFlag) + { + if (PF[0]) + udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, ", \"pf\": \"%s\"", PF); + } + else + { + // supervisory + + if (PF[0]) + udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, ", \"pf\": \"%s\", \"rseq\": %d, \"tseq\": %d", PF, NR, NS); + else + udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, ", \"rseq\": %d, \"tseq\": %d", NR, NS); + } + + + UDPMsg[udplen++] = '}'; + UDPMsg[udplen] = 0; +// Debugprintf(UDPMsg); + sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); + +} + + +int decodeNETROMUIMsg(unsigned char * Msg, int iLen, char * Buffer, int BufferLen) +{ + int Len = 0; + + // UI with NETROM PID are assumed to by NODES broadcast (INP3 routes are sent in I frames) + + // But check first byte is 0xff to be sure, or 0xfe for Paula's char Alias[7]= ""; + + char Dest[10]; + char Node[10]; + char Alias[10] = ""; + + memcpy(Alias, &Msg[1], 6); + strlop(Alias, ' '); + + if (Msg[0] == 0xfe) // Paula's Nodes Poll + { + Len = snprintf(Buffer, BufferLen, ", \"l3Type\": \"Routing info\", \"type\": \"Routing poll\""); + return Len; + } + + if (Msg[0] != 0xff) + return 0; + + Msg += 7; // to first field + + Len = snprintf(Buffer, BufferLen, ", \"l3Type\": \"Routing info\", \"type\": \"NODES\", \"nodes\": ["); + + iLen -= 7; //Header, mnemonic and signature length + + if (iLen < 21) // No Entries + { + Buffer[Len++] = ']'; + return Len; + } + + while(iLen > 20) // Entries are 21 bytes + { + Dest[ConvFromAX25(Msg, Dest)] = 0; + Msg +=7; + memcpy(Alias, Msg, 6); + Msg +=6; + strlop(Alias, ' '); + Node[ConvFromAX25(Msg, Node)] = 0; + Msg +=7; + + Len += snprintf(&Buffer[Len], BufferLen - Len, "{\"call\": \"%s\", \"alias\": \"%s\", \"via\": \"%s\", \"qual\": %d},", Dest, Alias, Node, Msg[0]); + Msg++; + iLen -= 21; + } + // Have to replace trailing , with ] + + Buffer[Len - 1] = ']'; + return Len; +} + +int decodeNETROMIFrame(unsigned char * Msg, int iLen, char * Buffer, int BufferLen) +{ + int Len = 0; + L3MESSAGE * L3MSG = (L3MESSAGE *)Msg; + char srcecall[64]; + char destcall[16]; + char srcUser[16]; + char srcNode[16]; + int Opcode; + int netromx = 0; + int service = 0; + + + if (Msg[0] == 0xff) // RIF? + return decodeINP3RIF(&Msg[1], iLen - 1, Buffer, BufferLen); + + // Netrom L3 /4 frame. Do standard L3 header + + destcall[ConvFromAX25(L3MSG->L3DEST, destcall)] = 0; + srcecall[ConvFromAX25(L3MSG->L3SRCE, srcecall)] = 0; + + if (!checkCall(destcall, Msg, iLen)) + return 0; + + if (!checkCall(srcecall, Msg, iLen)) + return 0; + + + if (strcmp(destcall, "KEEPLI") == 0) + return 0; + + Len = snprintf(Buffer, BufferLen, ", \"l3Type\": \"NetRom\", \"l3src\": \"%s\", \"l3dst\": \"%s\", \"ttl\": %d", srcecall, destcall, L3MSG->L3TTL); + + // L4 Stuff + + Opcode = L3MSG->L4FLAGS & 15; + + switch (Opcode) + { + case 0: + + // OPCODE 0 is used for a variety of functions, using L4INDEX and L4ID as qualifiers + // 0c0c is used for IP. Ignore for now + + // 00 01 Seesm to be Netrom Record Route + + if (L3MSG->L4ID == 1 && L3MSG->L4INDEX == 0) + { + Len += decodeRecordRoute(L3MSG, iLen, &Buffer[Len], BufferLen - Len); + return Len; + } + + case L4CREQX: + + netromx = 1; + service = (L3MSG->L4RXNO << 8) | L3MSG->L4TXNO; + + case L4CREQ: + + srcUser[ConvFromAX25(&L3MSG->L4DATA[1], srcUser)] = 0; + srcNode[ConvFromAX25(&L3MSG->L4DATA[8], srcNode)] = 0; + + if (!checkCall(srcUser, Msg, iLen)) + return 0; + + + if (!checkCall(srcNode, Msg, iLen)) + return 0; + + + if (netromx) + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"CONN REQX\", \"fromCct\": %d, \"srcUser\": \"%s\", \"srcNode\": \"%s\", \"window\": %d, \"service\": %d", + (L3MSG->L4INDEX << 8) | L3MSG->L4ID, srcUser, srcNode, L3MSG->L4DATA[0], service); + else + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"CONN REQ\", \"fromCct\": %d, \"srcUser\": \"%s\", \"srcNode\": \"%s\", \"window\": %d", + (L3MSG->L4INDEX << 8) | L3MSG->L4ID, srcUser, srcNode, L3MSG->L4DATA[0]); + + return Len; + + case L4CACK: + + // Can be ACK or NACK depending on Choke flag + + if (L3MSG->L4FLAGS & L4BUSY) + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"CONN NAK\", \"toCct\": %d", + (L3MSG->L4INDEX << 8) | L3MSG->L4ID); + else + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"CONN ACK\", \"toCct\": %d, \"fromCct\": %d, \"accWin\": %d", + (L3MSG->L4INDEX << 8) | L3MSG->L4ID, (L3MSG->L4TXNO << 8) | L3MSG->L4RXNO, L3MSG->L4DATA[0]); + + return Len; + + + case L4INFO: + + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"INFO\", \"toCct\": %d, \"txSeq\": %d, \"rxSeq\": %d, \"paylen\": %d", + (L3MSG->L4INDEX << 8) | L3MSG->L4ID, L3MSG->L4TXNO, L3MSG->L4RXNO, iLen - 20); + + return Len; + + case L4IACK: + + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"INFO ACK\", \"toCct\": %d, \"rxSeq\": %d", + (L3MSG->L4INDEX << 8) | L3MSG->L4ID, L3MSG->L4RXNO); + + return Len; + + + case L4DREQ: + + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"DISC REQ\", \"toCct\": %d", (L3MSG->L4INDEX << 8) | L3MSG->L4ID); + return Len; + + case L4DACK: + + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"DISC ACK\", \"toCct\": %d", (L3MSG->L4INDEX << 8) | L3MSG->L4ID); + return Len; + + case L4RESET: + + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"RSET\", \"fromCct\": %d", (L3MSG->L4INDEX << 8) | L3MSG->L4ID); + return Len; + + + /* + "NRR Request" Netrom Record Route Request + "NRR Reply" Netrom Record Route Reply + "CONN REQ" Connect Request + "CONN REQX" Extended Connect Request + "CONN ACK" Connection Acknowledgement + "CONN NAK" Connection Negative Ack (refusal) + "DISC REQ" Disconnect request + "DISC ACK" Disconnect Acknowledgement + "INFO" Information-bearing frame + "INFO ACK" Acknowledgement for an INFO frame. + "RSET" Circuit Reset (kill) + "PROT EXT" Protocol Extension (e.g. IP, NCMP etc) + "unknown" Unrecognised type (shouldn't happen) + + + + + "l4type": "CONN ACK", + "fromCct": 10, + "toCct": 23809, + "accWin": 4, + */ + + } + return Len; +} + +int decodeRecordRoute(L3MESSAGE * L3, int iLen, char * Buffer, int BufferLen) +{ + int Len = 0; + char callList[512]; + char * ptr1 = callList; + unsigned char * ptr = L3->L4DATA; + char call[16]; + int Response = 0; + + iLen -= 20; + + while (iLen > 0) + { + call[ConvFromAX25(ptr, call)] = 0; + + ptr1 += sprintf(ptr1, " %s", call); + + if ((ptr[7] & 0x80) == 0x80) // Check turnround bit + { + *ptr1++ = '*'; + Response = 1; + } + + ptr += 8; + iLen -= 8; + } + + *ptr1 = 0; + + if (Response) + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"NRR Reply\", \"nrrId\": %d, \"nrrRoute\": \"%s\"", + (L3->L4TXNO << 8) | L3->L4RXNO, callList); + else + Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"NRR Request\", \"nrrId\": %d, \"nrrRoute\": \"%s\"", + (L3->L4TXNO << 8) | L3->L4RXNO, callList); + +// Debugprintf(Buffer); +>>>>>>> Stashed changes return Len; } diff --git a/KernelScript1.rc b/KernelScript1.rc index 4eef3b5..b230ace 100644 --- a/KernelScript1.rc +++ b/KernelScript1.rc @@ -50,6 +50,19 @@ BEGIN LTEXT "Enable IGate",IDC_STATIC,5,2,49,10 END +CLOSING DIALOG DISCARDABLE 300, 300, 200, 50 +STYLE DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | + WS_THICKFRAME +CAPTION "BPQ32 Close All" +CLASS "CLOSING" +FONT 8, "Fixedsys" +BEGIN + LTEXT "Closing Links - Please wait....",IDC_BACKGROUND,22,20,337,273 + +END + + + CONFIG DIALOGEX 249, 200, 160, 118 STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION EXSTYLE WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE diff --git a/L2Code.c b/L2Code.c index 8171d49..44015e1 100644 --- a/L2Code.c +++ b/L2Code.c @@ -2346,6 +2346,9 @@ VOID SFRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, UCHAR CTL, UCHA LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER + + LINK->framesResent++; + PORT = LINK->LINKPORT; if (PORT) @@ -2452,6 +2455,20 @@ treatasRR: LINK->L2FLAGS &= ~POLLSENT; // CLEAR I(P) or RR(P) SET + // ?? is this the place to do RTT? + + if (LINK->lastPSent) + { + int RTT = GetTickCount() - LINK->lastPSent; + + if (LINK->RTT) + LINK->RTT = ((LINK->RTT * 90) / 100) + RTT /10; // Smooth - 90% of old + 10% of new + else + LINK->RTT = RTT; + + LINK->lastPSent = 0; + } + if ((CTL & 0xf) == RNR) { // Dont Clear timer on receipt of RNR(F), spec says should poll for clearing of busy, @@ -2927,6 +2944,8 @@ VOID RESETNS(struct _LINKTABLE * LINK, UCHAR NS) { int Resent = (LINK->LINKNS - NS) & 7; // FRAMES TO RESEND + LINK->framesResent += Resent; + LINK->LINKNS = NS; // RESET N(S) if (LINK->LINKTYPE == 3) // mode-Node @@ -3150,6 +3169,11 @@ VOID SDETX(struct _LINKTABLE * LINK) LINK->LASTFRAMESENT = time(NULL); LINK->LASTSENTQCOUNT = COUNT_AT_L2(LINK); + if (LINK->LASTSENTQCOUNT > LINK->maxQueued) + LINK->maxQueued = LINK->LASTSENTQCOUNT; + + if (LINK->LASTSENTQCOUNT > LINK->intervalMaxQueued) + LINK->intervalMaxQueued = LINK->LASTSENTQCOUNT; if (LINK->AllowCompress && Msg->LENGTH > 20 && LINK->TX_Q && Msg->PID == 240) // if short and no more not worth trying compression { @@ -3352,6 +3376,7 @@ VOID SDETX(struct _LINKTABLE * LINK) // FLAG BUFFER TO CAUSE TIMER TO BE RESET AFTER SEND (or ACK if ACKMODE) Buffer->Linkptr = LINK; + LINK->lastPSent = GetTickCount(); } } diff --git a/L3Code.c b/L3Code.c index c25df5b..0aafe67 100644 --- a/L3Code.c +++ b/L3Code.c @@ -236,7 +236,7 @@ BOOL ACTIVATE_DEST(struct DEST_LIST * DEST) return L2SETUPCROSSLINK(ROUTE); } - // We umst be waiting for link to come up + // We must be waiting for link to come up return TRUE; @@ -627,9 +627,6 @@ VOID PROCROUTES(struct DEST_LIST * DEST, struct ROUTE * ROUTE, int Qual) if (Index == 0) { // THIS IS A REFRESH OF BEST - IF THIS ISNT ACTIVE ROUTE, MAKE IT ACTIVE - - if (DEST->DEST_ROUTE > 1) // LEAVE IT IF NOT SELECTED OR ALREADY USING BEST - DEST->DEST_ROUTE = 1; } goto UpdatateThisEntry; @@ -728,6 +725,8 @@ SORTROUTES: goto SORTROUTES; // 1 AND 2 MAY NOW BE WRONG! } + + DEST->DEST_ROUTE = 0; // OForce re-evaluation. } int COUNTNODES(struct ROUTE * ROUTE) @@ -1042,7 +1041,8 @@ VOID L3TimerProc() LINK = LINKS; i = MAXLINKS; - while (i--); + + while (i--) { if (LINK->LINKTYPE == 3) // Only if Internode { @@ -1310,6 +1310,9 @@ VOID REMOVENODE(dest_list * DEST) while (DEST->DEST_Q) ReleaseBuffer(Q_REM(&DEST->DEST_Q)); + if (DEST->DEST_STATE & 0x80) // LOCKED DESTINATION + return; + // MAY NEED TO CHECK FOR L4 CIRCUITS USING DEST, BUT PROBABLY NOT, // AS THEY SHOULD HAVE TIMED OUT LONG AGO diff --git a/L4Code.c b/L4Code.c index ecfd5f0..4bb6e18 100644 --- a/L4Code.c +++ b/L4Code.c @@ -1601,7 +1601,13 @@ VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT Appl int Index; char APPLCMD[13] = ""; +<<<<<<< Updated upstream memcpy(APPLCMD, APPL->APPLCMD, 13); +||||||| Stash base +======= + if (APPL) + memcpy(APPLCMD, APPL->APPLCMD, 13); +>>>>>>> Stashed changes memcpy(BPQPARAMS, &L4T1, 2); // SET DEFAULT T1 IN CASE NOT FROM ANOTHER BPQ NODE @@ -1674,6 +1680,12 @@ VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT Appl { // At the moment I only handle connects to appls. May support other node commands later. +<<<<<<< Updated upstream +||||||| Stash base +======= + memcpy(APPLCMD, CMD->String, 13); + +>>>>>>> Stashed changes if (n < APPL1 + NumberofAppls) goto doAPPLConnect; } @@ -2028,7 +2040,7 @@ TryAgain: while (n--) { - if (DEST->DEST_COUNT == 0 && DEST->DEST_RTT == 0) // Not used and not INP3 + if (DEST->DEST_COUNT == 0 && DEST->DEST_RTT == 0 && (DEST->DEST_STATE & 0x80) == 0) // Not used and not INP3 and not Appl { if (DEST->NRROUTE[0].ROUT_QUALITY < WorstQual) { diff --git a/LinBPQ.c b/LinBPQ.c index 1c16ef4..0000e1c 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -85,6 +85,11 @@ VOID GetPGConfig(); void SendBBSDataToPktMap(); void CloseAllLinks(); void hookNodeClosing(char * Reason); +<<<<<<< Updated upstream +||||||| Stash base +======= +void NETROMTCPResolve(); +>>>>>>> Stashed changes extern uint64_t INP3timeLoadedMS; @@ -1015,6 +1020,8 @@ int main(int argc, char * argv[]) return (0); } + NETROMTCPResolve(); + for (i=0;PWTEXT[i] > 0x20;i++); //Scan for cr or null PWLen=i; @@ -1546,6 +1553,8 @@ int main(int argc, char * argv[]) Consoleprintf(VerCopyright); Start(); + + NETROMTCPResolve(); INITIALISEPORTS(); diff --git a/MailTCP.c b/MailTCP.c index 289fb62..37c7cf9 100644 --- a/MailTCP.c +++ b/MailTCP.c @@ -2092,20 +2092,19 @@ int CreateSMTPMessage(SocketConn * sockptr, int i, char * MsgTitle, time_t Date, struct tm * tm; tm = gmtime(&Date); - + sprintf(DateString, "%04d/%02d/%02d %02d:%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); if (strcmp(Msg->to, "RMS") == 0) // Address is in via - strcpy(B2To, Msg->via); - else - if (Msg->via[0]) - sprintf(B2To, "%s@%s", Msg->to, Msg->via); + strcpy(B2To, Msg->via); else - strcpy(B2To, Msg->to); + if (Msg->via[0]) + sprintf(B2To, "%s@%s", Msg->to, Msg->via); + else + strcpy(B2To, Msg->to); - Msg->B2Flags = B2Msg | Attachments; if (Msg->type == 'P') @@ -3934,12 +3933,12 @@ int CreatePOP3Message(char * From, char * To, char * MsgTitle, time_t Date, char if (strcmp(Msg->to, "RMS") == 0) // Address is in via - strcpy(B2To, Msg->via); - else - if (Msg->via[0]) - sprintf(B2To, "%s@%s", Msg->to, Msg->via); + strcpy(B2To, Msg->via); else - strcpy(B2To, Msg->to); + if (Msg->via[0]) + sprintf(B2To, "%s@%s", Msg->to, Msg->via); + else + strcpy(B2To, Msg->to); Msg->B2Flags = B2Msg | Attachments; diff --git a/NETROMTCP.c b/NETROMTCP.c index 79f186b..2041937 100644 --- a/NETROMTCP.c +++ b/NETROMTCP.c @@ -1,3 +1,4 @@ +<<<<<<< Updated upstream /* Copyright 2001-2022 John Wiseman G8BPQ @@ -549,3 +550,591 @@ void NETROMConnectionLost(struct ConnectionInfo * sockptr) memset(sockptr, 0, sizeof(struct ConnectionInfo)); } +||||||| Stash base +======= +/* +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 +*/ + +/* +Netrom over TCP Support + +This is intended for operation over radio links with an IP interface, eg New Packet Radio or possibly microwave links + +To simplify interface to the rest of the oode dummy LINK and PORT records are created + +Packet Format is Length (2 byte little endian) Call (10 bytes ASCII) NETROM L3/4 Packet, starting 0xcf (to detect framing errors). + +A TCP message can contain multiple packets and/or partial packets + +It uses the Telnet Server, with port defined in NETROMPORT + +ROUTE definitions have an extra field, the TCP Port Number + +*/ + +//#pragma data_seg("_BPQDATA") + + +#define _CRT_SECURE_NO_DEPRECATE + +#include "time.h" +#include "stdio.h" +#include +//#include "vmm.h" + +#include "cheaders.h" +#include "asmstrucs.h" +#include "telnetserver.h" + +#define NETROM_PID 0xCF + +void NETROMConnectionLost(struct ConnectionInfo * sockptr); +int DataSocket_ReadNETROM(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info, int portNo); +int NETROMTCPConnect(struct ROUTE * Route, struct ConnectionInfo * sockptr); +void NETROMConnected(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info); +VOID SendRTTMsg(struct ROUTE * Route); +BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE); +VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG); +int BPQTRACE(MESSAGE * Msg, BOOL TOAPRS); +VOID L3LINKCLOSED(struct _LINKTABLE * LINK, int Reason); + +struct NRTCPMsg +{ + short Length; + char Call[10]; + unsigned char PID; + char Packet[1024]; +}; + +struct NRTCPSTRUCT +{ + struct ConnectionInfo * sockptr; + struct _LINKTABLE * LINK; // Dummy Link Record for this ROUTE + struct ROUTE * Route; // May need backlink + char Call[10]; +}; + +struct NRTCPSTRUCT * NRTCPInfo[256] = {0}; + +// Do we want to use normal TCP server connections, which are limited, or our own. Let's try our own for now + +struct ConnectionInfo * AllocateNRTCPRec() +{ + struct ConnectionInfo * sockptr = 0; + struct NRTCPSTRUCT * Info; + int i; + + for (i = 0; i < 255; i++) + { + if (NRTCPInfo[i] == 0) + { + // only allocate as many as needed + + Info = NRTCPInfo[i] = (struct NRTCPSTRUCT *)zalloc(sizeof(struct NRTCPSTRUCT)); + Info->sockptr = (struct ConnectionInfo *)zalloc(sizeof(struct ConnectionInfo)); + Info->LINK = (struct _LINKTABLE *)zalloc(sizeof(struct _LINKTABLE)); + Info->sockptr->Number = i; + } + else + Info = NRTCPInfo[i]; + + sockptr = Info->sockptr; + + if (sockptr->SocketActive == FALSE) + { + sockptr->SocketActive = TRUE; + sockptr->ConnectTime = sockptr->LastSendTime = time(NULL); + + Debugprintf("NRTCP Allocated %d", i); + return sockptr; + } + } + return 0; +} + +void checkNRTCPSockets(int portNo) +{ + SOCKET sock; + int Active = 0; + SOCKET maxsock; + int retval; + int i; + + struct timeval timeout; + fd_set readfd, writefd, exceptfd; + + struct ConnectionInfo * sockptr; + + timeout.tv_sec = 0; + timeout.tv_usec = 0; // poll + + maxsock = 0; + + FD_ZERO(&readfd); + FD_ZERO(&writefd); + FD_ZERO(&exceptfd); + + for (i = 0; i < 255; i++) + { + if (NRTCPInfo[i] == 0) + break; // only as many as have been used + + sockptr = NRTCPInfo[i]->sockptr; + + if (sockptr->SocketActive == 0) + continue; + + if (sockptr->Connecting) + { + // look for complete or failed + + FD_SET(sockptr->socket, &writefd); + FD_SET(sockptr->socket, &exceptfd); + } + else + { + FD_SET(sockptr->socket, &readfd); + FD_SET(sockptr->socket, &exceptfd); + } + + Active++; + + if (sockptr->socket > maxsock) + maxsock = sockptr->socket; + } + + if (Active) + { + retval = select((int)maxsock + 1, &readfd, &writefd, &exceptfd, &timeout); + + if (retval == -1) + { + perror("data select"); + Debugprintf("NRTCP Select Error %d Active %d", WSAGetLastError(), Active); + } + else + { + if (retval) + { + // see who has data + + for (i = 0; i < 255; i++) + { + if (NRTCPInfo[i] == 0) + break; + + sockptr = NRTCPInfo[i]->sockptr; + + if (sockptr->SocketActive == 0) + continue; + + sock = sockptr->socket; + + if (FD_ISSET(sock, &writefd)) + NETROMConnected(sockptr, sock, NRTCPInfo[i]); + + if (FD_ISSET(sock, &readfd)) + DataSocket_ReadNETROM(sockptr, sock, NRTCPInfo[i], portNo); + + if (FD_ISSET(sock, &exceptfd)) + NETROMConnectionLost(sockptr); + } + } + } + } +} + +int NETROMOpenConnection(struct ROUTE * Route) +{ + struct NRTCPSTRUCT * Info; + struct ConnectionInfo * sockptr; + + Debugprintf("Opening NRTCP Connection"); + + if (Route->TCPSession) + { + // SESSION ALREADY EXISTS + + sockptr = Route->TCPSession->sockptr; + + if (sockptr->Connected || sockptr->Connecting) + return TRUE; + + // previous connect failed + } + else + { + sockptr = AllocateNRTCPRec(); + + if (sockptr == NULL) + return 0; + + Info = Route->TCPSession = NRTCPInfo[sockptr->Number]; + memcpy(Info->Call, MYNETROMCALL, 10); + Route->NEIGHBOUR_LINK = Info->LINK; + + Info->Route = Route; + Info->LINK->NEIGHBOUR = Route; + Info->LINK->LINKPORT = GetPortTableEntryFromPortNum(Route->NEIGHBOUR_PORT); + } + + return NETROMTCPConnect(Route, sockptr); + +} + +void NETROMTCPResolve() +{ + struct ROUTE * Route = NEIGHBOURS; + int n = MAXNEIGHBOURS; + struct addrinfo hints, *res = 0; + char PortString[20]; + int err; + + while (n--) + { + if (Route->TCPAddress) + { + // try to resolve host + + sprintf(PortString, "%d", Route->TCPPort); + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + getaddrinfo(Route->TCPHost, PortString, &hints, &res); + + err = WSAGetLastError(); + + if (res) + { + Route->TCPAddress->ai_family = res->ai_family; + Route->TCPAddress->ai_socktype = res->ai_socktype; + Route->TCPAddress->ai_protocol = res->ai_protocol; + Route->TCPAddress->ai_addrlen = res->ai_addrlen; + memcpy(Route->TCPAddress->ai_addr, res->ai_addr, sizeof(struct sockaddr)); + freeaddrinfo(res); + } + } + + Route++; + } +} + +int NETROMTCPConnect(struct ROUTE * Route, struct ConnectionInfo * sockptr) +{ + int err; + u_long param=1; + BOOL bcopt=TRUE; + SOCKET sock; + struct sockaddr_in sinx; + int addrlen=sizeof(sinx); + char PortString[20]; + struct addrinfo * res = Route->TCPAddress; + int Port = Route->TCPPort; + + sprintf(PortString, "%d", Port); + + // get host info, make socket, and connect it + + if (res->ai_family == 0) + { +// err = WSAGetLastError(); +// Debugprintf("Resolve HostName %s Failed - Error %d", Route->TCPHost, err); + return FALSE; // Resolve failed + } + + sock = sockptr->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + if (sock == INVALID_SOCKET) + { + Debugprintf, ("Netrom over TCP Create Socket Failed"); + return FALSE; + } + + ioctl(sock, FIONBIO, ¶m); + + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); + + + if (connect(sock, res->ai_addr, (int)res->ai_addrlen) == 0) + { + // + // Connected successful + // + + sockptr->Connected = TRUE; + return TRUE; + } + else + { + err=WSAGetLastError(); + + if (err == 10035 || err == 115 || err == 36) //EWOULDBLOCK + { + // Connect in Progress + + sockptr->Connecting = TRUE; + return TRUE; + } + else + { + // Connect failed + + closesocket(sockptr->socket); + + return FALSE; + } + } + + return FALSE; +} + + + + +void NETROMConnectionAccepted(struct ConnectionInfo * sockptr) +{ + // Not sure we can do much here until first message arrives with callsign + + sockptr->Connected = TRUE; + Debugprintf("NRTCP Connection Accepted"); +} + +void NETROMConnected(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info) +{ + // Connection Complete + + Debugprintf("NRTCP Connected"); + + sockptr->Connecting = FALSE; + sockptr->Connected = TRUE; + + Info->LINK->L2STATE = 5; + + if (Info->Route->INP3Node) + SendRTTMsg(Info->Route); +} + +int DataSocket_ReadNETROM(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info, int portNo) +{ + int len=0, maxlen; + struct NRTCPMsg * Msg; + struct _L3MESSAGEBUFFER * L3Msg; + struct ROUTE * Route; + UCHAR axCall[7]; + PMESSAGE Buffer; + + ioctl(sock,FIONREAD,&len); + + maxlen = InputBufferLen - sockptr->InputLen; + + if (len > maxlen) len = maxlen; + + len = recv(sock, &sockptr->InputBuffer[sockptr->InputLen], len, 0); + + if (len == SOCKET_ERROR || len == 0) + { + // Failed or closed - clear connection + + NETROMConnectionLost(sockptr); + return 0; + } + + sockptr->InputLen += len; + + // Process data + +checkLen: + + // See if we have a whole packet + + Msg = (struct NRTCPMsg *)&sockptr->InputBuffer[0]; + + if (Msg->Length > sockptr->InputLen) // if not got whole frame wait + return 0; + + if (Info->Call[0] == 0) + { + // first packet - do we need to do anything? + + // This must be an incoming connection as Call is set before calling so need to find route record and set things up. + + Debugprintf("New NRTCP Connection from %s", Msg->Call); + + memcpy(Info->Call, Msg->Call, 10); + + ConvToAX25(Msg->Call, axCall); + + if (FindNeighbour(axCall, portNo, &Route)) + { + Info->Route = Route; + Route->NEIGHBOUR_LINK = Info->LINK; + Route->NEIGHBOUR_PORT = portNo; + Info->LINK->NEIGHBOUR = Route; + Info->LINK->LINKPORT = GetPortTableEntryFromPortNum(portNo); + Route->TCPSession = Info; + Info->LINK->L2STATE = 5; + + if (Info->Route->INP3Node) + SendRTTMsg(Info->Route); + } + else + { + Debugprintf("Neighbour %s port %d not found - closing connection", Msg->Call, portNo); + closesocket(sockptr->socket); + sockptr->SocketActive = FALSE; + memset(sockptr, 0, sizeof(struct ConnectionInfo)); + Info->Call[0] = 0; + return 0; + } + } + + + if (memcmp(Info->Call, Msg->Call, 10) != 0) + { + // something wrong - maybe connection reused + } + + // Format as if come from an ax.25 link + + L3Msg = GetBuff(); + + if (L3Msg == 0) + goto seeifMore; + + L3Msg->LENGTH = (Msg->Length - 12) + MSGHDDRLEN; + L3Msg->Next = 0; + L3Msg->Port = portNo; + L3Msg->L3PID = NETROM_PID; + memcpy(&L3Msg->L3SRCE, Msg->Packet, Msg->Length - 13); + + // Create a dummy L2 message so we can trace it + + Buffer = GetBuff(); + + if (Buffer) + { + Buffer->CHAIN = 0; + Buffer->CTL = 0; + Buffer->PORT = portNo; + + ConvToAX25(Info->Call, Buffer->ORIGIN); + ConvToAX25(MYNETROMCALL, Buffer->DEST); + + memcpy(Buffer->L2DATA, &L3Msg->L3SRCE[0], Msg->Length - 13); + Buffer->ORIGIN[6] |= 1; // Set end of calls + Buffer->PID = NETROM_PID; + Buffer->LENGTH = Msg->Length + 10; + time(&Buffer->Timestamp); + + BPQTRACE(Buffer, FALSE); + ReleaseBuffer(Buffer); + } + + NETROMMSG(Info->LINK, L3Msg); + +seeifMore: + + sockptr->InputLen -= Msg->Length; + + if (sockptr->InputLen > 0) + { + memmove(sockptr->InputBuffer, &sockptr->InputBuffer[Msg->Length], sockptr->InputLen); + goto checkLen; + } + + return 0; +} + +VOID TCPNETROMSend(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame) +{ + struct NRTCPMsg Msg; + unsigned char * Data = (unsigned char *)&Frame->L3SRCE[0]; + int DataLen = Frame->LENGTH - (MSGHDDRLEN + 1); // Not including PID + int Ret; + PMESSAGE Buffer; + + Msg.Length = DataLen + 13; // include PID + memcpy(Msg.Call, MYNETROMCALL, 10); + Msg.PID = NETROM_PID; + memcpy(Msg.Packet, Data, DataLen); + + if (Route->TCPSession == 0) + return; + + Ret = send(Route->TCPSession->sockptr->socket, (char *)&Msg, DataLen + 13, 0); + + // Create a dummy L2 message so we can trace it + + Buffer = GetBuff(); + + if (Buffer) + { + Buffer->CHAIN = 0; + Buffer->CTL = 0; + Buffer->PORT = Route->NEIGHBOUR_PORT | 128; // TX Flag + + ConvToAX25(Route->TCPSession->Call, Buffer->DEST); + ConvToAX25(MYNETROMCALL, Buffer->ORIGIN); + + memcpy(Buffer->L2DATA, &Frame->L3SRCE[0], DataLen); + Buffer->ORIGIN[6] |= 1; // Set end of calls + Buffer->PID = NETROM_PID; + Buffer->LENGTH = DataLen + 15 + MSGHDDRLEN; + time(&Buffer->Timestamp); + + BPQTRACE(Buffer, FALSE); + ReleaseBuffer(Buffer); + } + +} + + +void NETROMConnectionLost(struct ConnectionInfo * sockptr) +{ + struct NRTCPSTRUCT * Info = NRTCPInfo[sockptr->Number]; + struct ROUTE * Route; + + closesocket(sockptr->socket); + + // If there is an attached route (there should be) clear all connections + + if (Info) + { + Route = Info->Route; + + if (sockptr->Connected) + L3LINKCLOSED(Info->LINK, LINKLOST); + + if (sockptr->Connecting) + L3LINKCLOSED(Info->LINK, SETUPFAILED); + + if (Route) + Route->TCPSession = 0; + + Info->Call[0] = 0; + } + + sockptr->SocketActive = FALSE; + + memset(sockptr, 0, sizeof(struct ConnectionInfo)); +} + +>>>>>>> Stashed changes diff --git a/TelnetV6.c b/TelnetV6.c index 0761363..590186c 100644 --- a/TelnetV6.c +++ b/TelnetV6.c @@ -3874,12 +3874,14 @@ MsgLoop: LFPtr=memchr(MsgPtr, 10, InputLen); if (LFPtr == 0) + { if (CRPtr) { LFPtr = ++CRPtr; InputLen++; } - if (LFPtr == 0) + } + if (LFPtr == 0) { // Check Paclen @@ -3895,7 +3897,7 @@ MsgLoop: } // Send to Node - + // Line could be up to 500 chars if coming from a program rather than an interative user // Limit send to node to 255 @@ -3907,16 +3909,16 @@ MsgLoop: memmove(MsgPtr,MsgPtr+255,InputLen); } - + SendtoNode(TNC, sockptr->Number, MsgPtr, InputLen); sockptr->InputLen = 0; - + } // PACLEN return 0; // No CR } - + // Got a LF // Process data up to the cr @@ -3929,7 +3931,7 @@ MsgLoop: case 2: // Normal Data State - + STREAM->bytesRXed += MsgLen; SendIndex = 0; @@ -3944,7 +3946,7 @@ MsgLoop: } SendtoNode(TNC, sockptr->Number, MsgPtr + SendIndex, MsgLen); - + MsgLen += SendIndex; // If anything left, copy down buffer, and go back @@ -3963,20 +3965,20 @@ MsgLoop: return 0; case 0: - - // Check Username - // + + // Check Username + // *(LFPtr-1)=0; // remove cr - - // send(sock, NLMsg, 2, 0); - if (LogEnabled) + // send(sock, NLMsg, 2, 0); + + if (LogEnabled) { char Addr[256]; - + Tel_Format_Addr(sockptr, Addr); - + if (strlen(MsgPtr) > 64) { MsgPtr[64] = 0; @@ -4571,7 +4573,8 @@ MsgLoop: if (P8 == 1) SendPortsForMonitor(sock, sockptr->UserPointer->Secure); - sockptr->InputLen = 0; + + sockptr->InputLen = 0; return 0; } } @@ -6386,10 +6389,10 @@ VOID SaveCMSHostInfo(int port, struct TCPINFO * TCP, int CMSNo) char ip[256]; int n; - if (sizeof(time_t) == 4) - n = sscanf(buf,"%s %d %s", addr, (int *)&t, ip); - else - n = sscanf(buf, "%s %lld %s", addr, &t, ip); + if (sizeof(time_t) == 4) + n = sscanf(buf,"%s %d %s", addr, (int *)&t, ip); + else + n = sscanf(buf, "%s %lld %s", addr, &t, ip); if (n == 3) { diff --git a/UZ7HODrv.c b/UZ7HODrv.c index e166b36..2adfe12 100644 --- a/UZ7HODrv.c +++ b/UZ7HODrv.c @@ -1586,81 +1586,81 @@ static int ProcessLine(char * buf, int Port) if (TNC->TCPPort == 0) TNC->TCPPort = 8000; - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(TNC->TCPPort); - TNC->HostName = malloc(strlen(p_ipad)+1); + TNC->destaddr.sin_family = AF_INET; + TNC->destaddr.sin_port = htons(TNC->TCPPort); + TNC->HostName = malloc(strlen(p_ipad)+1); - if (TNC->HostName == NULL) return TRUE; + if (TNC->HostName == NULL) return TRUE; - strcpy(TNC->HostName,p_ipad); + strcpy(TNC->HostName,p_ipad); - ptr = strtok(NULL, " \t\n\r"); + ptr = strtok(NULL, " \t\n\r"); - if (ptr) + if (ptr) + { + if (_stricmp(ptr, "PTT") == 0) { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); + ptr = strtok(NULL, " \t\n\r"); - if (ptr) - { - DecodePTTString(TNC, ptr); - ptr = strtok(NULL, " \t\n\r"); - } - } - - if (ptr &&_memicmp(ptr, "PATH", 4) == 0) + if (ptr) { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); + DecodePTTString(TNC, ptr); + ptr = strtok(NULL, " \t\n\r"); } } - // Read Initialisation lines - - while(TRUE) + if (ptr &&_memicmp(ptr, "PATH", 4) == 0) { - if (GetLine(buf) == 0) - return TRUE; + p_cmd = strtok(NULL, "\n\r"); + if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); + } + } - strcpy(errbuf, buf); + // Read Initialisation lines - if (memcmp(buf, "****", 4) == 0) - return TRUE; + while(TRUE) + { + if (GetLine(buf) == 0) + return TRUE; - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if (_memicmp(buf, "MAXSESSIONS", 11) == 0) - { - AGW->MaxSessions = atoi(&buf[12]); - if (AGW->MaxSessions > 26 ) AGW->MaxSessions = 26; - } - if (_memicmp(buf, "CONTIMEOUT", 10) == 0) - AGW->ConnTimeOut = atoi(&buf[11]) * 10; - else + strcpy(errbuf, buf); + + if (memcmp(buf, "****", 4) == 0) + return TRUE; + + ptr = strchr(buf, ';'); + if (ptr) + { + *ptr++ = 13; + *ptr = 0; + } + + if (_memicmp(buf, "MAXSESSIONS", 11) == 0) + { + AGW->MaxSessions = atoi(&buf[12]); + if (AGW->MaxSessions > 26 ) AGW->MaxSessions = 26; + } + if (_memicmp(buf, "CONTIMEOUT", 10) == 0) + AGW->ConnTimeOut = atoi(&buf[11]) * 10; + else if (_memicmp(buf, "UPDATEMAP", 9) == 0) TNC->PktUpdateMap = TRUE; else - if (_memicmp(buf, "BEACONAFTERSESSION", 18) == 0) // Send Beacon after each session - TNC->RPBEACON = TRUE; - else - if (_memicmp(buf, "WINDOW", 6) == 0) - TNC->Window = atoi(&buf[7]); - else - if (_memicmp(buf, "DEFAULTMODEM", 12) == 0) - TNC->AGWInfo->Modem = atoi(&buf[13]); - else - if (_memicmp(buf, "MODEMCENTER", 11) == 0 || _memicmp(buf, "MODEMCENTRE", 11) == 0) - TNC->AGWInfo->CenterFreq = atoi(&buf[12]); - else - if (standardParams(TNC, buf) == FALSE) - strcat(TNC->InitScript, buf); - } + if (_memicmp(buf, "BEACONAFTERSESSION", 18) == 0) // Send Beacon after each session + TNC->RPBEACON = TRUE; + else + if (_memicmp(buf, "WINDOW", 6) == 0) + TNC->Window = atoi(&buf[7]); + else + if (_memicmp(buf, "DEFAULTMODEM", 12) == 0) + TNC->AGWInfo->Modem = atoi(&buf[13]); + else + if (_memicmp(buf, "MODEMCENTER", 11) == 0 || _memicmp(buf, "MODEMCENTRE", 11) == 0) + TNC->AGWInfo->CenterFreq = atoi(&buf[12]); + else + if (standardParams(TNC, buf) == FALSE) + strcat(TNC->InitScript, buf); + } return (TRUE); diff --git a/VARA.c b/VARA.c index 70f7461..f913fe8 100644 --- a/VARA.c +++ b/VARA.c @@ -423,8 +423,9 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) { TNC->Busy--; if (TNC->Busy == 0) - SetWindowText(TNC->xIDC_CHANSTATE, "Clear"); + { SetWindowText(TNC->xIDC_CHANSTATE, "Clear"); strcpy(TNC->WEB_CHANSTATE, "Clear"); + } } } diff --git a/Versions.h b/Versions.h index be8a65e..dfad8ec 100644 --- a/Versions.h +++ b/Versions.h @@ -10,8 +10,16 @@ #endif +<<<<<<< Updated upstream #define KVers 6,0,25,8 #define KVerstring "6.0.25.8\0" +||||||| Stash base +#define KVers 6,0,25,1 +#define KVerstring "6.0.25.1\0" +======= +#define KVers 6,0,25,9 +#define KVerstring "6.0.25.9\0" +>>>>>>> Stashed changes #ifdef CKernel diff --git a/WINMOR.c b/WINMOR.c index 836a070..94630b3 100644 --- a/WINMOR.c +++ b/WINMOR.c @@ -618,8 +618,10 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) { TNC->Busy--; if (TNC->Busy == 0) + { SetWindowText(TNC->xIDC_CHANSTATE, "Clear"); strcpy(TNC->WEB_CHANSTATE, "Clear"); + } } } diff --git a/WebMail.c b/WebMail.c index 63bfd6e..a97b9bf 100644 --- a/WebMail.c +++ b/WebMail.c @@ -3311,7 +3311,7 @@ char * xxReadTemplate(char * FormSet, char * DirName, char *FileName) while ((entry = readdir(dir)) != NULL) { if (entry->d_type == DT_DIR) - continue; + continue; if (stristr(entry->d_name, FileName)) { @@ -5609,7 +5609,7 @@ char * CheckFile(struct HtmlFormDir * Dir, char * FN) while ((entry = readdir(dir)) != NULL) { if (entry->d_type == DT_DIR) - continue; + continue; if (stricmp(entry->d_name, FN) == 0) { diff --git a/asmstrucs.h b/asmstrucs.h index 3ac464b..8b11d45 100644 --- a/asmstrucs.h +++ b/asmstrucs.h @@ -250,7 +250,13 @@ typedef struct ROUTE char * TCPHost; // For NETROM over TCP int TCPPort; +<<<<<<< Updated upstream struct NRTCPSTRUCT * TCPSession; +||||||| Stash base +======= + struct NRTCPSTRUCT * TCPSession; + struct addrinfo * TCPAddress; // Resolved Address +>>>>>>> Stashed changes } *PROUTE; @@ -977,6 +983,19 @@ typedef struct _LINKTABLE int framesRXed; int framesTXed; int framesResent; +<<<<<<< Updated upstream +||||||| Stash base +======= + time_t LastStatusTime; + int LastStatusbytesRXed; + int LastStatusbytesTXed; + int maxQueued; + int intervalMaxQueued; + + uint64_t lastPSent; // Time last I frame with P bit sent in mS (for RTT Measurements) + int RTT; + +>>>>>>> Stashed changes // Now support compressing L2 Sessions. // We collect as much data as possible before compressing and re-packetizing diff --git a/bpqaxip.c b/bpqaxip.c index 3491bbd..71f0ce1 100644 --- a/bpqaxip.c +++ b/bpqaxip.c @@ -444,7 +444,7 @@ static size_t ExtProc(int fn, int port, PMESSAGE buff) From[ConvFromAX25(call, &From[1]) + 1] = 0; if (strstr(CantReplyList, From) == 0) { - if (strlen(CantReplyList) < 500); + if (strlen(CantReplyList) < 500) strcat(CantReplyList, From); Debugprintf("AXIP Packet from %s dropped - can't reply", &From[1]); } @@ -557,7 +557,7 @@ static size_t ExtProc(int fn, int port, PMESSAGE buff) From[ConvFromAX25(call, &From[1]) + 1] = 0; if (strstr(CantReplyList, From) == 0) { - if (strlen(CantReplyList) < 500); + if (strlen(CantReplyList) < 500) strcat(CantReplyList, From); Debugprintf("AXIP Packet from %s dropped - can't reply", &From[1]); } diff --git a/cMain.c b/cMain.c index 74b6bc6..bcd24b0 100644 --- a/cMain.c +++ b/cMain.c @@ -57,7 +57,13 @@ VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD); void WritePacketLogThread(void * param); void hookNodeStarted(); void hookNodeRunning(); +<<<<<<< Updated upstream void APIL2Trace(struct _MESSAGE * Message, char Dirn); +||||||| Stash base + +======= +void APIL2Trace(struct _MESSAGE * Message, char * Dirn); +>>>>>>> Stashed changes #include "configstructs.h" @@ -1416,12 +1422,19 @@ BOOL Start() { ROUTE->TCPHost = Rcfg->tcphost; ROUTE->TCPPort = Rcfg->tcpport; +<<<<<<< Updated upstream +||||||| Stash base +======= + + ROUTE->TCPAddress = (struct addrinfo *)zalloc(sizeof(struct addrinfo)); + ROUTE->TCPAddress->ai_addr = (struct sockaddr *) zalloc(sizeof(struct sockaddr)); +>>>>>>> Stashed changes } Rcfg++; ROUTE++; } - + // SET UP INFO MESSAGE ptr2 = &cfg->C_INFOMSG[0]; @@ -2028,7 +2041,7 @@ VOID ReadNodes() ptr = strtok_s(NULL, seps, &Context); // INP3 if (ptr == NULL) continue; - if (ROUTE->NEIGHBOUR_FLAG == 0 || ROUTE->OtherendLocked == 0); // Not LOCKED ROUTE + if (ROUTE->NEIGHBOUR_FLAG == 0 || ROUTE->OtherendLocked == 0) // Not LOCKED ROUTE ROUTE->OtherendsRouteQual = atoi(ptr); ptr = strtok_s(NULL, seps, &Context); // INP3 @@ -2279,7 +2292,12 @@ VOID TIMERINTERRUPT() Message = (struct _MESSAGE *)Buffer; if(NodeAPISocket) +<<<<<<< Updated upstream APIL2Trace(Message, 'T'); +||||||| Stash base +======= + APIL2Trace(Message, "sent"); +>>>>>>> Stashed changes Message->PORT |= 0x80; // Set TX Bit @@ -2394,7 +2412,12 @@ L2Packet: MQTTKISSRX(Buffer); if(NodeAPISocket &&PORT->PROTOCOL == 0) +<<<<<<< Updated upstream APIL2Trace(Message, 'R'); +||||||| Stash base +======= + APIL2Trace(Message, "rcvd"); +>>>>>>> Stashed changes // Bridge if requested diff --git a/config.c b/config.c index bb0b2f2..d90ba74 100644 --- a/config.c +++ b/config.c @@ -635,6 +635,13 @@ BOOL ProcessConfig() paramok[93]=1; // ONLYVer2point0 paramok[94]=1; // DEBUGINP3 paramok[95]=1; // EnableOARCAPI +<<<<<<< Updated upstream +||||||| Stash base + paramok[93]=1; // C_ONLYVer2point0 +======= + paramok[96]=1; // OARCAPI + +>>>>>>> Stashed changes for (i=0; i < PARAMLIM; i++) { diff --git a/lzhuf32.c b/lzhuf32.c index c1aea82..961c624 100644 --- a/lzhuf32.c +++ b/lzhuf32.c @@ -487,124 +487,124 @@ static void reconst(void) static void update(int c) { - int i, j, l; + int i, j, l; unsigned int k; - if (freq[R] == MAX_FREQ) { - reconst(); - } - c = prnt[c + T]; - do { - k = ++freq[c]; + if (freq[R] == MAX_FREQ) { + reconst(); + } + c = prnt[c + T]; + do { + k = ++freq[c]; - /* if the order is disturbed, exchange nodes */ + /* if the order is disturbed, exchange nodes */ + + l = c + 1; - l = c + 1; - if ((unsigned)k > freq[l]) { - while ((unsigned)k > freq[++l]); - l--; - freq[c] = freq[l]; - freq[l] = k; + while ((unsigned)k > freq[++l]); + l--; + freq[c] = freq[l]; + freq[l] = k; - i = son[c]; - prnt[i] = l; - if (i < T) prnt[i + 1] = l; + i = son[c]; + prnt[i] = l; + if (i < T) prnt[i + 1] = l; - j = son[l]; - son[l] = i; + j = son[l]; + son[l] = i; - prnt[j] = c; - if (j < T) prnt[j + 1] = c; - son[c] = j; + prnt[j] = c; + if (j < T) prnt[j + 1] = c; + son[c] = j; - c = l; - } - } while ((c = prnt[c]) != 0); /* repeat up to root */ + c = l; + } + } while ((c = prnt[c]) != 0); /* repeat up to root */ } unsigned code, len; static void EncodeChar(unsigned int c) { - unsigned int i; - int j, k; + unsigned int i; + int j, k; - i = 0; - j = 0; - k = prnt[c + T]; + i = 0; + j = 0; + k = prnt[c + T]; - /* travel from leaf to root */ - do { - i >>= 1; + /* travel from leaf to root */ + do { + i >>= 1; - /* if node's address is odd-numbered, choose bigger brother node */ - if (k & 1) i += 0x8000; + /* if node's address is odd-numbered, choose bigger brother node */ + if (k & 1) i += 0x8000; - j++; - } while ((k = prnt[k]) != R); - Putcode(j, i); - code = i; - len = j; - update(c); + j++; + } while ((k = prnt[k]) != R); + Putcode(j, i); + code = i; + len = j; + update(c); } static void EncodePosition(unsigned int c) { - unsigned int i; + unsigned int i; - /* output upper 6 bits by table lookup */ - i = c >> 6; - Putcode(p_len[i], (unsigned)p_code[i] << 8); + /* output upper 6 bits by table lookup */ + i = c >> 6; + Putcode(p_len[i], (unsigned)p_code[i] << 8); - /* output lower 6 bits verbatim */ - Putcode(6, (c & 0x3f) << 10); + /* output lower 6 bits verbatim */ + Putcode(6, (c & 0x3f) << 10); } static void EncodeEnd(void) { - if (putlen) { - if (crc_fputc(putbuf >> 8) == EOF) { - Error(wterr); - } - codesize++; - } + if (putlen) { + if (crc_fputc(putbuf >> 8) == EOF) { + Error(wterr); + } + codesize++; + } } int DecodeChar(void) { - unsigned int c; + unsigned int c; - c = son[R]; + c = son[R]; - /* travel from root to leaf, */ - /* choosing the smaller child node (son[]) if the read bit is 0, */ - /* the bigger (son[]+1} if 1 */ - while (c < T) { - c += GetBit(); - c = son[c]; - } - c -= T; - update(c); - return (int)c; + /* travel from root to leaf, */ + /* choosing the smaller child node (son[]) if the read bit is 0, */ + /* the bigger (son[]+1} if 1 */ + while (c < T) { + c += GetBit(); + c = son[c]; + } + c -= T; + update(c); + return (int)c; } int DecodePosition(void) { - unsigned int i, j, c; + unsigned int i, j, c; - /* recover upper 6 bits from table */ - i = GetByte(); - c = (unsigned)d_code[i] << 6; - j = d_len[i]; + /* recover upper 6 bits from table */ + i = GetByte(); + c = (unsigned)d_code[i] << 6; + j = d_len[i]; - /* read lower 6 bits verbatim */ - j -= 2; - while (j--) { - i = (i << 1) + GetBit(); - } - return (int)(c | (i & 0x3f)); + /* read lower 6 bits verbatim */ + j -= 2; + while (j--) { + i = (i << 1) + GetBit(); + } + return (int)(c | (i & 0x3f)); } /* compression */ diff --git a/pngwutil.c b/pngwutil.c index dd7b150..2f42e07 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -350,10 +350,11 @@ png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) comp->output_ptr[i]=NULL; } if (comp->max_output_ptr != 0) - png_free(png_ptr, comp->output_ptr); - comp->output_ptr=NULL; + png_free(png_ptr, comp->output_ptr); + comp->output_ptr=NULL; /* write anything left in zbuf */ if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - png_ptr->zstream.avail_out);