New upstream version 6.0.24.77+repack

This commit is contained in:
Hibby 2025-07-22 20:56:59 +01:00
parent b128f2a43a
commit 1f40ff4a07
61 changed files with 11979 additions and 1281 deletions

View File

@ -36,7 +36,8 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
struct AGWHeader
{
unsigned int Port;
uint8_t Port;
uint8_t filler1[3];
unsigned char DataKind;
unsigned char filler2;
unsigned char PID;
@ -128,7 +129,7 @@ int DataSocket_Write(struct AGWSocketConnectionInfo * sockptr, SOCKET sock);
int AGWGetSessionKey(char * key, struct AGWSocketConnectionInfo * sockptr);
int ProcessAGWCommand(struct AGWSocketConnectionInfo * sockptr);
int SendDataToAppl(int Stream, byte * Buffer, int Length);
int InternalAGWDecodeFrame(char * msg, char * buffer, time_t Stamp, int * FrameType, int useLocalTime, int doNodes);
int InternalAGWDecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp, int * FrameType, int useLocalTime, int doNodes);
int AGWDataSocket_Disconnect( struct AGWSocketConnectionInfo * sockptr);
int SendRawPacket(struct AGWSocketConnectionInfo * sockptr, char *txmsg, int Length);
int ShowApps();
@ -720,7 +721,7 @@ int AGWDoMonitorData()
RawLen = monbuff->LENGTH;
if (RawLen < 7 || RawLen > 350)
if (RawLen < MSGHDDRLEN || RawLen > 350)
{
ReleaseBuffer(monbuff);
FreeSemaphore(&Semaphore);
@ -735,11 +736,15 @@ int AGWDoMonitorData()
FreeSemaphore(&Semaphore);
// Set monbuff to point to the copy
monbuff = (MESSAGE *)Buffer;
//' 4 byte chain
//' 1 byte port - top bit = transmit
//' 2 byte length (LO-HI)
Port = Buffer[4];
Port = monbuff->PORT;
if (Port > 127)
{
@ -751,6 +756,12 @@ int AGWDoMonitorData()
RXFlag = TRUE;
}
if (Port == 0)
{
Debugprintf("AGWMON Port number is zero");
return 0;
}
// Can now have different mon flags per connection, so need to run decode for each socket
for (n = 1; n<= CurrentSockets; n++)
@ -759,7 +770,7 @@ int AGWDoMonitorData()
if (sockptr->SocketActive && sockptr->MonFlag && (RXFlag || LoopMonFlag))
{
Length = InternalAGWDecodeFrame(Buffer, AGWBuffer, Stamp, &Frametype, sockptr->useLocalTime, sockptr->doNodes);
Length = InternalAGWDecodeFrame(monbuff, AGWBuffer, Stamp, &Frametype, sockptr->useLocalTime, sockptr->doNodes);
if (Length > 0)
{
@ -803,7 +814,7 @@ int AGWDoMonitorData()
}
}
RawLen = RawLen - 6;
RawLen = RawLen - (MSGHDDRLEN - 1); // One more for KISS control
if (RXFlag || Loopflag) // Send transmitted frames if requested
{
@ -812,7 +823,11 @@ int AGWDoMonitorData()
// Send raw data to any sockets that have requested Raw frames
//
Buffer[6]=0;
// Format is ax.25 packet prceeded by a KISS command byte 00 for channel 1 0x10 for channel 2 etc
// As this is an application API I think all should go as Port 1
Buffer[MSGHDDRLEN - 1] = 0; // Just in case big-endian
AGWTXHeader.Port = Port - 1; // AGW Ports start from 0
AGWTXHeader.DataKind = 'K';
@ -824,14 +839,12 @@ int AGWDoMonitorData()
sockptr=&Sockets[n];
if (sockptr->SocketActive && sockptr->RawFlag)
SendRawPacket(sockptr, &Buffer[6], RawLen);
SendRawPacket(sockptr, &Buffer[MSGHDDRLEN - 1], RawLen);
}
}
}
return 0;
}
int DeleteConnection(struct BPQConnectionInfo * Con)
@ -1128,6 +1141,7 @@ int AGWDataSocket_Read(struct AGWSocketConnectionInfo * sockptr, SOCKET sock)
int ProcessAGWCommand(struct AGWSocketConnectionInfo * sockptr)
{
int AGWVersion[2]={2003,999};
byte AGWPortCaps[12] = { 0, 255, 30, 10, 63, 10, 4, 0, 1, 0, 0, 0 };
char AGWRegReply[1];
struct BPQConnectionInfo * Connection;
int Stream;
@ -1195,7 +1209,7 @@ int ProcessAGWCommand(struct AGWSocketConnectionInfo * sockptr)
// Need to convert port index (used by AGW) to port number
conport=GetPortNumber(VisiblePortToRealPort[key[0]-48]);
conport=GetPortNumber(VisiblePortToRealPort[key[0]-49] + 1);
n = sprintf(ConnectMsg,"C %d %s",conport,ToCall);
@ -1293,9 +1307,7 @@ int ProcessAGWCommand(struct AGWSocketConnectionInfo * sockptr)
// Version
memset(&AGWTXHeader,0,36);
AGWTXHeader.DataKind = 'R';
AGWTXHeader.DataLength = 8; // Length
SendtoSocket(sockptr->socket, (char *)&AGWVersion[0]);
@ -1309,9 +1321,7 @@ int ProcessAGWCommand(struct AGWSocketConnectionInfo * sockptr)
memset(&AGWTXHeader,0,36);
AGWTXHeader.DataKind = 'G';
AGWTXHeader.DataLength =(int)strlen(AGWPorts)+1; // Length
SendtoSocket(sockptr->socket, AGWPorts);
@ -1319,6 +1329,20 @@ int ProcessAGWCommand(struct AGWSocketConnectionInfo * sockptr)
return 0;
case 'g':
// Port capabilities. Currently hard-coded.
AGWTXHeader.Port = sockptr->AGWRXHeader.Port;
AGWTXHeader.DataKind = 'g';
AGWTXHeader.DataLength = 12;
SendtoSocket(sockptr->socket, (char *)&AGWPortCaps[0]);
return 0;
case 'k':
// Toggle Raw receive
@ -1416,6 +1440,8 @@ int ProcessAGWCommand(struct AGWSocketConnectionInfo * sockptr)
AGWTXHeader.DataKind = 'X';
memcpy(&AGWTXHeader.callfrom, RegCall, 10);
AGWTXHeader.DataLength = 1; // Length
AGWRegReply[0] = 1;

View File

@ -49,9 +49,14 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
#define DM 0x0F
#define UA 0x63
#define FRMR 0x87
#define XID 0xAF
#define TEST 0xE3
#define RR 1
#define RNR 5
#define REJ 9
#define SREJ 0x0D
#define SABME 0x6F
#define PFBIT 0x10 // POLL/FINAL BIT IN CONTROL BYTE
@ -261,6 +266,18 @@ int InternalAGWDecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp, int * Fra
strcpy(SUP, "FRMR");
FRMRFLAG = 1;
break;
case XID:
strcpy(SUP, "XID");
XIDFLAG = 1;
break;
case TEST:
strcpy(SUP, "TEST");
TESTFLAG = 1;
break;
}
Output += sprintf((char *)Output, "<%s%s%s>", SUP, CRCHAR, PFCHAR);
@ -270,7 +287,7 @@ int InternalAGWDecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp, int * Fra
// Super
int NR = (CTL >> 5) & 7;
char SUP[4] = "??";
char SUP[5] = "??";
switch (CTL & 0x0F)
{
@ -288,6 +305,13 @@ int InternalAGWDecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp, int * Fra
strcpy(SUP, "REJ");
break;
case SREJ:
strcpy(SUP, "SREJ");
break;
}
Output += sprintf((char *)Output, "<%s%s%s R%d>", SUP, CRCHAR, PFCHAR, NR);
@ -300,6 +324,72 @@ int InternalAGWDecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp, int * Fra
if (FRMRFLAG)
Output += sprintf((char *)Output, "%02X %02X %02X", ADJBUFFER->PID, ADJBUFFER->L2DATA[0], ADJBUFFER->L2DATA[1]);
if (XIDFLAG)
{
// Decode and display XID
UCHAR * 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
// G8BPQ-2>G8BPQ:(XID cmd, p=1) Half-Duplex SREJ modulo-128 I-Field-Length-Rx=256 Window-Size-Rx=32 Ack-Timer=3000 Retries=10
while (xidlen > 0)
{
Type = *ptr++;
Len = *ptr++;
value = 0;
xidlen -= (Len + 2);
while (Len--)
{
value <<=8;
value += *ptr++;
}
switch(Type)
{
case 2: //Bin fields
case 3:
Output += sprintf((char *)Output, " %d=%x", Type, value);
break;
case 6: //RX Size
Output += sprintf((char *)Output, " RX Paclen=%d", value / 8);
break;
case 8: //RX Window
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;
}
}
}
}
if (Info)
{
// We have an info frame

36
ARDOP.c
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;
}
@ -2059,21 +2061,12 @@ VOID * ARDOPExtInit(EXTPORTDATA * PortEntry)
strcat(TempScript, "ARQTIMEOUT 90\r");
// strcat(TempScript, "ROBUST False\r");
strcat(TempScript, TNC->InitScript);
// Make MYAUX and MYCALL overridable
free(TNC->InitScript);
TNC->InitScript = TempScript;
// Set MYCALL
// strcat(TNC->InitScript,"FECRCV True\r");
// strcat(TNC->InitScript,"AUTOBREAK True\r");
sprintf(Msg, "MYCALL %s\r", TNC->NodeCall);
strcat(TNC->InitScript, Msg);
// strcat(TNC->InitScript,"PROCESSID\r");
// strcat(TNC->InitScript,"CODEC TRUE\r");
// strcat(TNC->InitScript,"LISTEN TRUE\r");
strcat(TempScript, Msg);
for (i = 0; i < 32; i++)
{
@ -2097,9 +2090,25 @@ VOID * ARDOPExtInit(EXTPORTDATA * PortEntry)
if (strlen(Aux) > 8)
{
Aux[strlen(Aux) - 1] = '\r';
strcat(TNC->InitScript, Aux);
strcat(TempScript, Aux);
}
strcat(TempScript, TNC->InitScript);
free(TNC->InitScript);
TNC->InitScript = TempScript;
// strcat(TNC->InitScript,"FECRCV True\r");
// strcat(TNC->InitScript,"AUTOBREAK True\r");
// strcat(TNC->InitScript,"PROCESSID\r");
// strcat(TNC->InitScript,"CODEC TRUE\r");
// strcat(TNC->InitScript,"LISTEN TRUE\r");
strcpy(TNC->CurrentMYC, TNC->NodeCall);
if (TNC->WL2K == NULL)
@ -3141,6 +3150,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

@ -69,6 +69,10 @@ extern BPQVECSTRUC ** BPQHOSTVECPTR;
UCHAR * GetLogDirectory();
DllExport int APIENTRY SessionStateNoAck(int stream, int * state);
int RefreshWebMailIndex();
struct PORTCONTROL * GetPortTableEntryFromSlot(int portslot);
int GetPortHardwareType(struct PORTCONTROL *PORT);
int GetNumberofPorts();
#else
__declspec(dllimport) BPQVECSTRUC ** BPQHOSTVECPTR;
typedef char * (WINAPI FAR *FARPROCZ)();
@ -2085,6 +2089,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 +2184,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 +2224,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 +2271,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 +2335,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 +2349,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 +3426,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 +3438,7 @@ void Flush(CIRCUIT * conn)
}
SendUnbuffered(conn->BPQStream, &conn->OutputQueue[conn->OutputGetPointer], len);
conn->bytesSent += len;
conn->OutputGetPointer+=len;
@ -5216,7 +5256,6 @@ char * CheckToAddress(CIRCUIT * conn, char * Addr)
return NewAddr;
}
}
else
{
WPRecP WP = LookupWP(Addr);
@ -5437,6 +5476,17 @@ BOOL DecodeSendParams(CIRCUIT * conn, char * Context, char ** From, char *To, ch
}
else
{
// See if a WP entry
WP = LookupWP(To);
if (WP)
{
*ATBBS = WP->first_homebbs;
nodeprintf(conn, "Address @%s added from WP\r", *ATBBS);
conn->LocalMsg = FALSE;
}
else
conn->LocalMsg = TRUE;
}
}
@ -9016,6 +9066,10 @@ CheckForSID:
return TRUE;
}
#ifndef LINBPQ
extern FARPROCX pGetPortHardwareType;
#endif
VOID Parse_SID(CIRCUIT * conn, char * SID, int len)
{
ChangeSessionIdletime(conn->BPQStream, BBSIDLETIME); // Default Idletime for BBS Sessions
@ -9072,9 +9126,43 @@ VOID Parse_SID(CIRCUIT * conn, char * SID, int len)
{
// We should really only do this on Telnet Connections, as OpenBCM flag is used to remove relnet transparency
// See if Telnet
struct PORTCONTROL * PORT;
char Call[11] = "";
int port, dummy;
GetConnectionInfo(conn->BPQStream, Call, &port, &dummy, &dummy, &dummy, &dummy);
PORT = GetPortTableEntryFromSlot(0); // Get first entry
do
{
if (PORT->PORTNUMBER == port)
break;
PORT=PORT->PORTPOINTER;
} while (PORT);
#define H_TELNET 6
#ifndef LINBPQ
if (pGetPortHardwareType)
{
if (PORT && GetPortHardwareType(PORT) == H_TELNET)
conn->OpenBCM = TRUE;
}
else
conn->OpenBCM = TRUE; // Old Node version so follow old behavoiur and treat all as telnet
#else
if (PORT && GetPortHardwareType(PORT) == H_TELNET)
conn->OpenBCM = TRUE;
#endif
}
if (_memicmp(SID, "PMS-3.2", 7) == 0)
{
@ -10245,7 +10333,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 +10638,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 +10722,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 +10792,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 +10852,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 +11145,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 +11161,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;

501
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)
{
@ -1115,6 +1341,9 @@ VOID SendRIPToNeighbour(struct ROUTE * Route)
if (Msg == NULL)
Msg = Route->Msg = CreateRIFHeader(Route);
if (Msg == NULL)
return;
Msg->LENGTH += BuildRIF(&Msg->L3SRCE[Msg->LENGTH],
Dest->DEST_CALL, Dest->DEST_ALIAS,
Entry->Hops + 1, Entry->SRTT + Entry->ROUT_NEIGHBOUR->SRTT/10);
@ -1142,8 +1371,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 +1386,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 +1402,7 @@ VOID SendNegativeInfo()
{
Dest++;
Entry = &Dest->ROUTE[0];
Entry = &Dest->INP3ROUTE[0];
if (Entry->SRTT > Entry->LastRTT)
{
@ -1194,15 +1427,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 +1448,7 @@ VOID SendPositiveInfo()
{
int i;
struct DEST_LIST * Dest = DESTS;
struct DEST_ROUTE_ENTRY * Entry;
struct INP3_DEST_ROUTE_ENTRY * Entry;
Dest--;
@ -1221,14 +1458,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 +1475,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 +1489,7 @@ VOID SendNewInfo()
{
Dest->INP3FLAGS &= ~NewNode;
Entry = &Dest->ROUTE[0];
Entry = &Dest->INP3ROUTE[0];
SendRIPToOtherNeighbours(Dest->DEST_CALL, Dest->DEST_ALIAS, Entry);
@ -1368,20 +1605,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,12 @@
// 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)
// Fix using OpenBCM on other than Telnet connections (75)
#include "bpqmail.h"
#include "winstdint.h"
@ -1168,6 +1174,7 @@ FARPROCX pRunEventProgram;
FARPROCX pGetPortFrequency;
FARPROCX pSendWebRequest;
FARPROCX pGetLatLon;
FARPROCX pGetPortHardwareType;
BOOL WINE = FALSE;
@ -1724,6 +1731,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
// SaveUserDatabase();
SaveMessageDatabase();
SaveBIDDatabase();
SaveRestartData();
configSaved = 1;
SaveConfig(ConfigName);
@ -1950,6 +1958,8 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
pGetPortFrequency = GetProcAddress(ExtDriver,"_GetPortFrequency@8");
pSendWebRequest = GetProcAddress(ExtDriver,"_SendWebRequest@16");
pGetLatLon = GetProcAddress(ExtDriver,"_GetLatLon@8");
pGetPortHardwareType = GetProcAddress(ExtDriver,"_GetPortHardwareType@4");
if (pGetLOC)
@ -3020,9 +3030,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 +3093,7 @@ static PSOCKADDR_IN psin;
SOCKET sock;
void GetRestartData();
BOOL Initialise()
{
@ -3270,6 +3281,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;
};

29
Bpq32.c
View File

@ -1255,7 +1255,28 @@ 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)
// Support IPv6 for Telnet outward connects (72)
// Fix decaying NETROM routes (72)
// Add OnlyVer2point0 config command (72)
// Add option to allow AX/UDP on a network using NAT (72)
// Include AGWAPI fixes from Martin KD6YAM to enable use with Paracon terminal (72)
// Fix 64 bit compatiblility issues with AGWAPI (73)
// Fix KAM Pactor Interlock (73)
// Fix Node map reporting, broken in .73 (74)
// Fixes to build on FreeBSD and NetBSD from jg1uaa (77)
// Fix to L4Compress from Stece G7TAJ (77)
#define CKernel
@ -2379,6 +2400,8 @@ FirstInit()
timeLoadedMS = GetTickCount();
srand(time(NULL));
INITIALISEPORTS();
OpenReportingSockets();
@ -6153,7 +6176,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 +6185,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);

View File

@ -590,7 +590,7 @@ VOID SendChatStatusPage(char * Reply, int * ReplyLen, char * Key)
{
if (conn->Flags & CHATLINK)
{
if (conn->BPQStream > 64 || conn->u.link == 0)
if (conn->BPQStream > 64 || conn->u.link == 0 || conn->u.link->alias == 0)
Len += sprintf(&Streams[Len], "<tr><td onclick= SelectRow(%d) id=cell_%d>** Corrupt ChatLink **</td>"
"<td>&nbsp;&nbsp;</td><td>&nbsp;&nbsp;</td><td>&nbsp;&nbsp;</td><td>&nbsp;&nbsp;</td></tr>", i, i);
else
@ -600,7 +600,7 @@ VOID SendChatStatusPage(char * Reply, int * ReplyLen, char * Key)
"", conn->OutputQueueLength - conn->OutputGetPointer);
}
else
if ((conn->Flags & CHATMODE) && conn->topic)
if ((conn->Flags & CHATMODE) && conn->topic && conn->u.user && conn->u.user->call)
{
Len += sprintf(&Streams[Len], "<tr><td onclick='SelectRow(%d)' id='cell_%d'>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%d</td></tr>",
i, i, conn->u.user->name, conn->u.user->call, conn->BPQStream,

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
@ -2129,7 +2142,16 @@ int CanPortDigi(int Port)
return TRUE;
}
struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum)
DllExport int APIENTRY GetPortHardwareType(struct PORTCONTROL *PORT)
{
if (PORT)
return PORT->Hardware;
return 0;
}
DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum)
{
struct PORTCONTROL * PORTVEC = PORTTABLE;

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

@ -100,7 +100,10 @@ TODo ?Multiple Adapters
#ifdef WIN32
int pcap_sendpacket(pcap_t *p, u_char *buf, int size);
#else
PCAP_API int pcap_sendpacket(pcap_t *, const u_char *, int);
#ifndef PCAP_API
#define PCAP_API extern
#endif
PCAP_API int pcap_sendpacket(pcap_t *, const u_char *, int);
#endif
#ifndef LINBPQ
@ -387,7 +390,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 +4975,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
@ -887,15 +916,30 @@ VOID KAMPoll(int Port)
TNC->Streams[0].MyCall[calllen] = 0;
EncodeAndSend(TNC, "X", 1); // ??Return to packet mode??
if (TNC->VeryOldMode)
{
datalen = sprintf(TXMsg, "C20MYCALL %s", TNC->Streams[0].MyCall);
EncodeAndSend(TNC, TXMsg, datalen);
}
else
{
datalen = sprintf(TXMsg, "C20MYPTCALL %s", TNC->Streams[0].MyCall);
EncodeAndSend(TNC, TXMsg, datalen);
if (TNC->OldMode == 0)
{
EncodeAndSend(TNC, TXMsg, datalen);
datalen = sprintf(TXMsg, "C20MYGTCALL %s", TNC->Streams[0].MyCall);
}
}
TNC->InternalCmd = 'M';
TNC->NeedPACTOR = 0; // Cancel enter Pactor
SuspendOtherPorts(TNC);
sprintf(TNC->WEB_TNCSTATE, "In Use by %s", TNC->Streams[0].MyCall);
SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
@ -1036,16 +1080,30 @@ VOID KAMPoll(int Port)
UCHAR TXMsg[80] = "D20";
if (TNC->VeryOldMode)
{
datalen = sprintf(TXMsg, "C20MYCALL %s", TNC->NodeCall);
EncodeAndSend(TNC, TXMsg, datalen);
}
else
{
datalen = sprintf(TXMsg, "C20MYPTCALL %s", TNC->NodeCall);
EncodeAndSend(TNC, TXMsg, datalen);
if (TNC->OldMode == 0)
{
datalen = sprintf(TXMsg, "C20MYGTCALL %s", TNC->NodeCall);
EncodeAndSend(TNC, TXMsg, datalen);
}
}
EncodeAndSend(TNC, TXMsg, datalen);
if (TNC->OldMode)
EncodeAndSend(TNC, "C20PACTOR", 9); // Back to Listen
else
EncodeAndSend(TNC, "C20TOR", 6); // Back to Listen
TNC->InternalCmd = 'T';
TNC->Timeout = 50;
TNC->IntCmdDelay--;
@ -1266,6 +1324,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 +1747,10 @@ VOID ProcessKHOSTPacket(struct TNCINFO * TNC, UCHAR * Msg, int Len)
return;
}
WritetoTrace(TNC, Buffer, Len);
// Pass to Appl
Stream = TNC->CmdStream;
@ -1680,6 +1787,76 @@ VOID ProcessKHOSTPacket(struct TNCINFO * TNC, UCHAR * Msg, int Len)
if (Msg[0] == '?') // Status
{
TNC->Timeout = 0;
/*
The response frame from the TNC will be:
<FEND>?0MSXY<FEND> - where MSXY are coded as follows:
M One byte indicating the current mode of operation.
A=Packet
B=RTTY
C=ASCII
D=AMTOR
E=FEC
F=SELFEC
G=LAMTOR
H=PACTOR
I=PTLISTEN
J=GTOR
K=NAVTEX
L=CW
M=TOR Standby
N=GMON
O=PSK31
S One byte indicating a sub-mode of operation. The byte
contains an ASCII character as follows:
0=Standby
1=Phasing
2=Connected
3=Disconnecting
4=FEC
5=SELFEC
6=PTFEC
X One byte (called status byte X). This byte is bit-
encoded to indicate specific conditions as follows:
Bit 0 = (IDLE) set to 1 when receiving IDLE
characters in a frame.
Bit 1 = (ERR) set to 1 to indicate the received frame
failed CRC check, or was not a valid CS
response frame.
Bit 2 = (Combined receive) set to 1 to indicate that
the data was constructed through the use of
error correction (i.e. Golay error correction
for G-TOR or Memory ARQ for Pactor).
Bit 3 = (RQ) set to 1 to indicate an RQ frame. If you
are the ISS, it indicates that the receiving
station has asked for a repeat of the last
data due to received errors. When you are the
IRS, it indicates that the transmitting
station has sent the same data that you have
already received. This means that the sending
station did not properly copy your
acknowledgement (CS code).
Bit 4 = (Huffman) set to 1 to indicate that this
frame contains data which uses Huffman
compression.
Bit 5 = (ISS) set to 1 to indicate that your station
is currently the ISS.
Bit 6&7 = (Speed) these two bits indicate the current
speed of an ARQ link or the PSK31 mode. The
coding of the bits is:
00 = 100 baud or BPSK31
01 = 200 baud or QPSK31
10 = 300 baud
Y One byte (called status byte Y). This byte is bit-
encoded to indicate specific conditions as follows:
Bit 0 = reserved (set to 0).
Bit 1 = (PTT) PTT is active.
Bit 2 = (Changeover) changeover in progress
Bits 3-7 = reserved (set to 0).
*/
return;
}
@ -1790,6 +1967,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 +2228,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;
}

442
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;
@ -142,6 +154,8 @@ extern BOOL LogAllConnects;
APPLCALLS * APPL;
int SUPPORT2point2 = 1;
void SendL2ToMonMap(struct PORTCONTROL * PORT, char * ReportCall, char Mode, char Direction)
{
@ -842,6 +856,7 @@ VOID ProcessXIDCommand(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESS
while (xidlen > 0)
{
unsigned char * typeptr = ptr;
Type = *ptr++;
Len = *ptr++;
@ -889,6 +904,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 +932,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 +1033,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 +1089,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 +1097,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 +1187,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 +1219,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 +1278,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 +1813,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 +1973,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 +2122,6 @@ VOID SDUFRM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffe
SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION
}
ReleaseBuffer(Buffer);
}
@ -2358,12 +2461,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 +2552,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 +2583,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 +2600,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 +2754,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 +2822,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 +2969,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 +2977,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 +2989,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
@ -2901,7 +3244,7 @@ VOID L2TimerProc()
if (PORT == NULL)
{
LINK++;
continue; // just ion case!!
continue; // just in case!!
}
if (LINK->L2TIMER)
@ -3000,6 +3343,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 +3362,7 @@ VOID L2TimerProc()
InformPartner(LINK, NORMALCLOSE);
}
}
LINK++;
}
}
@ -3311,6 +3666,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 +3703,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 +3737,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 +3948,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.
@ -3636,7 +4005,9 @@ VOID CONNECTREFUSED(struct _LINKTABLE * LINK)
ConnectFailedOrRefused(LINK, "Busy from");
}
VOID L3CONNECTFAILED(struct _LINKTABLE * LINK);
VOID L3LINKSETUPFAILED(struct _LINKTABLE * LINK);
VOID ConnectFailedOrRefused(struct _LINKTABLE * LINK, char * Msg)
{
@ -3651,7 +4022,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 +4549,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,19 +1313,25 @@ VOID REMOVENODE(dest_list * DEST)
NUMBEROFNODES--;
}
VOID L3CONNECTFAILED(struct _LINKTABLE * LINK)
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);
}
TellINP3LinkSetupFailed(ROUTE);
ROUTE->NEIGHBOUR_LINK = 0; // CLEAR IT
@ -1313,9 +1340,10 @@ 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 +1356,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)
{

124
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,23 +781,22 @@ 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
// Fragment if more than L4CompPaclen
// Entered with original first fragment in saveMsg;
// Check for too big a compressed frame size. Bigger compresses better but adds latency to link
maxCompSendLen = L4CompPaclen * L4CompMaxframe;
@ -762,8 +808,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 +817,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 +825,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, Len);
Debugprintf("Chunked %d %d %d%%", Len, complen, ((Len - complen) * 100) / Len);
sendChunk(L4, Compressed, complen, savePort);
@ -793,10 +839,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 +851,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 +981,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
@ -902,7 +913,10 @@ int main(int argc, char * argv[])
Debugprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring);
#ifndef MACBPQ
#if defined(MACBPQ) || defined(FREEBSD)
time_t dummy;
_MYTIMEZONE = -localtime(&dummy)->tm_gmtoff;
#else
_MYTIMEZONE = _timezone;
#endif
@ -1174,6 +1188,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 +1211,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 +1459,7 @@ int main(int argc, char * argv[])
SaveMessageDatabase();
SaveBIDDatabase();
SaveConfig(ConfigName);
SaveRestartData();
}
KEEPGOING--; // Give time for links to close

View File

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

@ -241,8 +241,14 @@ typedef struct _SERIAL_STATUS {
#ifndef WIN32
#ifdef MACBPQ
#if defined(MACBPQ)
#include <util.h>
#elif defined(FREEBSD)
#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <libutil.h>
#else
#include <util.h>
#endif
#endif
extern int posix_openpt (int __oflag);
@ -262,7 +268,7 @@ HANDLE LinuxOpenPTY(char * Name)
u_long param=1;
struct termios term;
#ifdef MACBPQ
#if defined(MACBPQ) || defined(FREEBSD)
// Create a pty pair

View File

@ -1498,6 +1498,8 @@ void * TelnetExtInit(EXTPORTDATA * PortEntry)
PortEntry->PORTCONTROL.TNC = TNC;
PortEntry->PORTCONTROL.Hardware = TNC->Hardware;
TNC->WebWindowProc = WebProc;
TNC->WebWinX = 260;
TNC->WebWinY = 325;
@ -6342,26 +6344,80 @@ int TCPConnect(struct TNCINFO * TNC, struct TCPINFO * TCP, struct STREAMINFO * S
struct ConnectionInfo * sockptr;
SOCKET sock;
struct sockaddr_in sinx;
struct sockaddr_in destaddr;
int addrlen=sizeof(sinx);
int i;
char PortString[20];
struct addrinfo hints, *res = 0, *saveres;
sprintf(PortString, "%d", Port);
// get host info, make socket, and connect it
memset(&hints, 0, sizeof hints);
if (TCP->IPV6 == 0 && TCP->IPV4)
hints.ai_family = AF_INET;
else if (TCP->IPV4 == 0 && TCP->IPV6)
hints.ai_family = AF_INET6;
else if (TCP->IPV4 && TCP->IPV6)
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
else
{
ReportError(STREAM, "Neither IPv4 nor IPv5 are enabled");
return FALSE; // Resolve failed
}
hints.ai_socktype = SOCK_STREAM;
getaddrinfo(Host, PortString, &hints, &res);
if (!res)
{
char Msg[256];
err = WSAGetLastError();
sprintf(Msg, "Resolve HostName Failed - Error %d", err);
ReportError(STREAM, Msg);
return FALSE; // Resolve failed
}
// Step thorough the list of hosts
saveres = res; // Save for free
/* if (res->ai_next) // More than one
{
int n = ISHostIndex;
while (n && res->ai_next)
{
res = res->ai_next;
n--;
}
if (n)
{
// We have run off the end of the list
ISHostIndex = 0; // Back to start
res = saveres;
}
else
ISHostIndex++;
}
*/
// getnameinfo(res->ai_addr, (int)res->ai_addrlen, RealISHost, 256, serv, 256, 0);
sockptr = STREAM->ConnectionInfo;
sock = sockptr->socket = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
ReportError(STREAM, "Create Socket Failed");
return FALSE;
}
sock = sockptr->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
sockptr->SocketActive = TRUE;
sockptr->InputLen = 0;
sockptr->LoginState = 2;
sockptr->UserPointer = 0;
sockptr->DoEcho = FALSE;
sockptr->FBBMode = FBB; // Raw Data
if (sockptr->ADIF == NULL)
@ -6370,49 +6426,19 @@ int TCPConnect(struct TNCINFO * TNC, struct TCPINFO * TCP, struct STREAMINFO * S
memset(sockptr->ADIF, 0, sizeof(struct ADIF));
// Resolve Name if needed
sockptr->sin.sin_family = AF_INET;
sockptr->sin.sin_port = htons(Port);
sockptr->sin.sin_addr.s_addr = inet_addr(Host);
if (sockptr->sin.sin_addr.s_addr == INADDR_NONE)
if (sock == INVALID_SOCKET)
{
struct hostent * HostEnt;
// Resolve name to address
HostEnt = gethostbyname(Host);
if (!HostEnt)
{
ReportError(STREAM, "Resolve HostName Failed");
return FALSE; // Resolve failed
}
i = 0;
while (HostEnt->h_addr_list[i] != 0)
{
struct in_addr addr;
addr.s_addr = *(u_long *) HostEnt->h_addr_list[i++];
}
memcpy(&sockptr->sin.sin_addr.s_addr, HostEnt->h_addr, 4);
}
ioctl (sockptr->socket, FIONBIO, &param);
setsockopt (sockptr->socket, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4);
sinx.sin_family = AF_INET;
sinx.sin_addr.s_addr = INADDR_ANY;
sinx.sin_port = 0;
if (bind(sockptr->socket, (struct sockaddr *) &sinx, addrlen) != 0 )
{
ReportError(STREAM, "Bind Failed");
ReportError(STREAM, "Create Socket Failed");
return FALSE;
}
ioctl (sock, FIONBIO, &param);
setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4);
// memcpy(work, res->ai_addr->sa_data, 4);
if (LogEnabled)
{
char logmsg[512];
@ -6421,21 +6447,21 @@ int TCPConnect(struct TNCINFO * TNC, struct TCPINFO * TCP, struct STREAMINFO * S
WriteLog (logmsg);
}
if (connect(sockptr->socket,(struct sockaddr *) &sockptr->sin, sizeof(destaddr)) == 0)
if (connect(sock, res->ai_addr, (int)res->ai_addrlen) == 0)
{
//
// Connected successful
//
ReportError(STREAM, "*** Connected");
// Get Send Buffer Size
freeaddrinfo(saveres);
return TRUE;
}
else
{
freeaddrinfo(saveres);
err=WSAGetLastError();
if (err == 10035 || err == 115 || err == 36) //EWOULDBLOCK
@ -6461,7 +6487,6 @@ int TCPConnect(struct TNCINFO * TNC, struct TCPINFO * TCP, struct STREAMINFO * S
}
return FALSE;
}

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,77
#define KVerstring "6.0.24.77\0"
#ifdef CKernel
#define Vers KVers
#define Verstring KVerstring
#define Datestring "February 2025"
#define Datestring "July 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()

223
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;
}
@ -2731,6 +2822,18 @@ VOID SaveNewMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, char * R
strcpy(Msg->via, ToUser->HomeBBS);
sprintf(Prompt, "%s added from HomeBBS. Message Saved", Msg->via);
}
else
{
// No HomeBBS - check WP
WPRecP WP = LookupWP(Msg->to);
if (WP)
{
strcpy(Msg->via, WP->first_homebbs);
sprintf(Prompt, "%s added from WP", Msg->via);
}
}
}
else
{
@ -2883,7 +2986,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 +3000,7 @@ char * GetHTMLViewerTemplate(char * FN)
{
if (strcmp(FN, Dir->Forms[j]->FileName) == 0)
{
*FormDir = Dir;
return CheckFile(Dir, FN);
}
}
@ -2917,6 +3021,7 @@ char * GetHTMLViewerTemplate(char * FN)
{
if (_stricmp(FN, SDir->Forms[k]->FileName) == 0)
{
*FormDir = SDir;
return CheckFile(SDir, SDir->Forms[k]->FileName);
}
}
@ -2980,6 +3085,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 +3405,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 +3515,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 +3530,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 +3550,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 +3698,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 +3730,8 @@ int DisplayWebForm(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, ch
break;
}
KeyValue++;
if (KeyValue->Key == NULL)
{
// Not found in XML
@ -3588,7 +3741,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;
@ -4098,6 +4251,18 @@ VOID SaveTemplateMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, cha
strcpy(Msg->via, ToUser->HomeBBS);
sprintf(Prompt, "%s added from HomeBBS. Message Saved", Msg->via);
}
else
{
// No HomeBBS - Check WP
WPRecP WP = LookupWP(Msg->to);
if (WP)
{
strcpy(Msg->via, WP->first_homebbs);
sprintf(Prompt, "%s added from WP", Msg->via);
}
}
}
else
{
@ -4318,6 +4483,18 @@ VOID BuildMessageFromHTMLInput(struct HTTPConnectionInfo * Session, char * Reply
strcpy(Msg->via, ToUser->HomeBBS);
sprintf(Prompt, "%s added from HomeBBS", Msg->via);
}
else
{
// No HomeBBS - Check WP
WPRecP WP = LookupWP(Msg->to);
if (WP)
{
strcpy(Msg->via, WP->first_homebbs);
sprintf(Prompt, "%s added from WP", Msg->via);
}
}
}
else
{
@ -5448,8 +5625,6 @@ char * CheckFile(struct HtmlFormDir * Dir, char * FN)
#endif
printf("%s\n", MsgFile);
if (stat(MsgFile, &STAT) != -1)
{
hFile = fopen(MsgFile, "rb");
@ -5466,8 +5641,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;
@ -725,6 +727,9 @@ typedef struct PORTCONTROL
UCHAR * TX; // % Sending
UCHAR * BUSY; // % Active (Normally DCD active or TX)
int Hardware; // TNC H_TYPE. Copied here for access from application context
} PORTCONTROLX, *PPORTCONTROL;
typedef struct FULLPORTDATA
@ -959,6 +964,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)
@ -1067,7 +1087,11 @@ struct SEM
int Gets;
int Rels;
DWORD SemProcessID;
#ifdef WIN32
DWORD SemThreadID;
#else
pthread_t SemThreadID;
#endif
int Line; // caller file and line
char File[MAX_PATH];
};
@ -1354,6 +1378,8 @@ struct arp_table_entry
// SOCKET SourceSocket;
struct AXIPPORTINFO * PORT;
BOOL noUpdate; // Don't update dest address from incoming packet
BOOL replytoSourcePort; // Update map entry dest port from source port of each packet.
time_t LastHeard; // Last Packet received from this ststiom
};

