Compare commits

...

8 Commits

Author SHA1 Message Date
Hibby 6a4b588a48
Release and autoport magic 2025-05-21 22:12:07 +01:00
Hibby 426f47ccb6
It builds successfully! 2025-05-21 21:45:54 +01:00
Hibby 3ecb593511 Update upstream source from tag 'upstream/6.0.24.71+repack'
Update to upstream version '6.0.24.71+repack'
with Debian dir d79186aef0
2025-05-21 21:33:54 +01:00
Hibby 0d3ee7fd56 New upstream version 6.0.24.71+repack 2025-05-21 21:33:52 +01:00
Hibby 96197688e7
New upstream version 6.0.24.69.1+repack 2025-05-21 21:32:18 +01:00
Hibby d3b4158645
New upstream version 6.0.24.69+repack 2025-05-21 21:32:18 +01:00
Hibby fec78cece5
Update changelog 2025-05-21 21:32:17 +01:00
Hibby bdf8a8367e
New upstream version 6.0.24.67+repack 2025-05-21 21:32:17 +01:00
53 changed files with 11441 additions and 1151 deletions

View File

@ -888,6 +888,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
{
if (TNC->SessionTimeLimit && STREAM->ConnectTime && time(NULL) > (TNC->SessionTimeLimit + STREAM->ConnectTime))
{
Debugprintf("ARDOP closing session on SessionTimelimit");
ARDOPSendCommand(TNC, "DISCONNECT", TRUE);
STREAM->ReportDISC = 1;
STREAM->AttachTime = 0;
@ -900,6 +901,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
{
if (STREAM->AttachTime && TNC->AttachTimeLimit && time(NULL) > (TNC->AttachTimeLimit + STREAM->AttachTime))
{
Debugprintf("ARDOP closing session on AttachTimelimit");
STREAM->ReportDISC = 1;
STREAM->AttachTime = 0;
}
@ -3141,6 +3143,7 @@ VOID ARDOPProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
// Incoming Connect
TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit
STREAM->AttachTime = time(NULL);
// Stop other ports in same group

View File

@ -117,6 +117,7 @@ struct UserInfo * FindBBS(char * Name);
void ReleaseWebMailStruct(WebMailInfo * WebMail);
VOID TidyWelcomeMsg(char ** pPrompt);
int MailAPIProcessHTTPMessage(struct HTTPConnectionInfo * Session, char * response, char * Method, char * URL, char * request, BOOL LOCAL, char * Param, char * Token);
void UndoTransparency(char * input);
char UNC[] = "";
char CHKD[] = "checked=checked ";
@ -186,7 +187,7 @@ char RefreshMainPage[] = "<html><head>"
char StatusPage [] =
"<form style=\"font-family: monospace; text-align: center\" method=post action=/Mail/DisSession?%s>"
"<br>User&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Callsign&nbsp;&nbsp; Stream Queue<br>"
"<br>User&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Callsign&nbsp;&nbsp; Stream &nbsp;Queue &nbsp;Sent &nbsp;Rxed<br>"
"<select style=\"font-family: monospace;\" tabindex=1 size=10 name=call>";
char StreamEnd[] =
@ -1701,6 +1702,8 @@ VOID ProcessConfUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char
free(Filters);
Filters = NULL;
UndoTransparency(input);
while (input)
{
// extract and validate before saving
@ -1714,7 +1717,7 @@ VOID ProcessConfUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char
input = strstr(input, "&Type=");
if (Filter.Action == 'H' || Filter.Action == 'R')
if (Filter.Action == 'H' || Filter.Action == 'R' || Filter.Action == 'A')
{
Filter.Type = toupper(input[6]);
input = strstr(input, "&From=");
@ -2755,6 +2758,19 @@ VOID SendUIPage(char * Reply, int * ReplyLen, char * Key)
*ReplyLen = Len;
}
void ConvertSpaceTonbsp(char * msg)
{
// Replace any space with &nbsp;
char * ptr;
while (ptr = strchr(msg, ' '))
{
memmove(ptr + 5, ptr, strlen(ptr) + 1);
memcpy(ptr, "&nbsp;", 6);
}
}
VOID SendStatusPage(char * Reply, int * ReplyLen, char * Key)
{
int Len;
@ -2776,6 +2792,8 @@ VOID SendStatusPage(char * Reply, int * ReplyLen, char * Key)
if (!conn->Active)
{
strcpy(msg,"Idle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n");
}
@ -2789,16 +2807,16 @@ VOID SendStatusPage(char * Reply, int * ReplyLen, char * Key)
strcpy(Name, conn->UserPointer->Name);
Name[9] = 0;
i=sprintf_s(msg, sizeof(msg), "%s%s%s%s%2d&nbsp;%5d\r\n",
i=sprintf_s(msg, sizeof(msg), "%-12s %-9s %3d %6d%6d%6d\r\n",
Name,
&TenSpaces[strlen(Name) * 6],
conn->UserPointer->Call,
&TenSpaces[strlen(conn->UserPointer->Call) * 6],
conn->BPQStream,
conn->OutputQueueLength - conn->OutputGetPointer);
conn->OutputQueueLength - conn->OutputGetPointer, conn->bytesSent, conn->bytesRxed);
}
}
}
ConvertSpaceTonbsp(msg);
Len += sprintf(&Reply[Len], StatusLine, conn->BPQStream, msg);
}

View File

@ -2085,6 +2085,7 @@ hold certain types or sizes of messages.
The first letter of each valid line specifies the action :
A = Accept : Message is accepted without checking other filters
R = Reject : The message will not be received.
H = Hold : The message will be received but held until the sysop reviews.
L = Local Hold : Only messages created on this BBS will be held.
@ -2179,21 +2180,38 @@ BOOL CheckRejFilters(char * From, char * To, char * ATBBS, char * BID, char Type
while (p)
{
if (p->Action != 'R')
if (p->Action != 'R' && p->Action != 'A')
goto Continue;
if (p->Type != Type && p->Type != '*')
goto Continue;
// wildcardcompare returns true on a match
if (wildcardcompare(From, p->From) == 0)
goto Continue;
if (p->TO[0] == '!')
{
if (wildcardcompare(ToCopy, &p->TO[1]) == 1)
goto Continue;
}
else
{
if (wildcardcompare(ToCopy, p->TO) == 0)
goto Continue;
}
if (ATBBS)
if (wildcardcompare(ATBBS, p->AT) == 0)
{
char AtCopy[256];
strcpy(AtCopy, ATBBS);
_strupr(AtCopy);
if (wildcardcompare(AtCopy, p->AT) == 0)
goto Continue;
}
if (BID)
if (wildcardcompare(BID, p->BID) == 0)
@ -2202,6 +2220,11 @@ BOOL CheckRejFilters(char * From, char * To, char * ATBBS, char * BID, char Type
if (p->MaxLen && Len < p->MaxLen)
goto Continue;
// if type 'A' matches all rules then accept without checking rest
if (p->Action == 'A')
return FALSE;
return TRUE; // Hold
Continue:
@ -2244,6 +2267,7 @@ BOOL CheckHoldFilters(struct MsgInfo * Msg, char * From, char * To, char * ATBBS
{
char ** Calls;
FBBFilter * p = Filters;
char ToCopy[256];
if (HoldFrom && From)
{
@ -2307,6 +2331,9 @@ BOOL CheckHoldFilters(struct MsgInfo * Msg, char * From, char * To, char * ATBBS
// check fbb reject.sys type filters
strcpy(ToCopy, To);
_strupr(ToCopy);
while (p)
{
if (p->Action != 'H')
@ -2318,9 +2345,16 @@ BOOL CheckHoldFilters(struct MsgInfo * Msg, char * From, char * To, char * ATBBS
if (wildcardcompare(Msg->from, p->From) == 0)
goto Continue;
if (wildcardcompare(Msg->to, p->TO) == 0)
if (p->TO[0] == '!')
{
if (wildcardcompare(ToCopy, &p->TO[1]) == 1)
goto Continue;
}
else
{
if (wildcardcompare(ToCopy, p->TO) == 0)
goto Continue;
}
if (wildcardcompare(Msg->via, p->AT) == 0)
goto Continue;
@ -3388,6 +3422,7 @@ void Flush(CIRCUIT * conn)
SendUnbuffered(conn->BPQStream, &conn->OutputQueue[conn->OutputGetPointer], len);
conn->OutputGetPointer+=len;
conn->bytesSent += len;
tosend-=len;
SendUnbuffered(conn->BPQStream, "<A>bort, <CR> Continue..>", 25);
FreeSemaphore(&OutputSEM);
@ -3399,6 +3434,7 @@ void Flush(CIRCUIT * conn)
}
SendUnbuffered(conn->BPQStream, &conn->OutputQueue[conn->OutputGetPointer], len);
conn->bytesSent += len;
conn->OutputGetPointer+=len;
@ -10245,7 +10281,7 @@ BOOL GetConfig(char * ConfigName)
GetStringValue(group, "ISPAccountPass", EncryptedISPAccountPass, 100);
sprintf(SignoffMsg, "73 de %s\r", BBSName); // Default
GetStringValue(group, "SignoffMsg", ISPAccountName, 50);
GetStringValue(group, "SignoffMsg", SignoffMsg, 50);
DecryptPass(EncryptedISPAccountPass, ISPAccountPass, (int)strlen(EncryptedISPAccountPass));
@ -10550,7 +10586,7 @@ int Connected(int Stream)
char callsign[10];
int port, paclen, maxframe, l4window;
char ConnectedMsg[] = "*** CONNECTED ";
char Msg[100];
char Msg[256];
char Title[100];
int64_t Freq = 0;
int Mode = 0;
@ -10634,6 +10670,12 @@ int Connected(int Stream)
}
}
if (Mode < 0 || Mode > 54)
Mode = 0;
if (Freq < 0 || Freq > 11000000000)
Freq = 0;
memset(conn, 0, sizeof(ConnectionInfo)); // Clear everything
conn->Active = TRUE;
conn->BPQStream = Stream;
@ -10698,7 +10740,7 @@ int Connected(int Stream)
LongFreq = GetPortFrequency(port, FreqString);
#endif
}
Length += sprintf(MailBuffer, "New User %s Connected to Mailbox on Port %d Freq %d Mode %ld\r\n", callsign, port, LongFreq, Mode);
Length += sprintf(MailBuffer, "New User %s Connected to Mailbox on Port %d Freq %lld Mode %d\r\n", callsign, port, LongFreq, Mode);
sprintf(Title, "New User %s", callsign);
@ -10758,10 +10800,10 @@ int Connected(int Stream)
}
if (port)
n=sprintf_s(Msg, sizeof(Msg), "Incoming Connect from %s on Port %d Freq %d Mode %s",
n = sprintf_s(Msg, sizeof(Msg), "Incoming Connect from %s on Port %d Freq %lld Mode %s",
user->Call, port, Freq, WL2KModes[Mode]);
else
n=sprintf_s(Msg, sizeof(Msg), "Incoming Connect from %s", user->Call);
n = sprintf_s(Msg, sizeof(Msg), "Incoming Connect from %s", user->Call);
// Send SID and Prompt (Unless Sync)
@ -11051,7 +11093,6 @@ int DoReceivedData(int Stream)
if (Stream == conn->BPQStream)
{
conn->SIDResponseTimer = 0; // Got a message, so cancel timeout.
do
{
// May have several messages per packet, or message split over packets
@ -11068,6 +11109,7 @@ int DoReceivedData(int Stream)
if (InputLen == 0 && conn->InputMode != 'Y')
return 0;
conn->bytesRxed += InputLen;
conn->InputLen += InputLen;
if (conn->InputLen == 0) return 0;

498
BPQINP3.c
View File

@ -37,6 +37,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
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)
{
@ -71,9 +74,9 @@ 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 DEST_ROUTE_ENTRY * ROUTEPTR, int hops, int rtt);
VOID KillRoute(struct DEST_ROUTE_ENTRY * ROUTEPTR);
VOID AddHere(struct DEST_ROUTE_ENTRY * ROUTEPTR,struct ROUTE * Route , 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);
@ -133,8 +136,14 @@ VOID DeleteINP3Routes(struct ROUTE * Route)
{
int i;
struct DEST_LIST * Dest = DESTS;
char Call1[10];
char Call2[10];
// Delete any NETROM Dest entries via this Route
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;
@ -156,48 +165,65 @@ VOID DeleteINP3Routes(struct ROUTE * Route)
if (Dest->NRROUTE[0].ROUT_OBSCOUNT >= 128) // Not if locked
continue;
if (Dest->ROUTE[0].ROUT_NEIGHBOUR == Route)
Call2[ConvFromAX25(Dest->DEST_CALL, Call2)] = 0;
if (Dest->INP3ROUTE[0].ROUT_NEIGHBOUR == Route)
{
// We are deleting the best route, so need to tell other nodes
// 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 (Dest->ROUTE[1].ROUT_NEIGHBOUR == 0)
// 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->ROUTE[0].SRTT = 60000;
Dest->ROUTE[0].Hops = 255;
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->ROUTE[1].LastRTT = Dest->ROUTE[0].SRTT; // So next scan will check if rtt has increaced
// enough to need a RIF
memcpy(&Dest->ROUTE[0], &Dest->ROUTE[1], sizeof(struct DEST_ROUTE_ENTRY));
memcpy(&Dest->ROUTE[1], &Dest->ROUTE[2], sizeof(struct DEST_ROUTE_ENTRY));
memset(&Dest->ROUTE[2], 0, sizeof(struct DEST_ROUTE_ENTRY));
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->ROUTE[1].ROUT_NEIGHBOUR == Route)
if (Dest->INP3ROUTE[1].ROUT_NEIGHBOUR == Route)
{
memcpy(&Dest->ROUTE[1], &Dest->ROUTE[2], sizeof(struct DEST_ROUTE_ENTRY));
memset(&Dest->ROUTE[2], 0, sizeof(struct DEST_ROUTE_ENTRY));
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->ROUTE[2].ROUT_NEIGHBOUR == Route)
if (Dest->INP3ROUTE[2].ROUT_NEIGHBOUR == Route)
{
memset(&Dest->ROUTE[2], 0, sizeof(struct DEST_ROUTE_ENTRY));
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)
@ -233,7 +259,7 @@ VOID DecayNETROMRoutes(struct ROUTE * Route)
if (Dest->NRROUTE[1].ROUT_NEIGHBOUR == 0) // No more Netrom Routes
{
if (Dest->ROUTE[0].ROUT_NEIGHBOUR == 0) // Any INP3 ROutes?
if (Dest->INP3ROUTE[0].ROUT_NEIGHBOUR == 0) // Any INP3 ROutes?
{
// No More Routes - ZAP Dest
@ -306,19 +332,9 @@ VOID ProcessRTTReply(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff)
int RTT;
unsigned int OrigTime;
if ((Route->Status & GotRTTResponse) == 0)
{
// Link is just starting
char Normcall[10];
Route->Status |= GotRTTResponse;
if (Route->Status & GotRTTRequest)
{
Route->Status |= SentOurRIF;
SendOurRIF(Route);
SendRIPToNeighbour(Route);
}
}
Normcall[ConvFromAX25(Route->NEIGHBOUR_CALL, Normcall)] = 0;
Route->Timeout = 0; // Got Response
@ -334,6 +350,16 @@ VOID ProcessRTTReply(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff)
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)
@ -345,6 +371,13 @@ VOID ProcessINP3RIF(struct ROUTE * Route, UCHAR * ptr1, int msglen, int Port)
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
@ -386,10 +419,9 @@ VOID ProcessINP3RIF(struct ROUTE * Route, UCHAR * ptr1, int msglen, int Port)
rtt = (*ptr1++ << 8);
rtt += *ptr1++;
// rtt is value from remote node. Add our RTT to that node and update hops
// rtt is value from remote node. Add our RTT to that node
rtt += Route->SRTT;
hops++;
msglen -= 10;
@ -424,7 +456,7 @@ VOID ProcessINP3RIF(struct ROUTE * Route, UCHAR * ptr1, int msglen, int Port)
return;
}
VOID KillRoute(struct DEST_ROUTE_ENTRY * ROUTEPTR)
VOID KillRoute(struct INP3_DEST_ROUTE_ENTRY * ROUTEPTR)
{
}
@ -432,21 +464,58 @@ VOID KillRoute(struct DEST_ROUTE_ENTRY * ROUTEPTR)
VOID UpdateNode(struct ROUTE * Route, UCHAR * axcall, UCHAR * alias, int hops, int rtt)
{
struct DEST_LIST * Dest;
struct DEST_ROUTE_ENTRY * ROUTEPTR;
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("Node %s Hops %d RTT %d Ignored - Hop Count too high", call, hops, rtt);
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("Node %s Hops %d RTT %d Ignored - rtt too high", call, hops, rtt);
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;
}
@ -454,10 +523,12 @@ VOID UpdateNode(struct ROUTE * Route, UCHAR * axcall, UCHAR * alias, int hops,
goto Found;
if (Dest == NULL)
return; // Tsble Full
{
Debugprintf("INP3 Table Full - discarding");
return; // Table Full
}
if (rtt >= 60000)
return; // No Point addind a new dead route
memset(Dest, 0, sizeof(struct DEST_LIST));
@ -466,58 +537,63 @@ VOID UpdateNode(struct ROUTE * Route, UCHAR * axcall, UCHAR * alias, int hops,
// Set up First Route
Dest->ROUTE[0].Hops = hops;
Dest->ROUTE[0].SRTT = rtt;
Dest->ROUTE[0].LastRTT = 0;
Dest->INP3ROUTE[0].Hops = hops;
Dest->INP3ROUTE[0].SRTT = rtt;
Dest->INP3ROUTE[0].LastRTT = 0;
Dest->INP3FLAGS = NewNode;
Dest->ROUTE[0].ROUT_NEIGHBOUR = Route;
Dest->INP3ROUTE[0].ROUT_NEIGHBOUR = Route;
NUMBEROFNODES++;
ConvFromAX25(Dest->DEST_CALL, call);
Debugprintf("Adding Node %s Hops %d RTT %d", call, hops, rtt);
Debugprintf("INP3 Adding New Node %s Hops %d RTT %d", call, hops, rtt);
return;
Found:
if (Dest->DEST_STATE & 0x80) // Application Entry
return;
{
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->ROUTE[0];
if (rtt >= 60000)
{
i=rtt+1;
}
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->ROUTE[1];
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->ROUTE[2];
ROUTEPTR = &Dest->INP3ROUTE[2];
if (ROUTEPTR->ROUT_NEIGHBOUR == Route)
{
Debugprintf("INP3 Already have as route[2] - updating");
UpdateRoute(Dest, ROUTEPTR, hops, rtt);
return;
}
@ -525,64 +601,68 @@ Found:
// Not in list. If any spare, add.
// If full, see if this is better
if (rtt >= 60000)
return; // No Point addind a new dead route
ROUTEPTR = &Dest->ROUTE[0];
for (i = 1; i < 4; i++)
for (i = 0; i < 3; i++)
{
ROUTEPTR = &Dest->INP3ROUTE[i];
if (ROUTEPTR->ROUT_NEIGHBOUR == NULL)
{
// Add here
Dest->ROUTE[0].Hops = hops;
Dest->ROUTE[0].SRTT = rtt;
Dest->ROUTE[0].ROUT_NEIGHBOUR = Route;
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->ROUTE[0].SRTT > rtt)
if (Dest->INP3ROUTE[0].SRTT > rtt)
{
// We are better. Move others down and add on front
memcpy(&Dest->ROUTE[2], &Dest->ROUTE[1], sizeof(struct DEST_ROUTE_ENTRY));
memcpy(&Dest->ROUTE[1], &Dest->ROUTE[0], sizeof(struct DEST_ROUTE_ENTRY));
Debugprintf("INP3 Replacing route 0");
AddHere(&Dest->ROUTE[0], Route, hops, rtt);
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->ROUTE[1].SRTT > rtt)
if (Dest->INP3ROUTE[1].SRTT > rtt)
{
// We are better. Move 2nd down and add
memcpy(&Dest->ROUTE[2], &Dest->ROUTE[1], sizeof(struct DEST_ROUTE_ENTRY));
AddHere(&Dest->ROUTE[1], Route, hops, rtt);
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->ROUTE[2].SRTT > rtt)
if (Dest->INP3ROUTE[2].SRTT > rtt)
{
// We are better. Add here
AddHere(&Dest->ROUTE[2], Route, hops, rtt);
Debugprintf("INP3 Replacing route 2");
AddHere(&Dest->INP3ROUTE[2], Route, hops, rtt);
return;
}
// Worse than any - ignoee
Debugprintf("INP3 Worse that any existing route");
// Worse than any - ignore
}
VOID AddHere(struct DEST_ROUTE_ENTRY * ROUTEPTR,struct ROUTE * Route , int hops, int rtt)
VOID AddHere(struct INP3_DEST_ROUTE_ENTRY * ROUTEPTR,struct ROUTE * Route , int hops, int rtt)
{
ROUTEPTR->Hops = hops;
ROUTEPTR->SRTT = rtt;
@ -643,38 +723,122 @@ NOTBADROUTE:
JMP SENDOK
*/
struct INP3_DEST_ROUTE_ENTRY Temp;
VOID SortRoutes(struct DEST_LIST * Dest)
{
struct DEST_ROUTE_ENTRY Temp;
char Call1[10], Call2[10], Call3[10];
// May now be out of order
if (Dest->ROUTE[1].ROUT_NEIGHBOUR == 0)
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->ROUTE[2].ROUT_NEIGHBOUR == 0)
}
if (Dest->INP3ROUTE[2].ROUT_NEIGHBOUR == 0)
{
// Only 2
if (Dest->ROUTE[0].SRTT <= Dest->ROUTE[1].SRTT)
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->ROUTE[0], sizeof(struct DEST_ROUTE_ENTRY));
memcpy(&Dest->ROUTE[0], &Dest->ROUTE[1], sizeof(struct DEST_ROUTE_ENTRY));
memcpy(&Dest->ROUTE[1], &Temp, sizeof(struct DEST_ROUTE_ENTRY));
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 DEST_ROUTE_ENTRY * ROUTEPTR, int hops, int rtt)
VOID UpdateRoute(struct DEST_LIST * Dest, struct INP3_DEST_ROUTE_ENTRY * ROUTEPTR, int hops, int rtt)
{
if (ROUTEPTR->Hops == 0)
{
@ -706,20 +870,28 @@ VOID UpdateRoute(struct DEST_LIST * Dest, struct DEST_ROUTE_ENTRY * ROUTEPTR, in
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;
}
else
{
int OtherRTT;
int Dummy;
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
}
@ -737,29 +909,31 @@ VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len
{
// Link is just starting
Debugprintf("INP3 Processing first RTT frame from %s - link is (re)starting", Normcall);
Route->Status |= GotRTTRequest;
if (Route->Status & GotRTTResponse)
{
// 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);
}
else
{
// We have not yet seen a response (and maybe haven't sent one
Route->BCTimer = 0; // So send one
}
}
}
}
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)
@ -788,6 +962,14 @@ VOID SendRTTMsg(struct ROUTE * Route)
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)
@ -821,7 +1003,9 @@ int BuildRIF(UCHAR * RIF, UCHAR * Call, UCHAR * Alias, int Hops, int RTT)
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
@ -848,10 +1032,13 @@ int BuildRIF(UCHAR * RIF, UCHAR * Call, UCHAR * Alias, int Hops, int RTT)
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);
}
@ -863,11 +1050,17 @@ VOID SendOurRIF(struct ROUTE * Route)
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
@ -898,6 +1091,8 @@ int SendRIPTimer()
struct ROUTE * Route = NEIGHBOURS;
int MaxRoutes = MAXNEIGHBOURS;
int INP3Delay;
char Normcall[10];
for (count=0; count<MaxRoutes; count++)
{
@ -946,6 +1141,12 @@ int SendRIPTimer()
// 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;
@ -1007,7 +1208,7 @@ int SendRIPTimer()
char Call [11] = "";
ConvFromAX25(Route->NEIGHBOUR_CALL, Call);
Debugprintf("BPQ32 INP Neighbour %s Lost", Call);
Debugprintf("BPQ32 INP3 Neighbour %s Lost", Call);
Route->Status = 0; // Down
}
@ -1042,27 +1243,39 @@ 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 DEST_ROUTE_ENTRY * Entry)
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; count<MaxRoutes; count++)
{
@ -1073,7 +1286,14 @@ VOID SendRIPToOtherNeighbours(UCHAR * axcall, UCHAR * alias, struct DEST_ROUTE_E
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);
@ -1085,6 +1305,7 @@ VOID SendRIPToOtherNeighbours(UCHAR * axcall, UCHAR * alias, struct DEST_ROUTE_E
Routes->Msg = NULL;
}
}
}
Routes+=1;
}
}
@ -1093,9 +1314,14 @@ VOID SendRIPToNeighbour(struct ROUTE * Route)
{
int i;
struct DEST_LIST * Dest = DESTS;
struct DEST_ROUTE_ENTRY * Entry;
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
@ -1104,7 +1330,7 @@ VOID SendRIPToNeighbour(struct ROUTE * Route)
{
Dest++;
Entry = &Dest->ROUTE[0];
Entry = &Dest->INP3ROUTE[0];
if (Entry->ROUT_NEIGHBOUR && Entry->Hops && Route != Entry->ROUT_NEIGHBOUR)
{
@ -1142,8 +1368,12 @@ VOID FlushRIFs()
{
if (Routes->Msg)
{
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;
}
@ -1153,7 +1383,7 @@ VOID SendNegativeInfo()
{
int i, Preload;
struct DEST_LIST * Dest = DESTS;
struct DEST_ROUTE_ENTRY * Entry;
struct INP3_DEST_ROUTE_ENTRY * Entry;
Dest--;
@ -1169,7 +1399,7 @@ VOID SendNegativeInfo()
{
Dest++;
Entry = &Dest->ROUTE[0];
Entry = &Dest->INP3ROUTE[0];
if (Entry->SRTT > Entry->LastRTT)
{
@ -1194,15 +1424,19 @@ VOID SendNegativeInfo()
{
char call[11]="";
ConvFromAX25(Dest->DEST_CALL, call);
Debugprintf("Deleting Node %s", 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 DEST_ROUTE_ENTRY));
memset(Entry, 0, sizeof(struct INP3_DEST_ROUTE_ENTRY));
}
if (Dest->DEST_ROUTE == 4) // we were using it
Dest->DEST_ROUTE = 0;
}
}
}
@ -1211,7 +1445,7 @@ VOID SendPositiveInfo()
{
int i;
struct DEST_LIST * Dest = DESTS;
struct DEST_ROUTE_ENTRY * Entry;
struct INP3_DEST_ROUTE_ENTRY * Entry;
Dest--;
@ -1221,14 +1455,14 @@ VOID SendPositiveInfo()
{
Dest++;
Entry = &Dest->ROUTE[0];
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->ROUTE[0].LastRTT = (Dest->ROUTE[0].SRTT * 11) / 10; //10% Negative Preload
Dest->INP3ROUTE[0].LastRTT = (Dest->INP3ROUTE[0].SRTT * 11) / 10; //10% Negative Preload
}
}
}
@ -1238,7 +1472,7 @@ VOID SendNewInfo()
int i;
unsigned int NewRTT;
struct DEST_LIST * Dest = DESTS;
struct DEST_ROUTE_ENTRY * Entry;
struct INP3_DEST_ROUTE_ENTRY * Entry;
Dest--;
@ -1252,7 +1486,7 @@ VOID SendNewInfo()
{
Dest->INP3FLAGS &= ~NewNode;
Entry = &Dest->ROUTE[0];
Entry = &Dest->INP3ROUTE[0];
SendRIPToOtherNeighbours(Dest->DEST_CALL, Dest->DEST_ALIAS, Entry);
@ -1368,20 +1602,34 @@ UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, unsigned int msglen)
{
memcpy(IP, ptr1+2, len-2);
}
ptr1+=len;
msglen -=len;
}
if (IP[0])
ptr2+=sprintf(ptr2, " %s:%s %d %4.2d %d.%d.%d.%d\r", alias, call, hops, rtt, IP[0], IP[1], IP[2], IP[3]);
else
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);
}

BIN
BPQMail.aps Normal file

Binary file not shown.

View File

@ -1148,6 +1148,11 @@
// Fix bug in WP Message processing (56)
// Fix treating addresses ending in WW as Internet (57)
// Run sending to packetnodes.spots.radio in a separate thread (61)
// Fix loading ISP Account Name from config file (67)
// Fixes to using {FormFolder} in Webmail Templates (68)
// Save FBB transfer restart data over program restarts (69)
// Add Send and Receive byte counts to status displays (69)
// Validate Mode and Frequency and fix formatting in Connected Message (71)
#include "bpqmail.h"
#include "winstdint.h"
@ -1724,6 +1729,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
// SaveUserDatabase();
SaveMessageDatabase();
SaveBIDDatabase();
SaveRestartData();
configSaved = 1;
SaveConfig(ConfigName);
@ -3020,9 +3026,9 @@ int RefreshMainWindow()
strcpy(msg,"Logging in");
else
{
i=sprintf_s(msg, sizeof(msg), "%-10s %-10s %2d %-10s%5d",
i=sprintf_s(msg, sizeof(msg), "%-10s %-10s %2d %-10s%5d %5d %5d",
conn->UserPointer->Name, conn->UserPointer->Call, conn->BPQStream,
"BBS", conn->OutputQueueLength - conn->OutputGetPointer);
"BBS", conn->OutputQueueLength - conn->OutputGetPointer, conn->bytesSent, conn->bytesRxed);
}
}
}
@ -3083,6 +3089,7 @@ static PSOCKADDR_IN psin;
SOCKET sock;
void GetRestartData();
BOOL Initialise()
{
@ -3270,6 +3277,8 @@ BOOL Initialise()
GetBadWordFile();
GetHTMLForms();
GetRestartData();
UsingingRegConfig = FALSE;
// Make sure SYSOPCALL is set

1090
BPQMail.rc

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
main :
{
BPQHostIP = "192.168.1.64";
COM1 = "COM43";
COM2 = "";
COM3 = "";
COM4 = "";
HamLibPort1 = 4534;
HamLibPort2 = 0;
HamLibPort3 = 0;
HamLibPort4 = 0;
};

20
Bpq32.c
View File

@ -1255,8 +1255,18 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
// 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)
#define CKernel
@ -2379,6 +2389,8 @@ FirstInit()
timeLoadedMS = GetTickCount();
srand(time(NULL));
INITIALISEPORTS();
OpenReportingSockets();
@ -6153,7 +6165,7 @@ DllExport BOOL APIENTRY SaveReg(char * KeyIn, HANDLE hFile)
{
if (len > 76)
{
len += sprintf(RegLine[len], "\\\r\n");
len += sprintf(&RegLine[len], "\\\r\n");
WriteFile(hFile, RegLine, len, &written, NULL);
strcpy(RegLine, " ");
len = 2;
@ -6162,7 +6174,7 @@ DllExport BOOL APIENTRY SaveReg(char * KeyIn, HANDLE hFile)
len += sprintf(&RegLine[len], "%02x,", Value[k]);
if (len > 76)
{
len += sprintf(RegLine[len], "\\\r\n");
len += sprintf(&RegLine[len], "\\\r\n");
WriteFile(hFile, RegLine, len, &written, NULL);
strcpy(RegLine, " ");
}

View File

@ -23,7 +23,6 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
#ifdef LINBPQ
#include "compatbits.h"
char * strlop(char * buf, char delim);
#define APIENTRY
#define VOID void
@ -32,6 +31,8 @@ char * strlop(char * buf, char delim);
#include <windows.h>
#endif
char * strlop(char * buf, char delim);
VOID APIENTRY md5 (char *arg, unsigned char * checksum);

123
Cmd.c
View File

@ -70,6 +70,10 @@ void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, st
VOID WriteMiniDump();
int CheckKissInterlock(struct PORTCONTROL * PORT, int Exclusive);
int seeifInterlockneeded(struct PORTCONTROL * PORT);
int CompareNode(const void *a, const void *b);
int CompareAlias(const void *a, const void *b);
int CompareRoutes(const void * a, const void * b);
extern VOID KISSTX(struct KISSINFO * KISS, PMESSAGE Buffer);
@ -1225,15 +1229,57 @@ VOID CMDSTATS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
#define PFBIT 0x10 // POLL/FINAL BIT IN CONTROL BYTE
VOID InformPartner(struct _LINKTABLE * LINK, int Reason);
VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD);
BOOL FindLink(UCHAR * LinkCall, UCHAR * OurCall, int Port, struct _LINKTABLE ** REQLINK);
VOID CMDL00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// PROCESS 'LINKS' MESSAGE
struct _LINKTABLE * LINK = LINKS;
int n = MAXLINKS;
int len;
int len, Count;
char Normcall[11] = "";
UCHAR DEST[7];
UCHAR ORIGIN[7];
int Port = 0;
char * ptr = 0, * Context;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr && _stricmp(ptr, "reset") == 0)
{
ptr = strtok_s(NULL, " ", &Context);
if (ptr)
ConvToAX25(ptr, DEST);
ptr = strtok_s(NULL, " ", &Context);
if (ptr)
ConvToAX25(ptr, ORIGIN);
ptr = strtok_s(NULL, " ", &Context);
if (ptr)
Port = atoi(ptr);
if (FindLink(DEST, ORIGIN, Port, &LINK))
{
InformPartner(LINK, NORMALCLOSE); // TELL OTHER END ITS GONE
LINK->L2RETRIES -= 1; // Just send one DISC
LINK->L2STATE = 4; // CLOSING
L2SENDCOMMAND(LINK, DISC | PFBIT);
Bufferptr = Cmdprintf(Session, Bufferptr, "Link Reset\r");
}
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Link Not Found\r");
}
else
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Links\r");
while (n--)
@ -1241,6 +1287,7 @@ VOID CMDL00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct C
if (LINK->LINKCALL[0])
{
len = ConvFromAX25(LINK->LINKCALL, Normcall);
Count = COUNT_AT_L2(LINK);
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", Normcall);
@ -1248,15 +1295,15 @@ VOID CMDL00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct C
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", Normcall);
if (LINK->Ver2point2)
Bufferptr = Cmdprintf(Session, Bufferptr, " S=%d P=%d T=%d V=2.2\r",
LINK->L2STATE, LINK->LINKPORT->PORTNUMBER, LINK->LINKTYPE);
Bufferptr = Cmdprintf(Session, Bufferptr, " S=%d P=%d T=%d V=2.2 Q=%d\r",
LINK->L2STATE, LINK->LINKPORT->PORTNUMBER, LINK->LINKTYPE, Count);
else
Bufferptr = Cmdprintf(Session, Bufferptr, " S=%d P=%d T=%d V=%d\r",
LINK->L2STATE, LINK->LINKPORT->PORTNUMBER, LINK->LINKTYPE, 2 - LINK->VER1FLAG);
Bufferptr = Cmdprintf(Session, Bufferptr, " S=%d P=%d T=%d V=%d Q=%d\r",
LINK->L2STATE, LINK->LINKPORT->PORTNUMBER, LINK->LINKTYPE, 2 - LINK->VER1FLAG, Count);
}
LINK++;
}
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
@ -1604,6 +1651,8 @@ VOID CMDR00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct C
int Port = 0;
char AXCALL[7];
BOOL Found;
int count, i, n = 0;
struct ROUTE * List[1000];
ptr = strtok_s(CmdTail, " ", &Context);
@ -1624,14 +1673,31 @@ VOID CMDR00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct C
Bufferptr = Cmdprintf(Session, Bufferptr, "Routes\r");
while (MaxRoutes--)
// Build and sort list of routes
for (count = 0; count < MaxRoutes; count++)
{
if (Routes->NEIGHBOUR_CALL[0] != 0)
if (Port == 0 || Port == Routes->NEIGHBOUR_PORT)
Bufferptr = DisplayRoute(Session, Bufferptr, Routes, Verbose);
{
List[n++] = Routes;
if (n > 999)
break;
}
Routes++;
}
if (n > 1)
qsort(List, n, sizeof(void *), CompareRoutes);
for (i = 0; i < n; i++)
{
Routes = List[i];
if (Port == 0 || Port == Routes->NEIGHBOUR_PORT)
Bufferptr = DisplayRoute(Session, Bufferptr, Routes, Verbose);
}
goto SendReply;
ROUTEUPDATE:
@ -2817,15 +2883,12 @@ VOID LINKCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
int CompareNode(const void *a, const void *b);
int CompareAlias(const void *a, const void *b);
char * DoOneNode(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIST * Dest)
{
char Normcall[10];
char Alias[10];
struct NR_DEST_ROUTE_ENTRY * NRRoute;
struct DEST_ROUTE_ENTRY * Route;
struct INP3_DEST_ROUTE_ENTRY * Route;
struct ROUTE * Neighbour;
int i, Active, len;
@ -2866,7 +2929,7 @@ char * DoOneNode(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIST *
// DISPLAY INP3 ROUTES
Route = &Dest->ROUTE[0];
Route = &Dest->INP3ROUTE[0];
Active = Dest->DEST_ROUTE;
@ -2923,17 +2986,17 @@ int DoINP3ViaEntry(struct DEST_LIST * Dest, int n, char * line, int cursor)
int len;
double srtt;
if (Dest->ROUTE[n].ROUT_NEIGHBOUR != 0)
if (Dest->INP3ROUTE[n].ROUT_NEIGHBOUR != 0)
{
srtt = Dest->ROUTE[n].SRTT/1000.0;
srtt = Dest->INP3ROUTE[n].SRTT/1000.0;
len=ConvFromAX25(Dest->ROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Portcall);
len=ConvFromAX25(Dest->INP3ROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Portcall);
Portcall[len]=0;
len=sprintf(&line[cursor],"%s %d %d %4.2fs ",
Portcall,
Dest->ROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_PORT,
Dest->ROUTE[n].Hops, srtt);
Dest->INP3ROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_PORT,
Dest->INP3ROUTE[n].Hops, srtt);
cursor+=len;
@ -3221,7 +3284,7 @@ NODE_VIA:
{
Dest+=1;
if (Dest->NRROUTE[0].ROUT_NEIGHBOUR == 0 && Dest->ROUTE[0].ROUT_NEIGHBOUR == 0)
if (Dest->NRROUTE[0].ROUT_NEIGHBOUR == 0 && Dest->INP3ROUTE[0].ROUT_NEIGHBOUR == 0)
continue;
@ -3229,9 +3292,9 @@ NODE_VIA:
|| (Dest->NRROUTE[1].ROUT_NEIGHBOUR && CompareCalls(Dest->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->NRROUTE[2].ROUT_NEIGHBOUR && CompareCalls(Dest->NRROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->ROUTE[0].ROUT_NEIGHBOUR && CompareCalls(Dest->ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->ROUTE[1].ROUT_NEIGHBOUR && CompareCalls(Dest->ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->ROUTE[2].ROUT_NEIGHBOUR && CompareCalls(Dest->ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL)))
|| (Dest->INP3ROUTE[0].ROUT_NEIGHBOUR && CompareCalls(Dest->INP3ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->INP3ROUTE[1].ROUT_NEIGHBOUR && CompareCalls(Dest->INP3ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->INP3ROUTE[2].ROUT_NEIGHBOUR && CompareCalls(Dest->INP3ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL)))
{
len=ConvFromAX25(Dest->DEST_CALL,Normcall);
@ -3602,7 +3665,7 @@ VOID MHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CM
}
else
{
if (CMD->String[2] == 'V') // MHV
if (CMD->String[2] == 'V' || CMD->String[3] == 'V') // MHV
{
Bufferptr = Cmdprintf(Session, Bufferptr, "MHeard List %s for Port %d\r", MYNODECALL, Port);
Bufferptr = Cmdprintf(Session, Bufferptr, "Callsign Last heard Pkts RX via Digi ;) \r");
@ -4306,6 +4369,8 @@ struct CMDX COMMANDS[] =
"MHU ",3,MHCMD,0, // UTC Times
"MHL ",3,MHCMD,0, // Local Times
"MHV ",3,MHCMD,0,
"MHUV ",3,MHCMD,0, // UTC Times
"MHLV ",3,MHCMD,0, // Local Times
"MHEARD ",1,MHCMD,0,
"APRS ",2,APRSCMD,0,
"ATTACH ",1,ATTACHCMD,0,
@ -5523,22 +5588,14 @@ VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct
KISS = (struct KISSINFO *) PORT;
if (KISS->FIRSTPORT != KISS)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not first port of a Multidrop Set\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// Send Command
KissLen = KissEncode(KissString, ENCBUFF, KissLen);
PORT = (struct PORTCONTROL *)KISS->FIRSTPORT; // ALL FRAMES GO ON SAME Q
PORT->Session = Session;
PORT->LastKISSCmdTime = time(NULL);
PORT = (struct PORTCONTROL *)KISS->FIRSTPORT; // ALL FRAMES GO ON SAME Q
ASYSEND(PORT, ENCBUFF, KissLen);
Bufferptr = Cmdprintf(Session, Bufferptr, "Command Sent\r");

View File

@ -77,6 +77,8 @@ char * stristr (char *ch1, char *ch2);
extern VOID * ENDBUFFERPOOL;
extern int PoolBuilt;
// Read/Write length field in a buffer header
@ -363,7 +365,7 @@ BOK1:
if (n > 1000)
{
Debugprintf("Loop searching free chain - pointer = %p %p", debug, pointer);
Debugprintf("Releasebuffer Loop searching free chain - pointer = %p %p from %s Line %d", debug, pointer, File, Line);
return 0;
}
}
@ -376,6 +378,11 @@ BOK1:
QCOUNT++;
if (PoolBuilt && QCOUNT > MAXBUFFS)
{
Debugprintf("Releasebuffer QCOUNT > MAXBUFFS - pointer = %p from %s Line %d", pointer, File, Line);
return 0;
}
return 0;
}
@ -473,7 +480,7 @@ int C_Q_ADD_NP(VOID *PQ, VOID *PBUFF)
next = Q[0];
while (next[0] != 0)
next=next[0]; // Chain to end of queue
next = next[0]; // Chain to end of queue
next[0] = BUFF; // New one on end
@ -1061,6 +1068,7 @@ BOOL ReadConfigFile(int Port, int ProcLine(char * buf, int Port))
WritetoConsoleLocal("\n");
WritetoConsoleLocal("Bad config record ");
WritetoConsoleLocal(errbuf);
WritetoConsoleLocal("\n");
}
}
}
@ -1124,6 +1132,11 @@ int CompareNode(struct DEST_LIST ** a, struct DEST_LIST ** b)
return memcmp(a[0]->DEST_CALL, b[0]->DEST_CALL, 7);
}
int CompareRoutes(struct ROUTE ** a, struct ROUTE ** b)
{
return memcmp(a[0]->NEIGHBOUR_CALL, b[0]->NEIGHBOUR_CALL, 7);
}
DllExport int APIENTRY CountFramesQueuedOnStream(int Stream)
{
BPQVECSTRUC * PORTVEC = &BPQHOSTVECTOR[Stream-1]; // API counts from 1

View File

@ -168,6 +168,12 @@ void hookL2SessionDeleted(struct _LINKTABLE * LINK)
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)

View File

@ -27,6 +27,8 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
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);
@ -41,6 +43,130 @@ 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
@ -985,12 +1111,12 @@ loop:
{
RestartRec = RestartData[i];
if ((RestartRec->UserPointer == conn->UserPointer)
&& (strcmp(RestartRec->TempMsg->bid, conn->TempMsg->bid) == 0))
if ((strcmp(RestartRec->Call, conn->UserPointer->Call) == 0)
&& (strcmp(RestartRec->bid, conn->TempMsg->bid) == 0))
{
if (RestartRec->TempMsg->length <= offset)
if (RestartRec->length <= offset)
{
conn->TempMsg->length = RestartRec->TempMsg->length;
conn->TempMsg->length = RestartRec->length;
conn->MailBuffer = RestartRec->MailBuffer;
conn->MailBufferSize = RestartRec->MailBufferSize;
@ -1019,6 +1145,7 @@ loop:
RestartData[n] = RestartData[n+1]; // move down all following entries
}
RestartCount--;
SaveRestartData();
}
}
@ -1146,6 +1273,7 @@ loop:
{
#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
}
@ -1845,14 +1973,14 @@ VOID SaveFBBBinary(CIRCUIT * conn)
{
RestartRec = RestartData[i];
if ((RestartRec->UserPointer == conn->UserPointer)
&& (strcmp(RestartRec->TempMsg->bid, conn->TempMsg->bid) == 0))
if ((strcmp(RestartRec->Call, conn->UserPointer->Call) == 0)
&& (strcmp(RestartRec->bid, conn->TempMsg->bid) == 0))
{
// Fund it, so reuse
// Found it, so reuse
// If we have more data, reset retry count
if (RestartRec->TempMsg->length < conn->TempMsg->length)
if (RestartRec->length < conn->TempMsg->length)
RestartRec->Count = 0;;
break;
@ -1869,19 +1997,53 @@ VOID SaveFBBBinary(CIRCUIT * conn)
RestartData[RestartCount] = RestartRec;
FreeSemaphore(&AllocSemaphore);
RestartRec->TimeCreated = time(NULL);
}
RestartRec->UserPointer = conn->UserPointer;
RestartRec->TempMsg = conn->TempMsg;
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;
@ -1895,15 +2057,15 @@ BOOL LookupRestart(CIRCUIT * conn, struct FBBHeaderLine * FBBHeader)
{
RestartRec = RestartData[i];
if ((RestartRec->UserPointer == conn->UserPointer)
&& (strcmp(RestartRec->TempMsg->bid, FBBHeader->BID) == 0))
if ((strcmp(RestartRec->Call, conn->UserPointer->Call) == 0)
&& (strcmp(RestartRec->bid, FBBHeader->BID) == 0))
{
char Msg[120];
int len;
RestartRec->Count++;
if (RestartRec->Count > 3)
if (RestartRec->Count > 10)
{
len = sprintf_s(Msg, sizeof(Msg), "Too many restarts for %s - Requesting restart from beginning",
FBBHeader->BID);
@ -1918,15 +2080,16 @@ BOOL LookupRestart(CIRCUIT * conn, struct FBBHeaderLine * FBBHeader)
}
RestartCount--;
SaveRestartData();
return FALSE;
}
len = sprintf_s(Msg, sizeof(Msg), "Restart Data found for %s - Requesting restart from %d",
FBBHeader->BID, RestartRec->TempMsg->length);
FBBHeader->BID, RestartRec->length);
WriteLogLine(conn, '|',Msg, len, LOG_BBS);
return (RestartRec->TempMsg->length);
return (RestartRec->length);
}
}

3860
FLDigi64.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -452,6 +452,11 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
TNC->lasttime = ltime;
ConnecttoFreeData(port);
}
while (TNC->PortRecord->UI_Q)
{
buffptr = Q_REM(&TNC->PortRecord->UI_Q);
ReleaseBuffer(buffptr);
}
}

