mirror of git://vps1.g8bpq.net/linbpq
parent
d42eee0da4
commit
f9898cf633
@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioUserFile
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
ShowAllFiles="false"
|
||||||
|
>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<DebugSettings
|
||||||
|
Command="$(TargetPath)"
|
||||||
|
WorkingDirectory=""
|
||||||
|
CommandArguments=""
|
||||||
|
Attach="false"
|
||||||
|
DebuggerType="3"
|
||||||
|
Remote="1"
|
||||||
|
RemoteMachine="NOTTSDESKTOP"
|
||||||
|
RemoteCommand=""
|
||||||
|
HttpUrl=""
|
||||||
|
PDBPath=""
|
||||||
|
SQLDebugging=""
|
||||||
|
Environment=""
|
||||||
|
EnvironmentMerge="true"
|
||||||
|
DebuggerFlavor=""
|
||||||
|
MPIRunCommand=""
|
||||||
|
MPIRunArguments=""
|
||||||
|
MPIRunWorkingDirectory=""
|
||||||
|
ApplicationCommand=""
|
||||||
|
ApplicationArguments=""
|
||||||
|
ShimCommand=""
|
||||||
|
MPIAcceptMode=""
|
||||||
|
MPIAcceptFilter=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<DebugSettings
|
||||||
|
Command="$(TargetPath)"
|
||||||
|
WorkingDirectory=""
|
||||||
|
CommandArguments=""
|
||||||
|
Attach="false"
|
||||||
|
DebuggerType="3"
|
||||||
|
Remote="1"
|
||||||
|
RemoteMachine="NOTTSDESKTOP"
|
||||||
|
RemoteCommand=""
|
||||||
|
HttpUrl=""
|
||||||
|
PDBPath=""
|
||||||
|
SQLDebugging=""
|
||||||
|
Environment=""
|
||||||
|
EnvironmentMerge="true"
|
||||||
|
DebuggerFlavor=""
|
||||||
|
MPIRunCommand=""
|
||||||
|
MPIRunArguments=""
|
||||||
|
MPIRunWorkingDirectory=""
|
||||||
|
ApplicationCommand=""
|
||||||
|
ApplicationArguments=""
|
||||||
|
ShimCommand=""
|
||||||
|
MPIAcceptMode=""
|
||||||
|
MPIAcceptFilter=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
</VisualStudioUserFile>
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioUserFile
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
ShowAllFiles="false"
|
||||||
|
>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<DebugSettings
|
||||||
|
Command="$(TargetPath)"
|
||||||
|
WorkingDirectory=""
|
||||||
|
CommandArguments=""
|
||||||
|
Attach="false"
|
||||||
|
DebuggerType="3"
|
||||||
|
Remote="1"
|
||||||
|
RemoteMachine="LAPTOP-Q6S4RP5Q"
|
||||||
|
RemoteCommand=""
|
||||||
|
HttpUrl=""
|
||||||
|
PDBPath=""
|
||||||
|
SQLDebugging=""
|
||||||
|
Environment=""
|
||||||
|
EnvironmentMerge="true"
|
||||||
|
DebuggerFlavor=""
|
||||||
|
MPIRunCommand=""
|
||||||
|
MPIRunArguments=""
|
||||||
|
MPIRunWorkingDirectory=""
|
||||||
|
ApplicationCommand=""
|
||||||
|
ApplicationArguments=""
|
||||||
|
ShimCommand=""
|
||||||
|
MPIAcceptMode=""
|
||||||
|
MPIAcceptFilter=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<DebugSettings
|
||||||
|
Command="$(TargetPath)"
|
||||||
|
WorkingDirectory=""
|
||||||
|
CommandArguments=""
|
||||||
|
Attach="false"
|
||||||
|
DebuggerType="3"
|
||||||
|
Remote="1"
|
||||||
|
RemoteMachine="LAPTOP-Q6S4RP5Q"
|
||||||
|
RemoteCommand=""
|
||||||
|
HttpUrl=""
|
||||||
|
PDBPath=""
|
||||||
|
SQLDebugging=""
|
||||||
|
Environment=""
|
||||||
|
EnvironmentMerge="true"
|
||||||
|
DebuggerFlavor=""
|
||||||
|
MPIRunCommand=""
|
||||||
|
MPIRunArguments=""
|
||||||
|
MPIRunWorkingDirectory=""
|
||||||
|
ApplicationCommand=""
|
||||||
|
ApplicationArguments=""
|
||||||
|
ShimCommand=""
|
||||||
|
MPIAcceptMode=""
|
||||||
|
MPIAcceptFilter=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
</VisualStudioUserFile>
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioUserFile
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
ShowAllFiles="false"
|
||||||
|
>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<DebugSettings
|
||||||
|
Command="C:\Devprogs\BPQ32\bpq32.exe"
|
||||||
|
WorkingDirectory=""
|
||||||
|
CommandArguments=""
|
||||||
|
Attach="false"
|
||||||
|
DebuggerType="3"
|
||||||
|
Remote="1"
|
||||||
|
RemoteMachine="LAPTOP-Q6S4RP5Q"
|
||||||
|
RemoteCommand=""
|
||||||
|
HttpUrl=""
|
||||||
|
PDBPath=""
|
||||||
|
SQLDebugging=""
|
||||||
|
Environment=""
|
||||||
|
EnvironmentMerge="true"
|
||||||
|
DebuggerFlavor=""
|
||||||
|
MPIRunCommand=""
|
||||||
|
MPIRunArguments=""
|
||||||
|
MPIRunWorkingDirectory=""
|
||||||
|
ApplicationCommand=""
|
||||||
|
ApplicationArguments=""
|
||||||
|
ShimCommand=""
|
||||||
|
MPIAcceptMode=""
|
||||||
|
MPIAcceptFilter=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<DebugSettings
|
||||||
|
Command=""
|
||||||
|
WorkingDirectory=""
|
||||||
|
CommandArguments=""
|
||||||
|
Attach="false"
|
||||||
|
DebuggerType="3"
|
||||||
|
Remote="1"
|
||||||
|
RemoteMachine="LAPTOP-Q6S4RP5Q"
|
||||||
|
RemoteCommand=""
|
||||||
|
HttpUrl=""
|
||||||
|
PDBPath=""
|
||||||
|
SQLDebugging=""
|
||||||
|
Environment=""
|
||||||
|
EnvironmentMerge="true"
|
||||||
|
DebuggerFlavor=""
|
||||||
|
MPIRunCommand=""
|
||||||
|
MPIRunArguments=""
|
||||||
|
MPIRunWorkingDirectory=""
|
||||||
|
ApplicationCommand=""
|
||||||
|
ApplicationArguments=""
|
||||||
|
ShimCommand=""
|
||||||
|
MPIAcceptMode=""
|
||||||
|
MPIAcceptFilter=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
</VisualStudioUserFile>
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioUserFile
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
ShowAllFiles="false"
|
||||||
|
>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<DebugSettings
|
||||||
|
Command="C:\DevProgs\BPQ32\bpq32.exe"
|
||||||
|
WorkingDirectory=""
|
||||||
|
CommandArguments=""
|
||||||
|
Attach="false"
|
||||||
|
DebuggerType="3"
|
||||||
|
Remote="1"
|
||||||
|
RemoteMachine="SKIGACER"
|
||||||
|
RemoteCommand=""
|
||||||
|
HttpUrl=""
|
||||||
|
PDBPath=""
|
||||||
|
SQLDebugging=""
|
||||||
|
Environment=""
|
||||||
|
EnvironmentMerge="true"
|
||||||
|
DebuggerFlavor=""
|
||||||
|
MPIRunCommand=""
|
||||||
|
MPIRunArguments=""
|
||||||
|
MPIRunWorkingDirectory=""
|
||||||
|
ApplicationCommand=""
|
||||||
|
ApplicationArguments=""
|
||||||
|
ShimCommand=""
|
||||||
|
MPIAcceptMode=""
|
||||||
|
MPIAcceptFilter=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<DebugSettings
|
||||||
|
Command=""
|
||||||
|
WorkingDirectory=""
|
||||||
|
CommandArguments=""
|
||||||
|
Attach="false"
|
||||||
|
DebuggerType="3"
|
||||||
|
Remote="1"
|
||||||
|
RemoteMachine="SKIGACER"
|
||||||
|
RemoteCommand=""
|
||||||
|
HttpUrl=""
|
||||||
|
PDBPath=""
|
||||||
|
SQLDebugging=""
|
||||||
|
Environment=""
|
||||||
|
EnvironmentMerge="true"
|
||||||
|
DebuggerFlavor=""
|
||||||
|
MPIRunCommand=""
|
||||||
|
MPIRunArguments=""
|
||||||
|
MPIRunWorkingDirectory=""
|
||||||
|
ApplicationCommand=""
|
||||||
|
ApplicationArguments=""
|
||||||
|
ShimCommand=""
|
||||||
|
MPIAcceptMode=""
|
||||||
|
MPIAcceptFilter=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
</VisualStudioUserFile>
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,641 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Paula (G8PZT)'s Remote Host Protocol interface.
|
||||||
|
For now only sufficient support for WhatsPac
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define _CRT_SECURE_NO_DEPRECATE
|
||||||
|
|
||||||
|
#include "cheaders.h"
|
||||||
|
#include "bpq32.h"
|
||||||
|
|
||||||
|
int FindFreeStreamNoSem();
|
||||||
|
DllExport int APIENTRY DeallocateStream(int stream);
|
||||||
|
int SendMsgNoSem(int stream, char * msg, int len);
|
||||||
|
|
||||||
|
static void GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value, int Len);
|
||||||
|
static int GetJSONInt(char * _REPLYBUFFER, char * Name);
|
||||||
|
|
||||||
|
// Generally Can have multiple RHP connections and each can have multiple RHF Sessions
|
||||||
|
|
||||||
|
struct RHPSessionInfo
|
||||||
|
{
|
||||||
|
SOCKET Socket; // Websocks Socket
|
||||||
|
int BPQStream;
|
||||||
|
int Handle; // RHP session ID
|
||||||
|
int Seq;
|
||||||
|
char Local[12];
|
||||||
|
char Remote[12];
|
||||||
|
BOOL Connecting; // Set while waiting for connection to complete
|
||||||
|
BOOL Listening;
|
||||||
|
BOOL Connected;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RHPConnectionInfo
|
||||||
|
{
|
||||||
|
SOCKET socket;
|
||||||
|
struct RHPSessionInfo ** RHPSessions;
|
||||||
|
int NumberofRHPSessions;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct RHPConnectionInfo ** RHPSockets = NULL;
|
||||||
|
int NumberofRHPConnections = 0;
|
||||||
|
|
||||||
|
struct RHPSessionInfo ** RHPSessions;
|
||||||
|
int NumberofRHPSessions;
|
||||||
|
|
||||||
|
char ErrCodes[18][24] =
|
||||||
|
{"Ok", "Unspecified", "Bad or missing type", "Invalid handle", "No memory", "Bad or missing mode",
|
||||||
|
|
||||||
|
"Invalid local address",
|
||||||
|
"Invalid remote address" ,
|
||||||
|
"Bad or missing family" ,
|
||||||
|
"Duplicate socket" ,
|
||||||
|
"No such port" ,
|
||||||
|
"Invalid protocol" ,
|
||||||
|
"Bad parameter" ,
|
||||||
|
"No buffers" ,
|
||||||
|
"Unauthorised" ,
|
||||||
|
"No Route" ,
|
||||||
|
"Operation not supported"};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern char pgm[256];
|
||||||
|
|
||||||
|
SOCKET agwsock;
|
||||||
|
|
||||||
|
extern int SemHeldByAPI;
|
||||||
|
|
||||||
|
char szBuff[80];
|
||||||
|
|
||||||
|
int WhatsPacConfigured = 1;
|
||||||
|
|
||||||
|
|
||||||
|
int RHPPaclen = 236;
|
||||||
|
|
||||||
|
|
||||||
|
int processRHCPOpen(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer);
|
||||||
|
int processRHCPSend(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer);
|
||||||
|
int processRHCPClose(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void SendWebSockMessage(SOCKET socket, char * Msg, int Len)
|
||||||
|
{
|
||||||
|
int Loops = 0;
|
||||||
|
int Sent;
|
||||||
|
int TxLen;
|
||||||
|
char * OutBuffer = Msg;
|
||||||
|
|
||||||
|
// WebSock Encode. Buffer has 10 bytes on front for header but header len depends on Msg len
|
||||||
|
|
||||||
|
|
||||||
|
if (Len < 126)
|
||||||
|
{
|
||||||
|
// Two Byte Header
|
||||||
|
|
||||||
|
OutBuffer[8] = 0x81; // Fin, Data
|
||||||
|
OutBuffer[9] = Len;
|
||||||
|
|
||||||
|
TxLen = Len + 2;
|
||||||
|
OutBuffer = &Msg[8];
|
||||||
|
}
|
||||||
|
else if (Len < 65536)
|
||||||
|
{
|
||||||
|
OutBuffer[6] = 0x81; // Fin, Data
|
||||||
|
OutBuffer[7] = 126; // Unmasked, Extended Len 16
|
||||||
|
OutBuffer[8] = Len >> 8;
|
||||||
|
OutBuffer[9] = Len & 0xff;
|
||||||
|
TxLen = Len + 4;
|
||||||
|
OutBuffer = &Msg[6];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OutBuffer[0] = 0x81; // Fin, Data
|
||||||
|
OutBuffer[1] = 127; // Unmasked, Extended Len 64 bits
|
||||||
|
// Len is 32 bits, so pad with zeros
|
||||||
|
OutBuffer[2] = 0;
|
||||||
|
OutBuffer[3] = 0;
|
||||||
|
OutBuffer[4] = 0;
|
||||||
|
OutBuffer[5] = 0;
|
||||||
|
OutBuffer[6] = (Len >> 24) & 0xff;
|
||||||
|
OutBuffer[7] = (Len >> 16) & 0xff;
|
||||||
|
OutBuffer[8] = (Len >> 8) & 0xff;
|
||||||
|
OutBuffer[9] = Len & 0xff;
|
||||||
|
|
||||||
|
TxLen = Len + + 10;
|
||||||
|
OutBuffer = &Msg[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send may block
|
||||||
|
|
||||||
|
Sent = send(socket, OutBuffer, TxLen, 0);
|
||||||
|
|
||||||
|
while (Sent != TxLen && Loops++ < 3000) // 100 secs max
|
||||||
|
{
|
||||||
|
if (Sent > 0) // something sent
|
||||||
|
{
|
||||||
|
TxLen -= Sent;
|
||||||
|
memmove(OutBuffer, &OutBuffer[Sent], TxLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sleep(30);
|
||||||
|
Sent = send(socket, OutBuffer, TxLen, 0);
|
||||||
|
if (Sent == -1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(Msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int RHPProcessHTTPMessage(struct ConnectionInfo * conn, char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE)
|
||||||
|
{
|
||||||
|
// RHP messages can be sent over Websocks or normal http but I think WhatsPac only uses WebSocks
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ProcessRHPWebSock(SOCKET socket, char * Msg, int MsgLen)
|
||||||
|
{
|
||||||
|
int Loops = 0;
|
||||||
|
int InputLen = 0;
|
||||||
|
int Len;
|
||||||
|
|
||||||
|
char Value[16];
|
||||||
|
char * OutBuffer = malloc(250000);
|
||||||
|
|
||||||
|
struct RHPConnectionInfo * RHPSocket = NULL;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
Msg[MsgLen] = 0;
|
||||||
|
|
||||||
|
// Find Connection Record. If none, create one
|
||||||
|
|
||||||
|
for (n = 0; n < NumberofRHPConnections; n++)
|
||||||
|
{
|
||||||
|
if (RHPSockets[n]->socket == socket)
|
||||||
|
{
|
||||||
|
RHPSocket = RHPSockets[n];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RHPSocket == 0)
|
||||||
|
{
|
||||||
|
NumberofRHPConnections;
|
||||||
|
RHPSockets = realloc(RHPSockets, sizeof(void *) * (NumberofRHPConnections + 1));
|
||||||
|
RHPSocket = RHPSockets[NumberofRHPConnections] = zalloc(sizeof (struct RHPConnectionInfo));
|
||||||
|
NumberofRHPConnections++;
|
||||||
|
RHPSocket->socket = socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// {"type":"open","id":5,"pfam":"ax25","mode":"stream","port":"1","local":"G8BPQ","remote":"G8BPQ-2","flags":128}
|
||||||
|
// {"type": "openReply", "id": 82, "handle": 1, "errCode": 0, "errText": "Ok"}
|
||||||
|
// {"seqno": 0, "type": "status", "handle": 1, "flags": 0}
|
||||||
|
// ("seqno": 1, "type": "close", "handle": 1}
|
||||||
|
// {"id":40,"type":"close","handle":1}
|
||||||
|
|
||||||
|
// {"seqno": 0, "type": "status", "handle": 1, "flags": 2}.~.
|
||||||
|
// {"seqno": 1, "type": "recv", "handle": 1, "data": "Welcome to G8BPQ's Test Switch in Nottingham \rType ? for list of available commands.\r"}.
|
||||||
|
|
||||||
|
GetJSONValue(Msg, "\"type\":", Value, 15);
|
||||||
|
|
||||||
|
if (_stricmp(Value, "open") == 0)
|
||||||
|
{
|
||||||
|
Len = processRHCPOpen(RHPSocket, Msg, &OutBuffer[10]); // Space at front for WebSock Header
|
||||||
|
if (Len)
|
||||||
|
SendWebSockMessage(RHPSocket->socket, OutBuffer, Len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_stricmp(Value, "send") == 0)
|
||||||
|
{
|
||||||
|
Len = processRHCPSend(RHPSocket, Msg, &OutBuffer[10]); // Space at front for WebSock Header
|
||||||
|
SendWebSockMessage(RHPSocket->socket, OutBuffer, Len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_stricmp(Value, "close") == 0)
|
||||||
|
{
|
||||||
|
Len = processRHCPClose(RHPSocket, Msg, &OutBuffer[10]); // Space at front for WebSock Header
|
||||||
|
SendWebSockMessage(RHPSocket->socket, OutBuffer, Len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Debugprintf(Msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRHPWebSockClosed(SOCKET socket)
|
||||||
|
{
|
||||||
|
// Close any connections on this scoket and delete socket entry
|
||||||
|
|
||||||
|
struct RHPConnectionInfo * RHPSocket = NULL;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
// Find Connection Record. CLear any Sessions
|
||||||
|
|
||||||
|
for (n = 0; n < NumberofRHPConnections; n++)
|
||||||
|
{
|
||||||
|
if (RHPSockets[n]->socket == socket)
|
||||||
|
{
|
||||||
|
RHPSocket = RHPSockets[n];
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int processRHCPOpen(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer)
|
||||||
|
{
|
||||||
|
//{"type":"open","id":5,"pfam":"ax25","mode":"stream","port":"1","local":"G8BPQ","remote":"G8BPQ-2","flags":128}
|
||||||
|
|
||||||
|
struct RHPSessionInfo * RHPSession = 0;
|
||||||
|
|
||||||
|
char * Value = malloc(strlen(Msg)); // Will always be long enough
|
||||||
|
int ID;
|
||||||
|
|
||||||
|
char pfam[16];
|
||||||
|
char Mode[16];
|
||||||
|
int Port;
|
||||||
|
char Local[16];
|
||||||
|
char Remote[16];
|
||||||
|
int flags;
|
||||||
|
int Handle = 1;
|
||||||
|
int Stream;
|
||||||
|
unsigned char AXCall[10];
|
||||||
|
int Len;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
// ID seems to be used for control commands like open. SeqNo for data within a session (i Think!
|
||||||
|
|
||||||
|
ID = GetJSONInt(Msg, "\"id\":");
|
||||||
|
GetJSONValue(Msg, "\"pfam\":", pfam, 15);
|
||||||
|
GetJSONValue(Msg, "\"mode\":", Mode, 15);
|
||||||
|
Port = GetJSONInt(Msg, "\"port\":");
|
||||||
|
GetJSONValue(Msg, "\"local\":", Local, 15);
|
||||||
|
GetJSONValue(Msg, "\"remote\":", Remote, 15);
|
||||||
|
flags = GetJSONInt(Msg, "\"flags\":");
|
||||||
|
|
||||||
|
if (_stricmp(pfam, "ax25") != 0)
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0);
|
||||||
|
|
||||||
|
if (_stricmp(Mode, "stream") == 0)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// Allocate a RHP Session
|
||||||
|
|
||||||
|
// See if there is an old one we can reuse
|
||||||
|
|
||||||
|
for (n = 0; n < NumberofRHPSessions; n++)
|
||||||
|
{
|
||||||
|
if (RHPSessions[n]->BPQStream == 0)
|
||||||
|
{
|
||||||
|
RHPSession = RHPSessions[n];
|
||||||
|
Handle = n + 1;
|
||||||
|
Stream = RHPSessions[n]->BPQStream;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RHPSession == 0)
|
||||||
|
{
|
||||||
|
RHPSessions = realloc(RHPSessions, sizeof(void *) * (NumberofRHPSessions + 1));
|
||||||
|
RHPSession = RHPSessions[NumberofRHPSessions] = zalloc(sizeof (struct RHPSessionInfo));
|
||||||
|
NumberofRHPSessions++;
|
||||||
|
|
||||||
|
Handle = NumberofRHPSessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(pgm, "RHP");
|
||||||
|
Stream = FindFreeStreamNoSem();
|
||||||
|
strcpy(pgm, "bpq32.exe");
|
||||||
|
|
||||||
|
if (Stream == 255)
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0);
|
||||||
|
|
||||||
|
RHPSession->BPQStream = Stream;
|
||||||
|
RHPSession->Handle = Handle;
|
||||||
|
RHPSession->Connecting = TRUE;
|
||||||
|
RHPSession->Socket = RHPSocket->socket;
|
||||||
|
|
||||||
|
strcpy(RHPSession->Local, Local);
|
||||||
|
strcpy(RHPSession->Remote, Remote);
|
||||||
|
|
||||||
|
Connect(Stream);
|
||||||
|
|
||||||
|
ConvToAX25(Local, AXCall);
|
||||||
|
ChangeSessionCallsign(Stream, AXCall);
|
||||||
|
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 0, \"errText\": \"Ok\"}", ID, Handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int processRHCPSend(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer)
|
||||||
|
{
|
||||||
|
// {"type":"send","handle":1,"data":";;;;;;\r","id":70}
|
||||||
|
|
||||||
|
struct RHPSessionInfo * RHPSession;
|
||||||
|
|
||||||
|
int ID;
|
||||||
|
char * Data;
|
||||||
|
char * ptr;
|
||||||
|
int c;
|
||||||
|
int Len;
|
||||||
|
|
||||||
|
int Handle = 1;
|
||||||
|
|
||||||
|
Data = malloc(strlen(Msg));
|
||||||
|
|
||||||
|
ID = GetJSONInt(Msg, "\"id\":");
|
||||||
|
Handle = GetJSONInt(Msg, "\"handle\":");
|
||||||
|
GetJSONValue(Msg, "\"data\":", Data, strlen(Msg) - 1);
|
||||||
|
|
||||||
|
if (Handle < 1 || Handle > NumberofRHPSessions)
|
||||||
|
{
|
||||||
|
free(Data);
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"sendReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errtext\": \"Invalid handle\"}", ID, Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
RHPSession = RHPSessions[Handle - 1];
|
||||||
|
|
||||||
|
// Look for \ escapes
|
||||||
|
|
||||||
|
ptr = Data;
|
||||||
|
|
||||||
|
while (ptr = strchr(ptr, '\\'))
|
||||||
|
{
|
||||||
|
c = ptr[1];
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'r':
|
||||||
|
|
||||||
|
*ptr = 13;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
|
||||||
|
*ptr = '\\';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
|
||||||
|
*ptr = '"';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memmove(ptr + 1, ptr + 2, strlen(ptr + 1));
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debugprintf(Data);
|
||||||
|
|
||||||
|
Len = strlen(Data);
|
||||||
|
ptr = Data;
|
||||||
|
|
||||||
|
|
||||||
|
while (Len > RHPPaclen)
|
||||||
|
{
|
||||||
|
SendMsgNoSem(RHPSession->BPQStream, ptr, RHPPaclen);
|
||||||
|
Len -= RHPPaclen;
|
||||||
|
ptr += RHPPaclen;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendMsgNoSem(RHPSession->BPQStream, ptr, Len);
|
||||||
|
|
||||||
|
free(Data);
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"sendReply\", \"id\": %d, \"handle\": %d, \"errCode\": 0, \"errText\": \"Ok\", \"status\": %d}", ID, Handle, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int processRHCPClose(struct RHPConnectionInfo * RHPSocket, char * Msg, char * ReplyBuffer)
|
||||||
|
{
|
||||||
|
|
||||||
|
// {"id":70,"type":"close","handle":1}
|
||||||
|
|
||||||
|
|
||||||
|
struct RHPSessionInfo * RHPSession;
|
||||||
|
|
||||||
|
int ID;
|
||||||
|
int Handle = 1;
|
||||||
|
|
||||||
|
char * OutBuffer = malloc(256);
|
||||||
|
|
||||||
|
ID = GetJSONInt(Msg, "\"id\":");
|
||||||
|
Handle = GetJSONInt(Msg, "\"handle\":");
|
||||||
|
|
||||||
|
if (Handle < 1 || Handle > NumberofRHPSessions)
|
||||||
|
return sprintf(ReplyBuffer, "{\"id\": %d, \"type\": \"closeReply\", \"handle\": %d, \"errcode\": 12, \"errtext\": \"Invalid handle\"}", ID, Handle);
|
||||||
|
|
||||||
|
|
||||||
|
RHPSession = RHPSessions[Handle - 1];
|
||||||
|
Disconnect(RHPSession->BPQStream);
|
||||||
|
RHPSession->Connected = 0;
|
||||||
|
RHPSession->Connecting = 0;
|
||||||
|
|
||||||
|
DeallocateStream(RHPSession->BPQStream);
|
||||||
|
RHPSession->BPQStream = 0;
|
||||||
|
|
||||||
|
return sprintf(ReplyBuffer, "{\"id\": %d, \"type\": \"closeReply\", \"handle\": %d, \"errcode\": 0, \"errtext\": \"Ok\"}", ID, Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void RHPPoll()
|
||||||
|
{
|
||||||
|
int Stream;
|
||||||
|
int n;
|
||||||
|
int state, change;
|
||||||
|
int Len;
|
||||||
|
char * RHPMsg;
|
||||||
|
unsigned char Buffer[1024]; // Space to escape control chars
|
||||||
|
int pktlen, count;
|
||||||
|
|
||||||
|
struct RHPSessionInfo * RHPSession;
|
||||||
|
|
||||||
|
for (n = 0; n < NumberofRHPSessions; n++)
|
||||||
|
{
|
||||||
|
RHPSession = RHPSessions[n];
|
||||||
|
Stream = RHPSession->BPQStream;
|
||||||
|
|
||||||
|
// See if connected state has changed
|
||||||
|
|
||||||
|
SessionState(Stream, &state, &change);
|
||||||
|
|
||||||
|
if (change == 1)
|
||||||
|
{
|
||||||
|
if (state == 1)
|
||||||
|
{
|
||||||
|
// Connected
|
||||||
|
|
||||||
|
RHPSession->Seq = 0;
|
||||||
|
RHPSession->Connecting = FALSE;
|
||||||
|
RHPSession->Connected = TRUE;
|
||||||
|
|
||||||
|
RHPMsg = malloc(256);
|
||||||
|
Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"status\", \"handle\": %d, \"flags\": 2}", RHPSession->Seq++, RHPSession->Handle);
|
||||||
|
SendWebSockMessage(RHPSession->Socket, RHPMsg, Len);
|
||||||
|
|
||||||
|
// Send RHP CTEXT
|
||||||
|
|
||||||
|
RHPMsg = malloc(256);
|
||||||
|
Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"recv\", \"handle\": %d, \"data\": \"Connected to RHP Server\\r\"}", RHPSession->Seq++, RHPSession->Handle);
|
||||||
|
SendWebSockMessage(RHPSession->Socket, RHPMsg, Len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Disconnected. Send Close to client
|
||||||
|
|
||||||
|
RHPMsg = malloc(256);
|
||||||
|
Len = sprintf(&RHPMsg[10], "{\"type\": \"close\", \"seqno\": %d, \"handle\": %d}", RHPSession->Seq++, RHPSession->Handle);
|
||||||
|
SendWebSockMessage(RHPSession->Socket, RHPMsg, Len);
|
||||||
|
|
||||||
|
RHPSession->Connected = 0;
|
||||||
|
RHPSession->Connecting = 0;
|
||||||
|
|
||||||
|
DeallocateStream(RHPSession->BPQStream);
|
||||||
|
RHPSession->BPQStream = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
GetMsg(Stream, Buffer, &pktlen, &count);
|
||||||
|
|
||||||
|
if (pktlen > 0)
|
||||||
|
{
|
||||||
|
char * ptr = Buffer;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
Buffer[pktlen] = 0;
|
||||||
|
|
||||||
|
// Message is JSON so Convert CR to \r, \ to \\ " to \"
|
||||||
|
|
||||||
|
while (c = *(ptr))
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 13:
|
||||||
|
|
||||||
|
memmove(ptr + 2, ptr + 1, strlen(ptr));
|
||||||
|
*(ptr++) = '\\';
|
||||||
|
*(ptr++) = 'r';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
|
||||||
|
memmove(ptr + 2, ptr + 1, strlen(ptr));
|
||||||
|
*(ptr++) = '\\';
|
||||||
|
*(ptr++) = '"';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
|
||||||
|
memmove(ptr + 2, ptr + 1, strlen(ptr));
|
||||||
|
*(ptr++) = '\\';
|
||||||
|
*(ptr++) = '\\';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RHPMsg = malloc(1024);
|
||||||
|
|
||||||
|
Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"recv\", \"handle\": %d, \"data\": \"%s\"}", RHPSession->Seq++, RHPSession->Handle, Buffer);
|
||||||
|
SendWebSockMessage(RHPSession->Socket, RHPMsg, Len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while (count > 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value, int Len)
|
||||||
|
{
|
||||||
|
char * ptr1, * ptr2;
|
||||||
|
|
||||||
|
Value[0] = 0;
|
||||||
|
|
||||||
|
ptr1 = strstr(_REPLYBUFFER, Name);
|
||||||
|
|
||||||
|
if (ptr1 == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ptr1 += (strlen(Name) + 1);
|
||||||
|
|
||||||
|
// "data":"{\"t\":\"c\",\"n\":\"John\",\"c\":\"G8BPQ\",\"lm\":1737912636,\"le\":1737883907,\"led\":1737758451,\"v\":0.33,\"cc\":[{\"cid\":1,\"lp\":1737917257201,\"le\":1737913735726,\"led\":1737905249785},{\"cid\":0,\"lp\":1737324074107,\"le\":1737323831510,\"led\":1737322973662},{\"cid\":5,\"lp\":1737992107419,\"le\":1737931466510,\"led\":1737770056244}]}\r","id":28}
|
||||||
|
|
||||||
|
// There may be escaped " in data stream
|
||||||
|
|
||||||
|
ptr2 = strchr(ptr1, '"');
|
||||||
|
|
||||||
|
while (*(ptr2 - 1) == '\\')
|
||||||
|
{
|
||||||
|
ptr2 = strchr(ptr2 + 2, '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (ptr2)
|
||||||
|
{
|
||||||
|
size_t ValLen = ptr2 - ptr1;
|
||||||
|
if (ValLen > Len)
|
||||||
|
ValLen = Len;
|
||||||
|
|
||||||
|
memcpy(Value, ptr1, ValLen);
|
||||||
|
Value[ValLen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int GetJSONInt(char * _REPLYBUFFER, char * Name)
|
||||||
|
{
|
||||||
|
char * ptr1;
|
||||||
|
|
||||||
|
ptr1 = strstr(_REPLYBUFFER, Name);
|
||||||
|
|
||||||
|
if (ptr1 == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ptr1 += (strlen(Name));
|
||||||
|
|
||||||
|
return atoi(ptr1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,711 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Paula (G8PZT)'s Remote Host Protocol interface.
|
||||||
|
For now only sufficient support for WhatsPac
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define _CRT_SECURE_NO_DEPRECATE
|
||||||
|
|
||||||
|
#include "cheaders.h"
|
||||||
|
#include "bpq32.h"
|
||||||
|
|
||||||
|
int FindFreeStreamNoSem();
|
||||||
|
DllExport int APIENTRY DeallocateStream(int stream);
|
||||||
|
int SendMsgNoSem(int stream, char * msg, int len);
|
||||||
|
|
||||||
|
static void GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value, int Len);
|
||||||
|
static int GetJSONInt(char * _REPLYBUFFER, char * Name);
|
||||||
|
|
||||||
|
// Generally Can have multiple RHP connections and each can have multiple RHF Sessions
|
||||||
|
|
||||||
|
struct RHPSessionInfo
|
||||||
|
{
|
||||||
|
SOCKET Socket; // Websocks Socket
|
||||||
|
int BPQStream;
|
||||||
|
int Handle; // RHP session ID
|
||||||
|
int Seq;
|
||||||
|
char Local[12];
|
||||||
|
char Remote[12];
|
||||||
|
BOOL Connecting; // Set while waiting for connection to complete
|
||||||
|
BOOL Listening;
|
||||||
|
BOOL Connected;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RHPConnectionInfo
|
||||||
|
{
|
||||||
|
SOCKET socket;
|
||||||
|
struct RHPSessionInfo ** RHPSessions;
|
||||||
|
int NumberofRHPSessions;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Struct passed by beginhread
|
||||||
|
|
||||||
|
struct RHPParamBlock
|
||||||
|
{
|
||||||
|
unsigned char * Msg;
|
||||||
|
int Len;
|
||||||
|
SOCKET Socket;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//struct RHPConnectionInfo ** RHPSockets = NULL;
|
||||||
|
//int NumberofRHPConnections = 0;
|
||||||
|
|
||||||
|
struct RHPSessionInfo ** RHPSessions;
|
||||||
|
int NumberofRHPSessions;
|
||||||
|
|
||||||
|
char ErrCodes[18][24] =
|
||||||
|
{"Ok", "Unspecified", "Bad or missing type", "Invalid handle", "No memory", "Bad or missing mode",
|
||||||
|
|
||||||
|
"Invalid local address",
|
||||||
|
"Invalid remote address" ,
|
||||||
|
"Bad or missing family" ,
|
||||||
|
"Duplicate socket" ,
|
||||||
|
"No such port" ,
|
||||||
|
"Invalid protocol" ,
|
||||||
|
"Bad parameter" ,
|
||||||
|
"No buffers" ,
|
||||||
|
"Unauthorised" ,
|
||||||
|
"No Route" ,
|
||||||
|
"Operation not supported"};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern char pgm[256];
|
||||||
|
|
||||||
|
SOCKET agwsock;
|
||||||
|
|
||||||
|
extern int SemHeldByAPI;
|
||||||
|
|
||||||
|
char szBuff[80];
|
||||||
|
|
||||||
|
int WhatsPacConfigured = 1;
|
||||||
|
|
||||||
|
|
||||||
|
int RHPPaclen = 236;
|
||||||
|
|
||||||
|
|
||||||
|
int processRHCPOpen(SOCKET Socket, char * Msg, char * ReplyBuffer);
|
||||||
|
int processRHCPSend(SOCKET Socket, char * Msg, char * ReplyBuffer);
|
||||||
|
int processRHCPClose(SOCKET Socket, char * Msg, char * ReplyBuffer);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void SendWebSockMessage(SOCKET socket, char * Msg, int Len)
|
||||||
|
{
|
||||||
|
int Loops = 0;
|
||||||
|
int Sent;
|
||||||
|
int TxLen;
|
||||||
|
char * OutBuffer = Msg;
|
||||||
|
|
||||||
|
// WebSock Encode. Buffer has 10 bytes on front for header but header len depends on Msg len
|
||||||
|
|
||||||
|
|
||||||
|
if (Len < 126)
|
||||||
|
{
|
||||||
|
// Two Byte Header
|
||||||
|
|
||||||
|
OutBuffer[8] = 0x81; // Fin, Data
|
||||||
|
OutBuffer[9] = Len;
|
||||||
|
|
||||||
|
TxLen = Len + 2;
|
||||||
|
OutBuffer = &Msg[8];
|
||||||
|
}
|
||||||
|
else if (Len < 65536)
|
||||||
|
{
|
||||||
|
OutBuffer[6] = 0x81; // Fin, Data
|
||||||
|
OutBuffer[7] = 126; // Unmasked, Extended Len 16
|
||||||
|
OutBuffer[8] = Len >> 8;
|
||||||
|
OutBuffer[9] = Len & 0xff;
|
||||||
|
TxLen = Len + 4;
|
||||||
|
OutBuffer = &Msg[6];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OutBuffer[0] = 0x81; // Fin, Data
|
||||||
|
OutBuffer[1] = 127; // Unmasked, Extended Len 64 bits
|
||||||
|
// Len is 32 bits, so pad with zeros
|
||||||
|
OutBuffer[2] = 0;
|
||||||
|
OutBuffer[3] = 0;
|
||||||
|
OutBuffer[4] = 0;
|
||||||
|
OutBuffer[5] = 0;
|
||||||
|
OutBuffer[6] = (Len >> 24) & 0xff;
|
||||||
|
OutBuffer[7] = (Len >> 16) & 0xff;
|
||||||
|
OutBuffer[8] = (Len >> 8) & 0xff;
|
||||||
|
OutBuffer[9] = Len & 0xff;
|
||||||
|
|
||||||
|
TxLen = Len + + 10;
|
||||||
|
OutBuffer = &Msg[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send may block
|
||||||
|
|
||||||
|
Sent = send(socket, OutBuffer, TxLen, 0);
|
||||||
|
|
||||||
|
while (Sent != TxLen && Loops++ < 3000) // 100 secs max
|
||||||
|
{
|
||||||
|
if (Sent > 0) // something sent
|
||||||
|
{
|
||||||
|
TxLen -= Sent;
|
||||||
|
memmove(OutBuffer, &OutBuffer[Sent], TxLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sleep(30);
|
||||||
|
Sent = send(socket, OutBuffer, TxLen, 0);
|
||||||
|
if (Sent == -1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(Msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRHPWebSock(SOCKET Socket, char * Msg, int MsgLen);
|
||||||
|
|
||||||
|
void RHPThread(void * Params)
|
||||||
|
{
|
||||||
|
// Params and data buffer are malloced blocks so free when done with it
|
||||||
|
|
||||||
|
struct RHPParamBlock * Block = (struct RHPParamBlock *)Params;
|
||||||
|
|
||||||
|
ProcessRHPWebSock(Block->Socket, Block->Msg, Block->Len);
|
||||||
|
|
||||||
|
free(Block->Msg);
|
||||||
|
free(Params);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RHPProcessHTTPMessage(void * conn, char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE)
|
||||||
|
{
|
||||||
|
// RHP messages can be sent over Websocks or normal http but I think WhatsPac only uses WebSocks
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRHPWebSock(SOCKET Socket, char * Msg, int MsgLen)
|
||||||
|
{
|
||||||
|
int Loops = 0;
|
||||||
|
int InputLen = 0;
|
||||||
|
int Len;
|
||||||
|
|
||||||
|
char Value[16];
|
||||||
|
char * OutBuffer = malloc(250000);
|
||||||
|
|
||||||
|
// struct RHPConnectionInfo * RHPSocket = NULL;
|
||||||
|
// int n;
|
||||||
|
|
||||||
|
Msg[MsgLen] = 0;
|
||||||
|
|
||||||
|
// Find Connection Record. If none, create one
|
||||||
|
|
||||||
|
// I dont think I need connection records
|
||||||
|
|
||||||
|
/*
|
||||||
|
for (n = 0; n < NumberofRHPConnections; n++)
|
||||||
|
{
|
||||||
|
if (RHPSockets[n]->socket == socket)
|
||||||
|
{
|
||||||
|
RHPSocket = RHPSockets[n];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RHPSocket == 0)
|
||||||
|
{
|
||||||
|
// See if there is an old one we can reuse
|
||||||
|
|
||||||
|
for (n = 0; n < NumberofRHPConnections; n++)
|
||||||
|
{
|
||||||
|
if (RHPSockets[n]-Socket == -1)
|
||||||
|
{
|
||||||
|
RHPSocket = RHPSockets[n];
|
||||||
|
RHP
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RHPSocket == 0)
|
||||||
|
|
||||||
|
NumberofRHPConnections;
|
||||||
|
RHPSockets = realloc(RHPSockets, sizeof(void *) * (NumberofRHPConnections + 1));
|
||||||
|
RHPSocket = RHPSockets[NumberofRHPConnections] = zalloc(sizeof (struct RHPConnectionInfo));
|
||||||
|
NumberofRHPConnections++;
|
||||||
|
RHPSocket->socket = socket;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// {"type":"open","id":5,"pfam":"ax25","mode":"stream","port":"1","local":"G8BPQ","remote":"G8BPQ-2","flags":128}
|
||||||
|
// {"type": "openReply", "id": 82, "handle": 1, "errCode": 0, "errText": "Ok"}
|
||||||
|
// {"seqno": 0, "type": "status", "handle": 1, "flags": 0}
|
||||||
|
// ("seqno": 1, "type": "close", "handle": 1}
|
||||||
|
// {"id":40,"type":"close","handle":1}
|
||||||
|
|
||||||
|
// {"seqno": 0, "type": "status", "handle": 1, "flags": 2}.~.
|
||||||
|
// {"seqno": 1, "type": "recv", "handle": 1, "data": "Welcome to G8BPQ's Test Switch in Nottingham \rType ? for list of available commands.\r"}.
|
||||||
|
|
||||||
|
GetJSONValue(Msg, "\"type\":", Value, 15);
|
||||||
|
|
||||||
|
if (_stricmp(Value, "open") == 0)
|
||||||
|
{
|
||||||
|
Len = processRHCPOpen(Socket, Msg, &OutBuffer[10]); // Space at front for WebSock Header
|
||||||
|
if (Len)
|
||||||
|
SendWebSockMessage(Socket, OutBuffer, Len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_stricmp(Value, "send") == 0)
|
||||||
|
{
|
||||||
|
Len = processRHCPSend(Socket, Msg, &OutBuffer[10]); // Space at front for WebSock Header
|
||||||
|
SendWebSockMessage(Socket, OutBuffer, Len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_stricmp(Value, "close") == 0)
|
||||||
|
{
|
||||||
|
Len = processRHCPClose(Socket, Msg, &OutBuffer[10]); // Space at front for WebSock Header
|
||||||
|
SendWebSockMessage(Socket, OutBuffer, Len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Debugprintf(Msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRHPWebSockClosed(SOCKET socket)
|
||||||
|
{
|
||||||
|
// Close any connections on this scoket and delete socket entry
|
||||||
|
|
||||||
|
struct RHPSessionInfo * RHPSession = 0;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
// Find and close any Sessions
|
||||||
|
|
||||||
|
for (n = 0; n < NumberofRHPSessions; n++)
|
||||||
|
{
|
||||||
|
if (RHPSessions[n]->Socket == socket)
|
||||||
|
{
|
||||||
|
RHPSession = RHPSessions[n];
|
||||||
|
|
||||||
|
if (RHPSession->BPQStream)
|
||||||
|
{
|
||||||
|
Disconnect(RHPSession->BPQStream);
|
||||||
|
DeallocateStream(RHPSession->BPQStream);
|
||||||
|
|
||||||
|
RHPSession->BPQStream = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RHPSession->Connecting = 0;
|
||||||
|
|
||||||
|
// We can't send a close to RHP endpont as socket has gone
|
||||||
|
|
||||||
|
RHPSession->Connected = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int processRHCPOpen(SOCKET Socket, char * Msg, char * ReplyBuffer)
|
||||||
|
{
|
||||||
|
//{"type":"open","id":5,"pfam":"ax25","mode":"stream","port":"1","local":"G8BPQ","remote":"G8BPQ-2","flags":128}
|
||||||
|
|
||||||
|
struct RHPSessionInfo * RHPSession = 0;
|
||||||
|
|
||||||
|
char * Value = malloc(strlen(Msg)); // Will always be long enough
|
||||||
|
int ID;
|
||||||
|
|
||||||
|
char pfam[16];
|
||||||
|
char Mode[16];
|
||||||
|
int Port;
|
||||||
|
char Local[16];
|
||||||
|
char Remote[16];
|
||||||
|
int flags;
|
||||||
|
int Handle = 1;
|
||||||
|
int Stream;
|
||||||
|
unsigned char AXCall[10];
|
||||||
|
int Len;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
// ID seems to be used for control commands like open. SeqNo for data within a session (i Think!
|
||||||
|
|
||||||
|
ID = GetJSONInt(Msg, "\"id\":");
|
||||||
|
GetJSONValue(Msg, "\"pfam\":", pfam, 15);
|
||||||
|
GetJSONValue(Msg, "\"mode\":", Mode, 15);
|
||||||
|
Port = GetJSONInt(Msg, "\"port\":");
|
||||||
|
GetJSONValue(Msg, "\"local\":", Local, 15);
|
||||||
|
GetJSONValue(Msg, "\"remote\":", Remote, 15);
|
||||||
|
flags = GetJSONInt(Msg, "\"flags\":");
|
||||||
|
|
||||||
|
if (_stricmp(pfam, "ax25") != 0)
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0);
|
||||||
|
|
||||||
|
if (_stricmp(Mode, "stream") == 0)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// Allocate a RHP Session
|
||||||
|
|
||||||
|
// See if there is an old one we can reuse
|
||||||
|
|
||||||
|
for (n = 0; n < NumberofRHPSessions; n++)
|
||||||
|
{
|
||||||
|
if (RHPSessions[n]->BPQStream == 0)
|
||||||
|
{
|
||||||
|
RHPSession = RHPSessions[n];
|
||||||
|
Handle = n + 1;
|
||||||
|
Stream = RHPSessions[n]->BPQStream;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RHPSession == 0)
|
||||||
|
{
|
||||||
|
RHPSessions = realloc(RHPSessions, sizeof(void *) * (NumberofRHPSessions + 1));
|
||||||
|
RHPSession = RHPSessions[NumberofRHPSessions] = zalloc(sizeof (struct RHPSessionInfo));
|
||||||
|
NumberofRHPSessions++;
|
||||||
|
|
||||||
|
Handle = NumberofRHPSessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(pgm, "RHP");
|
||||||
|
Stream = FindFreeStreamNoSem();
|
||||||
|
strcpy(pgm, "bpq32.exe");
|
||||||
|
|
||||||
|
if (Stream == 255)
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0);
|
||||||
|
|
||||||
|
RHPSession->BPQStream = Stream;
|
||||||
|
RHPSession->Handle = Handle;
|
||||||
|
RHPSession->Connecting = TRUE;
|
||||||
|
RHPSession->Socket = Socket;
|
||||||
|
|
||||||
|
strcpy(RHPSession->Local, Local);
|
||||||
|
strcpy(RHPSession->Remote, Remote);
|
||||||
|
|
||||||
|
Connect(Stream);
|
||||||
|
|
||||||
|
ConvToAX25(Local, AXCall);
|
||||||
|
ChangeSessionCallsign(Stream, AXCall);
|
||||||
|
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 0, \"errText\": \"Ok\"}", ID, Handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"openReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errText\": \"Bad parameter\"}", ID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int processRHCPSend(SOCKET Socket, char * Msg, char * ReplyBuffer)
|
||||||
|
{
|
||||||
|
// {"type":"send","handle":1,"data":";;;;;;\r","id":70}
|
||||||
|
|
||||||
|
struct RHPSessionInfo * RHPSession;
|
||||||
|
|
||||||
|
int ID;
|
||||||
|
char * Data;
|
||||||
|
char * ptr;
|
||||||
|
int c;
|
||||||
|
int Len;
|
||||||
|
|
||||||
|
int Handle = 1;
|
||||||
|
|
||||||
|
Data = malloc(strlen(Msg));
|
||||||
|
|
||||||
|
ID = GetJSONInt(Msg, "\"id\":");
|
||||||
|
Handle = GetJSONInt(Msg, "\"handle\":");
|
||||||
|
GetJSONValue(Msg, "\"data\":", Data, strlen(Msg) - 1);
|
||||||
|
|
||||||
|
if (Handle < 1 || Handle > NumberofRHPSessions)
|
||||||
|
{
|
||||||
|
free(Data);
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"sendReply\", \"id\": %d, \"handle\": %d, \"errCode\": 12, \"errtext\": \"Invalid handle\"}", ID, Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
RHPSession = RHPSessions[Handle - 1];
|
||||||
|
|
||||||
|
// Look for \ escapes
|
||||||
|
|
||||||
|
ptr = Data;
|
||||||
|
|
||||||
|
while (ptr = strchr(ptr, '\\'))
|
||||||
|
{
|
||||||
|
c = ptr[1];
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'r':
|
||||||
|
|
||||||
|
*ptr = 13;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
|
||||||
|
*ptr = '\\';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
|
||||||
|
*ptr = '"';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memmove(ptr + 1, ptr + 2, strlen(ptr + 1));
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debugprintf(Data);
|
||||||
|
|
||||||
|
Len = strlen(Data);
|
||||||
|
ptr = Data;
|
||||||
|
|
||||||
|
|
||||||
|
while (Len > RHPPaclen)
|
||||||
|
{
|
||||||
|
SendMsgNoSem(RHPSession->BPQStream, ptr, RHPPaclen);
|
||||||
|
Len -= RHPPaclen;
|
||||||
|
ptr += RHPPaclen;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendMsgNoSem(RHPSession->BPQStream, ptr, Len);
|
||||||
|
|
||||||
|
free(Data);
|
||||||
|
return sprintf(ReplyBuffer, "{\"type\": \"sendReply\", \"id\": %d, \"handle\": %d, \"errCode\": 0, \"errText\": \"Ok\", \"status\": %d}", ID, Handle, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int processRHCPClose(SOCKET Socket, char * Msg, char * ReplyBuffer)
|
||||||
|
{
|
||||||
|
|
||||||
|
// {"id":70,"type":"close","handle":1}
|
||||||
|
|
||||||
|
|
||||||
|
struct RHPSessionInfo * RHPSession;
|
||||||
|
|
||||||
|
int ID;
|
||||||
|
int Handle = 1;
|
||||||
|
|
||||||
|
char * OutBuffer = malloc(256);
|
||||||
|
|
||||||
|
ID = GetJSONInt(Msg, "\"id\":");
|
||||||
|
Handle = GetJSONInt(Msg, "\"handle\":");
|
||||||
|
|
||||||
|
if (Handle < 1 || Handle > NumberofRHPSessions)
|
||||||
|
return sprintf(ReplyBuffer, "{\"id\": %d, \"type\": \"closeReply\", \"handle\": %d, \"errcode\": 12, \"errtext\": \"Invalid handle\"}", ID, Handle);
|
||||||
|
|
||||||
|
|
||||||
|
RHPSession = RHPSessions[Handle - 1];
|
||||||
|
Disconnect(RHPSession->BPQStream);
|
||||||
|
RHPSession->Connected = 0;
|
||||||
|
RHPSession->Connecting = 0;
|
||||||
|
|
||||||
|
DeallocateStream(RHPSession->BPQStream);
|
||||||
|
RHPSession->BPQStream = 0;
|
||||||
|
|
||||||
|
return sprintf(ReplyBuffer, "{\"id\": %d, \"type\": \"closeReply\", \"handle\": %d, \"errcode\": 0, \"errtext\": \"Ok\"}", ID, Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
char toHex[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
void RHPPoll()
|
||||||
|
{
|
||||||
|
int Stream;
|
||||||
|
int n;
|
||||||
|
int state, change;
|
||||||
|
int Len;
|
||||||
|
char * RHPMsg;
|
||||||
|
unsigned char Buffer[2048]; // Space to escape control chars
|
||||||
|
int pktlen, count;
|
||||||
|
|
||||||
|
struct RHPSessionInfo * RHPSession;
|
||||||
|
|
||||||
|
for (n = 0; n < NumberofRHPSessions; n++)
|
||||||
|
{
|
||||||
|
RHPSession = RHPSessions[n];
|
||||||
|
Stream = RHPSession->BPQStream;
|
||||||
|
|
||||||
|
// See if connected state has changed
|
||||||
|
|
||||||
|
SessionState(Stream, &state, &change);
|
||||||
|
|
||||||
|
if (change == 1)
|
||||||
|
{
|
||||||
|
if (state == 1)
|
||||||
|
{
|
||||||
|
// Connected
|
||||||
|
|
||||||
|
RHPSession->Seq = 0;
|
||||||
|
RHPSession->Connecting = FALSE;
|
||||||
|
RHPSession->Connected = TRUE;
|
||||||
|
|
||||||
|
RHPMsg = malloc(256);
|
||||||
|
Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"status\", \"handle\": %d, \"flags\": 2}", RHPSession->Seq++, RHPSession->Handle);
|
||||||
|
SendWebSockMessage(RHPSession->Socket, RHPMsg, Len);
|
||||||
|
|
||||||
|
// Send RHP CTEXT
|
||||||
|
|
||||||
|
RHPMsg = malloc(256);
|
||||||
|
Sleep(10); // otherwise WhatsPac doesn't display connected
|
||||||
|
Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"recv\", \"handle\": %d, \"data\": \"Connected to RHP Server\\r\"}", RHPSession->Seq++, RHPSession->Handle);
|
||||||
|
SendWebSockMessage(RHPSession->Socket, RHPMsg, Len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Disconnected. Send Close to client
|
||||||
|
|
||||||
|
RHPMsg = malloc(256);
|
||||||
|
Len = sprintf(&RHPMsg[10], "{\"type\": \"close\", \"seqno\": %d, \"handle\": %d}", RHPSession->Seq++, RHPSession->Handle);
|
||||||
|
SendWebSockMessage(RHPSession->Socket, RHPMsg, Len);
|
||||||
|
|
||||||
|
RHPSession->Connected = 0;
|
||||||
|
RHPSession->Connecting = 0;
|
||||||
|
|
||||||
|
DeallocateStream(RHPSession->BPQStream);
|
||||||
|
RHPSession->BPQStream = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
GetMsg(Stream, Buffer, &pktlen, &count);
|
||||||
|
|
||||||
|
if (pktlen > 0)
|
||||||
|
{
|
||||||
|
char * ptr = Buffer;
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
|
Buffer[pktlen] = 0;
|
||||||
|
|
||||||
|
// Message is JSON so Convert CR to \r, \ to \\ " to \"
|
||||||
|
|
||||||
|
// Looks like I need to escape everything not between 0x20 and 0x7f eg \U00c3
|
||||||
|
|
||||||
|
|
||||||
|
while (c = *(ptr))
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 13:
|
||||||
|
|
||||||
|
memmove(ptr + 2, ptr + 1, strlen(ptr) + 1);
|
||||||
|
*(ptr++) = '\\';
|
||||||
|
*(ptr++) = 'r';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
|
||||||
|
memmove(ptr + 2, ptr + 1, strlen(ptr) + 1);
|
||||||
|
*(ptr++) = '\\';
|
||||||
|
*(ptr++) = '"';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
|
||||||
|
memmove(ptr + 2, ptr + 1, strlen(ptr) + 1);
|
||||||
|
*(ptr++) = '\\';
|
||||||
|
*(ptr++) = '\\';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
if (c > 127)
|
||||||
|
{
|
||||||
|
memmove(ptr + 6, ptr + 1, strlen(ptr) + 1);
|
||||||
|
*(ptr++) = '\\';
|
||||||
|
*(ptr++) = 'u';
|
||||||
|
*(ptr++) = '0';
|
||||||
|
*(ptr++) = '0';
|
||||||
|
*(ptr++) = toHex[c >> 4];
|
||||||
|
*(ptr++) = toHex[c & 15];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RHPMsg = malloc(2048);
|
||||||
|
|
||||||
|
Len = sprintf(&RHPMsg[10], "{\"seqno\": %d, \"type\": \"recv\", \"handle\": %d, \"data\": \"%s\"}", RHPSession->Seq++, RHPSession->Handle, Buffer);
|
||||||
|
SendWebSockMessage(RHPSession->Socket, RHPMsg, Len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while (count > 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value, int Len)
|
||||||
|
{
|
||||||
|
char * ptr1, * ptr2;
|
||||||
|
|
||||||
|
Value[0] = 0;
|
||||||
|
|
||||||
|
ptr1 = strstr(_REPLYBUFFER, Name);
|
||||||
|
|
||||||
|
if (ptr1 == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ptr1 += (strlen(Name) + 1);
|
||||||
|
|
||||||
|
// "data":"{\"t\":\"c\",\"n\":\"John\",\"c\":\"G8BPQ\",\"lm\":1737912636,\"le\":1737883907,\"led\":1737758451,\"v\":0.33,\"cc\":[{\"cid\":1,\"lp\":1737917257201,\"le\":1737913735726,\"led\":1737905249785},{\"cid\":0,\"lp\":1737324074107,\"le\":1737323831510,\"led\":1737322973662},{\"cid\":5,\"lp\":1737992107419,\"le\":1737931466510,\"led\":1737770056244}]}\r","id":28}
|
||||||
|
|
||||||
|
// There may be escaped " in data stream
|
||||||
|
|
||||||
|
ptr2 = strchr(ptr1, '"');
|
||||||
|
|
||||||
|
while (*(ptr2 - 1) == '\\')
|
||||||
|
{
|
||||||
|
ptr2 = strchr(ptr2 + 2, '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (ptr2)
|
||||||
|
{
|
||||||
|
size_t ValLen = ptr2 - ptr1;
|
||||||
|
if (ValLen > Len)
|
||||||
|
ValLen = Len;
|
||||||
|
|
||||||
|
memcpy(Value, ptr1, ValLen);
|
||||||
|
Value[ValLen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int GetJSONInt(char * _REPLYBUFFER, char * Name)
|
||||||
|
{
|
||||||
|
char * ptr1;
|
||||||
|
|
||||||
|
ptr1 = strstr(_REPLYBUFFER, Name);
|
||||||
|
|
||||||
|
if (ptr1 == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ptr1 += (strlen(Name));
|
||||||
|
|
||||||
|
return atoi(ptr1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,125 @@
|
|||||||
|
|
||||||
|
#ifdef Kernel
|
||||||
|
|
||||||
|
#define Vers 5,2,9,2
|
||||||
|
#define Verstring "5.2.9.2\0"
|
||||||
|
#define Datestring "September 2012"
|
||||||
|
#define VerComments "G8BPQ Packet Switch V5.2.9.2\0"
|
||||||
|
#define VerCopyright "Copyright © 2001-2012 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "BPQ32 Switch\0"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define KVers 6,0,24,59
|
||||||
|
#define KVerstring "6.0.24.59\0"
|
||||||
|
|
||||||
|
#ifdef CKernel
|
||||||
|
|
||||||
|
#define Vers KVers
|
||||||
|
#define Verstring KVerstring
|
||||||
|
#define Datestring "January 2025"
|
||||||
|
#define VerComments "G8BPQ Packet Switch (C Version)" KVerstring
|
||||||
|
#define VerCopyright "Copyright © 2001-2025 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "BPQ32 Switch\0"
|
||||||
|
#define VerProduct "BPQ32"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TermTCP
|
||||||
|
|
||||||
|
#define Vers 1,0,16,2
|
||||||
|
#define Verstring "1.0.16.2\0"
|
||||||
|
#define VerComments "Internet Terminal for G8BPQ Packet Switch\0"
|
||||||
|
#define VerCopyright "Copyright © 2011-2025 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "Simple TCP Terminal Program for G8BPQ Switch\0"
|
||||||
|
#define VerProduct "BPQTermTCP"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BPQTerm
|
||||||
|
|
||||||
|
#define Vers 2,2,5,2
|
||||||
|
#define Verstring "2.2.5.2\0"
|
||||||
|
#define VerComments "Simple Terminal for G8BPQ Packet Switch\0"
|
||||||
|
#define VerCopyright "Copyright © 1999-2025 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "Simple Terminal Program for G8BPQ Switch\0"
|
||||||
|
#define VerProduct "BPQTerminal"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BPQTermMDI
|
||||||
|
|
||||||
|
#define Vers 2,2,0,3
|
||||||
|
#define Verstring "2.2.0.3\0"
|
||||||
|
#define VerComments "MDI Terminal for G8BPQ Packet Switch\0"
|
||||||
|
#define VerCopyright "Copyright © 1999-2025 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "MDI Terminal Program for G8BPQ Switch\0"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAIL
|
||||||
|
|
||||||
|
#define Vers KVers
|
||||||
|
#define Verstring KVerstring
|
||||||
|
#define VerComments "Mail server for G8BPQ Packet Switch\0"
|
||||||
|
#define VerCopyright "Copyright © 2009-2025 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "Mail server for G8BPQ's 32 Bit Switch\0"
|
||||||
|
#define VerProduct "BPQMail"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HOSTMODES
|
||||||
|
|
||||||
|
#define Vers 1,1,8,1
|
||||||
|
#define Verstring "1.1.8.1\0"
|
||||||
|
//#define SPECIALVERSION "Test 3"
|
||||||
|
#define VerComments "Host Modes Emulator for G8BPQ Packet Switch\0"
|
||||||
|
#define VerCopyright "Copyright © 2009-2019 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "Host Modes Emulator for G8BPQ's 32 Bit Switch\0"
|
||||||
|
#define VerProduct "BPQHostModes"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef UIUTIL
|
||||||
|
|
||||||
|
#define Vers 0,1,3,1
|
||||||
|
#define Verstring "0.1.3.1\0"
|
||||||
|
#define VerComments "Beacon Utility for G8BPQ Packet Switch\0"
|
||||||
|
#define VerCopyright "Copyright © 2011-2019 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "Beacon Utility for G8BPQ Switch\0"
|
||||||
|
#define VerProduct "BPQUIUtil"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef AUTH
|
||||||
|
|
||||||
|
#define Vers 0,1,0,0
|
||||||
|
#define Verstring "0.1.0.0\0"
|
||||||
|
#define VerComments "Password Generation Utility for G8BPQ Packet Switch\0"
|
||||||
|
#define VerCopyright "Copyright © 2011-2025 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "Password Generation Utility for G8BPQ Switch\0"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef APRS
|
||||||
|
|
||||||
|
#define Vers KVers
|
||||||
|
#define Verstring KVerstring
|
||||||
|
#define VerComments "APRS Client for G8BPQ Switch\0"
|
||||||
|
#define VerCopyright "Copyright © 2012-2025 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "APRS Client for G8BPQ Switch\0"
|
||||||
|
#define VerProduct "BPQAPRS"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHAT
|
||||||
|
|
||||||
|
#define Vers KVers
|
||||||
|
#define Verstring KVerstring
|
||||||
|
#define VerComments "Chat server for G8BPQ Packet Switch\0"
|
||||||
|
#define VerCopyright "Copyright © 2009-2025 John Wiseman G8BPQ\0"
|
||||||
|
#define VerDesc "Chat server for G8BPQ's 32 Bit Switch\0"
|
||||||
|
#define VerProduct "BPQChat"
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioUserFile
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
ShowAllFiles="false"
|
||||||
|
>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<DebugSettings
|
||||||
|
Command="$(TargetPath)"
|
||||||
|
WorkingDirectory=""
|
||||||
|
CommandArguments=""
|
||||||
|
Attach="false"
|
||||||
|
DebuggerType="3"
|
||||||
|
Remote="1"
|
||||||
|
RemoteMachine="LAPTOP-Q6S4RP5Q"
|
||||||
|
RemoteCommand=""
|
||||||
|
HttpUrl=""
|
||||||
|
PDBPath=""
|
||||||
|
SQLDebugging=""
|
||||||
|
Environment=""
|
||||||
|
EnvironmentMerge="true"
|
||||||
|
DebuggerFlavor=""
|
||||||
|
MPIRunCommand=""
|
||||||
|
MPIRunArguments=""
|
||||||
|
MPIRunWorkingDirectory=""
|
||||||
|
ApplicationCommand=""
|
||||||
|
ApplicationArguments=""
|
||||||
|
ShimCommand=""
|
||||||
|
MPIAcceptMode=""
|
||||||
|
MPIAcceptFilter=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<DebugSettings
|
||||||
|
Command="$(TargetPath)"
|
||||||
|
WorkingDirectory=""
|
||||||
|
CommandArguments=""
|
||||||
|
Attach="false"
|
||||||
|
DebuggerType="3"
|
||||||
|
Remote="1"
|
||||||
|
RemoteMachine="LAPTOP-Q6S4RP5Q"
|
||||||
|
RemoteCommand=""
|
||||||
|
HttpUrl=""
|
||||||
|
PDBPath=""
|
||||||
|
SQLDebugging=""
|
||||||
|
Environment=""
|
||||||
|
EnvironmentMerge="true"
|
||||||
|
DebuggerFlavor=""
|
||||||
|
MPIRunCommand=""
|
||||||
|
MPIRunArguments=""
|
||||||
|
MPIRunWorkingDirectory=""
|
||||||
|
ApplicationCommand=""
|
||||||
|
ApplicationArguments=""
|
||||||
|
ShimCommand=""
|
||||||
|
MPIAcceptMode=""
|
||||||
|
MPIAcceptFilter=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
</VisualStudioUserFile>
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,447 @@
|
|||||||
|
//
|
||||||
|
// Prototypes for BPQ32 Node Functions
|
||||||
|
//
|
||||||
|
|
||||||
|
#define DllImport
|
||||||
|
|
||||||
|
#define EXCLUDEBITS
|
||||||
|
|
||||||
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
|
||||||
|
#include "compatbits.h"
|
||||||
|
|
||||||
|
#include "asmstrucs.h"
|
||||||
|
|
||||||
|
BOOL CheckExcludeList(UCHAR * Call);
|
||||||
|
|
||||||
|
Dll int ConvFromAX25(unsigned char * incall,unsigned char * outcall);
|
||||||
|
Dll BOOL ConvToAX25(unsigned char * callsign, unsigned char * ax25call);
|
||||||
|
DllExport BOOL ConvToAX25Ex(unsigned char * callsign, unsigned char * ax25call);
|
||||||
|
int WritetoConsoleLocal(char * buff);
|
||||||
|
VOID Consoleprintf(const char * format, ...);
|
||||||
|
VOID FreeConfig();
|
||||||
|
int GetListeningPortsPID(int Port);
|
||||||
|
|
||||||
|
void * InitializeExtDriver(PEXTPORTDATA PORTVEC);
|
||||||
|
|
||||||
|
VOID PutLengthinBuffer(PDATAMESSAGE buff, USHORT datalen); // Needed for arm5 portability
|
||||||
|
int GetLengthfromBuffer(PDATAMESSAGE buff);
|
||||||
|
int IntDecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp, uint64_t Mask, BOOL APRS, BOOL MCTL);
|
||||||
|
int IntSetTraceOptionsEx(uint64_t mask, int mtxparam, int mcomparam, int monUIOnly);
|
||||||
|
int CountBits64(uint64_t in);Buff() _GetBuff(__FILE__, __LINE__)
|
||||||
|
#define ReleaseBuffer(s) _ReleaseBuffer(s, __FILE__, __LINE__)
|
||||||
|
#define CheckGuardZone() _CheckGuardZone(__FILE__, __LINE__)
|
||||||
|
|
||||||
|
#define Q_REM(s) _Q_REM(s, __FILE__, __LINE__)
|
||||||
|
#define Q_REM_NP(s) _Q_REM_NP(s, __FILE__, __LINE__)
|
||||||
|
|
||||||
|
#define C_Q_ADD(s, b) _C_Q_ADD(s, b, __FILE__, __LINE__)
|
||||||
|
|
||||||
|
void _CheckGuardZone(char * File, int Line);
|
||||||
|
|
||||||
|
VOID * _Q_REM(VOID **Q, char * File, int Line);
|
||||||
|
VOID * _Q_REM_NP(VOID *Q, char * File, int Line);
|
||||||
|
|
||||||
|
int _C_Q_ADD(VOID *Q, VOID *BU
|
||||||
|
|
||||||
|
#define GetFF, char * File, int Line);
|
||||||
|
|
||||||
|
UINT _ReleaseBuffer(VOID *BUFF, char * File, int Line);
|
||||||
|
|
||||||
|
VOID * _GetBuff(char * File, int Line);
|
||||||
|
int _C_Q_ADD(VOID *PQ, VOID *PBUFF, char * File, int Line);
|
||||||
|
|
||||||
|
int C_Q_COUNT(VOID *Q);
|
||||||
|
|
||||||
|
DllExport char * APIENTRY GetApplCall(int Appl);
|
||||||
|
DllExport char * APIENTRY GetApplAlias(int Appl);
|
||||||
|
DllExport int APIENTRY FindFreeStream();
|
||||||
|
DllExport int APIENTRY DeallocateStream(int stream);
|
||||||
|
DllExport int APIENTRY SessionState(int stream, int * state, int * change);
|
||||||
|
DllExport int APIENTRY SetAppl(int stream, int flags, int mask);
|
||||||
|
DllExport int APIENTRY GetMsg(int stream, char * msg, int * len, int * count );
|
||||||
|
DllExport int APIENTRY GetConnectionInfo(int stream, char * callsign,
|
||||||
|
int * port, int * sesstype, int * paclen,
|
||||||
|
int * maxframe, int * l4window);
|
||||||
|
|
||||||
|
#define LIBCONFIG_STATIC
|
||||||
|
#include "libconfig.h"
|
||||||
|
|
||||||
|
int GetIntValue(config_setting_t * group, char * name);
|
||||||
|
BOOL GetStringValue(config_setting_t * group, char * name, char * value, int maxlen);
|
||||||
|
VOID SaveIntValue(config_setting_t * group, char * name, int value);
|
||||||
|
VOID SaveStringValue(config_setting_t * group, char * name, char * value);
|
||||||
|
|
||||||
|
int EncryptPass(char * Pass, char * Encrypt);
|
||||||
|
VOID DecryptPass(char * Encrypt, unsigned char * Pass, unsigned int len);
|
||||||
|
Dll VOID APIENTRY CreateOneTimePassword(char * Password, char * KeyPhrase, int TimeOffset);
|
||||||
|
Dll BOOL APIENTRY CheckOneTimePassword(char * Password, char * KeyPhrase);
|
||||||
|
|
||||||
|
DllExport int APIENTRY TXCount(int stream);
|
||||||
|
DllExport int APIENTRY RXCount(int stream);
|
||||||
|
DllExport int APIENTRY MONCount(int stream);
|
||||||
|
|
||||||
|
VOID ReadNodes();
|
||||||
|
int BPQTRACE(MESSAGE * Msg, BOOL APRS);
|
||||||
|
|
||||||
|
VOID CommandHandler(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer);
|
||||||
|
|
||||||
|
VOID PostStateChange(TRANSPORTENTRY * Session);
|
||||||
|
|
||||||
|
VOID InnerCommandHandler(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer);
|
||||||
|
VOID DoTheCommand(TRANSPORTENTRY * Session);
|
||||||
|
char * MOVEANDCHECK(TRANSPORTENTRY * Session, char * Bufferptr, char * Source, int Len);
|
||||||
|
VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer);
|
||||||
|
char * strlop(const char * buf, char delim);
|
||||||
|
BOOL CompareCalls(UCHAR * c1, UCHAR * c2);
|
||||||
|
|
||||||
|
VOID PostDataAvailable(TRANSPORTENTRY * Session);
|
||||||
|
int WritetoConsoleLocal(char * buff);
|
||||||
|
char * CHECKBUFFER(TRANSPORTENTRY * Session, char * Bufferptr);
|
||||||
|
VOID CLOSECURRENTSESSION(TRANSPORTENTRY * Session);
|
||||||
|
|
||||||
|
VOID SendCommandReply(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer, int Len);
|
||||||
|
|
||||||
|
struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum);
|
||||||
|
|
||||||
|
int cCOUNT_AT_L2(struct _LINKTABLE * LINK);
|
||||||
|
VOID SENDL4CONNECT(TRANSPORTENTRY * Session);
|
||||||
|
|
||||||
|
VOID CloseSessionPartner(TRANSPORTENTRY * Session);
|
||||||
|
int COUNTNODES(struct ROUTE * ROUTE);
|
||||||
|
int DecodeNodeName(char * NodeName, char * ptr);;
|
||||||
|
VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer);
|
||||||
|
int cCOUNT_AT_L2(struct _LINKTABLE * LINK);
|
||||||
|
void * zalloc(int len);
|
||||||
|
BOOL FindDestination(UCHAR * Call, struct DEST_LIST ** REQDEST);
|
||||||
|
|
||||||
|
BOOL ProcessConfig();
|
||||||
|
|
||||||
|
VOID PUT_ON_PORT_Q(struct PORTCONTROL * PORT, MESSAGE * Buffer);
|
||||||
|
VOID CLEAROUTLINK(struct _LINKTABLE * LINK);
|
||||||
|
VOID TellINP3LinkGone(struct ROUTE * Route);
|
||||||
|
VOID CLEARACTIVEROUTE(struct ROUTE * ROUTE, int Reason);
|
||||||
|
|
||||||
|
// Reason Equates
|
||||||
|
|
||||||
|
#define NORMALCLOSE 0
|
||||||
|
#define RETRIEDOUT 1
|
||||||
|
#define SETUPFAILED 2
|
||||||
|
#define LINKLOST 3
|
||||||
|
#define LINKSTUCK 4
|
||||||
|
|
||||||
|
int COUNT_AT_L2(struct _LINKTABLE * LINK);
|
||||||
|
VOID SENDIDMSG();
|
||||||
|
VOID SENDBTMSG();
|
||||||
|
VOID INP3TIMER();
|
||||||
|
VOID REMOVENODE(dest_list * DEST);
|
||||||
|
BOOL ACTIVATE_DEST(struct DEST_LIST * DEST);
|
||||||
|
VOID TellINP3LinkSetupFailed(struct ROUTE * Route);
|
||||||
|
BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE);
|
||||||
|
VOID PROCROUTES(struct DEST_LIST * DEST, struct ROUTE * ROUTE, int Qual);
|
||||||
|
BOOL L2SETUPCROSSLINK(PROUTE ROUTE);
|
||||||
|
VOID REMOVENODE(dest_list * DEST);
|
||||||
|
char * SetupNodeHeader(struct DATAMESSAGE * Buffer);
|
||||||
|
VOID L4CONNECTFAILED(TRANSPORTENTRY * L4);
|
||||||
|
int CountFramesQueuedOnSession(TRANSPORTENTRY * Session);
|
||||||
|
VOID CLEARSESSIONENTRY(TRANSPORTENTRY * Session);
|
||||||
|
VOID __cdecl Debugprintf(const char * format, ...);
|
||||||
|
|
||||||
|
int APIENTRY Restart();
|
||||||
|
int APIENTRY Reboot();
|
||||||
|
int APIENTRY Reconfig();
|
||||||
|
Dll int APIENTRY SaveNodes ();
|
||||||
|
|
||||||
|
|
||||||
|
struct SEM;
|
||||||
|
|
||||||
|
void GetSemaphore(struct SEM * Semaphore, int ID);
|
||||||
|
void FreeSemaphore(struct SEM * Semaphore);
|
||||||
|
|
||||||
|
void MySetWindowText(HWND hWnd, char * Msg);
|
||||||
|
|
||||||
|
Dll int APIENTRY SessionControl(int stream, int command, int Mask);
|
||||||
|
|
||||||
|
HANDLE OpenCOMPort(VOID * pPort, int speed, BOOL SetDTR, BOOL SetRTS, BOOL Quiet, int Stopbits);
|
||||||
|
int ReadCOMBlock(HANDLE fd, char * Block, int MaxLength);
|
||||||
|
BOOL WriteCOMBlock(HANDLE fd, char * Block, int BytesToWrite);
|
||||||
|
VOID CloseCOMPort(HANDLE fd);
|
||||||
|
|
||||||
|
VOID initUTF8();
|
||||||
|
int Is8Bit(unsigned char *cpt, int len);
|
||||||
|
int WebIsUTF8(unsigned char *ptr, int len);
|
||||||
|
int IsUTF8(unsigned char *ptr, int len);
|
||||||
|
int Convert437toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF);
|
||||||
|
int Convert1251toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF);
|
||||||
|
int Convert1252toUTF8(unsigned char * MsgPtr, int len, unsigned char * UTF);
|
||||||
|
int TrytoGuessCode(unsigned char * Char, int Len);
|
||||||
|
|
||||||
|
|
||||||
|
#define CMD_TO_APPL 1 // PASS COMMAND TO APPLICATION
|
||||||
|
#define MSG_TO_USER 2 // SEND 'CONNECTED' TO USER
|
||||||
|
#define MSG_TO_APPL 4 // SEND 'CONECTED' TO APPL
|
||||||
|
#define CHECK_FOR_ESC 8 // Look for ^d (^D) to disconnect session)
|
||||||
|
|
||||||
|
#define UI 3
|
||||||
|
#define SABM 0x2F
|
||||||
|
#define DISC 0x43
|
||||||
|
#define DM 0x0F
|
||||||
|
#define UA 0x63
|
||||||
|
#define FRMR 0x87
|
||||||
|
#define RR 1
|
||||||
|
#define RNR 5
|
||||||
|
#define REJ 9
|
||||||
|
|
||||||
|
// V2.2 Types
|
||||||
|
|
||||||
|
#define SREJ 0x0D
|
||||||
|
#define SABME 0x6F
|
||||||
|
#define XID 0xAF
|
||||||
|
#define TEST 0xE3
|
||||||
|
|
||||||
|
#define SUPPORT2point2 1
|
||||||
|
|
||||||
|
// XID Optional Functions
|
||||||
|
|
||||||
|
#define OPMustHave 0x02A080 // Sync TEST 16 bit FCS Extended Address
|
||||||
|
#define OPSREJ 4
|
||||||
|
#define OPSREJMult 0x200000
|
||||||
|
#define OPREJ 2
|
||||||
|
#define OPMod8 0x400
|
||||||
|
#define OPMod128 0x800
|
||||||
|
|
||||||
|
#define BPQHOSTSTREAMS 64
|
||||||
|
|
||||||
|
extern TRANSPORTENTRY * L4TABLE;
|
||||||
|
extern unsigned char NEXTID;
|
||||||
|
extern int MAXCIRCUITS;
|
||||||
|
extern int L4DEFAULTWINDOW;
|
||||||
|
extern int L4T1;
|
||||||
|
extern APPLCALLS APPLCALLTABLE[];
|
||||||
|
extern char * APPLS;
|
||||||
|
extern int NEEDMH;
|
||||||
|
extern int RFOnly;
|
||||||
|
|
||||||
|
extern char SESSIONHDDR[];
|
||||||
|
|
||||||
|
extern UCHAR NEXTID;
|
||||||
|
|
||||||
|
extern struct ROUTE * NEIGHBOURS;
|
||||||
|
extern int MAXNEIGHBOURS;
|
||||||
|
|
||||||
|
extern struct ROUTE * NEIGHBOURS;
|
||||||
|
extern int ROUTE_LEN;
|
||||||
|
extern int MAXNEIGHBOURS;
|
||||||
|
|
||||||
|
extern struct DEST_LIST * DESTS; // NODE LIST
|
||||||
|
extern struct DEST_LIST * ENDDESTLIST;
|
||||||
|
extern int DEST_LIST_LEN;
|
||||||
|
extern int MAXDESTS; // MAX NODES IN SYSTEM
|
||||||
|
|
||||||
|
extern struct _LINKTABLE * LINKS;
|
||||||
|
extern int LINK_TABLE_LEN;
|
||||||
|
extern int MAXLINKS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern char MYCALL[]; // DB 7 DUP (0) ; NODE CALLSIGN (BIT SHIFTED)
|
||||||
|
extern char MYALIASTEXT[]; // {" " ; NODE ALIAS (KEEP TOGETHER)
|
||||||
|
|
||||||
|
extern UCHAR MYCALLWITHALIAS[13];
|
||||||
|
extern APPLCALLS APPLCALLTABLE[NumberofAppls];
|
||||||
|
|
||||||
|
extern UCHAR MYNODECALL[]; // NODE CALLSIGN (ASCII)
|
||||||
|
extern char NODECALLLOPPED[]; // NODE CALLSIGN (ASCII). Null terminated
|
||||||
|
extern UCHAR MYNETROMCALL[]; // NETROM CALLSIGN (ASCII)
|
||||||
|
|
||||||
|
extern UCHAR NETROMCALL[]; // NETORM CALL (AX25)
|
||||||
|
|
||||||
|
extern VOID * FREE_Q;
|
||||||
|
|
||||||
|
extern struct PORTCONTROL * PORTTABLE;
|
||||||
|
extern int NUMBEROFPORTS;
|
||||||
|
|
||||||
|
|
||||||
|
extern int OBSINIT; // INITIAL OBSOLESCENCE VALUE
|
||||||
|
extern int OBSMIN; // MINIMUM TO BROADCAST
|
||||||
|
extern int L3INTERVAL; // "NODES" INTERVAL IN MINS
|
||||||
|
extern int IDINTERVAL; // "ID" BROADCAST INTERVAL
|
||||||
|
extern int BTINTERVAL; // "BT" BROADCAST INTERVAL
|
||||||
|
extern int MINQUAL; // MIN QUALITY FOR AUTOUPDATES
|
||||||
|
extern int HIDENODES; // N * COMMAND SWITCH
|
||||||
|
extern int BBSQUAL; // QUALITY OF BBS RELATIVE TO NODE
|
||||||
|
|
||||||
|
extern int NUMBEROFBUFFERS; // PACKET BUFFERS
|
||||||
|
extern int PACLEN; //MAX PACKET SIZE
|
||||||
|
|
||||||
|
// L2 SYSTEM TIMER RUNS AT 3 HZ
|
||||||
|
|
||||||
|
extern int T3; // LINK VALIDATION TIMER (3 MINS) (+ a bit to reduce RR collisions)
|
||||||
|
|
||||||
|
extern int L2KILLTIME; // IDLE LINK TIMER (16 MINS)
|
||||||
|
extern int L3LIVES; // MAX L3 HOPS
|
||||||
|
extern int L4N2; // LEVEL 4 RETRY COUNT
|
||||||
|
extern int L4LIMIT; // IDLE SESSION LIMIT - 15 MINS
|
||||||
|
extern int L4DELAY; // L4 DELAYED ACK TIMER
|
||||||
|
|
||||||
|
extern int BBS; // INCLUDE BBS SUPPORT
|
||||||
|
extern int NODE; // INCLUDE SWITCH SUPPORT
|
||||||
|
|
||||||
|
extern int FULL_CTEXT; // CTEXT ON ALL CONNECTS IF NZ
|
||||||
|
|
||||||
|
|
||||||
|
// Although externally streams are numbered 1 to 64, internally offsets are 0 - 63
|
||||||
|
|
||||||
|
extern BPQVECSTRUC DUMMYVEC; // Needed to force correct order of following
|
||||||
|
|
||||||
|
extern BPQVECSTRUC BPQHOSTVECTOR[BPQHOSTSTREAMS + 5];
|
||||||
|
|
||||||
|
extern int NODEORDER;
|
||||||
|
extern UCHAR LINKEDFLAG;
|
||||||
|
|
||||||
|
extern UCHAR UNPROTOCALL[80];
|
||||||
|
|
||||||
|
|
||||||
|
extern char * INFOMSG;
|
||||||
|
|
||||||
|
extern char * CTEXTMSG;
|
||||||
|
extern int CTEXTLEN;
|
||||||
|
|
||||||
|
extern UCHAR MYALIAS[7]; // ALIAS IN AX25 FORM
|
||||||
|
extern UCHAR BBSALIAS[7];
|
||||||
|
|
||||||
|
extern VOID * TRACE_Q; // TRANSMITTED FRAMES TO BE TRACED
|
||||||
|
|
||||||
|
extern char HEADERCHAR; // CHAR FOR _NODE HEADER MSGS
|
||||||
|
|
||||||
|
extern int AUTOSAVE; // AUTO SAVE NODES ON EXIT FLAG
|
||||||
|
extern int L4APPL; // Application for BBSCALL/ALIAS connects
|
||||||
|
extern int CFLAG; // C =HOST Command
|
||||||
|
|
||||||
|
extern VOID * IDMSG_Q; // ID/BEACONS WAITING TO BE SENT
|
||||||
|
|
||||||
|
extern struct DATAMESSAGE BTHDDR;
|
||||||
|
extern struct _MESSAGE IDHDDR;
|
||||||
|
|
||||||
|
extern VOID * IDMSG;
|
||||||
|
|
||||||
|
extern int L3TIMER; // TIMER FOR 'NODES' MESSAGE
|
||||||
|
extern int IDTIMER; // TIMER FOR ID MESSAGE
|
||||||
|
extern int BTTIMER; // TIMER FOR BT MESSAGE
|
||||||
|
|
||||||
|
extern int STATSTIME;
|
||||||
|
|
||||||
|
|
||||||
|
extern BOOL IPRequired;
|
||||||
|
extern int MaxHops;
|
||||||
|
extern int MAXRTT;
|
||||||
|
extern USHORT CWTABLE[];
|
||||||
|
extern TRANSPORTENTRY * L4TABLE;
|
||||||
|
extern UCHAR ROUTEQUAL;
|
||||||
|
extern UINT BPQMsg;
|
||||||
|
extern UCHAR ExcludeList[];
|
||||||
|
|
||||||
|
|
||||||
|
extern APPLCALLS APPLCALLTABLE[];
|
||||||
|
|
||||||
|
extern char VersionStringWithBuild[];
|
||||||
|
extern char VersionString[];
|
||||||
|
|
||||||
|
extern int MAXHEARDENTRIES;
|
||||||
|
extern int MHLEN;
|
||||||
|
|
||||||
|
extern int APPL1;
|
||||||
|
extern int PASSCMD;
|
||||||
|
extern int NUMBEROFCOMMANDS;
|
||||||
|
|
||||||
|
extern char * ConfigBuffer;
|
||||||
|
|
||||||
|
extern char * WL2KReportLine[];
|
||||||
|
|
||||||
|
extern struct CMDX COMMANDS[];
|
||||||
|
|
||||||
|
extern int QCOUNT, MAXBUFFS, MAXCIRCUITS, L4DEFAULTWINDOW, L4T1, CMDXLEN;
|
||||||
|
extern char CMDALIAS[ALIASLEN][NumberofAppls];
|
||||||
|
|
||||||
|
extern int SEMGETS;
|
||||||
|
extern int SEMRELEASES;
|
||||||
|
extern int SEMCLASHES;
|
||||||
|
extern int MINBUFFCOUNT;
|
||||||
|
|
||||||
|
extern UCHAR BPQDirectory[];
|
||||||
|
extern UCHAR BPQProgramDirectory[];
|
||||||
|
|
||||||
|
extern UCHAR WINMOR[];
|
||||||
|
extern UCHAR PACTORCALL[];
|
||||||
|
|
||||||
|
extern UCHAR MCOM;
|
||||||
|
extern UCHAR MUIONLY;
|
||||||
|
extern UCHAR MTX;
|
||||||
|
extern uint64_t MMASK;
|
||||||
|
|
||||||
|
extern UCHAR NODECALL[]; // NODES in ax.25
|
||||||
|
|
||||||
|
extern int L4CONNECTSOUT;
|
||||||
|
extern int L4CONNECTSIN;
|
||||||
|
extern int L4FRAMESTX;
|
||||||
|
extern int L4FRAMESRX;
|
||||||
|
extern int L4FRAMESRETRIED;
|
||||||
|
extern int OLDFRAMES;
|
||||||
|
extern int L3FRAMES;
|
||||||
|
|
||||||
|
extern char * PortConfig[];
|
||||||
|
extern struct SEM Semaphore;
|
||||||
|
extern UCHAR AuthorisedProgram; // Local Variable. Set if Program is on secure list
|
||||||
|
|
||||||
|
extern int REALTIMETICKS;
|
||||||
|
|
||||||
|
extern time_t CurrentSecs;
|
||||||
|
extern time_t lastSlowSecs;
|
||||||
|
extern time_t lastSaveSecs;
|
||||||
|
|
||||||
|
// SNMP Variables
|
||||||
|
|
||||||
|
extern int InOctets[64];
|
||||||
|
extern int OutOctets[64];
|
||||||
|
|
||||||
|
extern BOOL CloseAllNeeded;
|
||||||
|
extern int CloseOnError;
|
||||||
|
|
||||||
|
extern char * PortConfig[70];
|
||||||
|
extern struct TNCINFO * TNCInfo[71]; // Records are Malloc'd
|
||||||
|
|
||||||
|
#define MaxBPQPortNo 63 // Port 64 reserved for BBS Mon
|
||||||
|
#define MAXBPQPORTS 63
|
||||||
|
|
||||||
|
// IP, APRS use port ocnfig slots above the real port range
|
||||||
|
|
||||||
|
#define IPConfigSlot MaxBPQPortNo + 1
|
||||||
|
#define PortMapConfigSlot MaxBPQPortNo + 2
|
||||||
|
#define APRSConfigSlot MaxBPQPortNo + 3
|
||||||
|
|
||||||
|
|
||||||
|
extern char * UIUIDigi[MaxBPQPortNo + 1];
|
||||||
|
extern char UIUIDEST[MaxBPQPortNo + 1][11]; // Dest for Beacons
|
||||||
|
extern UCHAR FN[MaxBPQPortNo + 1][256]; // Filename
|
||||||
|
extern int Interval[MaxBPQPortNo + 1]; // Beacon Interval (Mins)
|
||||||
|
extern char Message[MaxBPQPortNo + 1][1000]; // Beacon Text
|
||||||
|
|
||||||
|
extern int MinCounter[MaxBPQPortNo + 1]; // Interval Countdown
|
||||||
|
extern BOOL SendFromFile[MaxBPQPortNo + 1];
|
||||||
|
|
||||||
|
extern BOOL MQTT;
|
||||||
|
extern char MQTT_HOST[80];
|
||||||
|
extern int MQTT_PORT;
|
||||||
|
extern char MQTT_USER[80];
|
||||||
|
extern char MQTT_PASS[80];
|
||||||
|
|
||||||
|
DllExport uint64_t APIENTRY GetPortFrequency(int PortNo, char * FreqStringMhz);
|
||||||
|
|
||||||
|
|
||||||
|
void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK);
|
||||||
|
void hookL2SessionDeleted(struct _LINKTABLE * LINK);
|
||||||
|
void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK);
|
||||||
|
|
||||||
|
void hookL4SessionAttempt(void * STREAM, char * remotecall, char * ourcall);
|
||||||
|
void hookL4SessionAccepted(void * STREAM, char * remotecall, char * ourcall);
|
||||||
|
void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM);
|
||||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,43 @@
|
|||||||
|
# LinBPQ Makefile
|
||||||
|
|
||||||
|
# To exclude i2c support run make noi2c
|
||||||
|
|
||||||
|
OBJS = pngwtran.o pngrtran.o pngset.o pngrio.o pngwio.o pngtrans.o pngrutil.o pngwutil.o\
|
||||||
|
pngread.o pngwrite.o png.o pngerror.o pngget.o pngmem.o APRSIconData.o AISCommon.o\
|
||||||
|
upnp.o APRSStdPages.o HSMODEM.o WinRPR.o KISSHF.o TNCEmulators.o bpqhdlc.o SerialPort.o\
|
||||||
|
adif.o WebMail.o utf8Routines.o VARA.o LzFind.o Alloc.o LzmaDec.o LzmaEnc.o LzmaLib.o \
|
||||||
|
Multicast.o ARDOP.o IPCode.o FLDigi.o linether.o CMSAuth.o APRSCode.o BPQtoAGW.o KAMPactor.o\
|
||||||
|
AEAPactor.o HALDriver.o MULTIPSK.o BBSHTMLConfig.o ChatHTMLConfig.o BBSUtilities.o bpqaxip.o\
|
||||||
|
BPQINP3.o BPQNRR.o cMain.o Cmd.o CommonCode.o HTMLCommonCode.o compatbits.o config.o datadefs.o \
|
||||||
|
FBBRoutines.o HFCommon.o Housekeeping.o HTTPcode.o kiss.o L2Code.o L3Code.o L4Code.o lzhuf32.o \
|
||||||
|
MailCommands.o MailDataDefs.o LinBPQ.o MailRouting.o MailTCP.o MBLRoutines.o md5.o Moncode.o \
|
||||||
|
NNTPRoutines.o RigControl.o TelnetV6.o WINMOR.o TNCCode.o UZ7HODrv.o WPRoutines.o \
|
||||||
|
SCSTrackeMulti.o SCSPactor.o SCSTracker.o HanksRT.o UIRoutines.o AGWAPI.o AGWMoncode.o \
|
||||||
|
DRATS.o FreeDATA.o base64.o Events.o nodeapi.o mailapi.o mqtt.o
|
||||||
|
|
||||||
|
# Configuration:
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
|
||||||
|
all: CFLAGS = -DLINBPQ -MMD -g -fcommon
|
||||||
|
all: LDFLAGS = -l:libpaho-mqtt3a.a -l:libjansson.a
|
||||||
|
all: linbpq
|
||||||
|
|
||||||
|
|
||||||
|
nomqtt: CFLAGS = -DLINBPQ -MMD -fcommon -g -DNOMQTT
|
||||||
|
nomqtt: linbpq
|
||||||
|
|
||||||
|
noi2c: CFLAGS = -DLINBPQ -MMD -DNOI2C -g -fcommon
|
||||||
|
noi2c: linbpq
|
||||||
|
|
||||||
|
|
||||||
|
linbpq: $(OBJS)
|
||||||
|
gcc $(OBJS) -Xlinker -Map=output.map -l:libminiupnpc.a -lrt -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
|
||||||
|
|
||||||
|
clean :
|
||||||
|
rm *.d
|
||||||
|
rm linbpq $(OBJS)
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue