400 lines
8.3 KiB
C
400 lines
8.3 KiB
C
/*
|
|
Copyright 2001-2022 John Wiseman G8BPQ
|
|
|
|
This file is part of LinBPQ/BPQ32.
|
|
|
|
LinBPQ/BPQ32 is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
LinBPQ/BPQ32 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
|
|
*/
|
|
|
|
//
|
|
// C replacement for TNCCode.asm
|
|
//
|
|
#define Kernel
|
|
|
|
#define _CRT_SECURE_NO_DEPRECATE
|
|
|
|
#pragma data_seg("_BPQDATA")
|
|
|
|
#include "time.h"
|
|
#include "stdio.h"
|
|
#include <fcntl.h>
|
|
|
|
#include "CHeaders.h"
|
|
#include "tncinfo.h"
|
|
|
|
int C_Q_COUNT(VOID *PQ);
|
|
VOID SENDUIMESSAGE(struct DATAMESSAGE * Msg);
|
|
|
|
VOID TNCTimerProc()
|
|
{
|
|
// CALLED AT 10 HZ
|
|
|
|
int n = BPQHOSTSTREAMS;
|
|
PBPQVECSTRUC HOSTSESS = BPQHOSTVECTOR;
|
|
TRANSPORTENTRY * Session;
|
|
UCHAR DISCFLAG = 0;
|
|
|
|
while (n--)
|
|
{
|
|
// Action any DISC Requests (must be done in timer owning process)
|
|
|
|
if (HOSTSESS->HOSTFLAGS & 0x40) // DISC REQUEST
|
|
{
|
|
if (HOSTSESS->HOSTFLAGS & 0x20) // Stay?
|
|
DISCFLAG = 'S';
|
|
|
|
HOSTSESS->HOSTFLAGS &= 0x9F; // Clear Flags
|
|
|
|
Session = HOSTSESS->HOSTSESSION;
|
|
|
|
if (Session == 0) // Gone??
|
|
{
|
|
HOSTSESS->HOSTFLAGS |= 3; // STATE CHANGE
|
|
#ifndef LINBPQ
|
|
if (HOSTSESS->HOSTHANDLE);
|
|
{
|
|
PostMessage(HOSTSESS->HOSTHANDLE, BPQMsg, HOSTSESS->HOSTSTREAM, 4);
|
|
}
|
|
#endif
|
|
continue;
|
|
}
|
|
|
|
if (Session->L4CROSSLINK)
|
|
Session->L4CROSSLINK->STAYFLAG = DISCFLAG;
|
|
|
|
HOSTSESS->HOSTSESSION = 0;
|
|
HOSTSESS->HOSTFLAGS |= 3; // STATE CHANGE
|
|
|
|
PostStateChange(Session);
|
|
|
|
CloseSessionPartner(Session); // SEND CLOSE TO PARTNER (IF PRESENT)
|
|
}
|
|
|
|
// Check Trace Q
|
|
|
|
if (HOSTSESS->HOSTAPPLFLAGS & 0x80)
|
|
{
|
|
if (HOSTSESS->HOSTTRACEQ)
|
|
{
|
|
int Count = C_Q_COUNT(&HOSTSESS->HOSTTRACEQ);
|
|
|
|
if (Count > 100)
|
|
ReleaseBuffer((void *)Q_REM((void *)&HOSTSESS->HOSTTRACEQ));
|
|
}
|
|
}
|
|
HOSTSESS++;
|
|
}
|
|
}
|
|
|
|
VOID SendSmartID(struct PORTCONTROL * PORT)
|
|
{
|
|
struct _MESSAGE * ID = IDMSG;
|
|
struct _MESSAGE * Buffer;
|
|
|
|
PORT->SmartIDNeeded = 0;
|
|
|
|
Buffer = GetBuff();
|
|
|
|
if (Buffer)
|
|
{
|
|
memcpy(Buffer, ID, ID->LENGTH);
|
|
|
|
Buffer->PORT = PORT->PORTNUMBER;
|
|
|
|
// IF PORT HAS A CALLSIGN DEFINED, SEND THAT INSTEAD
|
|
|
|
if (PORT->PORTCALL[0] > 0x40)
|
|
{
|
|
memcpy(Buffer->ORIGIN, PORT->PORTCALL, 7);
|
|
Buffer->ORIGIN[6] |= 1; // SET END OF CALL BIT
|
|
}
|
|
|
|
// If Pactor Style add to UI_Q
|
|
|
|
if (PORT->PROTOCOL == 10 && PORT->TNC && PORT->TNC->Hardware != H_KISSHF && PORT->UICAPABLE)
|
|
{
|
|
EXTPORTDATA * EXTPORT = (EXTPORTDATA *) PORT;
|
|
|
|
C_Q_ADD(&EXTPORT->UI_Q, Buffer);
|
|
return;
|
|
}
|
|
|
|
PUT_ON_PORT_Q(PORT, Buffer);
|
|
}
|
|
}
|
|
|
|
|
|
VOID SENDIDMSG()
|
|
{
|
|
struct PORTCONTROL * PORT = PORTTABLE;
|
|
struct _MESSAGE * ID = IDMSG;
|
|
struct _MESSAGE * Buffer;
|
|
|
|
while (PORT)
|
|
{
|
|
if (PORT->PROTOCOL < 10) // Not Pactor-style
|
|
{
|
|
Buffer = GetBuff();
|
|
|
|
if (Buffer)
|
|
{
|
|
memcpy(Buffer, ID, ID->LENGTH);
|
|
|
|
Buffer->PORT = PORT->PORTNUMBER;
|
|
|
|
// IF PORT HAS A CALLSIGN DEFINED, SEND THAT INSTEAD
|
|
|
|
if (PORT->PORTCALL[0] > 0x40)
|
|
{
|
|
memcpy(Buffer->ORIGIN, PORT->PORTCALL, 7);
|
|
Buffer->ORIGIN[6] |= 1; // SET END OF CALL BIT
|
|
}
|
|
C_Q_ADD(&IDMSG_Q, Buffer);
|
|
}
|
|
}
|
|
PORT = PORT->PORTPOINTER;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID SENDBTMSG()
|
|
{
|
|
struct PORTCONTROL * PORT = PORTTABLE;
|
|
struct _MESSAGE * Buffer;
|
|
char * ptr1, * ptr2;
|
|
|
|
while (PORT)
|
|
{
|
|
if (PORT->PROTOCOL >= 10 || PORT->PORTUNPROTO == 0) // Pactor-style or no UNPROTO ADDR?
|
|
{
|
|
PORT = PORT->PORTPOINTER;
|
|
continue;
|
|
}
|
|
|
|
Buffer = GetBuff();
|
|
|
|
if (Buffer)
|
|
{
|
|
memcpy(Buffer->DEST, PORT->PORTUNPROTO, 7);
|
|
Buffer->DEST[6] |= 0xC0; // Set Command bits
|
|
|
|
// Send from BBSCALL unless PORTBCALL defined
|
|
|
|
if (PORT->PORTBCALL[0] > 32)
|
|
memcpy(Buffer->ORIGIN, PORT->PORTBCALL, 7);
|
|
else if (APPLCALLTABLE->APPLCALL[0] > 32)
|
|
memcpy(Buffer->ORIGIN, APPLCALLTABLE->APPLCALL, 7);
|
|
else
|
|
memcpy(Buffer->ORIGIN, MYCALL, 7);
|
|
|
|
ptr1 = &PORT->PORTUNPROTO[7]; // First Digi
|
|
ptr2 = &Buffer->CTL; // Digi field in buffer
|
|
|
|
// Copy any digis
|
|
|
|
while (*(ptr1))
|
|
{
|
|
memcpy(ptr2, ptr1, 7);
|
|
ptr1 += 7;
|
|
ptr2 += 7;
|
|
}
|
|
|
|
*(ptr2 - 1) |= 1; // Set End of Address
|
|
*(ptr2++) = UI;
|
|
|
|
memcpy(ptr2, &BTHDDR.PID, BTHDDR.LENGTH);
|
|
ptr2 += BTHDDR.LENGTH;
|
|
Buffer->LENGTH = (int)(ptr2 - (char *)Buffer);
|
|
Buffer->PORT = PORT->PORTNUMBER;
|
|
|
|
C_Q_ADD(&IDMSG_Q, Buffer);
|
|
}
|
|
PORT = PORT->PORTPOINTER;
|
|
}
|
|
}
|
|
|
|
VOID SENDUIMESSAGE(struct DATAMESSAGE * Msg)
|
|
{
|
|
struct PORTCONTROL * PORT = PORTTABLE;
|
|
struct _MESSAGE * Buffer;
|
|
char * ptr1, * ptr2;
|
|
|
|
Msg->LENGTH -= MSGHDDRLEN; // Remove Header
|
|
|
|
while (PORT)
|
|
{
|
|
if ((PORT->PROTOCOL == 10 && PORT->UICAPABLE == 0) || PORT->PORTUNPROTO == 0) // Pactor-style or no UNPROTO ADDR?
|
|
{
|
|
PORT = PORT->PORTPOINTER;
|
|
continue;
|
|
}
|
|
|
|
Buffer = GetBuff();
|
|
|
|
if (Buffer)
|
|
{
|
|
memcpy(Buffer->DEST, PORT->PORTUNPROTO, 7);
|
|
Buffer->DEST[6] |= 0xC0; // Set Command bits
|
|
|
|
// Send from BBSCALL unless PORTBCALL defined
|
|
|
|
if (PORT->PORTBCALL[0] > 32)
|
|
memcpy(Buffer->ORIGIN, PORT->PORTBCALL, 7);
|
|
else if (APPLCALLTABLE->APPLCALL[0] > 32)
|
|
memcpy(Buffer->ORIGIN, APPLCALLTABLE->APPLCALL, 7);
|
|
else
|
|
memcpy(Buffer->ORIGIN, MYCALL, 7);
|
|
|
|
ptr1 = &PORT->PORTUNPROTO[7]; // First Digi
|
|
ptr2 = &Buffer->CTL; // Digi field in buffer
|
|
|
|
// Copy any digis
|
|
|
|
while (*(ptr1))
|
|
{
|
|
memcpy(ptr2, ptr1, 7);
|
|
ptr1 += 7;
|
|
ptr2 += 7;
|
|
}
|
|
|
|
*(ptr2 - 1) |= 1; // Set End of Address
|
|
*(ptr2++) = UI;
|
|
|
|
memcpy(ptr2, &Msg->PID, Msg->LENGTH);
|
|
ptr2 += Msg->LENGTH;
|
|
Buffer->LENGTH = (int)(ptr2 - (char *)Buffer);
|
|
Buffer->PORT = PORT->PORTNUMBER;
|
|
|
|
if (PORT->PROTOCOL == 10)
|
|
{
|
|
EXTPORTDATA * EXTPORT = (EXTPORTDATA *) PORT;
|
|
C_Q_ADD(&EXTPORT->UI_Q, Buffer);
|
|
}
|
|
else
|
|
C_Q_ADD(&IDMSG_Q, Buffer);
|
|
}
|
|
PORT = PORT->PORTPOINTER;
|
|
}
|
|
}
|
|
|
|
Dll VOID APIENTRY Send_AX(UCHAR * Block, DWORD Len, UCHAR Port)
|
|
{
|
|
// Block included the 7/11 byte header, Len does not
|
|
|
|
struct PORTCONTROL * PORT;
|
|
PMESSAGE Copy;
|
|
|
|
if (Len > 360 - 15)
|
|
return;
|
|
|
|
if (QCOUNT < 50)
|
|
return; // Running low
|
|
|
|
PORT = GetPortTableEntryFromPortNum(Port);
|
|
|
|
if (PORT == 0)
|
|
return;
|
|
|
|
Copy = GetBuff();
|
|
|
|
if (Copy == 0)
|
|
return;
|
|
|
|
memcpy(&Copy->DEST[0], &Block[MSGHDDRLEN], Len);
|
|
|
|
Copy->LENGTH = (USHORT)Len + MSGHDDRLEN;
|
|
|
|
if (PORT->PROTOCOL == 10 && PORT->TNC && PORT->TNC->Hardware != H_KISSHF)
|
|
{
|
|
// Pactor Style. Probably will only be used for Tracker uneless we do APRS over V4 or WINMOR
|
|
|
|
EXTPORTDATA * EXTPORT = (EXTPORTDATA *) PORT;
|
|
|
|
C_Q_ADD(&EXTPORT->UI_Q, Copy);
|
|
return;
|
|
}
|
|
|
|
Copy->PORT = Port;
|
|
|
|
PUT_ON_PORT_Q(PORT, Copy);
|
|
}
|
|
|
|
|
|
TRANSPORTENTRY * SetupSessionFromHost(PBPQVECSTRUC HOST, UINT ApplMask)
|
|
{
|
|
// Create a Transport (L4) session linked to an incoming HOST (API) Session
|
|
|
|
TRANSPORTENTRY * NewSess = L4TABLE;
|
|
int Index = 0;
|
|
|
|
|
|
while (Index < MAXCIRCUITS)
|
|
{
|
|
if (NewSess->L4USER[0] == 0)
|
|
{
|
|
// Got One
|
|
|
|
UCHAR * ourcall = &MYCALL[0];
|
|
|
|
// IF APPL PORT USE APPL CALL, ELSE NODE CALL
|
|
|
|
if (ApplMask)
|
|
{
|
|
// Circuit for APPL - look for an APPLCALL
|
|
|
|
APPLCALLS * APPL = APPLCALLTABLE;
|
|
|
|
while ((ApplMask & 1) == 0)
|
|
{
|
|
ApplMask >>= 1;
|
|
APPL++;
|
|
}
|
|
if (APPL->APPLCALL[0] > 0x40) // We have an applcall
|
|
ourcall = &APPL->APPLCALL[0];
|
|
}
|
|
|
|
memcpy(NewSess->L4USER, ourcall, 7);
|
|
memcpy(NewSess->L4MYCALL, ourcall, 7);
|
|
|
|
NewSess->CIRCUITINDEX = Index; //OUR INDEX
|
|
NewSess->CIRCUITID = NEXTID;
|
|
|
|
NEXTID++;
|
|
if (NEXTID == 0)
|
|
NEXTID++; // Keep Non-Zero
|
|
|
|
NewSess->L4TARGET.HOST = HOST;
|
|
NewSess->L4STATE = 5;
|
|
|
|
|
|
NewSess->SESSIONT1 = L4T1;
|
|
NewSess->L4WINDOW = (UCHAR)L4DEFAULTWINDOW;
|
|
NewSess->SESSPACLEN = PACLEN; // Default;
|
|
|
|
return NewSess;
|
|
}
|
|
Index++;
|
|
NewSess++;
|
|
}
|
|
|
|
// Table Full
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|