1907
HALDriver64.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1866,9 +1866,6 @@ static char ** SeparateMultiString(char * MultiString)
return Value;
}
extern int nextDummyInterlock;
int standardParams(struct TNCINFO * TNC, char * buf)
@ -1917,7 +1914,7 @@ int standardParams(struct TNCINFO * TNC, char * buf)
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
else if (_memicmp(buf, "DisconnectScript", 16) == 0) // Set at end of session
TNC->DisconnectScript = SeparateMultiString(&buf[17]);
else if (_memicmp(buf, "PTTONHEX", 8) == 0)
{

View File

@ -105,9 +105,13 @@ extern int NumberofPorts;
extern UCHAR ConfigDirectory[260];
extern struct AXIPPORTINFO * Portlist[];
VOID sendandcheck(SOCKET sock, const char * Buffer, int Len);
int CompareNode(const void *a, const void *b);
int CompareAlias(const void *a, const void *b);
int CompareRoutes(const void * a, const void * b);
void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen, char * Token);
void ProcessChatHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen);
struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot);
@ -3794,12 +3798,82 @@ doHeader:
*/
// AXIP Partners
if (_stricmp(NodeURL, "/Node/AXIP.html") == 0)
{
int i;
char Normcall[10];
int Width = 5;
int x = 0, n = 0, nd = 0;
struct arp_table_entry * List[1000];
struct arp_table_entry * ListD[1000];
char AXIPList[10000] = "";
int ListLen = 0;
struct AXIPPORTINFO * AXPORT = Portlist[0];
struct PORTCONTROL * PORT = PORTTABLE;
struct arp_table_entry * arp;
time_t NOW = time(NULL);
char AXIPHeader[] =
"<table align='center' bgcolor='ffffff' border=2 cellpadding=10 cellspacing=2 style=font-family:monospace>"
"<tr><td align='center'>AXIP Up</td><td align='center'>AXIP Down</td></tr><tr><td valign='top'>%s";
while (PORT)
{
AXPORT = Portlist[PORT->PORTNUMBER];
if (AXPORT)
{
// Get ARP entries
for (i = 0; i < AXPORT->arp_table_len; i++)
{
arp = &AXPORT->arp_table[i];
if (arp->LastHeard == 0 || (NOW - arp->LastHeard) > 3600) // Considered down
ListD[nd++] = arp;
else
List[n++] = arp;
}
}
PORT = PORT->PORTPOINTER;
}
if (n > 1)
qsort(List, n, sizeof(void *), CompareNode);
if (nd > 1)
qsort(ListD, nd, sizeof(void *), CompareNode);
for (i = 0; i < n; i++)
{
int len = ConvFromAX25(List[i]->callsign, Normcall);
Normcall[len]=0;
ListLen += sprintf(&AXIPList[ListLen], "%02d - %s %d<br>", i + 1, Normcall, (List[i]->LastHeard)?(NOW - List[i]->LastHeard):0);
}
ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], AXIPHeader, AXIPList);
ListLen = 0;
for (i = 0; i < nd; i++)
{
int len = ConvFromAX25(ListD[i]->callsign, Normcall);
Normcall[len]=0;
ListLen += sprintf(&AXIPList[ListLen], "%02d - %s %d<br>", i + 1, Normcall, (ListD[i]->LastHeard)?(NOW - ListD[i]->LastHeard):0);
}
ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "</td><td valign='top'>%s", AXIPList);
ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "</td></tr></table></body></html>");
}
if (_stricmp(NodeURL, "/Node/Routes.html") == 0)
{
struct ROUTE * Routes = NEIGHBOURS;
int MaxRoutes = MAXNEIGHBOURS;
int count;
int count, i;
char Normcall[10];
char locked[4] = " ";
int NodeCount;
@ -3808,11 +3882,33 @@ doHeader:
char Active[10];
int Queued;
int x = 0, n = 0;
struct ROUTE * List[1000];
ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", RouteHddr);
for (count=0; count<MaxRoutes; count++)
// Build and sort list of routes
for (count = 0; count < MaxRoutes; count++)
{
if (Routes->NEIGHBOUR_CALL[0] != 0)
{
List[n++] = Routes;
if (n > 999)
break;
}
Routes++;
}
if (n > 1)
qsort(List, n, sizeof(void *), CompareRoutes);
for (i = 0; i < n; i++)
{
Routes = List[i];
{
int len = ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall);
Normcall[len]=0;

View File

@ -387,7 +387,7 @@ char * FormatIP(uint32_t Addr)
return FormatIPWork;
}
int CompareRoutes (const VOID * a, const VOID * b)
int CompareIPRoutes (const VOID * a, const VOID * b)
{
PROUTEENTRY x;
PROUTEENTRY y;
@ -4972,7 +4972,7 @@ VOID SHOWIPROUTE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, str
Bufferptr = Cmdprintf(Session, Bufferptr, "%d Entries\r", NumberofRoutes);
if (NumberofRoutes)
qsort(RouteRecords, NumberofRoutes, sizeof(void *), CompareRoutes);
qsort(RouteRecords, NumberofRoutes, sizeof(void *), CompareIPRoutes);
for (i=0; i < NumberofRoutes; i++)
{

View File

@ -70,6 +70,8 @@ static RECT Rect;
int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len);
VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len);
VOID SuspendOtherPorts(struct TNCINFO * ThisTNC);
VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC);
static FILE * LogHandle[32] = {0};
@ -517,6 +519,28 @@ ok:
return 0;
}
VOID KAMSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC)
{
struct STREAMINFO * STREAM = &TNC->Streams[0];
strcpy(TNC->WEB_TNCSTATE, "Interlocked");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
// STREAM->CmdSet = STREAM->CmdSave = zalloc(100);
// sprintf(STREAM->CmdSet, "I%s\r", "SCSPTC"); // Should prevent connects
}
VOID KAMReleasePort(struct TNCINFO * TNC)
{
struct STREAMINFO * STREAM = &TNC->Streams[0];
strcpy(TNC->WEB_TNCSTATE, "Free");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
}
static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL)
{
int Len = sprintf(Buff, "<html><meta http-equiv=expires content=0><meta http-equiv=refresh content=15>"
@ -595,6 +619,11 @@ void * KAMExtInit(EXTPORTDATA * PortEntry)
PortEntry->PORTCONTROL.PORTSTARTCODE = KAMStartPort;
PortEntry->PORTCONTROL.PORTSTOPCODE = KAMStopPort;
// TNC->SuspendPortProc = KAMSuspendPort;
// TNC->ReleasePortProc = KAMReleasePort;
ptr=strchr(TNC->NodeCall, ' ');
if (ptr) *(ptr) = 0; // Null Terminate
@ -1266,6 +1295,51 @@ VOID KAMPoll(int Port)
return;
}
if (memcmp(MsgPtr, "GTOR ", 5) == 0) // GTOR Connect
{
memcpy(STREAM->RemoteCall, &MsgPtr[5], 9);
STREAM->Connecting = TRUE;
// If Stream 0, Convert C CALL to PACTOR CALL
if (Stream == 0)
{
datalen = sprintf(TXMsg, "C20GTOR %s", TNC->Streams[0].RemoteCall);
// If Pactor, check busy detecters on any interlocked ports
if (TNC->HFPacket == 0 && InterlockedCheckBusy(TNC) && TNC->OverrideBusy == 0)
{
// Channel Busy. Wait
TNC->ConnectCmd = _strdup(TXMsg);
sprintf(TNC->WEB_TNCSTATE, "Waiting for clear channel");
SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
TNC->BusyDelay = TNC->BusyWait * 10;
return;
}
TNC->OverrideBusy = FALSE;
sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s",
TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall);
SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
}
else
datalen = sprintf(TXMsg, "C1%cC %s", Stream + '@', STREAM->RemoteCall);
EncodeAndSend(TNC, TXMsg, datalen);
TNC->Timeout = 50;
TNC->InternalCmd = 'C'; // So we dont send the reply to the user.
ReleaseBuffer(buffptr);
STREAM->Connecting = TRUE;
return;
}
if (memcmp(MsgPtr, "DISCONNECT", datalen) == 0) // Disconnect
{
if (Stream == 0)
@ -1644,6 +1718,10 @@ VOID ProcessKHOSTPacket(struct TNCINFO * TNC, UCHAR * Msg, int Len)
return;
}
WritetoTrace(TNC, Buffer, Len);
// Pass to Appl
Stream = TNC->CmdStream;
@ -1790,6 +1868,10 @@ VOID ProcessKHOSTPacket(struct TNCINFO * TNC, UCHAR * Msg, int Len)
if (Msg[1] == '2' && Msg[2] == 'A')
TNC->HFPacket = TRUE;
// Stop other ports in same group
SuspendOtherPorts(TNC);
ProcessIncommingConnect(TNC, Call, Stream, TRUE);
SESS = TNC->PortRecord->ATTACHEDSESSIONS[Stream];
@ -2047,6 +2129,10 @@ VOID ForcedClose(struct TNCINFO * TNC, int Stream)
VOID CloseComplete(struct TNCINFO * TNC, int Stream)
{
sprintf(TNC->WEB_TNCSTATE, "Free");
SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
ReleaseOtherPorts(TNC);
TNC->NeedPACTOR = 50;
}