View File

@ -22,6 +22,8 @@ count on BPQ32.dll gets messed up, and the code will not unload cleanly.
struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portslot);
struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot);
int APIENTRY GetPortHardwareType(struct PORTCONTROL *PORT);
// Returns number of free buffers
// (BPQHOST function 7 (part)).

View File

@ -204,7 +204,7 @@ int Update_MH_KeepAlive(struct AXIPPORTINFO * PORT, struct in_addr ipad, char pr
unsigned short int compute_crc(unsigned char *buf,int l);
unsigned int find_arp(unsigned char * call);
BOOL add_arp_entry(struct AXIPPORTINFO * PORT, unsigned char * call, UCHAR * ip, int len, int port,unsigned char * name,
int keepalive, BOOL BCFlag, BOOL AutoAdded, int TCPMode, int SourcePort, BOOL IPv6, int noUpdate);
int keepalive, BOOL BCFlag, BOOL AutoAdded, int TCPMode, int SourcePort, BOOL IPv6, int noUpdate, int useSourcePort);
BOOL add_bc_entry(struct AXIPPORTINFO * PORT, unsigned char * call, int len);
BOOL convtoax25(unsigned char * callsign, unsigned char * ax25call, int * calllen);
static BOOL ReadConfigFile(int Port);
@ -213,7 +213,7 @@ int CheckKeepalives(struct AXIPPORTINFO * PORT);
BOOL CopyScreentoBuffer(char * buff, struct AXIPPORTINFO * PORT);
int DumpFrameInHex(unsigned char * msg, int len);
VOID SendFrame(struct AXIPPORTINFO * PORT, struct arp_table_entry * arp_table, UCHAR * buff, int txlen);
BOOL CheckSourceisResolvable(struct AXIPPORTINFO * PORT, char * call, int Port, VOID * rxaddr);
BOOL CheckSourceisResolvable(struct AXIPPORTINFO * PORT, char * call, int FromPort, VOID * rxaddr, int ToPort);
int DataSocket_Read(struct arp_table_entry * sockptr, SOCKET sock);
int GetMessageFromBuffer(struct AXIPPORTINFO * PORT, char * Buffer);
int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len);
@ -429,7 +429,7 @@ static size_t ExtProc(int fn, int port, PMESSAGE buff)
if (PORT->Checkifcanreply)
{
if (CheckSourceisResolvable(PORT, call, 0, &RXaddr))
if (CheckSourceisResolvable(PORT, call, 0, &RXaddr, 0))
return 1;
@ -437,7 +437,7 @@ static size_t ExtProc(int fn, int port, PMESSAGE buff)
// Can't reply. If AutoConfig is set, add to table and accept, else reject
if (PORT->AutoAddARP)
return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, 7, 0, inet_ntoa(RXaddr.rxaddr.sin_addr), 0, PORT->AutoAddBC, TRUE, 0, 0, FALSE, 0);
return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, 7, 0, inet_ntoa(RXaddr.rxaddr.sin_addr), 0, PORT->AutoAddBC, TRUE, 0, 0, FALSE, 0, 0);
else
{
char From[11] = "|";
@ -536,7 +536,7 @@ static size_t ExtProc(int fn, int port, PMESSAGE buff)
if (PORT->Checkifcanreply)
{
if (CheckSourceisResolvable(PORT, call, htons(RXaddr.rxaddr.sin_port), &RXaddr))
if (CheckSourceisResolvable(PORT, call, htons(RXaddr.rxaddr.sin_port), &RXaddr, PORT->udpport[i]))
return 1;
else
{
@ -547,10 +547,10 @@ static size_t ExtProc(int fn, int port, PMESSAGE buff)
{
char Addr[80];
Format_Addr((UCHAR *)&RXaddr.rxaddr6.sin6_addr, Addr, TRUE);
return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr6.sin6_addr, 7, htons(RXaddr.rxaddr6.sin6_port), Addr, 0, PORT->AutoAddBC, TRUE, 0, PORT->udpport[i], TRUE, 0);
return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr6.sin6_addr, 7, htons(RXaddr.rxaddr6.sin6_port), Addr, 0, PORT->AutoAddBC, TRUE, 0, PORT->udpport[i], TRUE, 0, 0);
}
else
return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, 7, htons(RXaddr.rxaddr.sin_port), inet_ntoa(RXaddr.rxaddr.sin_addr), 0, PORT->AutoAddBC, TRUE, 0, PORT->udpport[i], FALSE, 0);
return add_arp_entry(PORT, call, (UCHAR *)&RXaddr.rxaddr.sin_addr.s_addr, 7, htons(RXaddr.rxaddr.sin_port), inet_ntoa(RXaddr.rxaddr.sin_addr), 0, PORT->AutoAddBC, TRUE, 0, PORT->udpport[i], FALSE, 0, 0);
else
{
char From[11] = "|";
@ -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
@ -1343,6 +1343,7 @@ LRESULT FAR PASCAL ConfigWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lPa
char axcall[7];
BOOL UDPFlag, BCFlag;
struct AXIPPORTINFO * PORT;
int useSourcePort = 0;
for (i=1; i <= MAXBPQPORTS; i++)
{
@ -1391,7 +1392,7 @@ LRESULT FAR PASCAL ConfigWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lPa
{
if (convtoax25(call,axcall,&calllen))
{
add_arp_entry(PORT, axcall,0,calllen,port,host,Interval, BCFlag, FALSE, 0, port, FALSE, 0);
add_arp_entry(PORT, axcall,0,calllen,port,host,Interval, BCFlag, FALSE, 0, port, FALSE, 0, useSourcePort);
ResolveDelay = 2;
return(DestroyWindow(hWnd));
}
@ -2147,6 +2148,7 @@ static int ProcessLine(char * buf, struct AXIPPORTINFO * PORT)
int Interval;
int noUpdate=FALSE;
int TCPMode;
int useSourcePort = 0;
ptr = strtok(buf, " \t\n\r");
@ -2234,6 +2236,7 @@ static int ProcessLine(char * buf, struct AXIPPORTINFO * PORT)
bcflag=0;
TCPMode=0;
SourcePort = 0;
useSourcePort = 0;
//
// Look for (optional) KEEPALIVE, DYNAMIC, UDP or BROADCAST params
@ -2264,7 +2267,14 @@ static int ProcessLine(char * buf, struct AXIPPORTINFO * PORT)
if (p_udpport == NULL) return (FALSE);
if (_stricmp(p_udpport,"FROMPORT") == 0)
{
useSourcePort = TRUE;
port = 0;
}
else
port = atoi(p_udpport);
p_UDP = strtok(NULL, " \t\n\r");
continue;
}
@ -2327,7 +2337,7 @@ static int ProcessLine(char * buf, struct AXIPPORTINFO * PORT)
if (SourcePort == 0)
SourcePort = port;
add_arp_entry(PORT, axcall, 0, calllen, port, p_ipad, Interval, bcflag, FALSE, TCPMode, SourcePort, FALSE, noUpdate);
add_arp_entry(PORT, axcall, 0, calllen, port, p_ipad, Interval, bcflag, FALSE, TCPMode, SourcePort, FALSE, noUpdate, useSourcePort);
return (TRUE);
}
} // End of Process MAP
@ -2438,7 +2448,7 @@ BOOL convtoax25(unsigned char * callsign, unsigned char * ax25call,int * calllen
}
BOOL add_arp_entry(struct AXIPPORTINFO * PORT, UCHAR * call, UCHAR * ip, int len, int port,
UCHAR * name, int keepalive, BOOL BCFlag, BOOL AutoAdded, int TCPFlag, int SourcePort, BOOL IPv6, int noUpdate)
UCHAR * name, int keepalive, BOOL BCFlag, BOOL AutoAdded, int TCPFlag, int SourcePort, BOOL IPv6, int noUpdate, int useSourcePort)
{
struct arp_table_entry * arp;
@ -2457,7 +2467,8 @@ BOOL add_arp_entry(struct AXIPPORTINFO * PORT, UCHAR * call, UCHAR * ip, int len
arp->PORT = PORT;
if (port == 0) PORT->needip = 1; // Enable Raw IP Mode
if (port == 0 && arp->replytoSourcePort == 0)
PORT->needip = 1; // Enable Raw IP Mode
arp->ResolveFlag=TRUE;
PORT->NeedResolver=TRUE;
@ -2476,6 +2487,7 @@ BOOL add_arp_entry(struct AXIPPORTINFO * PORT, UCHAR * call, UCHAR * ip, int len
arp->TCPMode = TCPFlag;
arp->noUpdate = noUpdate;
PORT->arp_table_len++;
arp->replytoSourcePort = useSourcePort;
if (PORT->MaxResWindowlength < (PORT->arp_table_len * 14) + 70)
PORT->MaxResWindowlength = (PORT->arp_table_len * 14) + 70;
@ -2576,7 +2588,7 @@ int CheckKeepalives(struct AXIPPORTINFO * PORT)
return (0);
}
BOOL CheckSourceisResolvable(struct AXIPPORTINFO * PORT, char * call, int Port, VOID * rxaddr)
BOOL CheckSourceisResolvable(struct AXIPPORTINFO * PORT, char * call, int FromPort, VOID * rxaddr, int ToPort)
{
// Makes sure we can reply to call before accepting message
@ -2606,10 +2618,17 @@ BOOL CheckSourceisResolvable(struct AXIPPORTINFO * PORT, char * call, int Port,
struct sockaddr_in * SA = rxaddr;
memcpy(&arp->destaddr.sin_addr.s_addr, &SA->sin_addr, 4);
}
// Dont think I should update port
// Dont think I should update port unless using source port for dest
//arp->port = Port;
if (arp->replytoSourcePort)
{
arp->port = FromPort;
arp->destaddr.sin_port = htons(arp->port);
if (arp->SourcePort == 0)
arp->SourcePort = ToPort;
}
}
arp->LastHeard = time(NULL);
return 1; // Ok to process
}
index++;

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();

36
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,23 @@ 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;
if (cfg->C_OnlyVer2point0)
SUPPORT2point2 = 0;
// Get pointers to PASSWORD and APPL1 commands
// int APPL1 = 0;
@ -962,6 +987,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 +1012,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 +1472,8 @@ BOOL Start()
ENDBUFFERPOOL = NEXTFREEDATA;
PoolBuilt = 1;
// Copy Bridge Map
@ -1560,6 +1591,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 +1604,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

@ -105,7 +105,7 @@ VOID CLOSECURRENTSESSION(TRANSPORTENTRY * Session);
VOID SendCommandReply(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer, int Len);
struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum);
DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum);
int cCOUNT_AT_L2(struct _LINKTABLE * LINK);
VOID SENDL4CONNECT(TRANSPORTENTRY * Session);
@ -202,8 +202,6 @@ int TrytoGuessCode(unsigned char * Char, int Len);
#define XID 0xAF
#define TEST 0xE3
#define SUPPORT2point2 1
// XID Optional Functions
#define OPMustHave 0x02A080 // Sync TEST 16 bit FCS Extended Address
@ -438,6 +436,9 @@ extern int MQTT_PORT;
extern char MQTT_USER[80];
extern char MQTT_PASS[80];
extern int SUPPORT2point2;
DllExport uint64_t APIENTRY GetPortFrequency(int PortNo, char * FreqStringMhz);