436
L2Code.c
View File

@ -33,6 +33,15 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
#include "cheaders.h"
#include "tncinfo.h"
// This is needed to link with a lib built from source
#ifdef WIN32
#define ZEXPORT __stdcall
#endif
#include <zlib.h>
#define PFBIT 0x10 // POLL/FINAL BIT IN CONTROL BYTE
#define REJSENT 1 // SET WHEN FIRST REJ IS SENT IN REPLY
@ -111,7 +120,8 @@ int CheckKissInterlock(struct PORTCONTROL * MYPORT, int Exclusive);
void hookL2SessionAccepted(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK);
void hookL2SessionDeleted(struct _LINKTABLE * LINK);
void hookL2SessionAttempt(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK);
int L2Compressit(unsigned char * Out, int OutSize, unsigned char * In, int Len);
VOID DeleteINP3Routes(struct ROUTE * Route);
extern int REALTIMETICKS;
@ -126,7 +136,9 @@ extern int REALTIMETICKS;
#define SDINVC 1 // INVALID COMMAND
#define SDNRER 8 // INVALID N(R)
extern int L2Compress;
extern int L2CompMaxframe;
extern int L2CompPaclen;
UCHAR NO_CTEXT = 0;
UCHAR ALIASMSG = 0;
@ -842,6 +854,7 @@ VOID ProcessXIDCommand(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESS
while (xidlen > 0)
{
unsigned char * typeptr = ptr;
Type = *ptr++;
Len = *ptr++;
@ -889,6 +902,23 @@ VOID ProcessXIDCommand(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESS
case 8: //RX Window
break;
case 16:
// Compression
if (L2Compress)
{
LINK->AllowCompress = 1;
// return as 17
*typeptr = 17;
}
else
{
ptr = &ADJBUFFER->PID;
ptr[3] -= 2; // Length field - remove compress option
Buffer->LENGTH -=2;
}
}
}
@ -900,6 +930,8 @@ VOID ProcessXIDCommand(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESS
LINK->LINKPORT = PORT;
LINK->KILLTIMER = L2KILLTIME - 60*3; // Time out after 60 secs if SABM not received
// save calls so we can match up SABM when it comes
memcpy(LINK->LINKCALL, Buffer->ORIGIN, 7);
@ -999,6 +1031,7 @@ VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
// MESSAGE ON AN ACTIVE LINK
int CTLlessPF = CTL & ~PFBIT;
unsigned char * ptr;
PORT->L2FRAMESFORUS++;
@ -1054,7 +1087,7 @@ VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
LINK->L2STATE = 2;
LINK->Ver2point2 = FALSE;
LINK->L2TIMER = 1; // USe retry to send SABM
LINK->L2TIMER = 1; // Use retry to send SABM
}
else if (CTLlessPF == XID)
{
@ -1062,7 +1095,49 @@ VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
LINK->L2STATE = 2;
LINK->Ver2point2 = TRUE;// Must support 2.2 if responded to XID
LINK->L2TIMER = 1; // USe retry to send SABM
// if Compress enabled set it
ptr = &ADJBUFFER->PID;
if (*ptr++ == 0x82 && *ptr++ == 0x80)
{
int Type;
int Len;
unsigned int value;
int xidlen = *(ptr++) << 8;
xidlen += *ptr++;
// XID is set of Type, Len, Value n-tuples
while (xidlen > 0)
{
Type = *ptr++;
Len = *ptr++;
value = 0;
xidlen -= (Len + 2);
while (Len--)
{
value <<=8;
value += *ptr++;
}
switch(Type)
{
case 17:
// Compression
if (L2Compress)
LINK->AllowCompress = 1;
}
}
}
LINK->L2TIMER = 1; // Use retry to send SABM
}
ReleaseBuffer(Buffer);
@ -1110,8 +1185,9 @@ VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
// 2. OTHER END THINKS LINK HAS DIED
// 3. RECOVERY FROM FRMR CONDITION
// 4. REPEAT OF ORIGINAL SABM COS OTHER END MISSED UA
// 5. Other end has reloaded
// FOR 1-3 IT IS REASONABLE TO FULLY RESET THE CIRCUIT, BUT IN 4
// FOR 1-3 and 5 IT IS REASONABLE TO FULLY RESET THE CIRCUIT, BUT IN 4
// SUCH ACTION WILL LOSE THE INITIAL SIGNON MSG IF CONNECTING TO A
// BBS. THE PROBLEM IS TELLING THE DIFFERENCE. I'M GOING TO SET A FLAG
// WHEN FIRST INFO RECEIVED - IF SABM REPEATED BEFORE THIS, I'LL ASSUME
@ -1141,6 +1217,8 @@ VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffe
TRANSPORTENTRY * Session;
int CONERROR;
struct ROUTE * ROUTE = NULL;
char toCall[12], fromCall[12];
@ -1198,6 +1276,18 @@ VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffe
if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF)
AttachKISSHF(PORT, Buffer);
// if it is an INP3 connection tell INP3 it is up
if (FindNeighbour(LINK->LINKCALL, PORT->PORTNUMBER, &ROUTE))
{
if (ROUTE->INP3Node)
{
Debugprintf("INP3 Incoming connect from %s", fromCall);
DeleteINP3Routes(ROUTE);
}
}
if (NO_CTEXT == 1)
return;
@ -1721,9 +1811,9 @@ BOOL InternalL2SETUPCROSSLINK(PROUTE ROUTE, int Retries)
else
LINK->LINKWINDOW = PORT->PORTWINDOW;
// if (SUPPORT2point2)
// LINK->L2STATE = 1; // Send XID
// else
if (SUPPORT2point2)
LINK->L2STATE = 1; // Send XID
else
LINK->L2STATE = 2;
memcpy(LINK->LINKCALL, ROUTE->NEIGHBOUR_CALL, 7);
@ -1881,11 +1971,23 @@ VOID L2_PROCESS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * B
// RESPONSE TO SABM - SET LINK UP
char fromCall[12];
struct ROUTE * ROUTE;
fromCall[ConvFromAX25(Buffer->ORIGIN, fromCall)] = 0;
RESET2X(LINK); // LEAVE QUEUED STUFF
// See if INP3 route setup
if (FindNeighbour(Buffer->ORIGIN, PORT->PORTNUMBER, &ROUTE))
{
if (ROUTE->INP3Node)
{
Debugprintf("INP3 Route to %s connected", fromCall);
}
}
SendL2ToMonMap(PORT, fromCall, '+', 'O');
LINK->L2STATE = 5;
@ -2018,7 +2120,6 @@ VOID SDUFRM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffe
SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION
}
ReleaseBuffer(Buffer);
}
@ -2358,12 +2459,11 @@ CheckNSLoop:
{
// Already have a copy, so discard old and keep this
Debugprintf ("Frame %d out of seq but already have copy - release it", NS);
ReleaseBuffer(Q_REM(&LINK->RXFRAMES[NS]));
}
else
{
Debugprintf ("Frame %d out of seq - save", NS);
// Debugprintf ("Frame %d out of seq - save", NS);
}
Buffer->CHAIN = 0;
@ -2450,6 +2550,8 @@ CheckPF:
}
int doinflate(unsigned char * source, unsigned char * dest, int Len, int destlen, int * outLen);
VOID PROC_I_FRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer)
{
@ -2479,6 +2581,7 @@ VOID PROC_I_FRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
Info = &Buffer->PID;
LINK->bytesRXed += Length;
LINK->Received += Length - 1; // Exclude PID
// Adjust for DIGIS
@ -2495,6 +2598,111 @@ VOID PROC_I_FRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
switch(PID)
{
case 0xf2:
// Intermediate fragment of compressed. Save
// Length and Info include pid
Length--;
Info++;
if (LINK->unCompress == 0)
LINK->unCompress = malloc(8192);
// Save data
memcpy(&LINK->unCompress[LINK->unCompressLen], Info, Length);
LINK->unCompressLen += Length;
ReleaseBuffer(Buffer);
LINK->L2ACKREQ = PORT->PORTT2; // SET RR NEEDED
LINK->KILLTIMER = 0; // RESET IDLE LINK TIMER
return;
case 0xf1:
// Compressed last or only
{
char exBuffer[8192];
int Len;
int outLen;
int sendLen;
char * sendptr = exBuffer;
Length--;
Info++;
// we may have previous fragments
if (LINK->unCompressLen)
{
memcpy(&LINK->unCompress[LINK->unCompressLen], Info, Length);
LINK->unCompressLen += Length;
Len = doinflate(LINK->unCompress, exBuffer, LINK->unCompressLen, 8192, &outLen);
LINK->ReceivedAfterExpansion += outLen - 1;
LINK->unCompressLen = 0;
}
else
{
Len = doinflate(Info, exBuffer, Length, 8192, &outLen);
LINK->ReceivedAfterExpansion += outLen - 1;
}
sendLen = outLen;
// Send first bit in input buffer. If still some left get new buffers for it
if (sendLen > 257)
sendLen = 257;
// First byte is original PID
memcpy(&Msg->PID, exBuffer, sendLen);
Msg->LENGTH = sendLen + MSGHDDRLEN;
C_Q_ADD(&LINK->RX_Q, Msg);
outLen -= sendLen;
sendptr += sendLen;
while (outLen > 0)
{
sendLen = outLen;
if (sendLen > 236)
sendLen = 236;
Msg = GetBuff();
if (Msg)
{
// Just ignore if no buffers - shouldn't happen
Msg->PID = exBuffer[0];
Msg->PORT = LINK->LINKPORT->PORTNUMBER;
memcpy(Msg->L2DATA, sendptr, sendLen);
Length = sendLen + 1;
Msg->LENGTH = Length + MSGHDDRLEN;
C_Q_ADD(&LINK->RX_Q, Msg);
}
outLen -= sendLen;
sendptr += sendLen;
}
LINK->L2ACKREQ = PORT->PORTT2; // SET RR NEEDED
LINK->KILLTIMER = 0; // RESET IDLE LINK TIMER
return;
}
case 0xcc:
case 0xcd:
@ -2544,6 +2752,7 @@ VOID PROC_I_FRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
// Copy Data back over
memmove(&Msg->PID, Info, Length);
LINK->ReceivedAfterExpansion += Length - 1;
Buffer->LENGTH = Length + MSGHDDRLEN;
@ -2611,7 +2820,7 @@ VOID RESETNS(struct _LINKTABLE * LINK, UCHAR NS)
int COUNT_AT_L2(struct _LINKTABLE * LINK)
{
// COUNTS FRAMES QUEUED ON AN L2 SESSION (IN BX)
// COUNTS FRAMES QUEUED ON AN L2 SESSION (IN LINK)
int count = 0, abovelink = 0;
int n = 0;
@ -2758,7 +2967,7 @@ VOID SDETX(struct _LINKTABLE * LINK)
UCHAR * ptr1, * ptr2;
UCHAR CTL;
int count;
MESSAGE * Msg;
struct DATAMESSAGE * Msg;
MESSAGE * Buffer;
// DONT SEND IF RESEQUENCING RECEIVED FRAMES - CAN CAUSE FRMR PROBLEMS
@ -2766,11 +2975,6 @@ VOID SDETX(struct _LINKTABLE * LINK)
// if (LINK->L2RESEQ_Q)
// return;
if (LINK->LINKPORT->PORTNUMBER == 19)
{
int i = 0;
}
Outstanding = LINK->LINKNS - LINK->LINKOWS; // Was WS not NS
if (Outstanding < 0)
@ -2783,11 +2987,148 @@ VOID SDETX(struct _LINKTABLE * LINK)
while (LINK->TX_Q && LINK->FRAMES[LINK->SDTSLOT] == NULL)
{
// Try compressing here. Only Compress PID 0xF0 frames - NETROM doesn't treat L2 session as a byte stream
Msg = Q_REM(&LINK->TX_Q);
Msg->CHAIN = NULL;
if (LINK->AllowCompress && Msg->LENGTH > 20 && LINK->TX_Q && Msg->PID == 240) // if short and no more not worth trying compression
{
int complen = 0;
int dataLen;
int savePort = Msg->PORT;
int savePID = Msg->PID;
unsigned char Compressed[8192];
unsigned char toCompress[8192];
int toCompressLen = 0;
int slots = 0;
int n = LINK->SDTSLOT;
int maxcompsize;
int PACLEN = LINK->LINKPORT->PORTPACLEN;
unsigned char * compdata;
int sendLen = complen;
int uncompressed = 0;
if (PACLEN == 0)
PACLEN = 256;
// I think I need to know how many slots are available, so I don't compress too much
// Then collect data, compressing after each frame to make sure will fit in available space
while (LINK->FRAMES[n] == NULL && slots < 8)
{
slots++;
n++;
n &= 7;
}
maxcompsize = slots * PACLEN;
// Save first packet, then see if more on TX_Q
toCompressLen = 0;
dataLen = Msg->LENGTH - MSGHDDRLEN;
LINK->Sent += dataLen;
memcpy(&toCompress[toCompressLen], &Msg->PID, dataLen);
toCompressLen += dataLen;
complen = L2Compressit(Compressed, 8192, toCompress, toCompressLen);
ReleaseBuffer(Msg);
while (LINK->TX_Q)
{
Msg = LINK->TX_Q; // Leave on queue until sure it will fit
dataLen = Msg->LENGTH - MSGHDDRLEN -1; // PID only on 1st fragment
memcpy(&toCompress[toCompressLen], &Msg->L2DATA, dataLen);
toCompressLen += dataLen;
// Need to make sure we don't go over maxcompsize
complen = L2Compressit(Compressed, 8192, toCompress, toCompressLen);
if (complen > maxcompsize)
{
// Remove last fragment and compress again
toCompressLen -= dataLen;
complen = L2Compressit(Compressed, 8192, toCompress, toCompressLen);
break;
}
else
{
LINK->Sent += dataLen;
Msg = Q_REM(&LINK->TX_Q);
Msg->CHAIN = NULL;
ReleaseBuffer(Msg);
}
}
if (complen >= toCompressLen)
{
// Won't compress, so just send original data
// May still need to fragment
memcpy(Compressed, toCompress, toCompressLen);
complen = toCompressLen - 1; // Remove leading PID
uncompressed = 1;
compdata = &Compressed[1];
}
else
compdata = Compressed;
// We now need to packetize and add to FRAMES
LINK->SentAfterCompression += complen;
sendLen = PACLEN;
while (complen > 0)
{
int PID = 0xF1;
if (complen > sendLen)
PID = 0xF2; // More to come
else
sendLen = complen;
if (uncompressed)
PID = Compressed[0];
Msg = GetBuff();
if (!Msg)
return;
Msg->PORT = savePort;
Msg->PID = PID;
memcpy(&Msg->L2DATA, compdata, sendLen);
Msg->LENGTH = sendLen + MSGHDDRLEN + 1;
LINK->FRAMES[LINK->SDTSLOT] = Msg;
LINK->SDTSLOT ++;
LINK->SDTSLOT &= 7;
compdata += sendLen;
complen -= sendLen;
}
toCompressLen = 0;
}
else
{
LINK->FRAMES[LINK->SDTSLOT] = Msg;
LINK->SDTSLOT ++;
LINK->SDTSLOT &= 7;
}
}
// dont send while poll outstanding
@ -3000,6 +3341,17 @@ VOID L2TimerProc()
{
// CIRCUIT HAS BEEN IDLE TOO LONG - SHUT IT DOWN
// if in XID received state session was never established so don't send DISC
if (LINK->L2STATE == 1)
{
if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF)
DetachKISSHF(PORT);
CLEAROUTLINK(LINK);
}
else
{
LINK->KILLTIMER = 0;
LINK->L2TIMER = 1; // TO FORCE DISC
LINK->L2STATE = 4; // DISCONNECTING
@ -3008,6 +3360,7 @@ VOID L2TimerProc()
InformPartner(LINK, NORMALCLOSE);
}
}
LINK++;
}
}
@ -3311,6 +3664,9 @@ VOID CLEAROUTLINK(struct _LINKTABLE * LINK)
CLEARL2QUEUES(LINK); // TO RELEASE ANY BUFFERS
if (LINK->unCompress)
free(LINK->unCompress);
memset(LINK, 0, sizeof(struct _LINKTABLE));
}
@ -3345,6 +3701,10 @@ VOID L2SENDXID(struct _LINKTABLE * LINK)
*ptr++ = 0x82; // FI
*ptr++ = 0x80; // GI
*ptr++ = 0x0;
if (L2Compress)
*ptr++ = 0x12; // Length 18
else
*ptr++ = 0x10; // Length 16
*ptr++ = 0x02; // Classes of Procedures
@ -3375,6 +3735,14 @@ VOID L2SENDXID(struct _LINKTABLE * LINK)
*ptr++ = 0x01; // Len
*ptr++ = 0x07; // 7
// if L2Compress Enabled request it
if (L2Compress)
{
*ptr++ = 0x10; // Compress
*ptr++ = 0x00; // Len
}
Buffer->LENGTH = (int)(ptr - (UCHAR *)Buffer); // SET LENGTH
LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER
@ -3578,7 +3946,6 @@ CheckNSLoop2:
struct PORTCONTROL * PORT = LINK->LINKPORT;
MESSAGE * OldBuffer = Q_REM(&LINK->RXFRAMES[LINK->LINKNR]);
Debugprintf("L2 about to send REJ - process saved Frame %d", LINK->LINKNR);
PROC_I_FRAME(LINK, PORT, OldBuffer); // Passes on or releases Buffer
// NR has been updated.
@ -3637,6 +4004,8 @@ VOID CONNECTREFUSED(struct _LINKTABLE * LINK)
}
VOID L3CONNECTFAILED(struct _LINKTABLE * LINK);
VOID L3LINKSETUPFAILED(struct _LINKTABLE * LINK);
VOID ConnectFailedOrRefused(struct _LINKTABLE * LINK, char * Msg)
{
@ -3651,7 +4020,7 @@ VOID ConnectFailedOrRefused(struct _LINKTABLE * LINK, char * Msg)
if (LINK->LINKTYPE == 3)
{
L3CONNECTFAILED(LINK); // REPORT TO LEVEL 3
L3LINKSETUPFAILED(LINK); // REPORT TO LEVEL 3
return;
}
@ -4178,6 +4547,33 @@ int seeifUnlockneeded(struct _LINKTABLE * LINK)
return 0;
}
int L2Compressit(unsigned char * Out, int OutSize, unsigned char * In, int Len)
{
z_stream defstream;
int maxSize;
defstream.zalloc = Z_NULL;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
defstream.avail_in = Len; // size of input
defstream.next_in = (Bytef *)In; // input char array
deflateInit(&defstream, Z_BEST_COMPRESSION);
maxSize = deflateBound(&defstream, Len);
if (maxSize > OutSize)
return 0;
defstream.avail_out = maxSize; // size of output
defstream.next_out = (Bytef *)Out; // output char array
deflate(&defstream, Z_FINISH);
deflateEnd(&defstream);
return defstream.total_out;
}

View File

@ -67,6 +67,8 @@ extern dest_list * CURRENTNODE;
int L3_10SECS = 10;
extern int PREFERINP3ROUTES;
VOID L3BG()
{
@ -135,12 +137,14 @@ VOID L3BG()
// Drop through to Activate
}
// No Active Route
if (ACTIVATE_DEST(DEST) == FALSE)
{
// Node has no routes - get rid of it
REMOVENODE(DEST);
return; // Avoid riskof looking at lod entries
return; // Avoid risk of looking at old entries
}
}
}
@ -154,14 +158,24 @@ BOOL ACTIVATE_DEST(struct DEST_LIST * DEST)
{
int n = MAXDESTS;
struct PORTCONTROL * PORT = PORTTABLE;
struct ROUTE * ROUTE;
struct ROUTE * ROUTE = NULL;
struct _LINKTABLE * LINK;
struct TNCINFO * TNC;
int ActiveRoute;
if (DEST->DEST_ROUTE == 0) // ALREADY HAVE A SELECTED ROUTE?
DEST->DEST_ROUTE = 1; // TRY TO ACTIVATE FIRST
if (DEST->DEST_ROUTE == 0) // Don't ALREADY HAVE A SELECTED ROUTE?
{
DEST->DEST_ROUTE = 1;
if (PREFERINP3ROUTES)
{
// if we have any INP3 routes use the first. It will always be the fastest. The others are there for fallback if the first fails.
if (ROUTE = DEST->INP3ROUTE[0].ROUT_NEIGHBOUR)
DEST->DEST_ROUTE = 4; // TRY TO ACTIVATE FIRST
}
}
ActiveRoute = DEST->DEST_ROUTE - 1;
@ -169,7 +183,7 @@ BOOL ACTIVATE_DEST(struct DEST_LIST * DEST)
if (ROUTE == 0)
{
// Currnet Route not present
// Current Route not present
// If current route is 1, then we must have INP3 routes (or entry is corrupt)
if (DEST->DEST_ROUTE != 1)
@ -177,13 +191,17 @@ BOOL ACTIVATE_DEST(struct DEST_LIST * DEST)
// Current Route is 1
if (DEST->ROUTE[0].ROUT_NEIGHBOUR == 0)
if (DEST->INP3ROUTE[0].ROUT_NEIGHBOUR == 0)
return FALSE; // No INP3 so No Routes
DEST->DEST_ROUTE = 4; // First INP3
ROUTE = DEST->ROUTE[0].ROUT_NEIGHBOUR;
ROUTE = DEST->INP3ROUTE[0].ROUT_NEIGHBOUR;
}
if (ROUTE == 0) // Shouldn't happen
return FALSE;
// if NetROM over VARA conection is made by the driver
TNC = TNCInfo[ROUTE->NEIGHBOUR_PORT];
@ -204,7 +222,7 @@ BOOL ACTIVATE_DEST(struct DEST_LIST * DEST)
return L2SETUPCROSSLINK(ROUTE);
}
// We mst be waiting for link to come up
// We umst be waiting for link to come up
return TRUE;
@ -707,11 +725,11 @@ int COUNTNODES(struct ROUTE * ROUTE)
count++;
else if (DEST->NRROUTE[2].ROUT_NEIGHBOUR == ROUTE)
count++;
else if (DEST->ROUTE[0].ROUT_NEIGHBOUR == ROUTE)
else if (DEST->INP3ROUTE[0].ROUT_NEIGHBOUR == ROUTE)
count++;
else if (DEST->ROUTE[1].ROUT_NEIGHBOUR == ROUTE)
else if (DEST->INP3ROUTE[1].ROUT_NEIGHBOUR == ROUTE)
count++;
else if (DEST->ROUTE[2].ROUT_NEIGHBOUR == ROUTE)
else if (DEST->INP3ROUTE[2].ROUT_NEIGHBOUR == ROUTE)
count++;
DEST++;
@ -845,7 +863,7 @@ VOID SENDNEXTNODESFRAGMENT()
if (DEST->DEST_CALL[0] != 0x40 && DEST->NRROUTE[0].ROUT_QUALITY >= TXMINQUAL &&
DEST->NRROUTE[0].ROUT_OBSCOUNT >= OBSMIN &&
(NODE == 1 || DEST->DEST_STATE & 0x80)) // Only send appl nodes if DEST = 0;
(NODE == 1 || DEST->DEST_STATE & 0x80)) // Only send appl nodes if NODE = 0;
{
// Send it
@ -878,6 +896,9 @@ VOID SENDNEXTNODESFRAGMENT()
*(ptr1++) = (UCHAR)Qual;
if (Qual == 0)
continue;
Count--;
}
DEST++;
@ -924,7 +945,7 @@ VOID L3LINKCLOSED(struct _LINKTABLE * LINK, int Reason)
VOID CLEARACTIVEROUTE(struct ROUTE * ROUTE, int Reason)
{
// FIND ANY DESINATIONS WITH [ESI] AS ACTIVE NEIGHBOUR, AND
// FIND ANY DESINATIONS WITH ROUTE AS ACTIVE NEIGHBOUR, AND
// SET INACTIVE
dest_list * DEST;
@ -945,7 +966,7 @@ VOID CLEARACTIVEROUTE(struct ROUTE * ROUTE, int Reason)
if (DEST->DEST_ROUTE == 0)
continue;
if (DEST->ROUTE[DEST->DEST_ROUTE].ROUT_NEIGHBOUR == ROUTE) // Is this the active route
if (DEST->INP3ROUTE[DEST->DEST_ROUTE].ROUT_NEIGHBOUR == ROUTE) // Is this the active route
{
// Yes, so clear
@ -1120,7 +1141,7 @@ UPDEST000:
{
// Any INP3 Routes?
if (DEST->ROUTE[0].ROUT_NEIGHBOUR == 0)
if (DEST->INP3ROUTE[0].ROUT_NEIGHBOUR == 0)
{
// NO ROUTES LEFT TO DEST - REMOVE IT
@ -1292,6 +1313,32 @@ VOID REMOVENODE(dest_list * DEST)
NUMBEROFNODES--;
}
VOID L3LINKSETUPFAILED(struct _LINKTABLE * LINK)
{
// L2 LINK SETUP HAS FAILED - SEE IF ANOTHER NEIGHBOUR CAN BE USED
struct PORTCONTROL * PORT = PORTTABLE;
struct ROUTE * ROUTE;
ROUTE = LINK->NEIGHBOUR; // TO NEIGHBOUR
if (ROUTE == NULL)
return; // NOTHING ???
if (ROUTE->INP3Node)
{
char Normcall[10];
Normcall[ConvFromAX25(ROUTE->NEIGHBOUR_CALL, Normcall)] = 0;
Debugprintf("INP3 Route to %s connect failed", Normcall);
}
ROUTE->NEIGHBOUR_LINK = 0; // CLEAR IT
L3TRYNEXTDEST(ROUTE); // RESET ASSOCIATED DEST ENTRIES
}
VOID L3CONNECTFAILED(struct _LINKTABLE * LINK)
{
// L2 LINK SETUP HAS FAILED - SEE IF ANOTHER NEIGHBOUR CAN BE USED
@ -1305,6 +1352,14 @@ VOID L3CONNECTFAILED(struct _LINKTABLE * LINK)
if (ROUTE == NULL)
return; // NOTHING ???
if (ROUTE->INP3Node)
{
char Normcall[10];
Normcall[ConvFromAX25(ROUTE->NEIGHBOUR_CALL, Normcall)] = 0;
Debugprintf("INP3 Route to %s connect failed or refused", Normcall);
}
TellINP3LinkSetupFailed(ROUTE);
ROUTE->NEIGHBOUR_LINK = 0; // CLEAR IT
@ -1315,7 +1370,7 @@ VOID L3CONNECTFAILED(struct _LINKTABLE * LINK)
VOID L3TRYNEXTDEST(struct ROUTE * ROUTE)
{
// FIND ANY DESINATIONS WITH [ESI] AS ACTIVE NEIGHBOUR, AND
// FIND ANY DESINATIONS WITH ROUTE AS ACTIVE NEIGHBOUR, AND
// SET NEXT BEST NEIGHBOUR (IF ANY) ACTIVE
int n = MAXDESTS;
@ -1328,7 +1383,7 @@ VOID L3TRYNEXTDEST(struct ROUTE * ROUTE)
if (ActiveRoute)
{
ActiveRoute --; // Routes numbered 1 - 6, idex from 0
ActiveRoute --; // Routes numbered 1 - 6, index from 0
if (DEST->NRROUTE[ActiveRoute].ROUT_NEIGHBOUR == ROUTE)
{

122
L4Code.c
View File

@ -67,18 +67,23 @@ VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len
VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, UCHAR * ApplCall);
void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode);
void SendVARANetromMsg(struct TNCINFO * TNC, PL3MESSAGEBUFFER MSG);
unsigned char * Compressit(unsigned char * In, int Len, int * OutLen);
int doinflate(unsigned char * source, unsigned char * dest, int Len, int destlen, int * outLen);
int L2Compressit(unsigned char * Out, int OutSize, unsigned char * In, int Len);
static UINT APPLMASK;
extern BOOL LogL4Connects;
extern BOOL LogAllConnects;
extern int L4Compress;
extern int L4CompMaxframe;
extern int L4CompPaclen;
extern int L2Compress;
extern int L2CompMaxframe;
extern int L2CompPaclen;
// L4 Flags Values
#define DISCPENDING 8 // SEND DISC WHEN ALL DATA ACK'ED
@ -299,6 +304,7 @@ VOID SENDL4MESSAGE(TRANSPORTENTRY * L4, struct DATAMESSAGE * Msg)
return;
}
L3MSG = GetBuff();
if (L3MSG == 0)
@ -567,6 +573,55 @@ void sendChunk(TRANSPORTENTRY * L4, unsigned char * Compressed, int complen, int
}
}
void sendL2Chunk(struct _LINKTABLE * LINK, unsigned char * Compressed, int complen, int sendPacLen)
{
unsigned char * compdata;
struct DATAMESSAGE * Msg;
int sendLen = complen;
int fragments;
LINK->SentAfterCompression += complen;
if (complen > L2CompPaclen)
{
fragments = (complen / sendPacLen); // Split to roughly equal sized fraagments
if (fragments * sendPacLen != complen)
fragments++;
sendLen = (complen / fragments) + 1;
}
Debugprintf("L2 Chunk %d Bytes %d PACLEN %d Fragments %d FragSize", complen, sendPacLen, fragments, sendLen);
compdata = Compressed;
while (complen > 0)
{
int PID = 0xF1;
if (complen > sendLen)
PID = 0xF2; // More to come
Msg = GetBuff();
if (!Msg)
return;
Msg->PORT = LINK->LINKPORT->PORTNUMBER;
memcpy(Msg->L2DATA, compdata, sendLen);
Msg->LENGTH = sendLen + MSGHDDRLEN + 1; // 1 for pid field
Msg->PID = PID; // Not sent so use as a flag for compressed msg
compdata += sendLen;
complen -= sendLen;
C_Q_ADD(&LINK->TX_Q, Msg);
}
}
VOID L4BG()
{
// PROCESS DATA QUEUED ON SESSIONS
@ -628,7 +683,7 @@ VOID L4BG()
LINK = L4->L4TARGET.LINK;
if (COUNT_AT_L2(LINK) > 8)
if (COUNT_AT_L2(LINK) > 64)
break;
}
@ -666,36 +721,32 @@ VOID L4BG()
if (L4->AllowCompress)
{
int complen = 0;
unsigned char * Compressed;
unsigned char Compressed[8192];
unsigned char toCompress[8192];
int toCompressLen = 0;
int dataLen;
int savePort = Msg->PORT;
int maxCompSendLen;
// Save first packet, then see if more on TX_Q
L4->toCompress = malloc(8192);
L4->toCompressLen = 0;
dataLen = Msg->LENGTH - MSGHDDRLEN - 1; // No header or pid
L4->Sent += dataLen;
memcpy(&L4->toCompress[L4->toCompressLen], Msg->L2DATA, dataLen);
L4->toCompressLen += dataLen;
memcpy(&toCompress[toCompressLen], Msg->L2DATA, dataLen);
toCompressLen += dataLen;
// See if first will compress. If not assume too short or already compressed data and just send
Compressed = Compressit(L4->toCompress, L4->toCompressLen, &complen);
complen = L2Compressit(Compressed, 8192, toCompress, toCompressLen);
if (complen >= dataLen)
{
free(Compressed);
L4->SentAfterCompression += dataLen;
SENDL4MESSAGE(L4, Msg);
ReleaseBuffer(Msg);
free(L4->toCompress);
L4->toCompress = 0;
L4->toCompressLen = 0;
toCompressLen = 0;
continue;
}
@ -705,7 +756,7 @@ VOID L4BG()
{
// no more, so just send the stuff we've just compressed. Compressed data will fit in input packet
// Debugprintf("%d %d %d%%", L4->toCompressLen, complen, ((L4->toCompressLen - complen) * 100) / L4->toCompressLen);
// Debugprintf("%d %d %d%%", toCompressLen, complen, ((toCompressLen - complen) * 100) / toCompressLen);
memcpy(Msg->L2DATA, Compressed, complen);
@ -716,17 +767,13 @@ VOID L4BG()
SENDL4MESSAGE(L4, Msg);
ReleaseBuffer(Msg);
free(L4->toCompress);
L4->toCompressLen = 0;
L4->toCompress = 0;
free(Compressed);
toCompressLen = 0;
continue;
}
free(Compressed);
ReleaseBuffer(Msg); // Not going to use it
while (L4->L4TX_Q && L4->toCompressLen < (8192 - 256)) // Make sure can't overrin buffer
while (L4->L4TX_Q && toCompressLen < (8192 - 256)) // Make sure can't overrin buffer
{
// Collect the data from L4TX_Q
@ -734,16 +781,17 @@ VOID L4BG()
dataLen = Msg->LENGTH - MSGHDDRLEN - 1; // No header or pid
L4->Sent += dataLen;
memcpy(&L4->toCompress[L4->toCompressLen], Msg->L2DATA, dataLen);
L4->toCompressLen += dataLen;
memcpy(&toCompress[toCompressLen], Msg->L2DATA, dataLen);
toCompressLen += dataLen;
ReleaseBuffer(Msg);
}
L4->toCompress[L4->toCompressLen] = 0;
toCompress[toCompressLen] = 0;
Compressed = Compressit(L4->toCompress, L4->toCompressLen, &complen);
// Debugprintf("%d %d %d%%", L4->toCompressLen, complen, ((L4->toCompressLen - complen) * 100) / L4->toCompressLen);
complen = L2Compressit(Compressed, 8192, toCompress, toCompressLen);
Debugprintf("%d %d %d%%", toCompressLen, complen, ((toCompressLen - complen) * 100) / toCompressLen);
// Send compressed
@ -762,8 +810,8 @@ VOID L4BG()
int Fragments;
int ChunkSize;
unsigned char * CompressPtr = L4->toCompress;
int bytesleft = L4->toCompressLen;
unsigned char * CompressPtr = toCompress;
int bytesleft = toCompressLen;
// Assume 10% worse compression on smaller input
@ -771,7 +819,7 @@ VOID L4BG()
Fragments = j / maxCompSendLen;
Fragments++;
ChunkSize = (L4->toCompressLen / Fragments) + 1; // 1 for rounding
ChunkSize = (toCompressLen / Fragments) + 1; // 1 for rounding
while (bytesleft > 0)
{
@ -779,9 +827,9 @@ VOID L4BG()
if (Len > ChunkSize)
Len = ChunkSize;
free (Compressed);
Compressed = Compressit(CompressPtr, Len, &complen);
// Debugprintf("Chunked %d %d %d%%", Len, complen, ((Len - complen) * 100) / Len);
complen = L2Compressit(Compressed, 8192, toCompress, toCompressLen);
Debugprintf("Chunked %d %d %d%%", Len, complen, ((Len - complen) * 100) / Len);
sendChunk(L4, Compressed, complen, savePort);
@ -793,10 +841,7 @@ VOID L4BG()
else
sendChunk(L4, Compressed, complen,savePort);
free(L4->toCompress);
L4->toCompressLen = 0;
L4->toCompress = 0;
free(Compressed);
toCompressLen = 0;
}
else
{
@ -808,6 +853,8 @@ VOID L4BG()
continue;
}
// L2 Link
LINK = L4->L4TARGET.LINK;
// If we want to enforce PACLEN this may be a good place to do it
@ -936,9 +983,6 @@ VOID CLEARSESSIONENTRY(TRANSPORTENTRY * Session)
if (Session->PARTCMDBUFFER)
ReleaseBuffer(Session->PARTCMDBUFFER);
if (Session->toCompress)
free(Session->toCompress);
if (Session->unCompress)
free(Session->unCompress);

View File

@ -381,12 +381,11 @@ BOOL CtrlHandler(DWORD fdwCtrlType)
#include <signal.h>
// Linux Signal Handlers
static void segvhandler(int sig)
{
void *array[10];
size_t size;
char msg[] = "SIGSEGV Received\n";
char msg[] = "\nSIGSEGV Received\n";
write(STDERR_FILENO, msg, strlen(msg));
@ -397,6 +396,9 @@ static void segvhandler(int sig)
backtrace_symbols_fd(array, size, STDERR_FILENO);
write(STDOUT_FILENO, msg, strlen(msg));
backtrace_symbols_fd(array, size, STDOUT_FILENO);
exit(1);
}
@ -404,18 +406,23 @@ static void abrthandler(int sig)
{
void *array[10];
size_t size;
char msg[] = "SIGABRT Received\n";
char msg[] = "\nSIGABRT Received\n";
write(STDERR_FILENO, msg, strlen(msg));
write(STDOUT_FILENO, msg, strlen(msg));
// get void*'s for all entries on the stack
size = backtrace(array, 10);
backtrace_symbols_fd(array, size, STDERR_FILENO);
write(STDOUT_FILENO, msg, strlen(msg));
backtrace_symbols_fd(array, size, STDOUT_FILENO);
exit(1);
}
static void sigterm_handler(int sig)
{
syslog(LOG_INFO, "terminating on SIGTERM\n");
@ -787,6 +794,8 @@ int Redirected = 0;
static void segvhandler(int sig);
static void abrthandler(int sig);
void GetRestartData();
int main(int argc, char * argv[])
{
@ -845,6 +854,8 @@ int main(int argc, char * argv[])
printf("G8BPQ AX25 Packet Switch System Version %s %s\n", TextVerstring, Datestring);
printf("%s\n", VerCopyright);
srand(time(NULL));
// look for optarg format parameters
@ -1174,6 +1185,8 @@ int main(int argc, char * argv[])
chmod(MailDir, S_IRWXU | S_IRWXG | S_IRWXO);
#endif
// Make backup copies of Databases
// CopyConfigFile(ConfigName);
@ -1195,6 +1208,7 @@ int main(int argc, char * argv[])
GetBadWordFile();
GetHTMLForms();
GetPGConfig();
GetRestartData();
// Make sure there is a user record for the BBS, with BBS bit set.
@ -1442,6 +1456,7 @@ int main(int argc, char * argv[])
SaveMessageDatabase();
SaveBIDDatabase();
SaveConfig(ConfigName);
SaveRestartData();
}
KEEPGOING--; // Give time for links to close

1543
MULTIPSK64.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -535,6 +535,16 @@ KC6OAR*>ID:
Output += sprintf((char *)Output, " RX Window=%d", value);
break;
case 16:
Output += sprintf((char *)Output, " Can Compress");
break;
case 17:
Output += sprintf((char *)Output, " Compress ok");
break;
}
}
}
@ -551,6 +561,15 @@ KC6OAR*>ID:
switch (ADJBUFFER->PID)
{
case 0xF1:
case 0xF2:
// Compressed L2 Data
Output += sprintf((char *)Output, " <%d Bytes of Compressed L2 Data>", MsgLen - (19 + sizeof(void *)));
break;
case 0xF0: // Normal Data
{
char Infofield[257];

View File

@ -919,6 +919,9 @@ LRESULT APIENTRY InputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
DoRefresh(Cinfo);
Cinfo->Console->bytesRxed += Cinfo->kbptr+1;
if (Cinfo->Console->SysopChatStream)
SendUnbuffered(Cinfo->Console->SysopChatStream->BPQStream, &Cinfo->kbbuf[0], Cinfo->kbptr+1);
else

51
RHP.c
View File

@ -451,8 +451,13 @@ int processRHCPSend(SOCKET Socket, char * Msg, char * ReplyBuffer)
int ID;
char * Data;
char * ptr;
unsigned char * uptr;
int c;
int Len;
unsigned int HexCode1;
unsigned int HexCode2;
int n;
int Handle = 1;
@ -470,9 +475,10 @@ int processRHCPSend(SOCKET Socket, char * Msg, char * ReplyBuffer)
RHPSession = RHPSessions[Handle - 1];
// Look for \ escapes
// Look for \ escapes, Can now also get \u00c3
ptr = Data;
Len = strlen(Data); // in case no escapes
while (ptr = strchr(ptr, '\\'))
{
@ -483,23 +489,60 @@ int processRHCPSend(SOCKET Socket, char * Msg, char * ReplyBuffer)
case 'r':
*ptr = 13;
memmove(ptr + 1, ptr + 2, strlen(ptr + 1));
break;
case 'u':
HexCode1 = HexCode2 = 0;
n = toupper(ptr[2]) - '0';
if (n > 9) n = n - 7;
HexCode1 |= n << 4;
n = toupper(ptr[3]) - '0';
if (n > 9) n = n - 7;
HexCode1 |= n;
n = toupper(ptr[4]) - '0';
if (n > 9) n = n - 7;
HexCode2 |= n << 4;
n = toupper(ptr[5]) - '0';
if (n > 9) n = n - 7;
HexCode2 |= n;
if (HexCode1 == 0 || HexCode1 == 0xC2)
{
uptr = ptr;
*uptr = HexCode2;
}
else if (HexCode1 == 0xc2)
{
uptr = ptr;
*uptr = HexCode2 + 0x40;
}
memmove(ptr + 1, ptr + 6, strlen(ptr + 5));
break;
case '\\':
*ptr = '\\';
memmove(ptr + 1, ptr + 2, strlen(ptr + 1));
break;
case '"':
*ptr = '"';
memmove(ptr + 1, ptr + 2, strlen(ptr + 1));
break;
}
memmove(ptr + 1, ptr + 2, strlen(ptr + 1));
ptr++;
Len = ptr - Data;
}
Len = strlen(Data);
ptr = Data;
while (Len > RHPPaclen)
@ -640,7 +683,7 @@ void RHPPoll()
// Message is JSON so Convert CR to \r, \ to \\ " to \"
// Looks like I need to escape everything not between 0x20 and 0x7f eg \U00c3
// Looks like I need to escape everything not between 0x20 and 0x7f eg \u00c3
while (c = *(ptr))

View File

View File

@ -5293,6 +5293,7 @@ BOOL DecodeModePtr(char * Param, double * Dwell, double * Freq, char * Mode,
if (ptr == NULL || strlen(ptr) > 8)
return FALSE; // Mode Missing
// If channel, dont need mode
if (*MemoryNumber == 0)
{

1714
SCSTrackeMulti64.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -322,6 +322,9 @@ Dll VOID APIENTRY Send_AX(UCHAR * Block, DWORD Len, UCHAR Port)
EXTPORTDATA * EXTPORT = (EXTPORTDATA *) PORT;
if (EXTPORT->UI_Q)
C_Q_ADD(&EXTPORT->UI_Q, Copy);
else
C_Q_ADD(&EXTPORT->UI_Q, Copy);
return;
}

View File

@ -685,6 +685,11 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
ConnecttoUZ7HO(port);
lasttime[port] = ltime;
}
while (TNC->PortRecord->UI_Q)
{
buffptr = Q_REM(&TNC->PortRecord->UI_Q);
ReleaseBuffer(buffptr);
}
}
else
{

1
VARA.c
View File

@ -1720,7 +1720,6 @@ VConnected:
GetSemaphore(&Semaphore, 52);
VARAProcessReceivedControl(TNC);
FreeSemaphore(&Semaphore);
Debugprintf("VARA Returned from processing control packet");
}
if (FD_ISSET(TNC->TCPDataSock, &readfs))

View File

@ -10,14 +10,15 @@
#endif
#define KVers 6,0,24,66
#define KVerstring "6.0.24.66\0"
#define KVers 6,0,24,71
#define KVerstring "6.0.24.71\0"
#ifdef CKernel
#define Vers KVers
#define Verstring KVerstring
#define Datestring "February 2025"
#define Datestring "April 2025"
#define VerComments "G8BPQ Packet Switch (C Version)" KVerstring
#define VerCopyright "Copyright © 2001-2025 John Wiseman G8BPQ\0"
#define VerDesc "BPQ32 Switch\0"

View File

@ -139,6 +139,10 @@ VOID WritetoTraceSupport(struct TNCINFO * TNC, char * Msg, int Len)
int LineLen, i;
UCHAR Save;
int SaveLen = Len;
char Time[16];
time_t T;
struct tm * tm;
if (Len < 0)
return;
@ -206,10 +210,16 @@ lineloop:
#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], 4490); // Make sure null is moved
memmove(TNC->WebBuffer, &TNC->WebBuffer[500], strlen(&TNC->WebBuffer[500]) + 1); // Make sure null is moved
Skip:
ptr1 = ptr2;
@ -248,10 +258,16 @@ lineloop:
#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], 4490); // Make sure null is moved
memmove(TNC->WebBuffer, &TNC->WebBuffer[500], strlen(&TNC->WebBuffer[500]) + 1); // Make sure null is moved
}
}