View File

@ -308,7 +308,8 @@ 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", "OnlyVer2point0"
}; /* parameter keywords */
static void * offset[] =
@ -330,7 +331,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, &xxcfg.C_OnlyVer2point0}; /* offset for corresponding data in config file */
static int routine[] =
{
@ -351,6 +353,7 @@ static int routine[] =
15, 0, 2, 9, 9,
2, 2, 1, 2, 2, 2,
2, 2, 0, 1, 20, 20,
1, 1, 1, 1, 1,
1, 1, 1} ; // Routine to process param
int PARAMLIM = sizeof(routine)/sizeof(int);
@ -373,7 +376,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 +390,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 +404,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 +538,8 @@ BOOL ProcessConfig()
// xxcfg.SaveMH = TRUE; // Default to save
xxcfg.C_PREFERINP3ROUTES = 0; // Default to false
GetNextLine(rec);
while (rec[0])
@ -621,7 +626,11 @@ 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
paramok[93]=1; // C_ONLYVer2point0
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,11 @@ struct CONFIGTABLE
int C_L4Compress;
int C_L4CompMaxframe;
int C_L4CompPaclen;
int C_L2Compress;
int C_L2CompMaxframe;
int C_L2CompPaclen;
int C_PREFERINP3ROUTES;
int C_OnlyVer2point0;
//#define ApplOffset 80000 // Applications offset in config buffer

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