View File

@ -37,6 +37,7 @@ 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()

187
WebMail.c
View File

@ -1446,7 +1446,12 @@ void ProcessWebMailMessage(struct HTTPConnectionInfo * Session, char * Key, BOOL
// Neither do js or file downloads
if (_memicmp(NodeURL, "/WebMail/WMFile/", 16) == 0)
// 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;
@ -1456,9 +1461,10 @@ void ProcessWebMailMessage(struct HTTPConnectionInfo * Session, char * Key, BOOL
char TimeString[64];
char FileTimeString[64];
struct stat STAT;
char * FN = &NodeURL[16];
char * FN = &NodeURL[9];
char * fileBit = FN;
char * ext;
char Type[64] = "Content-Type: text/html\r\n";
UndoTransparency(FN);
ext = strchr(FN, '.');
@ -1491,24 +1497,109 @@ void ProcessWebMailMessage(struct HTTPConnectionInfo * Session, char * Key, BOOL
FormatTime2(FileTimeString, STAT.st_ctime);
FormatTime2(TimeString, time(NULL));
if (_stricmp(ext, ".htm") == 0 || _stricmp(ext, ".html") == 0 || _stricmp(ext, ".css") == 0 || _stricmp(ext, ".js") == 0)
{
*RLen = sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n"
"Content-Type: text/css\r\n"
"Date: %s\r\n"
"Last-Modified: %s\r\n"
"\r\n%s", FileSize, TimeString, FileTimeString, MsgBytes);
}
else
{
*RLen = sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n"
"Content-Type: application/octet-stream\r\n"
"Content-Disposition: attachment; filename=\"%s\"\r\n"
"Date: %s\r\n"
"Last-Modified: %s\r\n"
"\r\n%s", FileSize, fileBit, TimeString, FileTimeString, MsgBytes);
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;
}
@ -2883,7 +2974,7 @@ VOID SaveNewMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, char * R
// RMS Express Forms Support
char * GetHTMLViewerTemplate(char * FN)
char * GetHTMLViewerTemplate(char * FN, struct HtmlFormDir ** FormDir)
{
int i, j, k, l;
@ -2897,6 +2988,7 @@ char * GetHTMLViewerTemplate(char * FN)
{
if (strcmp(FN, Dir->Forms[j]->FileName) == 0)
{
*FormDir = Dir;
return CheckFile(Dir, FN);
}
}
@ -2917,6 +3009,7 @@ char * GetHTMLViewerTemplate(char * FN)
{
if (_stricmp(FN, SDir->Forms[k]->FileName) == 0)
{
*FormDir = SDir;
return CheckFile(SDir, SDir->Forms[k]->FileName);
}
}
@ -2980,6 +3073,13 @@ VOID GetPage(struct HTTPConnectionInfo * Session, char * NodeURL)
ptr = strchr(&NodeURL[17], ',');
Dir = HtmlFormDirs[DirNo];
if (DirNo == -1)
{
*WebMail->RLen = sprintf(WebMail->Reply, "<html><script>alert(\"No Page Selected. \");window.location.href = '/Webmail/NewMsg?%s';</script></html>", Session->Key);
return;
}
SubDir = strlop(&NodeURL[17], ':');
if (SubDir)
{
@ -3293,6 +3393,13 @@ BOOL ParseXML(WebMailInfo * WebMail, char * XMLOrig)
// Extract Fields (stuff between < and >. Ignore Whitespace between fields
// Add FormFolder Key with our folder
// XMLKeys->Key = "FormFolder";
// XMLKeys->Value = _strdup(FormDir);
// XMLKeys++;
ptr1 = strstr(XML, "<xml_file_version>");
while (ptr1)
@ -3396,6 +3503,8 @@ int DisplayWebForm(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, ch
size_t varlen, xmllen;
char var[100] = "<";
KeyValues * KeyValue;
struct HtmlFormDir * Dir;
char FormDir[MAX_PATH];
if (ParseXML(WebMail, XML))
ptr = FindXMLVariable(WebMail, "display_form");
@ -3409,7 +3518,11 @@ int DisplayWebForm(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, ch
strcpy(FN, ptr);
Form = GetHTMLViewerTemplate(FN);
Form = GetHTMLViewerTemplate(FN, &Dir);
sprintf(FormDir, "WMFile/%s/%s/", Dir->FormSet, Dir->DirName);
if (Form == NULL)
{
@ -3425,6 +3538,15 @@ int DisplayWebForm(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, ch
// Don't know why, but {MsgOriginalBody} is sent instead of {var MsgOriginalBody}
// So is {FormFolder} instread of {var FormFolder}
// As a fiddle replace {FormFolder} with {var Folder} and look for that
while (varptr = stristr(Form, "{FormFolder}"))
{
memcpy(varptr, "{var ", 5);
}
varptr = stristr(Form, "{MsgOriginalBody}");
{
char * temp, * tempsave;
@ -3564,6 +3686,23 @@ int DisplayWebForm(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, ch
while (KeyValue->Key)
{
if (_stricmp(var, "Folder") == 0)
{
// Local form folder, not senders
xmllen = strlen(FormDir);
// Ok, we have the position of the variable and the substitution text.
// Copy message up to variable to Result, then copy value
memcpy(Reply, formptr, varptr - formptr - 5); // omit "{var "
Reply += (varptr - formptr - 5);
strcpy(Reply, FormDir);
Reply += xmllen;
break;
}
if (_stricmp(var, KeyValue->Key) == 0)
{
xmllen = strlen(KeyValue->Value);
@ -3579,6 +3718,8 @@ int DisplayWebForm(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, ch
break;
}
KeyValue++;
if (KeyValue->Key == NULL)
{
// Not found in XML
@ -3588,7 +3729,7 @@ int DisplayWebForm(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, ch
sprintf(Err, VarNotFoundMsg, var, "%s");
return ReturnRawMessage(User, Msg, Key, SaveReply, RawMessage, (int)(XML - RawMessage), Err);
}
KeyValue++;
}
formptr = endptr + 1;
@ -5448,8 +5589,6 @@ char * CheckFile(struct HtmlFormDir * Dir, char * FN)
#endif
printf("%s\n", MsgFile);
if (stat(MsgFile, &STAT) != -1)
{
hFile = fopen(MsgFile, "rb");
@ -5466,8 +5605,6 @@ char * CheckFile(struct HtmlFormDir * Dir, char * FN)
MsgBytes[FileSize] = 0;
fclose(hFile);
printf("%d %s\n", strlen(MsgBytes), MsgBytes);
return MsgBytes;
}
return NULL;

View File

@ -1580,8 +1580,6 @@ TNCRunning:
// Send INIT script
// VARA needs each command in a separate send
ptr1 = &TNC->InitScript[0];
GetSemaphore(&Semaphore, 52);
@ -1606,7 +1604,6 @@ TNCRunning:
c = *(ptr2 + 1); // Save next char
*(ptr2 + 1) = 0; // Terminate string
}
// VARASendCommand(TNC, ptr1, TRUE);
if (ptr2)
*(1 + ptr2++) = c; // Put char back

View File

@ -176,8 +176,6 @@ typedef struct _TRANSPORTENTRY
// We collect as much data as possible before compressing and re-packetizing
int AllowCompress;
unsigned char * toCompress; // Data being saved to compress
int toCompressLen;
unsigned char * unCompress; // Data being saved to uncompress
int unCompressLen;
@ -255,6 +253,7 @@ typedef struct ROUTE
#define GotRTTResponse 2 // Other end has sent us a RTT Response
#define GotRIF 4 // Other end has sent RIF, so is probably an INP3 Node
// (could just be monitoring RTT for some reason
#define SentRTTRequest 8
#define SentOurRIF 16 // Set when we have sent a rif for our Call and any ApplCalls
// (only sent when we have seen both a request and response)
@ -462,16 +461,18 @@ typedef struct _APPLCALLS
// This way our times adjust to changes of neighbour SRTT. We can't cater for changes to other hop RTTs,
// But if these are significant (say 25% or 100 ms) they will be retransmitted
// We treat the Routes as an array of 6. First 3 are NODES routes, next 3 are INP3 Routes. This works, but maybe is not ideal
typedef struct NR_DEST_ROUTE_ENTRY
{
struct ROUTE * ROUT_NEIGHBOUR; // POINTER TO NEXT NODE IN PATH
UCHAR ROUT_QUALITY; // QUALITY
UCHAR ROUT_OBSCOUNT;
UCHAR ROUT_LOCKED;
UCHAR Padding[4]; // SO Entries are the same length
UCHAR Padding[4]; // So Entries are the same length
} *PNR_DEST_ROUTE_ENTRY;
typedef struct DEST_ROUTE_ENTRY
typedef struct INP3_DEST_ROUTE_ENTRY
{
struct ROUTE * ROUT_NEIGHBOUR; // POINTER TO NEXT NODE IN PATH
USHORT LastRTT; // Last Value Reported
@ -495,8 +496,8 @@ typedef struct DEST_LIST
UCHAR DEST_ROUTE; // CURRENTY ACTIVE DESTINATION
UCHAR INP3FLAGS;
struct NR_DEST_ROUTE_ENTRY NRROUTE[3];// Best 3 NR neighbours for this dest
struct DEST_ROUTE_ENTRY ROUTE[3]; // Best 3 INP neighbours for this dest
struct NR_DEST_ROUTE_ENTRY NRROUTE[3]; // Best 3 NR neighbours for this dest
struct INP3_DEST_ROUTE_ENTRY INP3ROUTE[3]; // Best 3 INP neighbours for this dest
void * DEST_Q; // QUEUE OF FRAMES FOR THIS DESTINATION
@ -700,6 +701,7 @@ typedef struct PORTCONTROL
BOOL NormalizeQuality; // Normalise Node Qualities
BOOL IgnoreUnlocked; // Ignore Unlocked routes
BOOL INP3ONLY; // Default to INP3 and disallow NODES
BOOL ALLOWINP3;
void (* UIHook)(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG); // Used for KISSARQ
struct PORTCONTROL * HookPort;
@ -959,6 +961,21 @@ typedef struct _LINKTABLE
int bytesRXed; // Info bytes only
int bytesTXed;
// Now support compressing L2 Sessions.
// We collect as much data as possible before compressing and re-packetizing
int AllowCompress;
unsigned char * unCompress; // Data being saved to uncompress
int unCompressLen;
int Sent;
int SentAfterCompression;
int Received;
int ReceivedAfterExpansion;
} LINKTABLE;
#pragma pack(1)
@ -1354,6 +1371,7 @@ struct arp_table_entry
// SOCKET SourceSocket;
struct AXIPPORTINFO * PORT;
BOOL noUpdate; // Don't update dest address from incoming packet
time_t LastHeard; // Last Packet received from this ststiom
};

View File

@ -733,7 +733,7 @@ VOID SendFrame(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp_table, U
return;
}
// Seelcte source port by choosing right socket
// Select source port by choosing right socket
// First Set Default for Protocol
@ -2610,6 +2610,7 @@ BOOL CheckSourceisResolvable(struct AXIPPORTINFO * PORT, char * call, int Port,
//arp->port = Port;
}
arp->LastHeard = time(NULL);
return 1; // Ok to process
}
index++;

View File

@ -290,6 +290,9 @@ typedef struct ConnectionInfo_S
struct ConnectionInfo_S * SysopChatStream; // Stream sysop is chatting to
int bytesSent;
int bytesRxed;
} ConnectionInfo, CIRCUIT;
// Flags Equates
@ -336,11 +339,13 @@ typedef struct ConnectionInfo_S
struct FBBRestartData
{
struct MsgInfo * TempMsg; // Header while message is being received
struct UserInfo * UserPointer;
char Call[10];
char bid[13];
int length;
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
time_t TimeCreated;
};
// We need to keep the B2Message file for B2 messages we are sending until the messages is acked, so
@ -1387,6 +1392,7 @@ BOOL CheckBBSHElements(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSFo
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 SaveRestartData();
VOID ReRouteMessages();

33
cMain.c
View File

@ -144,6 +144,12 @@ int L4Compress = 0;
int L4CompMaxframe = 3;
int L4CompPaclen = 236;
int L2Compress = 0;
int L2CompMaxframe = 3;
int L2CompPaclen = 236;
int PREFERINP3ROUTES = 0;
BOOL LogL4Connects = FALSE;
BOOL LogAllConnects = FALSE;
BOOL AUTOSAVEMH = TRUE;
@ -161,6 +167,8 @@ char MQTT_PASS[80] = "";
int MQTT_Connecting = 0;
int MQTT_Connected = 0;
int PoolBuilt = 0;
//TNCTABLE DD 0
//NUMBEROFSTREAMS DD 0
@ -837,6 +845,20 @@ BOOL Start()
if (L4CompPaclen < 64 || L4CompPaclen > 236)
L4CompPaclen = 236;
L2Compress = cfg->C_L2Compress;
L2CompMaxframe = cfg->C_L2CompMaxframe;
L2CompPaclen = cfg->C_L2CompPaclen;
if (L2CompMaxframe < 1 || L2CompMaxframe > 16)
L2CompMaxframe = 3;
if (L2CompPaclen < 64 || L2CompPaclen > 236)
L2CompPaclen = 236;
PREFERINP3ROUTES = cfg->C_PREFERINP3ROUTES;
// Get pointers to PASSWORD and APPL1 commands
// int APPL1 = 0;
@ -962,6 +984,7 @@ BOOL Start()
PORT->NormalizeQuality = !PortRec->NoNormalize;
PORT->IgnoreUnlocked = PortRec->IGNOREUNLOCKED;
PORT->INP3ONLY = PortRec->INP3ONLY;
PORT->ALLOWINP3 = PortRec->AllowINP3;
PORT->PORTWINDOW = (UCHAR)PortRec->MAXFRAME;
@ -986,6 +1009,9 @@ BOOL Start()
PORT->PORTPACLEN = (UCHAR)PortRec->PACLEN;
PORT->QUAL_ADJUST = (UCHAR)PortRec->QUALADJUST;
if (PORT->QUAL_ADJUST < 0 || PORT->QUAL_ADJUST > 100)
PORT->QUAL_ADJUST = 100;
PORT->DIGIFLAG = PortRec->DIGIFLAG;
if (PortRec->DIGIPORT && CanPortDigi(PortRec->DIGIPORT))
PORT->DIGIPORT = PortRec->DIGIPORT;
@ -1443,6 +1469,8 @@ BOOL Start()
ENDBUFFERPOOL = NEXTFREEDATA;
PoolBuilt = 1;
// Copy Bridge Map
@ -1560,6 +1588,7 @@ BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE)
struct ROUTE * ROUTE = NEIGHBOURS;
struct ROUTE * FIRSTSPARE = NULL;
int n = MAXNEIGHBOURS;
char Normcall[10];
while (n--)
{
@ -1572,6 +1601,10 @@ BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE)
ROUTE++;
continue;
}
Normcall[ConvFromAX25(ROUTE->NEIGHBOUR_CALL, Normcall)] = 0;
if (CompareCalls(ROUTE->NEIGHBOUR_CALL, Call))
{
*REQROUTE = ROUTE;

View File

@ -308,7 +308,7 @@ static char *keywords[] =
"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"
"L4Compress", "L4CompMaxframe", "L4CompPaclen", "L2Compress", "L2CompMaxframe", "L2CompPaclen", "PREFERINP3ROUTES"
}; /* parameter keywords */
static void * offset[] =
@ -330,7 +330,8 @@ static void * offset[] =
&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}; /* offset for corresponding data in config file */
&xxcfg.C_L4Compress, &xxcfg.C_L4CompMaxframe, &xxcfg.C_L4CompPaclen, &xxcfg.C_L2Compress, &xxcfg.C_L2CompMaxframe,
&xxcfg.C_L2CompPaclen, &xxcfg.C_PREFERINP3ROUTES}; /* offset for corresponding data in config file */
static int routine[] =
{
@ -351,7 +352,8 @@ static int routine[] =
15, 0, 2, 9, 9,
2, 2, 1, 2, 2, 2,
2, 2, 0, 1, 20, 20,
1, 1, 1} ; // Routine to process param
1, 1, 1, 1, 1,
1, 1} ; // Routine to process param
int PARAMLIM = sizeof(routine)/sizeof(int);
//int NUMBEROFKEYWORDS = sizeof(routine)/sizeof(int);
@ -373,7 +375,7 @@ static char *pkeywords[] =
"BCALL", "DIGIMASK", "NOKEEPALIVES", "COMPORT", "DRIVER", "WL2KREPORT", "UIONLY",
"UDPPORT", "IPADDR", "I2CBUS", "I2CDEVICE", "UDPTXPORT", "UDPRXPORT", "NONORMALIZE",
"IGNOREUNLOCKEDROUTES", "INP3ONLY", "TCPPORT", "RIGPORT", "PERMITTEDAPPLS", "HIDE",
"SMARTID", "KISSCOMMAND", "SendtoM0LTEMap", "PortFreq", "M0LTEMapInfo", "QTSMPort"}; /* parameter keywords */
"SMARTID", "KISSCOMMAND", "SendtoM0LTEMap", "PortFreq", "M0LTEMapInfo", "QTSMPort", "ALLOWINP3"}; /* parameter keywords */
static void * poffset[] =
{
@ -387,7 +389,7 @@ static void * poffset[] =
&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 */
&xxp.SmartID, &xxp.KissParams, &xxp.SendtoM0LTEMap, &xxp.PortFreq, &xxp.M0LTEMapInfo, &xxp.QtSMPort, &xxp.AllowINP3}; /* offset for corresponding data in config file */
static int proutine[] =
{
@ -401,7 +403,7 @@ static int proutine[] =
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 */
1, 20, 1, 21, 22, 1, 1}; /* routine to process parameter */
int PPARAMLIM = sizeof(proutine)/sizeof(int);
@ -535,6 +537,8 @@ BOOL ProcessConfig()
// xxcfg.SaveMH = TRUE; // Default to save
xxcfg.C_PREFERINP3ROUTES = 0; // Default to false
GetNextLine(rec);
while (rec[0])
@ -621,6 +625,10 @@ BOOL ProcessConfig()
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
paramok[92]=1; // PREFERINP3ROUTES
for (i=0; i < PARAMLIM; i++)

View File

@ -81,6 +81,7 @@ struct PORTCONFIG
uint64_t PortFreq;
char * M0LTEMapInfo;
int QtSMPort;
int AllowINP3;
};
struct ROUTECONFIG
@ -173,6 +174,10 @@ struct CONFIGTABLE
int C_L4Compress;
int C_L4CompMaxframe;
int C_L4CompPaclen;
int C_L2Compress;
int C_L2CompMaxframe;
int C_L2CompPaclen;
int C_PREFERINP3ROUTES;
//#define ApplOffset 80000 // Applications offset in config buffer

12
debian/changelog vendored
View File

@ -1,3 +1,15 @@
linbpq (6.0.24.71+repack-1~hibbian+1) bookworm-hibbian-unstable; urgency=medium
* New upstream version 6.0.24.67+repack
* New upstream version 6.0.24.69+repack
* New upstream version 6.0.24.69.1+repack
* New upstream version 6.0.24.71+repack
* Okay that's a lot of updates.
* Refreshed d/p/makefile to reflect new CFLAG
* MINI_BUILDD_OPTION: auto-ports=trixie-packetrepo-unstable,bookworm-packetrepo-unstable,bullseye-packetrepo-unstable,noble-packetrepo-unstable,jammy-packetrepo-unstable
-- Dave Hibberd <hibby@debian.org> Wed, 21 May 2025 21:45:59 +0100
linbpq (6.0.24.66+repack-1~hibbian+2) bookworm-hibbian-unstable; urgency=medium
* Update postinst script to be a little quieter

View File

@ -10,23 +10,24 @@
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\
@@ -18,9 +17,12 @@
@@ -18,9 +17,13 @@
# Configuration:
CC = gcc
-
-all: CFLAGS = -DLINBPQ -MMD -g -rdynamic -fcommon
-all: CFLAGS = -DLINBPQ -MMD -g -rdynamic -fcommon -fasynchronous-unwind-tables
-all: LDFLAGS = -l:libpaho-mqtt3a.a -l:libjansson.a
+
+CFLAGS:=$(shell dpkg-buildflags --get CFLAGS)
+CFLAGS+=$(shell dpkg-buildflags --get CPPFLAGS)
+LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS)
+
+all: CFLAGS += -DLINBPQ -MMD -g -fcommon -rdynamic
+all: CFLAGS += -DLINBPQ -MMD -g -rdynamic -fcommon -fasynchronous-unwind-tables
+all: LIBS = -lpaho-mqtt3a -ljansson -lminiupnpc -lrt -lm -lz -lpthread -lconfig -lpcap -lpng
all: linbpq
@@ -32,12 +34,15 @@
@@ -32,12 +35,15 @@
linbpq: $(OBJS)