@ -22,17 +22,29 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
// Normally uses a Raw socket, but that can't send to other apps on same machine.
// so can use a TAP device instead (or maybe as well??)
// Not suported on BSD based systems
#ifndef FREEBSD
#ifndef MACBPQ
#if !(defined(MACBPQ) || defined(FREEBSD))
#include <stdio.h>
#include "cheaders.h"
#include <sys/socket.h>
#if !(defined(FREEBSD))
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#endif
#endif
extern int tap_fd;
typedef struct PCAPStruct
@ -490,4 +502,10 @@ static int ProcessLine(char * buf, int Port, BOOL CheckPort)
}
#endif
//
#endif // MACBPQ
#endif // FREEBSD

View File

@ -1406,7 +1406,7 @@ File: 5566 NEWBOAT.HOMEPORT.JPG
if (SendBBStoSYSOPCall)
if (_stricmp(FullTo, BBSName) == 0)
strcpy(Msg->to, SYSOPCall);
strcpy(FullTo, SYSOPCall);
if ((Msg->via[0] == 0 || strcmp(Msg->via, "BPQ") == 0 || strcmp(Msg->via, "BBS") == 0)
&& (conn->Paclink || conn->RMSExpress))

View File

@ -17,22 +17,44 @@ OBJS = pngwtran.o pngrtran.o pngset.o pngrio.o pngwio.o pngtrans.o pngrutil.o pn
# Configuration:
CC = gcc
#Default to Linux
CC = gcc
EXTRA_LDFLAGS = -Xlinker -Map=output.map -lrt -l:libpaho-mqtt3a.a -l:libjansson.a
all: CFLAGS = -DLINBPQ -MMD -g -rdynamic -fcommon
all: LDFLAGS = -l:libpaho-mqtt3a.a -l:libjansson.a
#other OS
OS_NAME = $(shell uname -s)
ifeq ($(OS_NAME),NetBSD)
CC = cc
EXTRA_CFLAGS = -DFREEBSD -DNOMQTT -I/usr/pkg/include
EXTRA_LDFLAGS = -Xlinker -Map=output.map -Wl,-R/usr/pkg/lib -L/usr/pkg/lib -lrt -lutil -lexecinfo
endif
ifeq ($(OS_NAME),FreeBSD)
CC = cc
EXTRA_CFLAGS = -DFREEBSD -DNOMQTT -I/usr/local/include
EXTRA_LDFLAGS = -Xlinker -Map=output.map -L/usr/local/lib -lrt -liconv -lutil -lexecinfo
endif
ifeq ($(OS_NAME),Darwin)
CC = gcc
EXTRA_CFLAGS = -DMACBPQ -DNOMQTT
EXTRA_LDFLAGS = -liconv
endif
$(info OS_NAME is $(OS_NAME))
all: CFLAGS = -DLINBPQ -MMD -g -fcommon -fasynchronous-unwind-tables $(EXTRA_CFLAGS)
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
linbpq: $(OBJS)
gcc $(OBJS) -Xlinker -Map=output.map -l:libminiupnpc.a -lrt -lm -lz $(LDFLAGS) -lpthread -lconfig -lpcap -o linbpq
cc $(OBJS) $(EXTRA_LDFLAGS) -lminiupnpc -lm -lz $(LDFLAGS) -lpthread -lconfig -lpcap -o linbpq
sudo setcap "CAP_NET_ADMIN=ep CAP_NET_RAW=ep CAP_NET_BIND_SERVICE=ep" linbpq
-include *.d

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;'>"

18
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,15 +123,18 @@ 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");
return 0;
}
#if MINIUPNPC_API_VERSION == 18
#if MINIUPNPC_API_VERSION >= 18
i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr));
#else
i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
@ -150,15 +157,18 @@ 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");
return 0;
}
#if MINIUPNPC_API_VERSION == 18
#if MINIUPNPC_API_VERSION >= 18
i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr));
#else
i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));