2
kiss.c
View File

@ -2294,7 +2294,7 @@ VOID QtSMThread(struct PORTCONTROL * PORT)
char Msg[64];
int Len;
// We need tp send a QtSMPort message for each Channel sharing thia connection
// We need to send a QtSMPort message for each Channel sharing this connection
// Note struct KISSINFO and struct PORTCONTROL are different mappings of the same data
struct KISSINFO * KISS = (struct KISSINFO *)PORT;

View File

@ -19,15 +19,15 @@ OBJS = pngwtran.o pngrtran.o pngset.o pngrio.o pngwio.o pngtrans.o pngrutil.o pn
CC = gcc
all: CFLAGS = -DLINBPQ -MMD -g -rdynamic -fcommon
all: CFLAGS = -DLINBPQ -MMD -g -rdynamic -fcommon -fasynchronous-unwind-tables
all: LDFLAGS = -l:libpaho-mqtt3a.a -l:libjansson.a
all: linbpq
nomqtt: CFLAGS = -DLINBPQ -MMD -fcommon -g -rdynamic -DNOMQTT
nomqtt: CFLAGS = -DLINBPQ -MMD -fcommon -g -rdynamic -DNOMQTT -fasynchronous-unwind-tables
nomqtt: linbpq
noi2c: CFLAGS = -DLINBPQ -MMD -DNOI2C -g -rdynamic -fcommon
noi2c: CFLAGS = -DLINBPQ -MMD -DNOI2C -g -rdynamic -fcommon -fasynchronous-unwind-tables
noi2c: linbpq

2
mqtt.c
View File

@ -429,6 +429,6 @@ void MQTTKISSRX(void *message) {};
void MQTTKISSRX_RAW(char* buffer, int bufferLength, void* PORT) {};
void MQTTTimer() {};
void MQTTReportSession(char * Msg) {};
void MQTTMessageEvent(void* message) {};
#endif

View File

@ -520,7 +520,8 @@ char * MainConfigtxt()
"<textarea cols=\"8\" rows=\"5\" name=\"Hat\">%s</textarea>\r\n"
"<textarea cols=\"8\" rows=\"5\" name=\"HBID\">%s</textarea>\r\n"
"<p></p>"
"&nbsp;FBB reject.sys type filters (all fields must match, wildcards allowed)\r\n"
"&nbsp;FBB reject.sys type filters (all fields must match, wildcards allowed)<br>"
"&nbsp;'A' action accepts message if all fields match without checking following lines\r\n"
"<p></p>"
"<div style='position: absolute; left: 20px;height: 120px; overflow:auto;'>%s</div>"
"<div style='position: absolute; top: 1120px;left: 300px; overflow:auto;'>"

14
upnp.c
View File

@ -93,7 +93,11 @@ 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;
@ -119,8 +123,11 @@ int upnpInit()
{
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");
@ -150,8 +157,11 @@ int upnpClose()
{
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");