kopia lustrzana https://github.com/sp9skp/spdxl
6711 wiersze
192 KiB
C
6711 wiersze
192 KiB
C
/*
|
|
* dxlAPRS toolchain
|
|
*
|
|
* Copyright (C) Christian Rabler <oe5dxl@oevsv.at>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
|
|
#define X2C_int32
|
|
#define X2C_index32
|
|
#ifndef X2C_H_
|
|
#include "X2C.h"
|
|
#endif
|
|
#define udpgate4_C_
|
|
#ifndef udp_H_
|
|
#include "udp.h"
|
|
#endif
|
|
#ifndef tcp_H_
|
|
#include "tcp.h"
|
|
#endif
|
|
#ifndef osi_H_
|
|
#include "osi.h"
|
|
#endif
|
|
#include <osic.h>
|
|
#ifndef Select_H_
|
|
#include "Select.h"
|
|
#endif
|
|
#ifndef aprspos_H_
|
|
#include "aprspos.h"
|
|
#endif
|
|
#ifndef aprsstr_H_
|
|
#include "aprsstr.h"
|
|
#endif
|
|
|
|
/* axudp / tcpip aprs-is gateway and message repeater by OE5DXL */
|
|
/*FROM Storage IMPORT ALLOCATE, DEALLOCATE; */
|
|
/*FROM TimeConv IMPORT time; */
|
|
/*
|
|
FROM stat IMPORT fstat, stat_t;
|
|
*/
|
|
#define udpgate4_CALLLEN 7
|
|
|
|
#define udpgate4_HASHSIZE 65536
|
|
|
|
#define udpgate4_VERS "udpgate(c) 0.63"
|
|
|
|
#define udpgate4_TOCALL "APNL51"
|
|
|
|
#define udpgate4_HTTPTIMEOUT 60
|
|
|
|
#define udpgate4_APRSLISTENSOCKS 4
|
|
/* max same time tcp connects */
|
|
|
|
#define udpgate4_WWWLISTENSOCKS 16
|
|
/* max same time www tcp connects */
|
|
|
|
#define udpgate4_UDPSHOWTIME 600
|
|
/* show udp in html */
|
|
|
|
#define udpgate4_GATECONNDELAY 30
|
|
|
|
#define udpgate4_MAXINTERNALDELAY 5
|
|
/* max seconds between udp ports read to not discard data */
|
|
|
|
#define udpgate4_DEFAULTPONGTIME 30
|
|
/* s after last #ping stop datatransfer */
|
|
|
|
typedef char MONCALL[10];
|
|
|
|
typedef char FILENAME[1024];
|
|
|
|
typedef char FRAMEBUF[512];
|
|
|
|
typedef char FILTERST[256];
|
|
|
|
/*
|
|
FRAMEBUF=ARRAY[0..256+3+11*10] OF CHAR;
|
|
*/
|
|
typedef uint32_t CHSET[4];
|
|
|
|
|
|
struct BEACON {
|
|
uint32_t bintervall;
|
|
FILENAME bfile;
|
|
uint32_t btime;
|
|
};
|
|
|
|
struct POSCALL;
|
|
|
|
|
|
struct POSCALL {
|
|
MONCALL call;
|
|
char typ0;
|
|
struct aprspos_POSITION pos;
|
|
};
|
|
|
|
struct FILTERS;
|
|
|
|
|
|
struct FILTERS {
|
|
char typ0;
|
|
struct aprspos_POSITION base;
|
|
struct aprspos_POSITION edge;
|
|
float radius;
|
|
MONCALL viacalls[8];
|
|
char notvia;
|
|
MONCALL entrycalls[8];
|
|
char notentry;
|
|
MONCALL prefixes[8];
|
|
char notprefix;
|
|
MONCALL destcalls[8];
|
|
char notdestcall;
|
|
char typs[13];
|
|
char nottyps;
|
|
};
|
|
|
|
typedef char WWWB[1401];
|
|
|
|
struct WWWBUF;
|
|
|
|
typedef struct WWWBUF * pWWWBUF;
|
|
|
|
|
|
struct WWWBUF {
|
|
WWWB buf;
|
|
int32_t tlen;
|
|
char push;
|
|
pWWWBUF next;
|
|
};
|
|
|
|
struct QWatch;
|
|
|
|
|
|
struct QWatch {
|
|
uint32_t lasttb;
|
|
int32_t qsize;
|
|
int32_t lastqb;
|
|
int32_t txbyte[60];
|
|
};
|
|
|
|
struct TCPSOCK;
|
|
|
|
typedef struct TCPSOCK * pTCPSOCK;
|
|
|
|
|
|
struct TCPSOCK {
|
|
pTCPSOCK next;
|
|
int32_t fd;
|
|
uint32_t beacont;
|
|
uint32_t connt;
|
|
uint32_t pongtime;
|
|
char slowlink;
|
|
char valid;
|
|
char pingout; /* ping timeout state */
|
|
char service;
|
|
uint32_t gatepri;
|
|
char ipnum[64];
|
|
char port[6];
|
|
struct POSCALL user;
|
|
char vers[21];
|
|
uint32_t wwwst;
|
|
uint32_t reload;
|
|
char sortby[2];
|
|
struct QWatch qwatch;
|
|
uint32_t txframes;
|
|
uint32_t txbytes;
|
|
uint32_t txbytesh;
|
|
uint32_t rxframes;
|
|
uint32_t rxbytes;
|
|
uint32_t rxbytesh;
|
|
uint32_t losttxframes;
|
|
uint32_t lostrxframes;
|
|
struct FILTERS filters;
|
|
FILTERST outfilterst; /* for www show outconn filters */
|
|
int32_t rpos;
|
|
int32_t tlen;
|
|
FRAMEBUF rbuf;
|
|
char tbuf[1024];
|
|
char get[256];
|
|
pWWWBUF txbuf;
|
|
};
|
|
|
|
struct UDPSOCK;
|
|
|
|
typedef struct UDPSOCK * pUDPSOCK;
|
|
|
|
struct _0;
|
|
|
|
|
|
struct _0 {
|
|
uint32_t uip;
|
|
uint32_t uport;
|
|
uint32_t rxframes;
|
|
uint32_t rxbytes;
|
|
uint32_t utime;
|
|
uint32_t dtime;
|
|
};
|
|
|
|
|
|
struct UDPSOCK {
|
|
pUDPSOCK next;
|
|
int32_t fd;
|
|
aprsstr_GHOSTSET ghosts;
|
|
char rawread;
|
|
char checkip;
|
|
uint32_t ip;
|
|
uint32_t bindport;
|
|
uint32_t dport;
|
|
uint32_t lasttxtime; /* for net to rf bit/s limit */
|
|
uint32_t laststat;
|
|
float torfradius; /* radius 0 no gateing */
|
|
uint32_t maxbytes; /* byte/s tx */
|
|
uint32_t lasttxbytes; /* for tx byte/s limit */
|
|
uint32_t txframes;
|
|
uint32_t txbytes;
|
|
char allpathkey[10]; /* keyword on comment for allpath */
|
|
char portname[10];
|
|
struct _0 stat[16];
|
|
};
|
|
|
|
enum GATEFILT {udpgate4_gUNGATE, udpgate4_gRFONLY, udpgate4_gNOGATE,
|
|
udpgate4_gTCPIP, udpgate4_gTCPXX, udpgate4_gQ};
|
|
|
|
|
|
#define udpgate4_MAXHEARD 500
|
|
|
|
#define udpgate4_cUSERMSG ":"
|
|
|
|
#define udpgate4_cTHIRDPARTY "}"
|
|
|
|
#define udpgate4_ICONDIR "icon"
|
|
|
|
#define udpgate4_CALLINKFN "calllink.txt"
|
|
/* build an URL for a klicked mh call */
|
|
|
|
#define udpgate4_SERVERLINKFN "serverlink.txt"
|
|
/* build an URL for a klicked server ip */
|
|
|
|
#define udpgate4_MHSTEPS 48
|
|
|
|
#define udpgate4_tCELSIUS "C"
|
|
|
|
#define udpgate4_tSPEED "S"
|
|
|
|
#define udpgate4_UNACKRET 1
|
|
|
|
#define udpgate4_MSGLEN 67
|
|
|
|
typedef char MSGTEXT[68];
|
|
|
|
typedef char ACKTEXT[5];
|
|
|
|
typedef char REPLYACK[2];
|
|
|
|
enum SOURCE {udpgate4_OBSOLET, udpgate4_NET, udpgate4_INDIR, udpgate4_DIR};
|
|
|
|
|
|
struct MESSAGE;
|
|
|
|
typedef struct MESSAGE * pMESSAGE;
|
|
|
|
|
|
struct MESSAGE {
|
|
pMESSAGE next;
|
|
uint32_t chkt;
|
|
uint32_t txtime;
|
|
uint32_t gentime;
|
|
uint32_t txport;
|
|
uint32_t msg2rf;
|
|
uint32_t msg2net;
|
|
uint32_t ack2rf;
|
|
uint32_t ack2net;
|
|
uint32_t retryc;
|
|
uint8_t acksrc;
|
|
uint8_t src;
|
|
char reject;
|
|
char acked;
|
|
char ackackt;
|
|
char queryrep;
|
|
MONCALL from;
|
|
MONCALL to;
|
|
ACKTEXT ack;
|
|
REPLYACK replyack;
|
|
MSGTEXT text; /* no text is ack */
|
|
};
|
|
|
|
struct HEARD;
|
|
|
|
typedef struct HEARD * pHEARD;
|
|
|
|
|
|
struct HEARD {
|
|
pHEARD next;
|
|
uint32_t fromrx;
|
|
uint32_t time0;
|
|
MONCALL call;
|
|
uint32_t cntt;
|
|
struct aprspos_POSITION position;
|
|
char sym;
|
|
char symt;
|
|
uint16_t cnt[49];
|
|
char head[41];
|
|
char datatyp;
|
|
float data;
|
|
double sortval; /* sort value inserted depending on sort by */
|
|
char ungate; /* flag set by user to not igate this direct heard */
|
|
uint16_t txd;
|
|
uint8_t quali;
|
|
signed char level;
|
|
};
|
|
|
|
static uint32_t msgsendtime;
|
|
|
|
static uint32_t udpgate4_POLYNOM = 0x8408UL;
|
|
|
|
static uint32_t udpgate4_CRCINIT = 0xFFFFUL;
|
|
|
|
static uint32_t udpgate4_CRCRESULT = 0x9F0BUL;
|
|
|
|
#define udpgate4_CR "\015"
|
|
|
|
#define udpgate4_LF "\012"
|
|
|
|
#define udpgate4_cUSERMESSAGE ":"
|
|
|
|
#define udpgate4_cISGATEWAY "G"
|
|
|
|
#define udpgate4_cISSERVER "S"
|
|
|
|
#define udpgate4_cISWWW "W"
|
|
|
|
#define udpgate4_cTELEMETRY "T"
|
|
|
|
static char mhperport;
|
|
|
|
/* mh line for same call but different port */
|
|
static char datafilter;
|
|
|
|
static char verb;
|
|
|
|
/* send no data to user with no filter set */
|
|
static char callsrc;
|
|
|
|
static pTCPSOCK tcpsocks;
|
|
|
|
static uint32_t showip1;
|
|
|
|
static uint32_t showport1;
|
|
|
|
static uint32_t systime;
|
|
|
|
static uint32_t keeptime;
|
|
|
|
static char ungates[6][11];
|
|
|
|
static uint32_t timehash[65536];
|
|
|
|
static uint32_t realtime;
|
|
|
|
static uint32_t udpdonetime;
|
|
|
|
static uint32_t maxpongtime;
|
|
|
|
static uint32_t dupetime;
|
|
|
|
static uint32_t uptime;
|
|
|
|
static FILENAME rawlogname;
|
|
|
|
static FILENAME netbeaconfn;
|
|
|
|
static FILENAME logframename;
|
|
|
|
static uint32_t lastdnstime;
|
|
|
|
static uint32_t gateconndelay;
|
|
|
|
static uint32_t netbeaconintervall;
|
|
|
|
static uint32_t vcourse;
|
|
|
|
static uint32_t vspeed;
|
|
|
|
static uint32_t qas;
|
|
|
|
static uint32_t qasc;
|
|
|
|
static uint32_t maxusers;
|
|
|
|
static uint32_t httpcount;
|
|
|
|
static char vsym;
|
|
|
|
static char vsymt;
|
|
|
|
static int32_t valt;
|
|
|
|
static int32_t wwwsizelimit;
|
|
|
|
static int32_t logframes;
|
|
|
|
static MONCALL showid;
|
|
|
|
static MONCALL servercall;
|
|
|
|
static struct aprspos_POSITION home; /* own position */
|
|
|
|
static char passwd[6];
|
|
|
|
static char serverrangefilter[256];
|
|
|
|
static char actfilter[256];
|
|
|
|
static char wwwdir[1024];
|
|
|
|
static char tcpbindport[6];
|
|
|
|
static char wwwbindport[6];
|
|
|
|
static char nettorfpath[81];
|
|
|
|
static pUDPSOCK udpsocks;
|
|
|
|
static uint32_t trygate;
|
|
|
|
static int32_t qmaxtime;
|
|
|
|
static FILENAME gatesfn; /* filename with gateway table */
|
|
|
|
struct _1;
|
|
|
|
|
|
struct _1 {
|
|
char url[256];
|
|
char port[6];
|
|
uint32_t resolvtime;
|
|
uint32_t connecttime;
|
|
FILTERST filterst;
|
|
};
|
|
|
|
static struct _1 gateways[21];
|
|
|
|
static MONCALL rfdestcall;
|
|
|
|
static MONCALL netdestcall;
|
|
|
|
static MONCALL viacall;
|
|
|
|
static uint32_t netmhin;
|
|
|
|
static uint32_t netmhout;
|
|
|
|
static uint32_t msghttpcount;
|
|
|
|
static uint32_t mhhttpcount;
|
|
|
|
static uint32_t maxmsg;
|
|
|
|
static uint32_t maxatonce;
|
|
|
|
static uint32_t lastrfsent;
|
|
|
|
static uint32_t purgeunack;
|
|
|
|
static uint32_t purgemsg;
|
|
|
|
static uint32_t purgeacked;
|
|
|
|
static uint32_t purgeunacksent;
|
|
|
|
static uint32_t rfquiet;
|
|
|
|
static uint32_t heardtimevia;
|
|
|
|
static uint32_t heardtimew;
|
|
|
|
static uint32_t heardtimetcp;
|
|
|
|
static uint32_t heardtime;
|
|
|
|
static pMESSAGE messages;
|
|
|
|
static pHEARD heardvia;
|
|
|
|
static pHEARD hearddir;
|
|
|
|
static pHEARD heardtcp;
|
|
|
|
static char sendnetmsg;
|
|
|
|
static MONCALL netmh[100];
|
|
|
|
static uint32_t mhfilelines;
|
|
|
|
static FILENAME mhfilename;
|
|
|
|
static char udp2[100];
|
|
|
|
|
|
static void spintime(void)
|
|
{
|
|
/* make monotonic systime out of jumping realtime */
|
|
uint32_t dt;
|
|
uint32_t t;
|
|
t = osic_time();
|
|
dt = t-realtime;
|
|
realtime = t;
|
|
if (dt<60UL) systime += dt;
|
|
} /* end spintime() */
|
|
|
|
/*
|
|
PROCEDURE Rename(fname,newname: ARRAY OF CHAR);
|
|
VAR ok:BOOLEAN;
|
|
BEGIN
|
|
FileSys.Rename(fname, newname, ok);
|
|
END Rename;
|
|
*/
|
|
|
|
static void Err(const char text[], uint32_t text_len)
|
|
{
|
|
osi_WrStr("udpgate: ", 10ul);
|
|
osi_WrStr(text, text_len);
|
|
osi_WrStrLn(" error abort", 13ul);
|
|
X2C_ABORT();
|
|
} /* end Err() */
|
|
|
|
|
|
static uint32_t Max(uint32_t a, uint32_t b)
|
|
{
|
|
if (a>b) return a;
|
|
else return b;
|
|
return 0;
|
|
} /* end Max() */
|
|
|
|
|
|
static uint32_t Min(uint32_t a, uint32_t b)
|
|
{
|
|
if (a<b) return a;
|
|
else return b;
|
|
return 0;
|
|
} /* end Min() */
|
|
|
|
|
|
static void skipblank(const char s[], uint32_t s_len, uint32_t * p)
|
|
{
|
|
while (*p<s_len-1 && s[*p]==' ') ++*p;
|
|
} /* end skipblank() */
|
|
|
|
|
|
static void app(char s[], uint32_t s_len, float x, char rad)
|
|
{
|
|
char h[30];
|
|
aprsstr_Append(s, s_len, "/", 2ul);
|
|
if (rad) aprsstr_FixToStr(X2C_DIVR(x,1.7453292519444E-2f), 5UL, h, 30ul);
|
|
else aprsstr_FixToStr(x, 0UL, h, 30ul);
|
|
aprsstr_Append(s, s_len, h, 30ul);
|
|
} /* end app() */
|
|
|
|
|
|
static void wrcalls(char s[], uint32_t s_len, const MONCALL tab[],
|
|
uint32_t tab_len, char not, char sym)
|
|
{
|
|
uint32_t j;
|
|
if (tab[0UL][0U]) {
|
|
if (s[0UL]) aprsstr_Append(s, s_len, " ", 2ul);
|
|
if (not) aprsstr_Append(s, s_len, "-", 2ul);
|
|
aprsstr_Append(s, s_len, (char *) &sym, 1u/1u);
|
|
j = 0UL;
|
|
while (tab[j][0U]) {
|
|
aprsstr_Append(s, s_len, "/", 2ul);
|
|
aprsstr_Append(s, s_len, tab[j], 10ul);
|
|
++j;
|
|
}
|
|
}
|
|
} /* end wrcalls() */
|
|
|
|
|
|
static void FiltToStr(struct FILTERS f, char s[], uint32_t s_len)
|
|
{
|
|
struct FILTERS * anonym;
|
|
s[0UL] = 0;
|
|
{ /* with */
|
|
struct FILTERS * anonym = &f;
|
|
if (anonym->typ0=='a') {
|
|
aprsstr_Assign(s, s_len, "a", 2ul);
|
|
app(s, s_len, anonym->base.lat, 1);
|
|
app(s, s_len, anonym->base.long0, 1);
|
|
app(s, s_len, anonym->edge.lat, 1);
|
|
app(s, s_len, anonym->edge.long0, 1);
|
|
}
|
|
else if (anonym->typ0=='r') {
|
|
aprsstr_Assign(s, s_len, "r", 2ul);
|
|
app(s, s_len, anonym->base.lat, 1);
|
|
app(s, s_len, anonym->base.long0, 1);
|
|
app(s, s_len, anonym->radius, 0);
|
|
}
|
|
else if (anonym->typ0=='m') {
|
|
aprsstr_Assign(s, s_len, "m", 2ul);
|
|
app(s, s_len, anonym->radius, 0);
|
|
}
|
|
wrcalls(s, s_len, anonym->viacalls, 8ul, anonym->notvia, 'd');
|
|
wrcalls(s, s_len, anonym->entrycalls, 8ul, anonym->notentry, 'e');
|
|
wrcalls(s, s_len, anonym->prefixes, 8ul, anonym->notprefix, 'p');
|
|
wrcalls(s, s_len, anonym->destcalls, 8ul, anonym->notdestcall, 'u');
|
|
if (anonym->typs[0U]) {
|
|
aprsstr_Append(s, s_len, " ", 2ul);
|
|
if (anonym->nottyps) aprsstr_Append(s, s_len, "-", 2ul);
|
|
aprsstr_Append(s, s_len, "t/", 3ul);
|
|
aprsstr_Append(s, s_len, anonym->typs, 13ul);
|
|
}
|
|
}
|
|
} /* end FiltToStr() */
|
|
|
|
|
|
static char Watchclock(uint32_t * t, uint32_t intervall)
|
|
{
|
|
uint32_t tn;
|
|
if (intervall>0UL || *t==0UL) {
|
|
/* send once */
|
|
tn = systime;
|
|
if (*t<=tn) {
|
|
*t += intervall;
|
|
if (*t<=tn) *t = tn+intervall;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
} /* end Watchclock() */
|
|
|
|
static uint32_t udpgate4_ROOT = 0x73E2UL;
|
|
|
|
|
|
static uint32_t call2pass(const char c[], uint32_t c_len)
|
|
{
|
|
uint32_t i0;
|
|
uint32_t s;
|
|
s = 0x73E2UL;
|
|
i0 = 0UL;
|
|
while ((i0<=c_len-1 && c[i0]) && c[i0]!='-') {
|
|
s = s^X2C_LSH((uint32_t)(uint32_t)(uint8_t)X2C_CAP(c[i0]),32,
|
|
(int32_t)!(i0&1)*8L);
|
|
++i0;
|
|
}
|
|
return (uint32_t)(s&0x7FFFUL);
|
|
} /* end call2pass() */
|
|
|
|
|
|
static int32_t GetSec(char h[], uint32_t h_len, uint32_t * p,
|
|
uint32_t * n)
|
|
{
|
|
char ok0;
|
|
int32_t GetSec_ret;
|
|
X2C_PCOPY((void **)&h,h_len);
|
|
h[h_len-1] = 0;
|
|
*n = 0UL;
|
|
ok0 = 0;
|
|
while ((uint8_t)h[*p]>='0' && (uint8_t)h[*p]<='9') {
|
|
ok0 = 1;
|
|
*n = ( *n*10UL+(uint32_t)(uint8_t)h[*p])-48UL;
|
|
++*p;
|
|
}
|
|
if (!ok0) {
|
|
GetSec_ret = -1L;
|
|
goto label;
|
|
}
|
|
/*
|
|
IO.WrCard(n,10); IO.WrLn;
|
|
*/
|
|
GetSec_ret = 0L;
|
|
label:;
|
|
X2C_PFREE(h);
|
|
return GetSec_ret;
|
|
} /* end GetSec() */
|
|
|
|
|
|
static char callok(const char h[], uint32_t h_len)
|
|
{
|
|
uint32_t lit;
|
|
uint32_t num;
|
|
uint32_t i0;
|
|
char c;
|
|
num = 0UL;
|
|
lit = 0UL;
|
|
i0 = 0UL;
|
|
for (;;) {
|
|
c = h[i0];
|
|
if ((uint8_t)c>='0' && (uint8_t)c<='9') ++num;
|
|
else if ((uint8_t)c>='A' && (uint8_t)c<='Z') ++lit;
|
|
else break;
|
|
++i0;
|
|
}
|
|
if ((lit<2UL || num==0UL) || num>2UL) return 0;
|
|
if (h[i0]=='-') {
|
|
++i0;
|
|
if (h[i0]=='1') {
|
|
++i0;
|
|
if ((uint8_t)h[i0]>='0' && (uint8_t)h[i0]<='5') ++i0;
|
|
}
|
|
else {
|
|
if ((uint8_t)h[i0]<'1' || (uint8_t)h[i0]>'9') return 0;
|
|
++i0;
|
|
}
|
|
}
|
|
return h[i0]==0;
|
|
} /* end callok() */
|
|
|
|
|
|
static void readurlsfile(const char gatesfn0[], uint32_t gatesfn_len)
|
|
{
|
|
uint32_t i0;
|
|
uint32_t n;
|
|
int32_t ii;
|
|
int32_t len;
|
|
int32_t fd;
|
|
FILENAME h;
|
|
memset((char *)gateways,(char)0,sizeof(struct _1 [21]));
|
|
fd = osi_OpenRead(gatesfn0, gatesfn_len);
|
|
if (fd<0L) {
|
|
strncpy(h,"-g :file <",1024u);
|
|
aprsstr_Append(h, 1024ul, gatesfn0, gatesfn_len);
|
|
aprsstr_Append(h, 1024ul, "> not readable", 15ul);
|
|
osi_WrStrLn(h, 1024ul);
|
|
return;
|
|
}
|
|
n = 0UL;
|
|
do {
|
|
i0 = 0UL;
|
|
for (;;) {
|
|
len = osi_RdBin(fd, (char *) &h[i0], 1u/1u, 1UL);
|
|
if (((len<=0L || i0>=1023UL) || h[i0]=='\015') || h[i0]=='\012') {
|
|
h[i0] = 0;
|
|
break;
|
|
}
|
|
++i0;
|
|
}
|
|
if (h[0U] && h[0U]!='#') {
|
|
if (h[0U]=='[') {
|
|
ii = 1L;
|
|
while (h[ii] && h[ii]!=']') ++ii;
|
|
if (h[ii]!=']' || h[ii+1L]!=':') {
|
|
osi_WrStrLn("urlfile: [url]:port", 20ul);
|
|
}
|
|
h[ii] = 0;
|
|
i0 = 1UL;
|
|
while (i0<=1023UL) {
|
|
h[i0-1UL] = h[i0];
|
|
++i0;
|
|
}
|
|
}
|
|
else ii = aprsstr_InStr(h, 1024ul, ":", 2ul);
|
|
if (ii>=0L) h[ii] = 0;
|
|
aprsstr_Assign(gateways[n].url, 256ul, h, 1024ul);
|
|
if (ii>0L) {
|
|
/* port number */
|
|
++ii;
|
|
i0 = 0UL;
|
|
while (ii<=1023L) {
|
|
h[i0] = h[ii];
|
|
++i0;
|
|
++ii;
|
|
}
|
|
}
|
|
else osi_WrStrLn("urlfile: [url]:port", 20ul);
|
|
ii = aprsstr_InStr(h, 1024ul, "#", 2ul);
|
|
if (ii>=0L) h[ii] = 0;
|
|
if (h[0U]==0) {
|
|
osi_WrStrLn("urlfile: [url]:port#filters", 28ul);
|
|
}
|
|
aprsstr_Assign(gateways[n].port, 6ul, h, 1024ul);
|
|
if (ii>0L) {
|
|
/* we have a filter string */
|
|
++ii;
|
|
i0 = 0UL;
|
|
while (ii<=1023L) {
|
|
if (h[ii]==',') h[ii] = ' ';
|
|
h[i0] = h[ii];
|
|
++i0;
|
|
++ii;
|
|
}
|
|
aprsstr_Assign(gateways[n].filterst, 256ul, h, 1024ul);
|
|
}
|
|
++n;
|
|
}
|
|
} while (!(len<=0L || n>20UL));
|
|
osic_Close(fd);
|
|
} /* end readurlsfile() */
|
|
|
|
static aprsstr_GHOSTSET _cnst = {0x00000000UL,0x00000000UL,0x00000000UL,
|
|
0x00000000UL,0x00000000UL,0x00000000UL,0x00000000UL,
|
|
0x00000000UL,0x00000000UL};
|
|
|
|
static void parms(void)
|
|
{
|
|
char h[4096];
|
|
aprsstr_GHOSTSET ghost;
|
|
char err;
|
|
char lasth;
|
|
uint32_t n;
|
|
uint32_t i0;
|
|
uint32_t gatecnt;
|
|
int32_t len;
|
|
int32_t fd;
|
|
pUDPSOCK ush;
|
|
pUDPSOCK usock;
|
|
int32_t ii;
|
|
char allkey[10];
|
|
struct UDPSOCK * anonym;
|
|
uint32_t tmp;
|
|
err = 0;
|
|
verb = 0;
|
|
datafilter = 0;
|
|
gatecnt = 0UL;
|
|
memcpy(ghost,_cnst,36u);
|
|
keeptime = 0UL; /*600*/ /* default keep connected to gateway time */
|
|
allkey[0U] = 0;
|
|
for (;;) {
|
|
osi_NextArg(h, 4096ul);
|
|
if (h[0U]==0) break;
|
|
if ((h[0U]=='-' && h[1U]) && h[2U]==0) {
|
|
lasth = h[1U];
|
|
if (lasth=='R' || lasth=='M') {
|
|
osi_NextArg(h, 4096ul);
|
|
osic_alloc((char * *) &usock, sizeof(struct UDPSOCK));
|
|
if (usock==0) Err("out of memory", 14ul);
|
|
memset((char *)usock,(char)0,sizeof(struct UDPSOCK));
|
|
{ /* with */
|
|
struct UDPSOCK * anonym = usock;
|
|
if (aprsstr_GetIp2(h, 4096ul, &anonym->ip, &anonym->dport,
|
|
&anonym->bindport, &anonym->checkip)<0L) {
|
|
Err("-R or -M need ip:port:port", 27ul);
|
|
}
|
|
anonym->fd = openudp();
|
|
anonym->rawread = lasth=='R';
|
|
if (anonym->fd<0L || bindudp(anonym->fd,
|
|
anonym->bindport)<0L) {
|
|
Err("-R or -M cannot bind udpport", 29ul);
|
|
}
|
|
len = socknonblock(anonym->fd);
|
|
ii = aprsstr_InStr(h, 4096ul, "+", 2ul);
|
|
if (ii>0L) {
|
|
i0 = (uint32_t)(ii+1L);
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) {
|
|
anonym->maxbytes = n;
|
|
++i0;
|
|
if (h[i0-1UL]==':' && GetSec(h, 4096ul, &i0, &n)>=0L) {
|
|
anonym->torfradius = (float)n;
|
|
}
|
|
}
|
|
}
|
|
ii = aprsstr_InStr(h, 4096ul, "#", 2ul); /* get port name */
|
|
if (ii>0L) {
|
|
++ii;
|
|
i0 = 0UL;
|
|
while ((i0<=9UL && ii<=4095L) && h[ii]) {
|
|
anonym->portname[i0] = h[ii];
|
|
++i0;
|
|
++ii;
|
|
}
|
|
}
|
|
memcpy(anonym->ghosts,ghost,36u);
|
|
aprsstr_Assign(anonym->allpathkey, 10ul, allkey, 10ul);
|
|
anonym->next = 0;
|
|
}
|
|
if (udpsocks==0) udpsocks = usock;
|
|
else {
|
|
ush = udpsocks;
|
|
while (ush->next) ush = ush->next;
|
|
ush->next = usock;
|
|
}
|
|
memcpy(ghost,_cnst,36u);
|
|
}
|
|
else if (lasth=='c') callsrc = 1;
|
|
else if (lasth=='s' || lasth=='S') {
|
|
osi_NextArg(h, 4096ul);
|
|
aprsstr_Assign(servercall, 10ul, h, 4096ul);
|
|
if ((servercall[0U]==0 || servercall[0U]=='-')
|
|
|| lasth=='s' && !callok(h, 4096ul)) {
|
|
Err("-s call-ssid", 13ul);
|
|
}
|
|
}
|
|
else if (lasth=='p') {
|
|
osi_NextArg(h, 4096ul);
|
|
if ((uint8_t)h[0U]>='0' && (uint8_t)h[0U]<='9') {
|
|
i0 = 0UL;
|
|
while (i0<=5UL && (uint8_t)h[i0]>=' ') {
|
|
passwd[i0] = h[i0];
|
|
++i0;
|
|
}
|
|
}
|
|
else {
|
|
fd = osi_OpenRead(h, 4096ul);
|
|
if (fd<0L) Err("-p passcode or passwordfile", 28ul);
|
|
len = osi_RdBin(fd, (char *)passwd, 6u/1u, 5UL);
|
|
if (len>=0L) passwd[len] = 0;
|
|
else Err("-p error with password file", 28ul);
|
|
osic_Close(fd);
|
|
}
|
|
passwd[5U] = 0;
|
|
i0 = 0UL;
|
|
while ((uint8_t)passwd[i0]>='0' && (uint8_t)passwd[i0]<='9') {
|
|
++i0;
|
|
}
|
|
if (i0==0UL || passwd[i0]) Err("-p invalid passcode", 20ul);
|
|
}
|
|
else if (lasth=='m') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) maxusers = n;
|
|
else Err("-m number", 10ul);
|
|
}
|
|
else if (lasth=='D') {
|
|
osi_NextArg(h, 4096ul);
|
|
aprsstr_Assign(wwwdir, 1024ul, h, 4096ul);
|
|
if (h[0U]==0 || h[0U]=='-') Err("-D directory", 13ul);
|
|
i0 = aprsstr_Length(wwwdir, 1024ul);
|
|
if (i0>0UL && wwwdir[i0-1UL]!='/') {
|
|
aprsstr_Append(wwwdir, 1024ul, "/", 2ul);
|
|
}
|
|
}
|
|
else if (lasth=='d') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) dupetime = n;
|
|
else Err("-d number", 10ul);
|
|
if (dupetime<27UL) {
|
|
osi_WrStrLn("-d do not set dupefilter less 27s!", 35ul);
|
|
}
|
|
}
|
|
else if (lasth=='e') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) {
|
|
if (n==0UL) n = 1UL;
|
|
gateconndelay = n;
|
|
}
|
|
else Err("-e seconds", 11ul);
|
|
}
|
|
else if (lasth=='C') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) heardtimetcp = n*60UL;
|
|
else Err("-C minutes", 11ul);
|
|
}
|
|
else if (lasth=='H') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) heardtimew = n*60UL;
|
|
else Err("-H minutes", 11ul);
|
|
}
|
|
else if (lasth=='I') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) heardtimevia = n*60UL;
|
|
else Err("-I minutes", 11ul);
|
|
}
|
|
else if (lasth=='i') {
|
|
osi_NextArg(h, 4096ul);
|
|
if (h[0U]=='-') h[0U] = 0;
|
|
aprsstr_Assign(allkey, 10ul, h, 4096ul);
|
|
}
|
|
else if (lasth=='L') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) maxmsg = n;
|
|
else Err("-L number", 10ul);
|
|
}
|
|
else if (lasth=='l') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L && h[i0]==':') {
|
|
logframes = (int32_t)n;
|
|
++i0;
|
|
for (n = 0UL; n<=1023UL; n++) {
|
|
if (i0<=4095UL) {
|
|
logframename[n] = h[i0];
|
|
++i0;
|
|
}
|
|
} /* end for */
|
|
if ((uint8_t)logframename[0U]<=' ') {
|
|
Err("-l loglevel:filename", 21ul);
|
|
}
|
|
}
|
|
else Err("log format is level:file", 25ul);
|
|
}
|
|
else if (lasth=='r') {
|
|
osi_NextArg(rawlogname, 1024ul);
|
|
if ((uint8_t)rawlogname[0U]<=' ') {
|
|
Err("-r rawlogfilename", 18ul);
|
|
}
|
|
}
|
|
else if (lasth=='F') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L && h[i0]==':') {
|
|
mhfilelines = n;
|
|
++i0;
|
|
for (n = 0UL; n<=1023UL; n++) {
|
|
if (i0<=4095UL) {
|
|
mhfilename[n] = h[i0];
|
|
++i0;
|
|
}
|
|
} /* end for */
|
|
if ((uint8_t)mhfilename[0U]<=' ') {
|
|
Err("-F MHfilename", 14ul);
|
|
}
|
|
}
|
|
else Err("MH File lines:file", 19ul);
|
|
}
|
|
else if (lasth=='n') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L && h[i0]==':') {
|
|
netbeaconintervall = n*60UL;
|
|
++i0;
|
|
for (n = 0UL; n<=1023UL; n++) {
|
|
if (i0<=4095UL) {
|
|
netbeaconfn[n] = h[i0];
|
|
++i0;
|
|
}
|
|
} /* end for */
|
|
if ((uint8_t)netbeaconfn[0U]<=' ') {
|
|
Err("-n netbeacon filename", 22ul);
|
|
}
|
|
}
|
|
else Err("-n netbeacon format is minutes:file", 36ul);
|
|
}
|
|
else if (lasth=='N') sendnetmsg = 0;
|
|
else if (lasth=='t') {
|
|
osi_NextArg(h, 4096ul);
|
|
aprsstr_Assign(tcpbindport, 6ul, h, 4096ul);
|
|
if (h[0U]==0 || h[0U]=='-') Err("-t port", 8ul);
|
|
}
|
|
else if (lasth=='w') {
|
|
osi_NextArg(h, 4096ul);
|
|
aprsstr_Assign(wwwbindport, 6ul, h, 4096ul);
|
|
if (h[0U]==0 || h[0U]=='-') Err("-w port", 8ul);
|
|
}
|
|
else if (lasth=='f') {
|
|
osi_NextArg(h, 4096ul);
|
|
aprsstr_Assign(serverrangefilter, 256ul, h, 4096ul);
|
|
if (h[0U]==0 || h[0U]=='-') Err("-f rangefilter", 15ul);
|
|
tmp = aprsstr_Length(serverrangefilter, 256ul);
|
|
i0 = 0UL;
|
|
if (i0<=tmp) for (;; i0++) {
|
|
if (serverrangefilter[i0]==',') serverrangefilter[i0] = ' ';
|
|
if (i0==tmp) break;
|
|
} /* end for */
|
|
}
|
|
else if (lasth=='g') {
|
|
/* "url port" or "url:port" or "url:port#filter" */
|
|
osi_NextArg(h, 4096ul);
|
|
if (h[0U]==0) Err("-g url port", 12ul);
|
|
if (h[0U]==':') {
|
|
/* get urls later from file */
|
|
for (i0 = 1UL; i0<=4095UL; i0++) {
|
|
h[i0-1UL] = h[i0];
|
|
} /* end for */
|
|
h[4095U] = 0;
|
|
aprsstr_Assign(gatesfn, 1024ul, h, 4096ul);
|
|
}
|
|
else {
|
|
if (gatecnt>20UL) Err("-g gateway table full", 22ul);
|
|
h[4095U] = 0;
|
|
if (h[0U]=='[') {
|
|
ii = 1L;
|
|
while (h[ii] && h[ii]!=']') ++ii;
|
|
if (h[ii]!=']' || h[ii+1L]!=':') {
|
|
Err("-g [url]:port", 14ul);
|
|
}
|
|
h[ii] = 0;
|
|
i0 = 1UL;
|
|
while (i0<=4095UL) {
|
|
h[i0-1UL] = h[i0];
|
|
++i0;
|
|
}
|
|
}
|
|
else ii = aprsstr_InStr(h, 4096ul, ":", 2ul);
|
|
if (ii>=0L) h[ii] = 0;
|
|
aprsstr_Assign(gateways[gatecnt].url, 256ul, h, 4096ul);
|
|
if (ii>0L) {
|
|
/* port number */
|
|
++ii;
|
|
i0 = 0UL;
|
|
while (ii<=4095L) {
|
|
h[i0] = h[ii];
|
|
++i0;
|
|
++ii;
|
|
}
|
|
}
|
|
else osi_NextArg(h, 4096ul);
|
|
h[4095U] = 0;
|
|
ii = aprsstr_InStr(h, 4096ul, "#", 2ul);
|
|
if (ii>=0L) h[ii] = 0;
|
|
if (h[0U]==0) Err("-g url:port", 12ul);
|
|
aprsstr_Assign(gateways[gatecnt].port, 6ul, h, 4096ul);
|
|
if (ii>0L) {
|
|
/* we have a filter string */
|
|
++ii;
|
|
i0 = 0UL;
|
|
while (ii<=4095L) {
|
|
if (h[ii]==',') h[ii] = ' ';
|
|
h[i0] = h[ii];
|
|
++i0;
|
|
++ii;
|
|
}
|
|
aprsstr_Assign(gateways[gatecnt].filterst, 256ul, h,
|
|
4096ul);
|
|
}
|
|
++gatecnt;
|
|
}
|
|
}
|
|
else {
|
|
if (lasth=='h') {
|
|
osi_WrStrLn(" -0 send no Data (only Messages and a\
|
|
ck) to User with no Filter", 76ul);
|
|
osi_WrStrLn(" -C <time> connected (tcp) remember position\
|
|
minutes (Min) (-C 1440)", 74ul);
|
|
osi_WrStrLn(" -c delete frames with no valid sourc\
|
|
e call in APRS-IS stream", 74ul);
|
|
osi_WrStrLn(" -D <path> www server root directory (-D /us\
|
|
r/www/)", 57ul);
|
|
osi_WrStrLn(" -d <time> dupe filter time in seconds, not \
|
|
below 27s! (default 60s)", 74ul);
|
|
osi_WrStrLn(" -e <time> wait before (re)connect to (next)\
|
|
gateway in seconds, (30s)", 76ul);
|
|
osi_WrStrLn(" -F <lines>:<file> write direct heard file (call,\
|
|
sym,port,s,cnt,km,data,path)", 78ul);
|
|
osi_WrStrLn(" -f <filters> backstream filter text sent to ou\
|
|
t connected server -f m/50", 76ul);
|
|
osi_WrStrLn(" if blanks dont pass parameter set\
|
|
tings use , (-f m/30,-d/CW)", 77ul);
|
|
osi_WrStrLn(" -g <url>:<port>[#<filters>] connect to APRS-IS g\
|
|
ateway, repeat -g for a list", 78ul);
|
|
osi_WrStrLn(" with favorites first and all urls\
|
|
will be tried to connect", 75ul);
|
|
osi_WrStrLn(" if the active connect is not the \
|
|
first in list, urls", 69ul);
|
|
osi_WrStrLn(" before will be polled and if gets\
|
|
connected, data transfer", 75ul);
|
|
osi_WrStrLn(" is switched to this link and the \
|
|
old gets disconnected", 71ul);
|
|
osi_WrStrLn(" if no filter setting, global -f f\
|
|
ilter is used", 63ul);
|
|
osi_WrStrLn(" -g www.db0anf.de:14580#m/50 -g 12\
|
|
7.0.0.1:3000", 62ul);
|
|
osi_WrStrLn(" ipv6 if enabled by kernel -g [::1\
|
|
]:14580#m/200", 63ul);
|
|
osi_WrStrLn(" -g :<filename> read gateway urls from file url:p\
|
|
ort#filter,filter,...", 71ul);
|
|
osi_WrStrLn(" -h this", 21ul);
|
|
osi_WrStrLn(" -H <time> direct heard keep time minutes (M\
|
|
in) (-H 1440)", 63ul);
|
|
osi_WrStrLn(" -I <time> indirect heard keep time minutes \
|
|
(Min) (-I 30)", 63ul);
|
|
osi_WrStrLn(" -i <word> keyword in rf-frame-comment to en\
|
|
able multipath, * for all frames", 82ul);
|
|
osi_WrStrLn(" -j <time> maximum time to (re)send messages\
|
|
(s) (-j 43200)", 65ul);
|
|
osi_WrStrLn(" -k <time> 0 always connect to gateway else \
|
|
connect on demand and hold (0)", 80ul);
|
|
osi_WrStrLn(" (seconds) after last User gone or\
|
|
valid UDP Data arrived", 73ul);
|
|
osi_WrStrLn(" -L <number> max messages stored else delete o\
|
|
ldest (-L 1000)", 65ul);
|
|
osi_WrStrLn(" -L 0 and -x set and net-to-rf ena\
|
|
bled all msg to heard gatet", 77ul);
|
|
osi_WrStrLn(" -l <level>:<file> logfile -l 6:/tmp/log.txt",
|
|
45ul);
|
|
osi_WrStrLn(" level: 1 logins, 2 +sent frames, \
|
|
6 +fitered frames, 7 +dups", 76ul);
|
|
osi_WrStrLn(" -M <ip>:<dport>/<lport>[+<byte/s>[:<radius>]][#<\
|
|
portname>]", 60ul);
|
|
osi_WrStrLn(" udp rf port (monitor frame format\
|
|
) for local (t)rx", 67ul);
|
|
osi_WrStrLn(" <dport>/<lport> \"/\" only from t\
|
|
his ip, dport=0 no tx", 69ul);
|
|
osi_WrStrLn(" +byte/s enable inet to rf for ser\
|
|
vices like WLNK, WHO-IS", 73ul);
|
|
osi_WrStrLn(" :radius enable all inet to rf gat\
|
|
e (from km around digi)", 73ul);
|
|
osi_WrStrLn(" messages to NOT direct heard user\
|
|
s are gated at any radius >0", 78ul);
|
|
osi_WrStrLn(" if no <ip> given then \'127.0.0.1\\
|
|
' is used", 58ul);
|
|
osi_WrStrLn(" #portname max 10 char like \'1448\
|
|
00\'", 52ul);
|
|
osi_WrStrLn(" repeat -M for each radio port wit\
|
|
h a tx or different portname", 78ul);
|
|
osi_WrStrLn(" -m <maxconnects> max inbound connects -m 20 (def\
|
|
ault 50)", 58ul);
|
|
osi_WrStrLn(" -N send no stored messages to net ex\
|
|
cept query answers", 68ul);
|
|
osi_WrStrLn(" -n <min>:<file> netbeacon minutes:filename -n 10\
|
|
:netbeacon.txt", 64ul);
|
|
osi_WrStrLn(" \\\\z ddhhmm, \\\\h hhmmss, \\\\:\
|
|
filename: insert file, \\\\v insert", 77ul);
|
|
osi_WrStrLn(" Version, \\\\\\ insert \\\\",
|
|
39ul);
|
|
osi_WrStrLn(" beacon file like: !8959.00N/17959\
|
|
.00E&igate mars", 65ul);
|
|
osi_WrStrLn(" beacon file used by udpgate itsel\
|
|
f to find out own position", 76ul);
|
|
osi_WrStrLn(" -O make MH entry for same calls but \
|
|
different port", 64ul);
|
|
osi_WrStrLn(" -o <seconds> ping-pong: time to stop data forw\
|
|
arding after last ping", 72ul);
|
|
osi_WrStrLn(" use double time of igate ping int\
|
|
ervall", 56ul);
|
|
osi_WrStrLn(" -P <time[:time]> purge unacked (:acked) messages\
|
|
after seconds (-P 86400:300)", 79ul);
|
|
osi_WrStrLn(" -p <password> login passwort for aprs-is server\
|
|
s -p 12345", 60ul);
|
|
osi_WrStrLn(" to hide password in commandline u\
|
|
se file mode -p pass.txt", 74ul);
|
|
osi_WrStrLn(" -Q <n> send netbeacon with qAS if qAI do\
|
|
nt pass some servers", 70ul);
|
|
osi_WrStrLn(" 0=never, 1=always else every n be\
|
|
acons send 1 with qAI", 71ul);
|
|
osi_WrStrLn(" -q <time> minimum quiet time after rf tx se\
|
|
conds (-q 10)", 63ul);
|
|
osi_WrStrLn(" -r <filename> write a dated 1 day logfile with \
|
|
date+time+data lines", 70ul);
|
|
osi_WrStrLn(" -R same as -M but axudp format",
|
|
44ul);
|
|
osi_WrStrLn(" -s <call> server call of this server -s MYC\
|
|
ALL-10 (-S no callcheck)", 74ul);
|
|
osi_WrStrLn(" -T <seconds> kill link to server if unack tcp \
|
|
bytes are longer in tx queue", 78ul);
|
|
osi_WrStrLn(" avoids delayed trackpoints (defau\
|
|
lt 15s, off 0, max 60)", 72ul);
|
|
osi_WrStrLn(" -t <localport> local igate tcp port for in conne\
|
|
cts -t 14580", 62ul);
|
|
osi_WrStrLn(" -U <time[:time]> purge unsent(:sent) unack messa\
|
|
ges after seconds (-P 900:60)", 79ul);
|
|
osi_WrStrLn(" -v show frames and analytics on stdo\
|
|
ut", 52ul);
|
|
osi_WrStrLn(" -V Via Path for net to rf frames",
|
|
46ul);
|
|
osi_WrStrLn(" -W <filesize> limit www server file size in 102\
|
|
4byte, (-W 1000)", 66ul);
|
|
osi_WrStrLn(" -w <port> port of www server -w 14501",
|
|
44ul);
|
|
osi_WrStrLn(" -x <call> via <call> send messages to rf (-\
|
|
x OE0AAA-10) tx off: -x -", 75ul);
|
|
osi_WrStrLn(" default is server call", 39ul);
|
|
osi_WrStrLn(" -Y [num][,num]... bad digis fingerprints to inse\
|
|
rt GHOST* in otherwise false", 78ul);
|
|
osi_WrStrLn(" direct heard path", 34ul);
|
|
osi_WrStrLn("udpgate -v -R 127.0.0.1:9200:9201 -s MYCALL-10 -l\
|
|
7:aprs.log -n 10:beacon.txt -t 14580 -g www.server.org:14580#m/30 -p 12345",
|
|
125ul);
|
|
X2C_ABORT();
|
|
}
|
|
/*
|
|
ELSIF lasth="u" THEN
|
|
NextArg(h);
|
|
IF GetIp(h, rfgateip,
|
|
rfgateport)<0 THEN Err("-u wrong ip:port") END;
|
|
*/
|
|
if (lasth=='O') mhperport = 1;
|
|
else if (lasth=='j') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) msgsendtime = n;
|
|
else Err("-j seconds", 11ul);
|
|
}
|
|
else if (lasth=='P') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) purgemsg = n;
|
|
else Err("-P seconds", 11ul);
|
|
if (h[i0]==':') {
|
|
++i0;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) purgeacked = n;
|
|
else Err("-P seconds:seconds", 19ul);
|
|
}
|
|
}
|
|
else if (lasth=='U') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) purgeunack = n;
|
|
else Err("-U seconds", 11ul);
|
|
if (h[i0]==':') {
|
|
++i0;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) purgeunacksent = n;
|
|
else Err("-U seconds:seconds", 19ul);
|
|
}
|
|
}
|
|
else if (lasth=='Q') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) qas = n;
|
|
else Err("-Q number", 10ul);
|
|
}
|
|
else if (lasth=='q') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) rfquiet = n;
|
|
else Err("-q seconds", 11ul);
|
|
}
|
|
else if (lasth=='v') verb = 1;
|
|
else if (lasth=='V') {
|
|
osi_NextArg(h, 4096ul);
|
|
aprsstr_Assign(nettorfpath, 81ul, h, 4096ul);
|
|
if (h[0U]==0 || h[0U]=='-' && h[1U]) {
|
|
Err("-V net to rf via path", 22ul);
|
|
}
|
|
}
|
|
else if (lasth=='k') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) keeptime = n;
|
|
else Err("-k seconds", 11ul);
|
|
}
|
|
else if (lasth=='T') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) qmaxtime = (int32_t)n;
|
|
else Err("-T seconds", 11ul);
|
|
if (qmaxtime>59L) qmaxtime = 59L;
|
|
}
|
|
else if (lasth=='o') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) maxpongtime = n;
|
|
else Err("-o seconds", 11ul);
|
|
}
|
|
else if (lasth=='x') {
|
|
osi_NextArg(h, 4096ul);
|
|
aprsstr_Assign(viacall, 10ul, h, 4096ul);
|
|
if (h[0U]==0 || h[0U]=='-' && h[1U]) Err("-x call", 8ul);
|
|
}
|
|
else if (lasth=='W') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) {
|
|
wwwsizelimit = (int32_t)(n*1024UL);
|
|
}
|
|
else Err("-W kbytes", 10ul);
|
|
}
|
|
else if (lasth=='Y') {
|
|
osi_NextArg(h, 4096ul);
|
|
i0 = 0UL;
|
|
while (i0<4095UL && h[i0]) {
|
|
if (GetSec(h, 4096ul, &i0, &n)>=0L) X2C_INCL(ghost,n,257);
|
|
else Err("-Y <num>", 9ul);
|
|
if (h[i0]==',') ++i0;
|
|
}
|
|
}
|
|
else if (lasth=='0') datafilter = 1;
|
|
else err = 1;
|
|
}
|
|
}
|
|
else {
|
|
/*h[0]:=0C;*/
|
|
err = 1;
|
|
}
|
|
if (err) break;
|
|
}
|
|
if (err) {
|
|
aprsstr_Append(h, 4096ul, " ? use -h", 10ul);
|
|
Err(h, 4096ul);
|
|
}
|
|
if (servercall[0U]==0) {
|
|
osic_WrLn();
|
|
osi_WrStrLn("udpgate: NO SERVERCALL ?", 25ul);
|
|
osic_WrLn();
|
|
}
|
|
if (wwwbindport[0U] && wwwdir[0]==0) {
|
|
osic_WrLn();
|
|
osi_WrStrLn("udpgate: -w www-port but no -D icon-dir-path ?", 47ul);
|
|
osic_WrLn();
|
|
}
|
|
} /* end parms() */
|
|
|
|
|
|
static pUDPSOCK porttosock(uint32_t p)
|
|
{
|
|
pUDPSOCK s;
|
|
if (p==0UL) return 0;
|
|
s = udpsocks;
|
|
while (s && p>1UL) {
|
|
s = s->next;
|
|
--p;
|
|
}
|
|
return s;
|
|
} /* end porttosock() */
|
|
|
|
|
|
static void Sendudp(const FRAMEBUF s, uint32_t totx, char unlimit)
|
|
{
|
|
int32_t len;
|
|
FRAMEBUF raw;
|
|
pUDPSOCK us;
|
|
struct UDPSOCK * anonym;
|
|
/* udpstat(us, 0, dport, ip); */
|
|
us = porttosock(totx); /* send to which udp modem */
|
|
if (us && (unlimit || (systime-us->lasttxtime)
|
|
*us->maxbytes>us->lasttxbytes)) {
|
|
if (us->rawread) aprsstr_mon2raw(s, 512ul, raw, 512ul, &len);
|
|
else {
|
|
len = (int32_t)(aprsstr_Length(s, 512ul)+1UL);
|
|
memcpy(raw,s,512u);
|
|
}
|
|
if (len>1L) {
|
|
{ /* with */
|
|
struct UDPSOCK * anonym = us;
|
|
anonym->lasttxbytes = (uint32_t)len;
|
|
anonym->lasttxtime = systime;
|
|
++anonym->txframes;
|
|
anonym->txbytes += (uint32_t)len;
|
|
}
|
|
len = udpsend(us->fd, raw, len, us->dport, us->ip);
|
|
}
|
|
else if (verb) osi_WrStrLn("wrong inet to rf frame format", 30ul);
|
|
}
|
|
} /* end Sendudp() */
|
|
|
|
|
|
static char getudp(pUDPSOCK usock, FRAMEBUF buf,
|
|
aprsstr_GHOSTSET ghost)
|
|
{
|
|
uint32_t fromport;
|
|
uint32_t ipn;
|
|
char crc2;
|
|
/* len, i : INTEGER; */
|
|
char crc1;
|
|
int32_t oldi;
|
|
int32_t i0;
|
|
int32_t len;
|
|
uint32_t mlen;
|
|
FRAMEBUF mbuf0;
|
|
uint32_t oldt;
|
|
struct _0 * anonym;
|
|
aprsstr_GHOSTSET tmp;
|
|
int32_t tmp0;
|
|
char tmp1;
|
|
ghost = (uint32_t *)memcpy(tmp,ghost,36u);
|
|
for (;;) {
|
|
len = udpreceive(usock->fd, buf, 512L, &fromport, &ipn);
|
|
if ((len<=2L || len>=512L) || usock->checkip && usock->ip!=ipn) {
|
|
return 0;
|
|
}
|
|
buf[len] = 0;
|
|
udp2[0U] = 0;
|
|
if (usock->rawread) {
|
|
crc1 = buf[len-2L];
|
|
crc2 = buf[len-1L];
|
|
aprsstr_AppCRC(buf, 512ul, len-2L);
|
|
if (crc1!=buf[len-2L] || crc2!=buf[len-1L]) {
|
|
if (verb) osi_WrStrLn(" axudp crc error", 17ul);
|
|
buf[0U] = 0;
|
|
}
|
|
else {
|
|
if (buf[0U]=='\001') {
|
|
aprsstr_extrudp2(buf, 512ul, udp2, 100ul, &len); /* axudp2 */
|
|
}
|
|
if (len>2L) {
|
|
aprsstr_raw2mon(buf, 512ul, mbuf0, 512ul,
|
|
(uint32_t)(len-2L), &mlen, ghost);
|
|
if (mbuf0[0U]==0 && verb) {
|
|
osi_WrStrLn(" axudp frame decode error", 26ul);
|
|
tmp0 = len-3L;
|
|
i0 = 0L;
|
|
if (i0<=tmp0) for (;; i0++) {
|
|
osi_WrHex((uint32_t)(uint8_t)buf[i0], 3UL);
|
|
if (i0==tmp0) break;
|
|
} /* end for */
|
|
osic_WrLn();
|
|
i0 = 0L;
|
|
for (;;) {
|
|
if (i0>=len-3L) break;
|
|
if ((uint32_t)(uint8_t)buf[i0]/2UL<32UL) {
|
|
osi_WrStr("<", 2ul);
|
|
osi_WrHex((uint32_t)(uint8_t)buf[i0]/2UL, 1UL);
|
|
osi_WrStr(">", 2ul);
|
|
}
|
|
else {
|
|
osi_WrStr((char *)(tmp1 = (char)((uint32_t)
|
|
(uint8_t)buf[i0]/2UL),&tmp1), 1u/1u);
|
|
}
|
|
if (((uint32_t)(uint8_t)buf[i0]&1)) break;
|
|
if (i0%7L==6L) osi_WrStr(",", 2ul);
|
|
++i0;
|
|
}
|
|
osic_WrLn();
|
|
}
|
|
memcpy(buf,mbuf0,512u);
|
|
}
|
|
else buf[0U] = 0;
|
|
len = (int32_t)aprsstr_Length(buf, 512ul); /* for statistic */
|
|
}
|
|
}
|
|
/*- udpstat(usock, len, fromport, ipn); */
|
|
if (buf[0U]) {
|
|
/* statistic */
|
|
i0 = 0L;
|
|
oldt = systime;
|
|
oldi = 0L;
|
|
for (;;) {
|
|
if (usock->stat[i0].uip==ipn && usock->stat[i0].uport==fromport) {
|
|
oldi = i0;
|
|
i0 = 15L;
|
|
}
|
|
if (i0>=15L) {
|
|
{ /* with */
|
|
struct _0 * anonym = &usock->stat[oldi];
|
|
anonym->uport = fromport;
|
|
anonym->uip = ipn;
|
|
if (anonym->dtime/2UL+anonym->utime/2UL>systime || anonym->utime+600UL<systime)
|
|
{
|
|
/* allow clock back step till 1/2 uptime */
|
|
/* reset statistic */
|
|
anonym->dtime = systime;
|
|
/* usock^.txframes:=0; */
|
|
/* usock^.txbytes:=0; */
|
|
anonym->rxframes = 0UL;
|
|
anonym->rxbytes = 0UL;
|
|
}
|
|
++anonym->rxframes;
|
|
anonym->rxbytes += (uint32_t)len;
|
|
anonym->utime = systime;
|
|
usock->laststat = (uint32_t)oldi;
|
|
}
|
|
break;
|
|
}
|
|
if (usock->stat[i0].utime<oldt) {
|
|
oldt = usock->stat[i0].utime;
|
|
oldi = i0;
|
|
}
|
|
++i0;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
} /* end getudp() */
|
|
|
|
|
|
static int32_t Gettcp(int32_t fd, FRAMEBUF line, FRAMEBUF buf,
|
|
int32_t * pos)
|
|
{
|
|
int32_t j;
|
|
int32_t i0;
|
|
int32_t len;
|
|
int32_t tmp;
|
|
i0 = *pos;
|
|
if (i0>=512L) i0 = 0L;
|
|
/*
|
|
len:=RdBin(fd, line, SIZE(line)-i);
|
|
IF len<=0 THEN RETURN -1 END;
|
|
(* disconnected *)
|
|
*/
|
|
/*
|
|
IF len<0 THEN len:=0 END;
|
|
*/
|
|
len = readsock(fd, line, 512L-i0);
|
|
if (len<0L) return -1L;
|
|
if (*pos>=512L) {
|
|
/* hunt mode */
|
|
i0 = 0L;
|
|
while (i0<len && line[i0]!='\012') ++i0;
|
|
if (i0>=len) return 0L;
|
|
/* no line start found */
|
|
*pos = 0L;
|
|
++i0;
|
|
j = 0L;
|
|
while (i0<len) {
|
|
line[j] = line[i0];
|
|
++j;
|
|
++i0;
|
|
}
|
|
len = j;
|
|
}
|
|
if (*pos>0L) {
|
|
for (i0 = len-1L; i0>=0L; i0--) {
|
|
line[i0+*pos] = line[i0]; /* move up new */
|
|
} /* end for */
|
|
tmp = *pos-1L;
|
|
i0 = 0L;
|
|
if (i0<=tmp) for (;; i0++) {
|
|
line[i0] = buf[i0]; /* ins buf before */
|
|
if (i0==tmp) break;
|
|
} /* end for */
|
|
len += *pos;
|
|
*pos = 0L;
|
|
}
|
|
i0 = 0L;
|
|
while (i0<len && line[i0]!='\012') ++i0;
|
|
if (i0>=len) {
|
|
/* no line end found */
|
|
while (*pos<len) {
|
|
buf[*pos] = line[*pos]; /* move to buf */
|
|
++*pos;
|
|
}
|
|
len = 0L;
|
|
}
|
|
else {
|
|
j = i0+1L;
|
|
while (j<len) {
|
|
buf[*pos] = line[j]; /* move rest to buf */
|
|
++*pos;
|
|
++j;
|
|
}
|
|
len = i0;
|
|
}
|
|
line[len] = 0;
|
|
return len;
|
|
} /* end Gettcp() */
|
|
|
|
|
|
static void showpip(uint32_t ip, uint32_t port, char s[],
|
|
uint32_t s_len)
|
|
{
|
|
char h[21];
|
|
aprsstr_IntToStr((int32_t)(ip/16777216UL), 1UL, s, s_len);
|
|
aprsstr_Append(s, s_len, ".", 2ul);
|
|
aprsstr_IntToStr((int32_t)(ip/65536UL&255UL), 1UL, h, 21ul);
|
|
aprsstr_Append(s, s_len, h, 21ul);
|
|
aprsstr_Append(s, s_len, ".", 2ul);
|
|
aprsstr_IntToStr((int32_t)(ip/256UL&255UL), 1UL, h, 21ul);
|
|
aprsstr_Append(s, s_len, h, 21ul);
|
|
aprsstr_Append(s, s_len, ".", 2ul);
|
|
aprsstr_IntToStr((int32_t)(ip&255UL), 1UL, h, 21ul);
|
|
aprsstr_Append(s, s_len, h, 21ul);
|
|
if (port) {
|
|
aprsstr_Append(s, s_len, ":", 2ul);
|
|
aprsstr_IntToStr((int32_t)port, 1UL, h, 21ul);
|
|
aprsstr_Append(s, s_len, h, 21ul);
|
|
}
|
|
} /* end showpip() */
|
|
|
|
/*
|
|
PROCEDURE clrstr(VAR s:ARRAY OF CHAR);
|
|
VAR i:CARDINAL;
|
|
BEGIN
|
|
i:=0;
|
|
WHILE (i<=HIGH(s)) & (s[i]<>0C) DO
|
|
IF s[i]<" " THEN s[i]:="." END;
|
|
INC(i);
|
|
END;
|
|
END clrstr;
|
|
*/
|
|
|
|
static void logline(int32_t r, char s[], uint32_t s_len)
|
|
{
|
|
char h[512];
|
|
int32_t fd;
|
|
uint32_t i0;
|
|
X2C_PCOPY((void **)&s,s_len);
|
|
if (logframename[0U] && logframes+r>1L) {
|
|
fd = osi_OpenAppend(logframename, 1024ul);
|
|
if (fd<0L) fd = osi_OpenWrite(logframename, 1024ul);
|
|
if (fd>=0L) {
|
|
aprsstr_DateToStr(osic_time(), h, 512ul);
|
|
aprsstr_Append(h, 512ul, " ", 2ul);
|
|
aprsstr_Append(h, 512ul, s, s_len);
|
|
aprsstr_Append(h, 512ul, "\012", 2ul);
|
|
osi_WrBin(fd, (char *)h, 512u/1u, aprsstr_Length(h, 512ul));
|
|
osic_Close(fd);
|
|
}
|
|
else {
|
|
osi_WrStr("cannot write", 13ul);
|
|
osi_WrStr(logframename, 1024ul);
|
|
osic_WrLn();
|
|
}
|
|
}
|
|
if (verb) {
|
|
/* & (r<>-5) */
|
|
i0 = aprsstr_Length(s, s_len);
|
|
if ((i0>=2UL && s[i0-1UL]=='\012') && s[i0-2UL]=='\015') s[i0-2UL] = 0;
|
|
aprsstr_CtrlHex(s, s_len);
|
|
osi_WrStrLn(s, s_len);
|
|
}
|
|
X2C_PFREE(s);
|
|
} /* end logline() */
|
|
|
|
|
|
static void writerawlog(const FRAMEBUF b)
|
|
{
|
|
char h[512];
|
|
FILENAME fn;
|
|
uint32_t i0;
|
|
uint32_t l;
|
|
int32_t f;
|
|
l = aprsstr_Length(b, 512ul);
|
|
while (l>0UL && (uint8_t)b[l-1UL]<='\015') --l;
|
|
if (l>0UL) {
|
|
aprsstr_DateToStr(osic_time(), h, 512ul);
|
|
h[4U] = h[5U];
|
|
h[5U] = h[6U];
|
|
h[6U] = h[8U];
|
|
h[7U] = h[9U];
|
|
h[8U] = 0;
|
|
h[9U] = h[11U];
|
|
h[10U] = h[12U];
|
|
h[11U] = h[14U];
|
|
h[12U] = h[15U];
|
|
h[13U] = h[17U];
|
|
h[14U] = h[18U];
|
|
h[15U] = ' ';
|
|
aprsstr_Assign(fn, 1024ul, rawlogname, 1024ul);
|
|
aprsstr_Append(fn, 1024ul, h, 512ul);
|
|
h[8U] = ':';
|
|
f = osi_OpenAppend(fn, 1024ul);
|
|
if (f<0L) f = osi_OpenWrite(fn, 1024ul);
|
|
if (f>=0L) {
|
|
if (l>=495UL) l = 495UL;
|
|
i0 = 0UL;
|
|
do {
|
|
h[i0+16UL] = b[i0];
|
|
++i0;
|
|
} while (i0<l);
|
|
h[i0+16UL] = '\012';
|
|
++i0;
|
|
osi_WrBin(f, (char *)h, 512u/1u, i0+16UL);
|
|
osic_Close(f);
|
|
}
|
|
else if (verb) {
|
|
osi_WrStr("cannot write ", 14ul);
|
|
osi_WrStrLn(fn, 1024ul);
|
|
}
|
|
}
|
|
} /* end writerawlog() */
|
|
|
|
|
|
static void showframe(int32_t r, pTCPSOCK sp, pUDPSOCK su,
|
|
const char buf[], uint32_t buf_len,
|
|
struct aprspos_POSITION pos)
|
|
{
|
|
char s[512];
|
|
char h[512];
|
|
struct UDPSOCK * anonym;
|
|
if (sp==0) {
|
|
if (su) {
|
|
strncpy(s,"U:",512u);
|
|
{ /* with */
|
|
struct UDPSOCK * anonym = su;
|
|
if (anonym->stat[anonym->laststat]
|
|
.uip!=showip1 || anonym->stat[anonym->laststat]
|
|
.uport!=showport1) {
|
|
showip1 = anonym->stat[anonym->laststat].uip;
|
|
showport1 = anonym->stat[anonym->laststat].uport;
|
|
showpip(showip1, showport1, h, 512ul);
|
|
aprsstr_Append(s, 512ul, h, 512ul);
|
|
aprsstr_Append(s, 512ul, ":", 2ul);
|
|
}
|
|
}
|
|
}
|
|
else strncpy(s," :",512u);
|
|
}
|
|
else {
|
|
s[0U] = sp->service;
|
|
s[1U] = ':';
|
|
s[2U] = 0;
|
|
if (sp->user.call[0U] && !aprsstr_StrCmp(sp->user.call, 10ul, showid,
|
|
10ul)) {
|
|
aprsstr_Append(s, 512ul, sp->user.call, 10ul);
|
|
aprsstr_Append(s, 512ul, ":", 2ul);
|
|
aprsstr_Assign(showid, 10ul, sp->user.call, 10ul);
|
|
}
|
|
}
|
|
/*
|
|
IO.WrFixed(distance(home,pos), 1, 10); IO.WrStr("km"); IO.WrLn;
|
|
*/
|
|
switch (r) {
|
|
case 0L:
|
|
if (!aprspos_posvalid(pos) || !aprspos_posvalid(home)) {
|
|
strncpy(h,"--->",512u);
|
|
}
|
|
else {
|
|
aprsstr_IntToStr((int32_t)(uint32_t)
|
|
X2C_TRUNCC(0.5f+aprspos_distance(home, pos),0UL,
|
|
X2C_max_longcard), 3UL, h, 512ul);
|
|
aprsstr_Append(h, 512ul, ">", 2ul);
|
|
}
|
|
break;
|
|
case -1L:
|
|
strncpy(h,"syn:",512u);
|
|
break;
|
|
case -2L:
|
|
strncpy(h,"len:",512u);
|
|
break;
|
|
case -3L:
|
|
strncpy(h,"cal:",512u);
|
|
break;
|
|
case -4L:
|
|
strncpy(h,"msg:",512u);
|
|
break;
|
|
case -5L:
|
|
strncpy(h,"dup:",512u);
|
|
break;
|
|
case -6L:
|
|
strncpy(h,"ung:",512u);
|
|
break;
|
|
default:;
|
|
strncpy(h," :",512u);
|
|
break;
|
|
} /* end switch */
|
|
aprsstr_Append(s, 512ul, h, 512ul);
|
|
aprsstr_Append(s, 512ul, buf, buf_len);
|
|
logline(r, s, 512ul);
|
|
} /* end showframe() */
|
|
|
|
|
|
static void appkib(char s[], uint32_t s_len, uint32_t h,
|
|
uint32_t l)
|
|
{
|
|
char b[41];
|
|
if (h>0UL) {
|
|
aprsstr_CardToStr(l/1024UL+h*4194304UL, 1UL, b, 41ul);
|
|
aprsstr_Append(s, s_len, "kB=", 4ul);
|
|
}
|
|
else {
|
|
aprsstr_CardToStr(l, 1UL, b, 41ul);
|
|
aprsstr_Append(s, s_len, "B=", 3ul);
|
|
}
|
|
aprsstr_Append(s, s_len, b, 41ul);
|
|
} /* end appkib() */
|
|
|
|
|
|
static uint32_t bitsec64(uint32_t h, uint32_t l, uint32_t t)
|
|
{
|
|
float r;
|
|
r = X2C_DIVR(((float)h*4.294967296E+9f+(float)l)*8.0f,(float)t);
|
|
if (r>2.E+9f) return 2000000000UL;
|
|
return (uint32_t)X2C_TRUNCC(r,0UL,X2C_max_longcard);
|
|
} /* end bitsec64() */
|
|
|
|
|
|
static void Statist(pTCPSOCK cp, uint32_t t, char s[],
|
|
uint32_t s_len)
|
|
{
|
|
char h[256];
|
|
struct TCPSOCK * anonym;
|
|
{ /* with */
|
|
struct TCPSOCK * anonym = cp;
|
|
if (anonym->connt<t) t -= anonym->connt;
|
|
else t = 0UL;
|
|
aprsstr_Assign(s, s_len, " t=", 4ul);
|
|
aprsstr_TimeToStr(t, h, 256ul);
|
|
aprsstr_Append(s, s_len, h, 256ul);
|
|
aprsstr_CardToStr(anonym->txframes, 1UL, h, 256ul);
|
|
aprsstr_Append(s, s_len, " txf=", 6ul);
|
|
aprsstr_Append(s, s_len, h, 256ul);
|
|
aprsstr_CardToStr(anonym->rxframes, 1UL, h, 256ul);
|
|
aprsstr_Append(s, s_len, " rxf=", 6ul);
|
|
aprsstr_Append(s, s_len, h, 256ul);
|
|
aprsstr_Append(s, s_len, " tx", 4ul);
|
|
appkib(s, s_len, anonym->txbytesh, anonym->txbytes);
|
|
aprsstr_Append(s, s_len, " rx", 4ul);
|
|
appkib(s, s_len, anonym->rxbytesh, anonym->rxbytes);
|
|
if (t>0UL) {
|
|
aprsstr_Append(s, s_len, " ", 2ul);
|
|
aprsstr_CardToStr(bitsec64(anonym->txbytesh, anonym->txbytes, t),
|
|
1UL, h, 256ul);
|
|
aprsstr_Append(s, s_len, h, 256ul);
|
|
aprsstr_Append(s, s_len, "tbit/s ", 8ul);
|
|
aprsstr_CardToStr(bitsec64(anonym->rxbytesh, anonym->rxbytes, t),
|
|
1UL, h, 256ul);
|
|
aprsstr_Append(s, s_len, h, 256ul);
|
|
aprsstr_Append(s, s_len, "rbit/s", 7ul);
|
|
}
|
|
}
|
|
} /* end Statist() */
|
|
|
|
|
|
static void showlogout(pTCPSOCK sp)
|
|
{
|
|
char t[256];
|
|
char h[256];
|
|
struct TCPSOCK * anonym;
|
|
{ /* with */
|
|
struct TCPSOCK * anonym = sp;
|
|
if (anonym->slowlink) strncpy(h,"T:slowlink closed ",256u);
|
|
else strncpy(h,"T:connection closed ",256u);
|
|
aprsstr_Append(h, 256ul, anonym->user.call, 10ul);
|
|
aprsstr_Append(h, 256ul, " ", 2ul);
|
|
aprsstr_Append(h, 256ul, anonym->ipnum, 64ul);
|
|
if (anonym->connt) {
|
|
Statist(sp, systime, t, 256ul);
|
|
/*
|
|
ti:=time();
|
|
IF ti<connt THEN ti:=0 ELSE DEC(ti, connt) END;
|
|
Append(h," conntime ");
|
|
TimeToStr(ti, t);
|
|
*/
|
|
aprsstr_Append(h, 256ul, t, 256ul);
|
|
}
|
|
aprsstr_Append(h, 256ul, "\012", 2ul);
|
|
}
|
|
logline(1L, h, 256ul);
|
|
} /* end showlogout() */
|
|
|
|
|
|
static char vias(char dat[], uint32_t dat_len, pTCPSOCK to)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
uint32_t b;
|
|
uint32_t a;
|
|
struct FILTERS * anonym;
|
|
if (to->filters.viacalls[0U][0U]==0 || dat[0UL]==0) return 0;
|
|
b = 0UL;
|
|
do {
|
|
a = b+1UL;
|
|
do {
|
|
++b;
|
|
if (b>dat_len-1 || dat[b]==0) return 0;
|
|
} while (!(dat[b]==',' || dat[b]==':'));
|
|
/* not normal data */
|
|
if (a>1UL) {
|
|
j = 0UL;
|
|
{ /* with */
|
|
struct FILTERS * anonym = &to->filters;
|
|
while (j<=7UL && anonym->viacalls[j][0U]) {
|
|
i0 = 0UL;
|
|
for (;;) {
|
|
if (a+i0>=b || dat[a+i0]=='*') {
|
|
/* end of word 1 ignore h-bit "*" */
|
|
if ((i0>9UL || anonym->viacalls[j][i0]==0)
|
|
|| anonym->viacalls[j][i0]
|
|
=='*' && (i0+1UL>9UL || anonym->viacalls[j][i0+1UL]==0)) {
|
|
return 1;
|
|
}
|
|
else break;
|
|
}
|
|
if (i0>9UL || anonym->viacalls[j][i0]==0) {
|
|
break; /* end of word 2 */
|
|
}
|
|
if (anonym->viacalls[j][i0]
|
|
=='*' && (i0+1UL>9UL || anonym->viacalls[j][i0+1UL]==0)) {
|
|
return 1;
|
|
}
|
|
/* word 2 "*" at end */
|
|
if (anonym->viacalls[j][i0]!='*' && anonym->viacalls[j][i0]
|
|
!=dat[a+i0]) break;
|
|
++i0;
|
|
}
|
|
++j; /* next call in table */
|
|
}
|
|
}
|
|
}
|
|
} while (dat[b]!=':');
|
|
return 0;
|
|
} /* end vias() */
|
|
|
|
|
|
static char entrypoint(char dat[], uint32_t dat_len,
|
|
pTCPSOCK to)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
uint32_t b;
|
|
uint32_t a;
|
|
struct FILTERS * anonym;
|
|
if (to->filters.entrycalls[0U][0U]==0) return 0;
|
|
i0 = 0UL;
|
|
for (;;) {
|
|
if ((i0>(dat_len-1)-5UL || dat[i0]==0) || dat[i0]==':') return 0;
|
|
/* no qA */
|
|
if (((dat[i0]==',' && dat[i0+1UL]=='q') && dat[i0+2UL]=='A')
|
|
&& dat[i0+4UL]==',') {
|
|
/* ,qA., */
|
|
a = i0+5UL;
|
|
b = a;
|
|
while (((b<dat_len-1 && dat[b]) && dat[b]!=':') && dat[b]!=',') ++b;
|
|
break;
|
|
}
|
|
++i0;
|
|
}
|
|
j = 0UL;
|
|
{ /* with */
|
|
struct FILTERS * anonym = &to->filters;
|
|
while (j<=7UL && anonym->entrycalls[j][0U]) {
|
|
i0 = 0UL;
|
|
for (;;) {
|
|
if (a+i0>=b) {
|
|
/* end of word 1 */
|
|
if ((i0>9UL || anonym->entrycalls[j][i0]==0)
|
|
|| anonym->entrycalls[j][i0]
|
|
=='*' && (i0+1UL>9UL || anonym->entrycalls[j][i0+1UL]==0)) {
|
|
return 1;
|
|
}
|
|
else break;
|
|
}
|
|
if (i0>9UL || anonym->entrycalls[j][i0]==0) break;
|
|
if (anonym->entrycalls[j][i0]
|
|
=='*' && (i0+1UL>9UL || anonym->entrycalls[j][i0+1UL]==0)) {
|
|
return 1;
|
|
}
|
|
/* word 2 "*" at end */
|
|
if (anonym->entrycalls[j][i0]!='*' && anonym->entrycalls[j][i0]
|
|
!=dat[a+i0]) break;
|
|
++i0;
|
|
}
|
|
/*
|
|
WHILE (a+i<b) & ((entrycalls[j][i]="*")
|
|
OR (entrycalls[j][i]=dat[a+i])) DO
|
|
INC(i);
|
|
IF (a+i>=b) & ((i>HIGH(entrycalls[0]))
|
|
OR (entrycalls[j][i]=0C)) THEN RETURN TRUE END;
|
|
|
|
*/
|
|
++j;
|
|
}
|
|
}
|
|
return 0;
|
|
} /* end entrypoint() */
|
|
|
|
|
|
static char prefix(char dat[], uint32_t dat_len, pTCPSOCK to)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
struct FILTERS * anonym;
|
|
if (to->filters.prefixes[0U][0U]==0) return 0;
|
|
j = 0UL;
|
|
{ /* with */
|
|
struct FILTERS * anonym = &to->filters;
|
|
while (j<=7UL && anonym->prefixes[j][0U]) {
|
|
i0 = 0UL;
|
|
while (dat[i0]!='>' && anonym->prefixes[j][i0]==dat[i0]) {
|
|
++i0;
|
|
if (i0>9UL || anonym->prefixes[j][i0]==0) return 1;
|
|
}
|
|
++j;
|
|
}
|
|
}
|
|
return 0;
|
|
} /* end prefix() */
|
|
|
|
|
|
static char destcallfilt(char dat[], uint32_t dat_len,
|
|
pTCPSOCK to)
|
|
{
|
|
uint32_t b;
|
|
uint32_t a;
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
struct FILTERS * anonym;
|
|
if (to->filters.destcalls[0U][0U]==0) return 0;
|
|
a = 0UL;
|
|
while (dat[a]!='>') {
|
|
/* begin of dest call ">" */
|
|
if (a>=dat_len-1 || dat[a]==0) return 0;
|
|
/* not normal data */
|
|
++a;
|
|
}
|
|
++a;
|
|
b = a;
|
|
for (;;) {
|
|
if (b>dat_len-1 || dat[b]==0) return 0;
|
|
/* not normal data */
|
|
if (dat[b]==',' || dat[b]==':') break;
|
|
++b;
|
|
}
|
|
b -= a; /* len of dest call */
|
|
j = 0UL;
|
|
{ /* with */
|
|
struct FILTERS * anonym = &to->filters;
|
|
while (j<=7UL && anonym->destcalls[j][0U]) {
|
|
i0 = 0UL;
|
|
while (i0<b && (anonym->destcalls[j][i0]
|
|
=='*' || anonym->destcalls[j][i0]==dat[i0+a])) {
|
|
++i0;
|
|
if (i0>9UL || anonym->destcalls[j][i0]==0) return 1;
|
|
}
|
|
++j;
|
|
}
|
|
}
|
|
return 0;
|
|
} /* end destcallfilt() */
|
|
|
|
|
|
static char typ(struct POSCALL * posc, char dat[],
|
|
uint32_t dat_len, pTCPSOCK to, char * t)
|
|
{
|
|
uint32_t ii;
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
char c;
|
|
if (to->filters.typs[0U]==0) return 0;
|
|
i0 = 0UL;
|
|
j = 0UL;
|
|
c = 0;
|
|
for (;;) {
|
|
if (i0>(dat_len-1)-2UL || dat[i0]==0) return 0;
|
|
/* no typ */
|
|
if (dat[i0]==':') {
|
|
/* outer typ */
|
|
c = dat[i0+1UL];
|
|
if (c!='}') {
|
|
i0 += 2UL; /* inner typchar found*/
|
|
break;
|
|
}
|
|
if (aprsstr_InStr(to->filters.typs, 13ul, "3", 2ul)>=0L) return 1;
|
|
/* 3rd party frame */
|
|
j = i0+2UL; /* start of inner frame */
|
|
}
|
|
++i0;
|
|
}
|
|
if (c==':') {
|
|
ii = i0;
|
|
while (ii<dat_len-1 && dat[j]==dat[ii]) {
|
|
++ii; /* msg to itself */
|
|
++j;
|
|
}
|
|
if (dat[j]=='>') {
|
|
c = 'T'; /* gets type telemetry */
|
|
*t = 'T';
|
|
}
|
|
}
|
|
if (aprspos_posvalid(posc->pos) && aprsstr_InStr(to->filters.typs, 13ul, "\
|
|
p", 2ul)>=0L) return 1;
|
|
/* position frame */
|
|
if (c==';' && aprsstr_InStr(to->filters.typs, 13ul, "o", 2ul)>=0L) {
|
|
return 1;
|
|
}
|
|
/* object */
|
|
if (c==')') return aprsstr_InStr(to->filters.typs, 13ul, "i", 2ul)>=0L;
|
|
/* item */
|
|
if (c==':') {
|
|
if (dat[i0+10UL]=='?') {
|
|
return aprsstr_InStr(to->filters.typs, 13ul, "q", 2ul)>=0L;
|
|
}
|
|
else if ((((i0<(dat_len-1)-6UL && dat[i0]=='N') && dat[i0+1UL]=='W')
|
|
&& dat[i0+2UL]=='S') && dat[i0+3UL]=='-') {
|
|
/* query */
|
|
return aprsstr_InStr(to->filters.typs, 13ul, "n", 2ul)>=0L;
|
|
}
|
|
else {
|
|
/* NWS bulletin */
|
|
return aprsstr_InStr(to->filters.typs, 13ul, "m", 2ul)>=0L;
|
|
}
|
|
}
|
|
/* message */
|
|
if (c=='>') return aprsstr_InStr(to->filters.typs, 13ul, "s", 2ul)>=0L;
|
|
/* status */
|
|
if (c=='T') return aprsstr_InStr(to->filters.typs, 13ul, "t", 2ul)>=0L;
|
|
/* telemetry */
|
|
if (c=='{') return aprsstr_InStr(to->filters.typs, 13ul, "u", 2ul)>=0L;
|
|
/* user defined */
|
|
if (aprsstr_InStr(to->filters.typs, 13ul, "w", 2ul)>=0L) {
|
|
/* test if wx */
|
|
j = 0UL;
|
|
if (c=='_') return 1;
|
|
/* positionless wx */
|
|
if (c=='!' || c=='=') {
|
|
if ((uint8_t)dat[i0]>='0' && (uint8_t)dat[i0]<='9') j = i0+18UL;
|
|
else j = i0+9UL;
|
|
}
|
|
else if (c=='/' || c=='@') {
|
|
if ((uint8_t)dat[i0+7UL]>='0' && (uint8_t)dat[i0+7UL]<='9') {
|
|
j = i0+25UL;
|
|
}
|
|
else j = i0+16UL;
|
|
}
|
|
else if (c==';') j = i0+35UL;
|
|
/*WrStr("<<<"); WrStr(dat[j]);WrStrLn(">>>"); */
|
|
if (((j>0UL && j<dat_len-1) && dat[j]=='_')
|
|
&& aprspos_posvalid(posc->pos)) return 1;
|
|
}
|
|
return 0;
|
|
} /* end typ() */
|
|
|
|
|
|
static char Filter(pTCPSOCK to, struct POSCALL posc,
|
|
const char dat[], uint32_t dat_len)
|
|
{
|
|
char pass;
|
|
pass = 0;
|
|
if (vias(dat, dat_len, to)) {
|
|
if (to->filters.notvia) return 0;
|
|
pass = 1; /* exclusion overloads */
|
|
}
|
|
if (entrypoint(dat, dat_len, to)) {
|
|
if (to->filters.notentry) return 0;
|
|
pass = 1;
|
|
}
|
|
if (destcallfilt(dat, dat_len, to)) {
|
|
if (to->filters.notdestcall) return 0;
|
|
pass = 1;
|
|
}
|
|
if (prefix(dat, dat_len, to)) {
|
|
if (to->filters.notprefix) return 0;
|
|
pass = 1;
|
|
}
|
|
if (typ(&posc, dat, dat_len, to, &posc.typ0)) {
|
|
if (to->filters.nottyps) return 0;
|
|
pass = 1;
|
|
}
|
|
if (pass || posc.typ0==':') return 1;
|
|
/* pass messages and ack */
|
|
if (to->filters.typ0=='m') {
|
|
return (aprspos_posvalid(to->user.pos) && aprspos_posvalid(posc.pos))
|
|
&& aprspos_distance(to->user.pos,
|
|
posc.pos)<=to->filters.radius;
|
|
}
|
|
if (to->filters.typ0=='r') {
|
|
/*
|
|
IO.WrStr("l,b,l,b,d,r:"); IO.WrFixed(to^.filters.base.lat/RAD, 4,10);
|
|
IO.WrFixed(to^.filters.base.long/RAD, 4,10);
|
|
IO.WrFixed(posc.pos.lat/RAD, 4,10);
|
|
IO.WrFixed(posc.pos.long/RAD, 4,10);
|
|
IO.WrFixed(distance(to^.filters.base, posc.pos), 4,10);
|
|
IO.WrFixed(to^.filters.radius, 4,10);
|
|
IO.WrLn;
|
|
*/
|
|
return aprspos_posvalid(posc.pos) && aprspos_distance(to->filters.base,
|
|
posc.pos)<=to->filters.radius;
|
|
}
|
|
if (to->filters.typ0=='a') {
|
|
/*
|
|
IO.WrStr("l,b,l,b,l,b,d,r:");
|
|
IO.WrFixed(to^.filters.base.lat/RAD, 4,10);
|
|
IO.WrFixed(to^.filters.base.long/RAD, 4,10);
|
|
IO.WrFixed(to^.filters.edge.lat/RAD, 4,10);
|
|
IO.WrFixed(to^.filters.edge.long/RAD, 4,10);
|
|
IO.WrFixed(posc.pos.lat/RAD, 4,10);
|
|
IO.WrFixed(posc.pos.long/RAD, 4,10);
|
|
IO.WrLn;
|
|
*/
|
|
return (((aprspos_posvalid(posc.pos)
|
|
&& to->filters.base.lat>=posc.pos.lat)
|
|
&& to->filters.base.long0<=posc.pos.long0)
|
|
&& to->filters.edge.lat<=posc.pos.lat)
|
|
&& to->filters.edge.long0>=posc.pos.long0;
|
|
}
|
|
return !datafilter;
|
|
} /* end Filter() */
|
|
|
|
|
|
static void sendtcpbuf(pTCPSOCK to)
|
|
{
|
|
int32_t i0;
|
|
int32_t res0;
|
|
struct TCPSOCK * anonym;
|
|
int32_t tmp;
|
|
{ /* with */
|
|
struct TCPSOCK * anonym = to;
|
|
res0 = sendsock(anonym->fd, anonym->tbuf, anonym->tlen);
|
|
if (res0>0L) {
|
|
tmp = anonym->tlen-1L;
|
|
i0 = res0;
|
|
if (i0<=tmp) for (;; i0++) {
|
|
anonym->tbuf[i0-res0] = anonym->tbuf[i0];
|
|
if (i0==tmp) break;
|
|
} /* end for */
|
|
anonym->tlen -= res0;
|
|
}
|
|
}
|
|
} /* end sendtcpbuf() */
|
|
|
|
|
|
static void Sendtcp(pTCPSOCK to, const FRAMEBUF buf)
|
|
{
|
|
int32_t i0;
|
|
int32_t len;
|
|
struct TCPSOCK * anonym;
|
|
int32_t tmp;
|
|
len = (int32_t)aprsstr_Length(buf, 512ul);
|
|
{ /* with */
|
|
struct TCPSOCK * anonym = to;
|
|
if (anonym->tlen+len>=1024L) sendtcpbuf(to);
|
|
if (anonym->tlen+len<1024L) {
|
|
tmp = len-1L;
|
|
i0 = 0L;
|
|
if (i0<=tmp) for (;; i0++) {
|
|
anonym->tbuf[anonym->tlen] = buf[i0];
|
|
++anonym->tlen;
|
|
if (i0==tmp) break;
|
|
} /* end for */
|
|
++anonym->txframes;
|
|
anonym->txbytes += (uint32_t)len; /* 32 bit overflow */
|
|
if (anonym->txbytes<(uint32_t)len) ++anonym->txbytesh;
|
|
}
|
|
else {
|
|
++anonym->losttxframes;
|
|
if (verb) osi_WrStrLn("tx buf overflow", 16ul);
|
|
}
|
|
}
|
|
} /* end Sendtcp() */
|
|
|
|
|
|
static char filt(int32_t outer, char b[], uint32_t b_len,
|
|
const char s[], uint32_t s_len)
|
|
{
|
|
int32_t n;
|
|
n = aprsstr_InStr(b, b_len, s, s_len);
|
|
return n>=0L && n<outer;
|
|
} /* end filt() */
|
|
|
|
|
|
static void NetToRf(const char b[], uint32_t b_len, uint32_t rfport)
|
|
/* send as 3rd party frame to rf */
|
|
{
|
|
FRAMEBUF tb;
|
|
uint32_t viaused;
|
|
uint32_t viaend;
|
|
uint32_t len;
|
|
uint32_t i0;
|
|
int32_t ii;
|
|
int32_t outer;
|
|
outer = aprsstr_InStr(b, b_len, ":", 2ul);
|
|
/* test if gate to rf allowed */
|
|
if (outer<0L || filt(outer, b, b_len, "qAX", 4ul)) return;
|
|
viaend = (uint32_t)outer;
|
|
while (outer<(int32_t)(b_len-1) && (b[outer]!=':' || b[outer+1L]=='}')) {
|
|
++outer;
|
|
}
|
|
if ((filt(outer, b, b_len, "TCPXX", 6ul) || filt(outer, b, b_len,
|
|
"NOGATE", 7ul)) || filt(outer, b, b_len, "RFONLY", 7ul)) {
|
|
return;
|
|
}
|
|
aprsstr_Assign(tb, 512ul, viacall, 10ul);
|
|
aprsstr_Append(tb, 512ul, ">APNL51", 8ul);
|
|
if (nettorfpath[0U]) {
|
|
aprsstr_Append(tb, 512ul, ",", 2ul);
|
|
aprsstr_Append(tb, 512ul, nettorfpath, 81ul);
|
|
}
|
|
aprsstr_Append(tb, 512ul, ":}", 3ul);
|
|
viaused = 0UL;
|
|
while (viaused<viaend && b[viaused]!=',') ++viaused;
|
|
ii = aprsstr_InStr(b, b_len, ",TCPIP", 7ul);
|
|
if (ii<0L || ii>(int32_t)viaend) {
|
|
/* remove all via if via TCPIP */
|
|
i0 = viaused;
|
|
while (i0<viaend && b[i0]!='*') ++i0;
|
|
if (i0<viaend) viaused = i0;
|
|
}
|
|
len = aprsstr_Length(tb, 512ul);
|
|
i0 = 0UL;
|
|
/* WHILE (b[i]<>",") & (i<viaend) & (len<=HIGH(tb)) DO (* original head remove via*) */
|
|
while (i0<viaused && len<=511UL) {
|
|
/* original head with used via*/
|
|
tb[len] = b[i0];
|
|
++i0;
|
|
++len;
|
|
}
|
|
if (len<=511UL) tb[len] = 0;
|
|
aprsstr_Append(tb, 512ul, ",TCPIP,", 8ul);
|
|
aprsstr_Append(tb, 512ul, viacall, 10ul);
|
|
aprsstr_Append(tb, 512ul, "*", 2ul);
|
|
len = aprsstr_Length(tb, 512ul);
|
|
i0 = viaend;
|
|
while ((i0<=b_len-1 && b[i0]) && len<=511UL) {
|
|
/* original data part */
|
|
tb[len] = b[i0];
|
|
++i0;
|
|
++len;
|
|
}
|
|
if (len<=511UL) tb[len] = 0;
|
|
i0 = 0UL;
|
|
while (((i0<511UL && tb[i0]) && tb[i0]!='\015') && tb[i0]!='\012') ++i0;
|
|
tb[i0] = 0;
|
|
Sendudp(tb, rfport, 0);
|
|
} /* end NetToRf() */
|
|
|
|
|
|
static void Sendall(const FRAMEBUF buf, int32_t fromfd,
|
|
const struct POSCALL posc)
|
|
{
|
|
pTCPSOCK t;
|
|
pUDPSOCK u;
|
|
uint32_t uport;
|
|
/*
|
|
len:INTEGER;
|
|
*/
|
|
if (buf[0U]) {
|
|
t = tcpsocks;
|
|
while (t) {
|
|
if (((t->fd!=fromfd && t->service!='W') && t->connt>0UL)
|
|
&& (t->service!='S' || Filter(t, posc, buf, 512ul))) {
|
|
Sendtcp(t, buf);
|
|
}
|
|
t = t->next;
|
|
}
|
|
if ((fromfd>0L && aprspos_posvalid(home)) && aprspos_posvalid(posc.pos)
|
|
) {
|
|
u = udpsocks;
|
|
uport = 1UL;
|
|
while (u) {
|
|
if (u->torfradius>0.0f && aprspos_distance(home,
|
|
posc.pos)<=u->torfradius) NetToRf(buf, 512ul, uport);
|
|
++uport;
|
|
u = u->next;
|
|
}
|
|
}
|
|
/*
|
|
IF rfgateport>0 THEN
|
|
len:=Length(buf);
|
|
len:=udp.udpsend(udpsock.fd, buf, len, rfgateport, rfgateip);
|
|
END;
|
|
*/
|
|
if (rawlogname[0U]) writerawlog(buf);
|
|
}
|
|
} /* end Sendall() */
|
|
|
|
|
|
static char cmpfrom(const char a[], uint32_t a_len,
|
|
uint32_t from, const char b[], uint32_t b_len)
|
|
{
|
|
uint32_t i0;
|
|
i0 = 0UL;
|
|
while (from<=a_len-1 && b[i0]) {
|
|
if (a[from]!=b[i0]) return 0;
|
|
++i0;
|
|
++from;
|
|
}
|
|
return 1;
|
|
} /* end cmpfrom() */
|
|
|
|
#define udpgate4_MSYM "\\"
|
|
|
|
|
|
static void beaconmacros(char s[], uint32_t s_len)
|
|
{
|
|
uint32_t i0;
|
|
int32_t j;
|
|
int32_t len;
|
|
char ns[256];
|
|
char ds[256];
|
|
char fn[1024];
|
|
int32_t f;
|
|
i0 = 0UL;
|
|
ns[0U] = 0;
|
|
while (i0<s_len-1 && s[i0]) {
|
|
if (s[i0]=='\\' && s[i0+1UL]=='\\') {
|
|
i0 += 2UL;
|
|
if (s[i0]=='z') {
|
|
/* insert day, hour, min */
|
|
aprsstr_DateToStr(osic_time(), ds, 256ul);
|
|
ds[0U] = ds[8U];
|
|
ds[1U] = ds[9U];
|
|
ds[2U] = ds[11U];
|
|
ds[3U] = ds[12U];
|
|
ds[4U] = ds[14U];
|
|
ds[5U] = ds[15U];
|
|
ds[6U] = 0;
|
|
aprsstr_Append(ns, 256ul, ds, 256ul);
|
|
}
|
|
else if (s[i0]=='h') {
|
|
/* insert hour, min, s */
|
|
aprsstr_DateToStr(osic_time(), ds, 256ul);
|
|
ds[0U] = ds[11U];
|
|
ds[1U] = ds[12U];
|
|
ds[2U] = ds[14U];
|
|
ds[3U] = ds[15U];
|
|
ds[4U] = ds[17U];
|
|
ds[5U] = ds[18U];
|
|
ds[6U] = 0;
|
|
aprsstr_Append(ns, 256ul, ds, 256ul);
|
|
}
|
|
else if (s[i0]=='v') {
|
|
/* insert version */
|
|
aprsstr_Append(ns, 256ul, "udpgate(c) 0.63", 16ul);
|
|
}
|
|
else if (s[i0]==':') {
|
|
/* insert file */
|
|
fn[0U] = 0;
|
|
++i0;
|
|
while ((i0<s_len-1 && s[i0]) && s[i0]!=':') {
|
|
aprsstr_Append(fn, 1024ul, (char *) &s[i0], 1u/1u);
|
|
++i0;
|
|
}
|
|
f = osi_OpenRead(fn, 1024ul);
|
|
if (f>=0L) {
|
|
len = osi_RdBin(f, (char *)ds, 256u/1u, 255UL);
|
|
osic_Close(f);
|
|
j = 0L;
|
|
while (((j<len && ds[j]!='\015') && ds[j]!='\012') && ds[j]) {
|
|
aprsstr_Append(ns, 256ul, (char *) &ds[j], 1u/1u);
|
|
++j;
|
|
}
|
|
}
|
|
else {
|
|
if (verb) {
|
|
osic_WrLn();
|
|
osi_WrStrLn("beacon macro file not readable ", 32ul);
|
|
}
|
|
s[0UL] = 0;
|
|
return;
|
|
}
|
|
}
|
|
else if (s[i0]=='\\') aprsstr_Append(ns, 256ul, "\\\\", 3ul);
|
|
else {
|
|
if (verb) {
|
|
osic_WrLn();
|
|
osi_WrStrLn("bad beacon macro ", 18ul);
|
|
}
|
|
s[0UL] = 0;
|
|
return;
|
|
}
|
|
}
|
|
else aprsstr_Append(ns, 256ul, (char *) &s[i0], 1u/1u);
|
|
++i0;
|
|
}
|
|
aprsstr_Assign(s, s_len, ns, 256ul);
|
|
} /* end beaconmacros() */
|
|
|
|
|
|
static void AppQ(char h[], uint32_t h_len, const char q[],
|
|
uint32_t q_len, char appcall)
|
|
{
|
|
aprsstr_Append(h, h_len, ">APNL51,", 9ul);
|
|
aprsstr_Append(h, h_len, q, q_len);
|
|
if (appcall) aprsstr_Append(h, h_len, servercall, 10ul);
|
|
aprsstr_Append(h, h_len, ":", 2ul);
|
|
} /* end AppQ() */
|
|
|
|
|
|
static void Netbeacon(char h[], uint32_t h_len, char qai,
|
|
char withpath)
|
|
{
|
|
int32_t valt0;
|
|
int32_t i0;
|
|
int32_t f;
|
|
FRAMEBUF h1;
|
|
uint32_t j;
|
|
uint32_t vspeed0;
|
|
uint32_t vcourse0;
|
|
char vsymt0;
|
|
char vsym0;
|
|
char postyp;
|
|
h[0UL] = 0;
|
|
if (servercall[0U] && netbeaconfn[0U]) {
|
|
f = osi_OpenRead(netbeaconfn, 1024ul);
|
|
if (f>=0L) {
|
|
i0 = osi_RdBin(f, (char *)h1, 512u/1u, 511UL);
|
|
if (i0>=0L) {
|
|
h1[i0] = 0;
|
|
i0 = 0L;
|
|
while ((uint8_t)h1[i0]>=' ') ++i0;
|
|
h1[i0] = 0;
|
|
beaconmacros(h1, 512ul);
|
|
if (withpath) {
|
|
aprsstr_Assign(h, h_len, servercall, 10ul);
|
|
if (qai) AppQ(h, h_len, "TCPIP*,qAI,", 12ul, 1);
|
|
else AppQ(h, h_len, "TCPIP*", 7ul, 0);
|
|
aprsstr_Append(h, h_len, h1, 512ul);
|
|
aprsstr_Append(h, h_len, "\015\012", 3ul);
|
|
}
|
|
else aprsstr_Assign(h, h_len, h1, 512ul);
|
|
}
|
|
osic_Close(f);
|
|
j = 0UL;
|
|
while (j<(h_len-1)-1UL && h[j]!=':') ++j;
|
|
aprspos_GetPos(&home, &vspeed0, &vcourse0, &valt0, &vsym0, &vsymt0,
|
|
h, h_len, 0UL, j+1UL, h1, 512ul, &postyp);
|
|
/* find server position */
|
|
if (verb && !aprspos_posvalid(home)) {
|
|
osi_WrStrLn("netbeacon has no valid position", 32ul);
|
|
}
|
|
}
|
|
else if (verb) osi_WrStrLn("netbeacon file not found", 25ul);
|
|
}
|
|
} /* end Netbeacon() */
|
|
|
|
|
|
static void Timebeacon(pTCPSOCK cp)
|
|
{
|
|
FRAMEBUF h;
|
|
char qai;
|
|
if (cp->service!='W' && Watchclock(&cp->beacont, netbeaconintervall)) {
|
|
qai = 1;
|
|
if (cp->service=='G') {
|
|
if (qas==1UL || qas>qasc+1UL) {
|
|
qai = 0;
|
|
++qasc;
|
|
}
|
|
else qasc = 0UL;
|
|
}
|
|
Netbeacon(h, 512ul, qai, 1);
|
|
if (h[0U]) Sendtcp(cp, h);
|
|
}
|
|
/*
|
|
PROCEDURE inetrf(buf-:ARRAY OF CHAR);
|
|
CONST KW="RFONLY,";
|
|
VAR p,i:CARDINAL;
|
|
c:CHAR;
|
|
mon:FRAMEBUF;
|
|
BEGIN
|
|
(* call>RFONLY,igatecall:}txdata *)
|
|
p:=0;
|
|
LOOP
|
|
IF buf[p]=0C THEN RETURN END;
|
|
IF buf[p]=">" THEN EXIT END;
|
|
INC(p);
|
|
END;
|
|
INC(p);
|
|
i:=0;
|
|
LOOP
|
|
IF buf[p]=0C THEN RETURN END;
|
|
IF KW[i]=0C THEN EXIT END;
|
|
IF buf[p]<>KW[i] THEN RETURN END;
|
|
INC(p);
|
|
INC(i);
|
|
END;
|
|
i:=0;
|
|
LOOP
|
|
IF buf[p]=0C THEN RETURN END;
|
|
IF (i>HIGH(servercall)) OR (servercall[i]=0C) THEN EXIT END;
|
|
IF buf[p]<>servercall[i] THEN RETURN END;
|
|
INC(p);
|
|
INC(i);
|
|
END;
|
|
IF buf[p]<>":" THEN RETURN END;
|
|
INC(p);
|
|
IF buf[p]<>cTHIRDPARTY THEN RETURN END;
|
|
INC(p);
|
|
i:=0;
|
|
LOOP
|
|
c:=buf[p];
|
|
IF (i>=HIGH(mon)) OR (c=CR) THEN c:=0C END;
|
|
mon[i]:=c;
|
|
IF c=0C THEN EXIT END;
|
|
INC(p);
|
|
INC(i);
|
|
END;
|
|
Sendudp(mon);
|
|
END inetrf;
|
|
*/
|
|
} /* end Timebeacon() */
|
|
|
|
|
|
static void Showmsg(pMESSAGE m)
|
|
{
|
|
struct MESSAGE * anonym;
|
|
{ /* with */
|
|
struct MESSAGE * anonym = m;
|
|
osic_WrINT32(anonym->retryc, 3UL);
|
|
osic_WrINT32((uint32_t)anonym->acked, 1UL);
|
|
if (anonym->txtime) osic_WrINT32(systime-anonym->txtime, 5UL);
|
|
else osi_WrStr(" notx", 6ul);
|
|
osi_WrStr(":", 2ul);
|
|
osi_WrStr(anonym->from, 10ul);
|
|
osi_WrStr(">", 2ul);
|
|
osi_WrStr(anonym->to, 10ul);
|
|
osi_WrStr("|", 2ul);
|
|
osi_WrStr(anonym->ack, 5ul);
|
|
osi_WrStr(anonym->replyack, 2ul);
|
|
osi_WrStr("|", 2ul);
|
|
osi_WrStr(anonym->text, 68ul);
|
|
osi_WrStrLn("|", 2ul);
|
|
}
|
|
} /* end Showmsg() */
|
|
|
|
|
|
static void cpcall(char s[], uint32_t s_len, const char h[],
|
|
uint32_t h_len, uint32_t pr)
|
|
{
|
|
char c;
|
|
uint32_t i0;
|
|
i0 = 0UL;
|
|
for (;;) {
|
|
c = h[pr];
|
|
if ((((((i0>=s_len-1 || c==0) || c=='>') || c=='*') || c==':')
|
|
|| c==',') || c==' ') break;
|
|
s[i0] = c;
|
|
++i0;
|
|
++pr;
|
|
}
|
|
s[i0] = 0;
|
|
} /* end cpcall() */
|
|
|
|
|
|
static void SendMsg(pMESSAGE mp, uint32_t torf)
|
|
{
|
|
FRAMEBUF s;
|
|
uint32_t i0;
|
|
MONCALL h;
|
|
/*
|
|
tcp:BOOLEAN;
|
|
*/
|
|
struct POSCALL poscall0;
|
|
uint8_t srcpath;
|
|
pUDPSOCK uds;
|
|
struct MESSAGE * anonym;
|
|
/* rf: OE2XZR-10>RFONLY,OE2XZR-10:}
|
|
OE0AAA>TCPIP,OE2XZR-10::OE2WAO-12:hallo{123 */
|
|
/* ip: OE0AAA>TCPIP,OE2XZR-10::OE2WAO-12:hallo{123 */
|
|
if (verb) {
|
|
if (viacall[0U]==0) osi_WrStr("<no via call, to msg tx>", 25ul);
|
|
else if (torf) osi_WrStr("<send rf>", 10ul);
|
|
else osi_WrStr("<send net>", 11ul);
|
|
Showmsg(mp);
|
|
}
|
|
if (mp->ackackt || viacall[0U]==0) return;
|
|
/*
|
|
tcp:=udpsock.fd<0;
|
|
s[0]:=0C;
|
|
IF (torf<>0) & tcp THEN
|
|
Append(s, viacall);
|
|
Append(s, ">RFONLY,");
|
|
Append(s, servercall);
|
|
Append(s, ":}");
|
|
END;
|
|
IF mp^.acked THEN Append(s, mp^.to) ELSE Append(s, mp^.from) END;
|
|
*/
|
|
if (mp->acked) {
|
|
aprsstr_Assign(s, 512ul, mp->to, 10ul);
|
|
srcpath = mp->acksrc;
|
|
}
|
|
else {
|
|
aprsstr_Assign(s, 512ul, mp->from, 10ul);
|
|
srcpath = mp->src;
|
|
}
|
|
if (torf) {
|
|
aprsstr_Append(s, 512ul, ">", 2ul);
|
|
if (srcpath==udpgate4_NET) aprsstr_Append(s, 512ul, netdestcall, 10ul);
|
|
else aprsstr_Append(s, 512ul, rfdestcall, 10ul);
|
|
aprsstr_Append(s, 512ul, ",", 2ul);
|
|
aprsstr_Append(s, 512ul, viacall, 10ul);
|
|
aprsstr_Append(s, 512ul, "*::", 4ul);
|
|
}
|
|
else {
|
|
if (mp->queryrep) AppQ(s, 512ul, "qAS,", 5ul, 1);
|
|
else AppQ(s, 512ul, "NOGATE*,qAS,", 13ul, 1);
|
|
aprsstr_Append(s, 512ul, ":", 2ul);
|
|
}
|
|
if (mp->acked) memcpy(h,mp->from,10u);
|
|
else memcpy(h,mp->to,10u);
|
|
for (i0 = aprsstr_Length(h, 10ul); i0<=8UL; i0++) {
|
|
aprsstr_Append(h, 10ul, " ", 2ul);
|
|
} /* end for */
|
|
aprsstr_Append(s, 512ul, h, 10ul);
|
|
if (mp->acked) {
|
|
if (mp->reject) aprsstr_Append(s, 512ul, ":rej", 5ul);
|
|
else aprsstr_Append(s, 512ul, ":ack", 5ul);
|
|
}
|
|
else {
|
|
aprsstr_Append(s, 512ul, ":", 2ul);
|
|
{ /* with */
|
|
struct MESSAGE * anonym = mp;
|
|
i0 = 0UL;
|
|
while (i0<=67UL && anonym->text[i0]) {
|
|
/* blank not allowed chars */
|
|
if (((anonym->text[i0]=='|' || anonym->text[i0]=='~')
|
|
|| anonym->text[i0]=='{') || (uint8_t)anonym->text[i0]<' ')
|
|
anonym->text[i0] = ' ';
|
|
++i0;
|
|
}
|
|
aprsstr_Append(s, 512ul, anonym->text, 68ul);
|
|
if (anonym->ack[0U]) {
|
|
aprsstr_Append(s, 512ul, "{", 2ul);
|
|
}
|
|
}
|
|
}
|
|
aprsstr_Append(s, 512ul, mp->ack, 5ul);
|
|
aprsstr_Append(s, 512ul, mp->replyack, 2ul);
|
|
++mp->retryc;
|
|
poscall0.typ0 = ':';
|
|
if (torf) {
|
|
/*NOT tcp &*/
|
|
Sendudp(s, torf, 1);
|
|
}
|
|
else {
|
|
aprsstr_Append(s, 512ul, "\015\012", 3ul);
|
|
Sendall(s, 0L, poscall0);
|
|
}
|
|
mp->txport = torf;
|
|
if (verb || logframes>1L) {
|
|
uds = porttosock(torf);
|
|
showframe(-4L, 0, uds, s, 512ul, poscall0.pos);
|
|
}
|
|
if (mp->acked) {
|
|
if (torf) ++mp->ack2rf;
|
|
else ++mp->ack2net;
|
|
}
|
|
else if (torf) ++mp->msg2rf;
|
|
else ++mp->msg2net;
|
|
mp->txtime = systime;
|
|
} /* end SendMsg() */
|
|
|
|
|
|
static uint32_t FindUserHeard(pHEARD * ph, const MONCALL c,
|
|
uint32_t * rfport)
|
|
/* never heard or too long = 0 else time+1 */
|
|
{
|
|
while (*ph && (*ph)->time0+heardtime>systime) {
|
|
if (aprsstr_StrCmp((*ph)->call, 10ul, c, 10ul)) {
|
|
if ((*ph)->time0<=systime) {
|
|
*rfport = (*ph)->fromrx;
|
|
return (1UL+systime)-(*ph)->time0;
|
|
}
|
|
else return 0UL;
|
|
}
|
|
*ph = (*ph)->next;
|
|
}
|
|
return 0UL;
|
|
} /* end FindUserHeard() */
|
|
|
|
|
|
static uint32_t FindHeard(pHEARD ph, const MONCALL c, uint32_t * rfport)
|
|
/* never heard or too long = 0 else time+1 */
|
|
{
|
|
return FindUserHeard(&ph, c, rfport);
|
|
} /* end FindHeard() */
|
|
|
|
|
|
static char Heard(const char b[], uint32_t b_len, MONCALL from,
|
|
char * trust)
|
|
{
|
|
uint32_t len;
|
|
uint32_t i0;
|
|
uint32_t p;
|
|
/* from>to,path,gate:...*/
|
|
p = 0UL;
|
|
while (p<9UL && b[p]!='>') {
|
|
from[p] = b[p]; /* get user call */
|
|
++p;
|
|
}
|
|
from[p] = 0;
|
|
i0 = aprsstr_Length(b, b_len);
|
|
len = 0UL;
|
|
while (len<i0 && b[len]!=':') ++len;
|
|
*trust = b[len+1UL]!=':' && b[len+1UL]!='}';
|
|
/* not from physical sender */
|
|
/*
|
|
IF NOT udp THEN (* frame is from aprsis *)
|
|
lp:=Length(rfpath);
|
|
IF (lp=0) OR (lp>len) THEN RETURN END;
|
|
(* rfpath not fitting *)
|
|
|
|
DEC(len, lp); (* cut rfpath *)
|
|
FOR i:=0 TO lp-1 DO
|
|
IF b[len+i]<>rfpath[i] THEN RETURN END;
|
|
(* wrong rfpath *)
|
|
END;
|
|
END;
|
|
*/
|
|
while (p<len && b[p]!=',') ++p;
|
|
if (b[p]==',') {
|
|
/* get first via */
|
|
++p;
|
|
i0 = p;
|
|
while (p<len && b[p]!=',') ++p;
|
|
if (b[p-1UL]=='*') return 0;
|
|
/* is repeated */
|
|
if (((uint8_t)b[p-1UL]>='0' && (uint8_t)b[p-1UL]<='9')
|
|
&& b[p-1UL]!=b[p-3UL]) return 0;
|
|
/* WIDEn-x with n<>x */
|
|
/*
|
|
ELSIF ((p-i<=3) OR (b[p-2]<>"-") OR (b[p-1]<>b[p-3])
|
|
OR (b[p-1]<"1") OR (b[p-1]>"7"))
|
|
& ((p-i<>4) OR (b[i]<>"E") OR (b[i+1]<>"C") OR (b[i+2]<>"H")
|
|
OR (b[i+3]<>"O"))
|
|
& ((p-i<>4) OR (b[i]<>"G") OR (b[i+1]<>"A") OR (b[i+2]<>"T")
|
|
OR (b[i+3]<>"E"))
|
|
& ((p-i<>5) OR (b[i]<>"R") OR (b[i+1]<>"E") OR (b[i+2]<>"L")
|
|
OR (b[i+3]<>"A") OR (b[i+4]<>"Y"))
|
|
THEN RETURN FALSE END; (* strict direct heard via n-M or GATE or ECHO or RELAY *)
|
|
*/
|
|
while (p<len) {
|
|
/* more vias */
|
|
++p;
|
|
while (p<len && b[p]!=',') ++p;
|
|
if (b[p-1UL]=='*') return 0;
|
|
}
|
|
}
|
|
/* is repeated */
|
|
return 1;
|
|
} /* end Heard() */
|
|
|
|
|
|
static void IncHeard(pHEARD ph, char up, uint32_t livetime)
|
|
{
|
|
uint32_t t;
|
|
struct HEARD * anonym;
|
|
if (livetime>0UL) {
|
|
{ /* with */
|
|
struct HEARD * anonym = ph;
|
|
t = systime/(livetime/48UL)+49UL;
|
|
/*WrInt(t, 10); WrInt(cntt, 10); WrInt(ORD(up), 10); WrLn; */
|
|
if (anonym->cntt+49UL<t) anonym->cntt = t-49UL;
|
|
while (anonym->cntt<t) {
|
|
++anonym->cntt;
|
|
anonym->cnt[anonym->cntt%49UL] = 0U;
|
|
}
|
|
t = anonym->cntt%49UL;
|
|
if (up && anonym->cnt[t]<65535U) ++anonym->cnt[t];
|
|
}
|
|
}
|
|
/*FOR t:=0 TO HIGH(ph^.cnt) DO WrInt(ORD(ph^.cnt[t]), 2) END; WrLn; */
|
|
} /* end IncHeard() */
|
|
|
|
|
|
static void Wx(float * data, char * typ0, char b[],
|
|
uint32_t b_len, uint32_t p)
|
|
{
|
|
int32_t t;
|
|
char sig;
|
|
if (((b[p]!='/' && b[p]!='@') && b[p]!='!') && b[p]!='=') return;
|
|
if (b[p]=='/' || b[p]=='@') p += 7UL;
|
|
++p;
|
|
if ((uint8_t)b[p]>='0' && (uint8_t)b[p]<='9') p += 30UL;
|
|
else if ((uint8_t)b[p]>='/') p += 17UL;
|
|
if (b[p]!='t') return;
|
|
t = 0L;
|
|
sig = 0;
|
|
if (b[p+1UL]=='-') sig = 1;
|
|
else if ((uint8_t)b[p+1UL]>='0' && (uint8_t)b[p+1UL]<='9') {
|
|
t = (int32_t)(((uint32_t)(uint8_t)b[p+1UL]-48UL)*100UL);
|
|
}
|
|
else return;
|
|
if ((uint8_t)b[p+2UL]>='0' && (uint8_t)b[p+2UL]<='9') {
|
|
t += (int32_t)(((uint32_t)(uint8_t)b[p+2UL]-48UL)*10UL);
|
|
}
|
|
else return;
|
|
if ((uint8_t)b[p+3UL]>='0' && (uint8_t)b[p+3UL]<='9') {
|
|
t += (int32_t)((uint32_t)(uint8_t)b[p+3UL]-48UL);
|
|
}
|
|
else return;
|
|
if (sig) t = -t;
|
|
*typ0 = 'C';
|
|
*data = X2C_DIVR((float)(t-32L),1.8f);
|
|
} /* end Wx() */
|
|
|
|
|
|
static void DirectPos(const char b[], uint32_t b_len,
|
|
struct aprspos_POSITION * pos, char * sym,
|
|
char * symt, char * typ0, float * data)
|
|
{
|
|
uint32_t m;
|
|
uint32_t p;
|
|
struct aprspos_POSITION posn;
|
|
char symt1;
|
|
char sym1;
|
|
char postyp;
|
|
MONCALL dc;
|
|
FRAMEBUF com;
|
|
/* OE0AAA>ABCDEF-2,....:...*/
|
|
/* ^mice ^payload*/
|
|
p = 0UL;
|
|
while (p<b_len-1 && b[p]!='>') ++p;
|
|
m = p+1UL;
|
|
while (p<b_len-1 && b[p]!=':') ++p;
|
|
++p;
|
|
if (p<b_len-1 && b[p]!=';') {
|
|
/* objects say wrong pos */
|
|
vspeed = X2C_max_longcard;
|
|
aprspos_GetPos(&posn, &vspeed, &vcourse, &valt, &sym1, &symt1, b,
|
|
b_len, m, p, com, 512ul, &postyp);
|
|
dc[0U] = b[m];
|
|
dc[1U] = b[m+1UL];
|
|
dc[2U] = b[m+2UL];
|
|
dc[3U] = b[m+3UL];
|
|
dc[4U] = b[m+4UL];
|
|
dc[5U] = b[m+5UL];
|
|
dc[6U] = 0;
|
|
aprspos_GetSym(dc, 10ul, &sym1, &symt1);
|
|
*typ0 = 0;
|
|
if (aprspos_posvalid(posn)) {
|
|
*pos = posn;
|
|
*sym = sym1;
|
|
*symt = symt1;
|
|
if (*sym=='_') Wx(data, typ0, b, b_len, p);
|
|
else if (vspeed<X2C_max_longcard) {
|
|
*typ0 = 'S';
|
|
*data = (float)vspeed*1.852f;
|
|
}
|
|
}
|
|
}
|
|
} /* end DirectPos() */
|
|
|
|
|
|
static uint32_t MHcount(pHEARD ph, uint32_t maxtime)
|
|
{
|
|
uint32_t i0;
|
|
uint32_t ci;
|
|
/* clean count array */
|
|
struct HEARD * anonym;
|
|
IncHeard(ph, 0, maxtime);
|
|
{ /* with */
|
|
struct HEARD * anonym = ph;
|
|
ci = 0UL;
|
|
for (i0 = 0UL; i0<=48UL; i0++) {
|
|
ci += (uint32_t)anonym->cnt[i0];
|
|
} /* end for */
|
|
}
|
|
return ci;
|
|
} /* end MHcount() */
|
|
|
|
|
|
static void getval(const char s[], uint32_t s_len, uint32_t * i0,
|
|
int32_t * v)
|
|
{
|
|
char m;
|
|
++*i0;
|
|
*v = 0L;
|
|
m = s[*i0]=='-';
|
|
if (m) ++*i0;
|
|
while ((*i0<s_len-1 && (uint8_t)s[*i0]>='0') && (uint8_t)s[*i0]<='9') {
|
|
*v = *v*10L+(int32_t)((uint32_t)(uint8_t)s[*i0]-48UL);
|
|
++*i0;
|
|
}
|
|
while (*i0<s_len-1 && (uint8_t)s[*i0]>' ') ++*i0;
|
|
while (*i0<s_len-1 && s[*i0]==' ') ++*i0;
|
|
if (m) *v = -*v;
|
|
} /* end getval() */
|
|
|
|
|
|
static void AddHeard(pHEARD * table, uint32_t maxtime, const MONCALL from,
|
|
uint32_t fromport, const char buf[],
|
|
uint32_t buf_len, char * ungat,
|
|
char setungat)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
int32_t res0;
|
|
pHEARD po;
|
|
pHEARD ph;
|
|
struct HEARD * anonym;
|
|
struct HEARD * anonym0;
|
|
po = 0;
|
|
ph = *table;
|
|
if (mhperport) {
|
|
while (ph && (ph->fromrx!=fromport || !aprsstr_StrCmp(ph->call, 10ul,
|
|
from, 10ul))) {
|
|
po = ph;
|
|
ph = ph->next;
|
|
}
|
|
}
|
|
else {
|
|
while (ph && !aprsstr_StrCmp(ph->call, 10ul, from, 10ul)) {
|
|
po = ph;
|
|
ph = ph->next;
|
|
}
|
|
}
|
|
if (ph) {
|
|
/* entry found */
|
|
if (po) po->next = ph->next;
|
|
}
|
|
else {
|
|
/* new entry */
|
|
po = 0;
|
|
ph = *table;
|
|
if (ph) {
|
|
i0 = 0UL;
|
|
while (ph->next) {
|
|
++i0;
|
|
po = ph;
|
|
ph = ph->next;
|
|
}
|
|
if (i0>=500UL || ph->time0+maxtime<systime) {
|
|
/* old or table full */
|
|
if (po) po->next = ph->next;
|
|
}
|
|
else ph = 0;
|
|
}
|
|
if (ph==0) {
|
|
osic_alloc((char * *) &ph, sizeof(struct HEARD));
|
|
if (ph==0 && po) {
|
|
ph = po->next;
|
|
po->next = 0;
|
|
}
|
|
}
|
|
if (ph) {
|
|
{ /* with */
|
|
struct HEARD * anonym = ph;
|
|
memcpy(anonym->call,from,10u);
|
|
anonym->cntt = 0UL;
|
|
anonym->position.long0 = 0.0f;
|
|
anonym->position.lat = 0.0f;
|
|
anonym->sym = 0;
|
|
anonym->symt = 0;
|
|
anonym->datatyp = 0;
|
|
anonym->ungate = 0;
|
|
anonym->fromrx = 0UL;
|
|
anonym->head[0U] = 0;
|
|
anonym->data = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
if (ph) {
|
|
if (ph!=*table) {
|
|
ph->next = *table;
|
|
*table = ph;
|
|
}
|
|
IncHeard(ph, !setungat, maxtime);
|
|
{ /* with */
|
|
struct HEARD * anonym0 = ph;
|
|
anonym0->time0 = systime;
|
|
if (setungat) {
|
|
anonym0->ungate = *ungat;
|
|
if (!*ungat && MHcount(ph, maxtime)==0UL) {
|
|
ph->time0 = 0UL; /* delete 0 count entry */
|
|
}
|
|
}
|
|
else {
|
|
*ungat = ph->ungate;
|
|
DirectPos(buf, buf_len, &anonym0->position, &anonym0->sym,
|
|
&anonym0->symt, &anonym0->datatyp, &anonym0->data);
|
|
i0 = 0UL;
|
|
while ((i0<buf_len-1 && buf[i0]!='>') && buf[i0]) ++i0;
|
|
++i0;
|
|
j = 0UL;
|
|
while ((((j<40UL && i0<buf_len-1) && buf[i0]!=':') && buf[i0])
|
|
&& !(buf[i0]==',' && buf[i0+1UL]=='q')) {
|
|
anonym0->head[j] = buf[i0];
|
|
++j;
|
|
++i0;
|
|
}
|
|
anonym0->head[j] = 0;
|
|
anonym0->fromrx = fromport;
|
|
anonym0->txd = 0U;
|
|
anonym0->level = 0;
|
|
anonym0->quali = 0U;
|
|
if (udp2[0U] && udp2[1U]) {
|
|
i0 = 2UL;
|
|
while (i0<99UL && udp2[i0]) {
|
|
switch ((unsigned)udp2[i0]) {
|
|
case 'T':
|
|
getval(udp2, 100ul, &i0, &res0);
|
|
anonym0->txd = (uint16_t)res0;
|
|
break;
|
|
case 'V':
|
|
getval(udp2, 100ul, &i0, &res0);
|
|
anonym0->level = (signed char)res0;
|
|
break;
|
|
case 'Q':
|
|
getval(udp2, 100ul, &i0, &res0);
|
|
anonym0->quali = (uint8_t)res0;
|
|
break;
|
|
default:;
|
|
getval(udp2, 100ul, &i0, &res0);
|
|
break;
|
|
} /* end switch */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else *ungat = 0;
|
|
} /* end AddHeard() */
|
|
|
|
|
|
static void delmsg(pMESSAGE md)
|
|
{
|
|
pMESSAGE mp;
|
|
if (md==messages) messages = md->next;
|
|
else {
|
|
mp = messages;
|
|
for (;;) {
|
|
if (mp==0) return;
|
|
if (mp->next==md) {
|
|
mp->next = md->next;
|
|
break;
|
|
}
|
|
mp = mp->next;
|
|
}
|
|
}
|
|
if (verb) {
|
|
osi_WrStrLn("---delete:", 11ul);
|
|
Showmsg(md);
|
|
}
|
|
osic_free((char * *) &md, sizeof(struct MESSAGE));
|
|
} /* end delmsg() */
|
|
|
|
|
|
static uint32_t exp0(uint32_t n)
|
|
{
|
|
if (n>0UL) --n;
|
|
if (n>9UL) n = 9UL;
|
|
return (uint32_t)(1UL<<n);
|
|
} /* end exp() */
|
|
|
|
|
|
static void RfTimer(void)
|
|
{
|
|
pMESSAGE mp;
|
|
pMESSAGE mo;
|
|
char try0;
|
|
uint32_t ht;
|
|
uint32_t oldest;
|
|
uint32_t totx;
|
|
uint32_t maxi;
|
|
struct MESSAGE * anonym;
|
|
if (lastrfsent+rfquiet<=systime) {
|
|
maxi = 0UL;
|
|
for (;;) {
|
|
oldest = X2C_max_longcard;
|
|
mp = 0;
|
|
mo = messages;
|
|
while (mo) {
|
|
if (mo->chkt!=systime && mo->txtime<oldest) {
|
|
mp = mo;
|
|
oldest = mp->txtime;
|
|
}
|
|
mo = mo->next;
|
|
}
|
|
if (mp==0) break;
|
|
{ /* with */
|
|
struct MESSAGE * anonym = mp;
|
|
anonym->chkt = systime;
|
|
try0 = anonym->gentime+msgsendtime>systime && anonym->txtime+rfquiet*exp0(anonym->retryc)
|
|
<systime;
|
|
totx = 0UL;
|
|
if (try0) {
|
|
if (anonym->acked) {
|
|
try0 = (anonym->acksrc && anonym->retryc==0UL)
|
|
&& FindHeard(hearddir, anonym->from, &totx)>0UL;
|
|
}
|
|
else {
|
|
ht = FindHeard(hearddir, anonym->to, &totx);
|
|
try0 = 0;
|
|
if (ht>0UL) {
|
|
if (anonym->ack[0U]==0) {
|
|
try0 = anonym->retryc<1UL; /* msg with no ack */
|
|
}
|
|
else if (anonym->retryc<2UL) try0 = ht<3600UL;
|
|
else if (anonym->retryc<3UL) try0 = ht<1800UL;
|
|
else if (anonym->retryc<4UL) try0 = ht<900UL;
|
|
else try0 = ht<60UL;
|
|
if (try0) {
|
|
mo = messages;
|
|
for (;;) {
|
|
if (mo==mp) break;
|
|
if ((aprsstr_StrCmp(mo->to, 10ul, anonym->to,
|
|
10ul) && mo->gentime+msgsendtime>systime)
|
|
&& (mo->ack[0U] && !mo->acked || mo->ack[0U]
|
|
==0 && mo->retryc<1UL)) {
|
|
try0 = 0;
|
|
break;
|
|
}
|
|
mo = mo->next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (try0) {
|
|
SendMsg(mp, totx);
|
|
lastrfsent = systime;
|
|
/*
|
|
mo:=messages;
|
|
WHILE mo<>NIL DO
|
|
IF StrCmp(mo^.to,
|
|
to) & NOT acked THEN mo^.chkt:=systime END;
|
|
(* 1 msg to 1 call *)
|
|
mo:=mo^.next;
|
|
END;
|
|
*/
|
|
++maxi;
|
|
}
|
|
/*
|
|
IF (ack[0]=0C) & (retryc>=UNACKRET)
|
|
OR acked & (msg2rf+msg2net+ack2rf+ack2net=0)
|
|
THEN ht:=purgeunack ELSE ht:=purgemsg END;
|
|
(* fast if unack & retried out or acked & never sent *)
|
|
*/
|
|
if (anonym->ack[0U]==0) {
|
|
if (anonym->retryc>=1UL) ht = purgeunacksent;
|
|
else ht = purgeunack;
|
|
}
|
|
else if (anonym->acked) ht = purgeacked;
|
|
else ht = purgemsg;
|
|
if (anonym->gentime+ht<systime) {
|
|
delmsg(mp); /* purge message */
|
|
}
|
|
}
|
|
if (maxi>=maxatonce) break;
|
|
}
|
|
}
|
|
} /* end RfTimer() */
|
|
|
|
|
|
static void SendNet(void)
|
|
{
|
|
pMESSAGE mp;
|
|
while (netmhout!=netmhin) {
|
|
mp = messages;
|
|
while (mp) {
|
|
if (mp->retryc==0UL) {
|
|
if (mp->acked) {
|
|
if (mp->acksrc==udpgate4_DIR && aprsstr_StrCmp(mp->from, 10ul,
|
|
netmh[netmhout], 10ul)) {
|
|
SendMsg(mp, 0UL); /* send only 1 a time */
|
|
return;
|
|
}
|
|
}
|
|
else if ((mp->src==udpgate4_DIR || aprsstr_StrCmp(servercall,
|
|
10ul, mp->from, 10ul)) && aprsstr_StrCmp(mp->to, 10ul,
|
|
netmh[netmhout], 10ul)) {
|
|
SendMsg(mp, 0UL);
|
|
if (mp->ack[0U]) {
|
|
/* no more to this user if unack */
|
|
netmhout = (netmhout+1UL)%100UL;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
/* send only 1 a time */
|
|
mp = mp->next;
|
|
}
|
|
netmhout = (netmhout+1UL)%100UL;
|
|
}
|
|
} /* end SendNet() */
|
|
|
|
|
|
static void Stoack(pMESSAGE mp, char rej, uint8_t path)
|
|
{
|
|
struct MESSAGE * anonym;
|
|
{ /* with */
|
|
struct MESSAGE * anonym = mp;
|
|
if (!anonym->acked) {
|
|
/* ack first time */
|
|
anonym->acked = 1;
|
|
anonym->reject = rej;
|
|
anonym->acksrc = path;
|
|
anonym->retryc = 0UL;
|
|
anonym->txtime = 0UL;
|
|
}
|
|
else if (path>anonym->acksrc) anonym->acksrc = path;
|
|
}
|
|
} /* end Stoack() */
|
|
|
|
|
|
static void Ackback(pMESSAGE tomp)
|
|
/* mark all older messages before an now acked */
|
|
{
|
|
pMESSAGE mp;
|
|
struct MESSAGE * anonym;
|
|
mp = messages;
|
|
while (mp!=tomp) {
|
|
{ /* with */
|
|
struct MESSAGE * anonym = mp;
|
|
if ((aprsstr_StrCmp(tomp->from, 10ul, anonym->from,
|
|
10ul) && aprsstr_StrCmp(tomp->to, 10ul, anonym->to,
|
|
10ul)) && anonym->gentime+dupetime<systime) {
|
|
if (!anonym->acked) {
|
|
anonym->acked = 1;
|
|
anonym->acksrc = udpgate4_OBSOLET;
|
|
}
|
|
anonym->ackackt = 1;
|
|
}
|
|
mp = anonym->next;
|
|
}
|
|
}
|
|
} /* end Ackback() */
|
|
|
|
|
|
static char cmpmsg(MSGTEXT a, MSGTEXT b)
|
|
/* compare visable characters */
|
|
{
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
MSGTEXT tmp;
|
|
MSGTEXT tmp0;
|
|
a = (char *)memcpy(tmp,a,68u);
|
|
b = (char *)memcpy(tmp0,b,68u);
|
|
i0 = 0UL;
|
|
j = 0UL;
|
|
while (i0<=67UL && a[i0]) {
|
|
if ((uint8_t)a[i0]>' ') {
|
|
a[j] = a[i0];
|
|
++j;
|
|
}
|
|
++i0;
|
|
}
|
|
if (j<=67UL) a[j] = 0;
|
|
i0 = 0UL;
|
|
j = 0UL;
|
|
while (i0<=67UL && b[i0]) {
|
|
if ((uint8_t)b[i0]>' ') {
|
|
b[j] = b[i0];
|
|
++j;
|
|
}
|
|
++i0;
|
|
}
|
|
if (j<=67UL) b[j] = 0;
|
|
return aprsstr_StrCmp(a, 68ul, b, 68ul);
|
|
} /* end cmpmsg() */
|
|
|
|
#define udpgate4_REPACK "}"
|
|
|
|
|
|
static void Stomsg(MONCALL fromcall, MONCALL tocall, MSGTEXT msg,
|
|
ACKTEXT ackt, char isak, char rej,
|
|
char query, uint8_t path)
|
|
{
|
|
pMESSAGE mi;
|
|
pMESSAGE mp;
|
|
uint32_t cnt;
|
|
REPLYACK rack;
|
|
struct MESSAGE * anonym;
|
|
struct MESSAGE * anonym0;
|
|
MONCALL tmp;
|
|
MONCALL tmp0;
|
|
MSGTEXT tmp1;
|
|
ACKTEXT tmp2;
|
|
fromcall = (char *)memcpy(tmp,fromcall,10u);
|
|
tocall = (char *)memcpy(tmp0,tocall,10u);
|
|
msg = (char *)memcpy(tmp1,msg,68u);
|
|
ackt = (char *)memcpy(tmp2,ackt,5u);
|
|
if (verb && isak) osi_WrStrLn("---isak", 8ul);
|
|
if (aprsstr_StrCmp(fromcall, 10ul, tocall, 10ul)) return;
|
|
/* msg to him self ... */
|
|
msg[67U] = 0;
|
|
rack[0U] = 0;
|
|
if (aprsstr_Length(ackt, 5ul)>=3UL && ackt[2U]=='}') {
|
|
/* replyack xx}xx */
|
|
rack[0U] = ackt[3U]; /* split ack text xx}yy to xx} yy */
|
|
rack[1U] = ackt[4U];
|
|
ackt[3U] = 0;
|
|
}
|
|
mp = 0;
|
|
cnt = 0UL;
|
|
mi = messages;
|
|
while (mi) {
|
|
{ /* with */
|
|
struct MESSAGE * anonym = mi;
|
|
if (((aprsstr_StrCmp(ackt, 5ul, anonym->ack,
|
|
5ul) && aprsstr_StrCmp(fromcall, 10ul, anonym->from,
|
|
10ul)) && aprsstr_StrCmp(tocall, 10ul, anonym->to,
|
|
10ul)) && ((isak || anonym->text[0U]==0) || cmpmsg(msg,
|
|
anonym->text))) {
|
|
mp = mi;
|
|
memcpy(anonym->replyack,rack,2u);
|
|
/* may change in retransmissions */
|
|
if (isak) {
|
|
Stoack(mi, rej, path);
|
|
Ackback(mi);
|
|
}
|
|
else {
|
|
if (anonym->acked && path==udpgate4_DIR) {
|
|
/* is acked resend ack */
|
|
if (anonym->retryc>0UL) --anonym->retryc;
|
|
anonym->txtime = 0UL;
|
|
}
|
|
if (anonym->text[0U]==0) {
|
|
/* ack came before message */
|
|
memcpy(anonym->text,msg,68u);
|
|
if (anonym->acked) Ackback(mi);
|
|
}
|
|
if (path>anonym->src) anonym->src = path;
|
|
}
|
|
}
|
|
if ((((rack[0U] && rack[0U]==anonym->ack[0U])
|
|
&& (rack[1U]==anonym->ack[1U] || rack[1U]
|
|
==0 && anonym->ack[1U]=='}')) && aprsstr_StrCmp(fromcall,
|
|
10ul, anonym->to, 10ul)) && aprsstr_StrCmp(tocall, 10ul,
|
|
anonym->from, 10ul)) Stoack(mi, rej, path);
|
|
mi = anonym->next;
|
|
}
|
|
++cnt;
|
|
}
|
|
if (verb && mp) {
|
|
osi_WrStr("msg found ", 11ul);
|
|
Showmsg(mp);
|
|
}
|
|
if (mp==0) {
|
|
/* new msg */
|
|
if (cnt<maxmsg) {
|
|
osic_alloc((char * *) &mp, sizeof(struct MESSAGE));
|
|
}
|
|
if (mp==0 && messages) {
|
|
mp = messages; /* recycle oldest */
|
|
messages = messages->next;
|
|
}
|
|
if (mp) {
|
|
/* append to end of list */
|
|
memset((char *)mp,(char)0,sizeof(struct MESSAGE));
|
|
mp->next = 0;
|
|
if (messages==0) messages = mp;
|
|
else {
|
|
mi = messages;
|
|
while (mi->next) mi = mi->next;
|
|
mi->next = mp;
|
|
}
|
|
{ /* with */
|
|
struct MESSAGE * anonym0 = mp;
|
|
memcpy(anonym0->from,fromcall,10u);
|
|
memcpy(anonym0->to,tocall,10u);
|
|
memcpy(anonym0->text,msg,68u);
|
|
memcpy(anonym0->ack,ackt,5u);
|
|
memcpy(anonym0->replyack,rack,2u);
|
|
anonym0->gentime = systime;
|
|
if (path==udpgate4_DIR) anonym0->txtime = systime;
|
|
else anonym0->txtime = 0UL;
|
|
anonym0->acked = isak;
|
|
anonym0->reject = rej;
|
|
anonym0->src = path;
|
|
anonym0->acksrc = path;
|
|
anonym0->queryrep = query;
|
|
}
|
|
}
|
|
if (verb) {
|
|
if (path==udpgate4_DIR) osi_WrStr("new direct", 11ul);
|
|
else if (path==udpgate4_INDIR) osi_WrStr("new rf", 7ul);
|
|
else osi_WrStr("new net", 8ul);
|
|
osi_WrStr(" msg#", 6ul);
|
|
osic_WrINT32(cnt, 1UL);
|
|
osi_WrStr(" ", 2ul);
|
|
Showmsg(mp);
|
|
}
|
|
}
|
|
/*
|
|
IF mp<>NIL THEN Ackback(mp) END;
|
|
(* all before is thru and ack is at home so mark as done *)
|
|
*/
|
|
} /* end Stomsg() */
|
|
|
|
|
|
static void postoloc(char loc[], uint32_t loc_len,
|
|
struct aprspos_POSITION pos)
|
|
{
|
|
uint32_t bc;
|
|
uint32_t lc;
|
|
float br;
|
|
float lr;
|
|
lr = (pos.long0*5.7295779513082E+1f+180.0f)*2880.0f;
|
|
if (lr<=0.0f) lr = 0.0f;
|
|
lc = (uint32_t)X2C_TRUNCC(lr,0UL,X2C_max_longcard);
|
|
br = (pos.lat*5.7295779513082E+1f+90.0f)*5760.0f;
|
|
if (br<=0.0f) br = 0.0f;
|
|
bc = (uint32_t)X2C_TRUNCC(br,0UL,X2C_max_longcard);
|
|
loc[0UL] = (char)(65UL+lc/57600UL);
|
|
loc[1UL] = (char)(65UL+bc/57600UL);
|
|
loc[2UL] = (char)(48UL+(lc/5760UL)%10UL);
|
|
loc[3UL] = (char)(48UL+(bc/5760UL)%10UL);
|
|
loc[4UL] = (char)(65UL+(lc/240UL)%24UL);
|
|
loc[5UL] = (char)(65UL+(bc/240UL)%24UL);
|
|
loc[6UL] = (char)(48UL+(lc/24UL)%10UL);
|
|
loc[7UL] = (char)(48UL+(bc/24UL)%10UL);
|
|
loc[8UL] = (char)(65UL+lc%24UL);
|
|
loc[9UL] = (char)(65UL+bc%24UL);
|
|
loc[10UL] = 0;
|
|
} /* end postoloc() */
|
|
|
|
|
|
static void degtostr(char s[], uint32_t s_len, float d,
|
|
char posc, char negc)
|
|
{
|
|
uint32_t n;
|
|
char c;
|
|
char tmp;
|
|
d = X2C_DIVR(d,1.7453292519444E-2f);
|
|
if (d<0.0f) {
|
|
d = -d;
|
|
c = negc;
|
|
}
|
|
else c = posc;
|
|
n = (uint32_t)X2C_TRUNCC(d,0UL,X2C_max_longcard);
|
|
aprsstr_IntToStr((int32_t)n, 1UL, s, s_len);
|
|
aprsstr_Append(s, s_len, ".", 2ul);
|
|
n = (uint32_t)X2C_TRUNCC((d-(float)n)*3600.0f,0UL,X2C_max_longcard);
|
|
aprsstr_Append(s, s_len, (char *)(tmp = (char)(48UL+n/600UL),
|
|
&tmp), 1u/1u);
|
|
aprsstr_Append(s, s_len, (char *)(tmp = (char)(48UL+(n%600UL)/60UL),
|
|
&tmp), 1u/1u);
|
|
aprsstr_Append(s, s_len, ".", 2ul);
|
|
aprsstr_Append(s, s_len, (char *)(tmp = (char)(48UL+(n%60UL)/10UL),
|
|
&tmp), 1u/1u);
|
|
aprsstr_Append(s, s_len, (char *)(tmp = (char)(48UL+n%10UL),&tmp),
|
|
1u/1u);
|
|
aprsstr_Append(s, s_len, (char *) &c, 1u/1u);
|
|
} /* end degtostr() */
|
|
|
|
#define udpgate4_PARPOS 6
|
|
|
|
|
|
static void Ungate(const MONCALL mycall, const char msg[],
|
|
uint32_t msg_len, uint8_t path)
|
|
{
|
|
uint32_t p;
|
|
uint32_t n;
|
|
uint32_t i0;
|
|
MONCALL hn;
|
|
MONCALL h;
|
|
MSGTEXT answ;
|
|
char un;
|
|
pHEARD ph;
|
|
char tmp;
|
|
ACKTEXT tmp0;
|
|
/* ?APRS#, ?APRS# -9, ?APRS# 9, ?APRS# CALL*/
|
|
memcpy(h,mycall,10u);
|
|
i0 = 0UL;
|
|
for (;;) {
|
|
if (i0>9UL) break;
|
|
if (h[i0]=='-') {
|
|
h[i0] = 0;
|
|
break;
|
|
}
|
|
++i0;
|
|
}
|
|
memcpy(hn,h,10u);
|
|
i0 = 6UL;
|
|
skipblank(msg, msg_len, &i0);
|
|
p = i0;
|
|
un = msg[i0]=='-';
|
|
if (un) ++i0;
|
|
if (GetSec(msg, msg_len, &i0, &n)==0L && n<=15UL) {
|
|
if (n>0UL) {
|
|
aprsstr_Append(h, 10ul, "-", 2ul);
|
|
if (n>=10UL) aprsstr_Append(h, 10ul, "1", 2ul);
|
|
aprsstr_Append(h, 10ul, (char *)(tmp = (char)(n%10UL+48UL),
|
|
&tmp), 1u/1u);
|
|
}
|
|
AddHeard(&hearddir, Max(heardtime, heardtimew), h, 0UL, "", 1ul, &un,
|
|
1);
|
|
}
|
|
else {
|
|
n = aprsstr_Length(msg, msg_len);
|
|
i0 = 0UL;
|
|
while ((i0<=9UL && p<n) && (uint8_t)msg[p]>' ') {
|
|
hn[i0] = msg[p];
|
|
++i0;
|
|
++p;
|
|
}
|
|
if (i0>0UL && i0<=9UL) hn[i0] = 0;
|
|
}
|
|
strncpy(answ,"Not Gated:",68u);
|
|
un = 1;
|
|
ph = hearddir;
|
|
for (;;) {
|
|
if (ph==0) break;
|
|
if (ph->ungate && aprsstr_InStr(ph->call, 10ul, hn, 10ul)==0L) {
|
|
if (aprsstr_Length(answ, 68ul)+aprsstr_Length(ph->call,
|
|
10ul)>=64UL) {
|
|
aprsstr_Append(answ, 68ul, "...", 4ul);
|
|
break;
|
|
}
|
|
aprsstr_Append(answ, 68ul, " ", 2ul);
|
|
aprsstr_Append(answ, 68ul, ph->call, 10ul);
|
|
un = 0;
|
|
}
|
|
ph = ph->next;
|
|
}
|
|
if (un) {
|
|
aprsstr_Append(answ, 68ul, " None", 6ul);
|
|
if (n<=6UL) {
|
|
aprsstr_Append(answ, 68ul, " (igate your ssid off/on: ?APRS# -5 / 5)\
|
|
", 41ul);
|
|
}
|
|
}
|
|
Stomsg(servercall, mycall, answ, *(ACKTEXT *)memcpy(&tmp0,"",1u), 0, 0, 1,
|
|
path);
|
|
} /* end Ungate() */
|
|
|
|
|
|
static void Query(MONCALL fromcall, char msg[], uint32_t msg_len,
|
|
const char buf[], uint32_t buf_len, uint8_t path)
|
|
{
|
|
pMESSAGE mp;
|
|
char no;
|
|
MSGTEXT s;
|
|
MSGTEXT mh;
|
|
MONCALL callh;
|
|
uint32_t len;
|
|
uint32_t i0;
|
|
pHEARD hn;
|
|
pHEARD hp;
|
|
char cmd;
|
|
float maxdist;
|
|
float dist;
|
|
MONCALL tmp;
|
|
ACKTEXT tmp0;
|
|
MSGTEXT tmp1;
|
|
fromcall = (char *)memcpy(tmp,fromcall,10u);
|
|
X2C_PCOPY((void **)&msg,msg_len);
|
|
cmd = 0;
|
|
len = aprsstr_Length(msg, msg_len);
|
|
i0 = 1UL;
|
|
while (i0<len) {
|
|
msg[i0] = X2C_CAP(msg[i0]);
|
|
++i0;
|
|
}
|
|
if ((((msg[1UL]=='A' && msg[2UL]=='P') && msg[3UL]=='R') && msg[4UL]=='S')
|
|
&& (msg[6UL]==0 || msg[6UL]==' ')) cmd = msg[5UL];
|
|
else if ((msg[1UL]=='M' && msg[2UL]=='H')
|
|
&& (msg[3UL]==0 || msg[3UL]=='?')) cmd = 'D';
|
|
else if (((((msg[1UL]=='P' && msg[2UL]=='I') && msg[3UL]=='N')
|
|
&& msg[4UL]=='G') && msg[5UL]=='?') && msg[6UL]==0) {
|
|
cmd = 'T';
|
|
}
|
|
else if ((((msg[1UL]=='H' && msg[2UL]=='E') && msg[3UL]=='L')
|
|
&& msg[4UL]=='P') && msg[5UL]==0) cmd = 'h';
|
|
else if (((msg[1UL]=='V' && msg[2UL]=='E') && msg[3UL]=='R')
|
|
&& (msg[4UL]==0 || msg[4UL]=='?')) cmd = 'v';
|
|
else if ((msg[1UL]=='D' && msg[2UL]=='X') && msg[3UL]==0) cmd = 'x';
|
|
if (cmd=='M') {
|
|
/* activate messages for user */
|
|
no = verb;
|
|
mp = messages;
|
|
while (mp) {
|
|
if (!mp->acked && aprsstr_StrCmp(fromcall, 10ul, mp->to, 10ul)) {
|
|
mp->retryc = 0UL;
|
|
if (verb) {
|
|
no = 0;
|
|
osi_WrStr("query msg activated:", 21ul);
|
|
Showmsg(mp);
|
|
}
|
|
}
|
|
mp = mp->next;
|
|
}
|
|
if (no) osi_WrStrLn("query msg not found", 20ul);
|
|
}
|
|
else if (cmd=='T') {
|
|
/* return message path */
|
|
i0 = 0UL;
|
|
strncpy(mh,"Path - ",68u);
|
|
while ((i0+7UL<67UL && buf[i0]!=':') && buf[i0]) {
|
|
mh[i0+7UL] = buf[i0];
|
|
++i0;
|
|
}
|
|
mh[i0+7UL] = 0;
|
|
Stomsg(servercall, fromcall, mh, *(ACKTEXT *)memcpy(&tmp0,"",1u), 0, 0,
|
|
1, path);
|
|
}
|
|
else if (cmd=='D') {
|
|
/* return mh table */
|
|
strncpy(mh,"Directs=",68u);
|
|
hn = hearddir;
|
|
while ((hn && hn->time0+heardtimew>systime) && aprsstr_Length(mh,
|
|
68ul)+aprsstr_Length(hn->call, 10ul)+1UL<67UL) {
|
|
if (!hn->ungate) {
|
|
aprsstr_Append(mh, 68ul, " ", 2ul);
|
|
aprsstr_Append(mh, 68ul, hn->call, 10ul);
|
|
}
|
|
hn = hn->next;
|
|
}
|
|
Stomsg(servercall, fromcall, mh, *(ACKTEXT *)memcpy(&tmp0,"",1u), 0, 0,
|
|
1, path);
|
|
}
|
|
else if (cmd=='x' || cmd=='H') {
|
|
if (cmd=='H') {
|
|
for (i0 = 0UL; i0<=9UL; i0++) {
|
|
callh[i0] = X2C_CAP(msg[i0+7UL]);
|
|
} /* end for */
|
|
}
|
|
maxdist = 0.0f;
|
|
hn = 0;
|
|
hp = hearddir;
|
|
while (hp) {
|
|
if (((hp->time0+heardtimew>systime && !hp->ungate)
|
|
&& aprspos_posvalid(hp->position)) && aprspos_posvalid(home))
|
|
{
|
|
dist = aprspos_distance(home, hp->position);
|
|
if (cmd=='H') {
|
|
if (aprsstr_StrCmp(callh, 10ul, hp->call, 10ul)) {
|
|
hn = hp;
|
|
maxdist = dist;
|
|
}
|
|
}
|
|
else if (dist>maxdist) {
|
|
maxdist = dist;
|
|
hn = hp;
|
|
}
|
|
}
|
|
hp = hp->next;
|
|
}
|
|
if (hn) {
|
|
strncpy(mh,"DX: ",68u);
|
|
aprsstr_Append(mh, 68ul, hn->call, 10ul);
|
|
aprsstr_Append(mh, 68ul, " ", 2ul);
|
|
degtostr(s, 68ul, hn->position.lat, 'N', 'S');
|
|
aprsstr_Append(mh, 68ul, s, 68ul);
|
|
aprsstr_Append(mh, 68ul, " ", 2ul);
|
|
degtostr(s, 68ul, hn->position.long0, 'E', 'W');
|
|
aprsstr_Append(mh, 68ul, s, 68ul);
|
|
aprsstr_Append(mh, 68ul, " ", 2ul);
|
|
aprsstr_IntToStr((int32_t)(uint32_t)X2C_TRUNCC(maxdist+0.5f,0UL,
|
|
X2C_max_longcard), 1UL, s, 68ul);
|
|
aprsstr_Append(mh, 68ul, s, 68ul);
|
|
aprsstr_Append(mh, 68ul, "km ", 4ul);
|
|
aprsstr_TimeToStr(hn->time0%86400UL, s, 68ul);
|
|
aprsstr_Append(mh, 68ul, s, 68ul);
|
|
}
|
|
else strncpy(mh,"No position available",68u);
|
|
Stomsg(servercall, fromcall, mh, *(ACKTEXT *)memcpy(&tmp0,"",1u), 0, 0,
|
|
1, path);
|
|
}
|
|
else if (cmd=='S') {
|
|
Stomsg(servercall, fromcall, *(MSGTEXT *)memcpy(&tmp1,"udpgate(c) 0.63 \
|
|
Msg S&F Relay",30u), *(ACKTEXT *)memcpy(&tmp0,"",1u), 0, 0, 1, path);
|
|
}
|
|
else if (cmd=='v') {
|
|
Stomsg(servercall, fromcall, *(MSGTEXT *)memcpy(&tmp1,
|
|
"udpgate(c) 0.63",16u), *(ACKTEXT *)memcpy(&tmp0,"",1u), 0,
|
|
0, 1, path);
|
|
}
|
|
else if (cmd=='h') {
|
|
Stomsg(servercall, fromcall, *(MSGTEXT *)memcpy(&tmp1,"Cmd: ?APRS[D/H/M\
|
|
/P/S/T/#] ?DX ?MH ?VER? ?PING?",47u), *(ACKTEXT *)memcpy(&tmp0,"",1u), 0, 0,
|
|
1, path);
|
|
}
|
|
else if (cmd=='P') {
|
|
Netbeacon(mh, 68ul, 0, 0);
|
|
Stomsg(servercall, fromcall, mh, *(ACKTEXT *)memcpy(&tmp0,"",1u), 0, 0,
|
|
1, path);
|
|
}
|
|
else if (cmd=='#') Ungate(fromcall, msg, msg_len, path);
|
|
X2C_PFREE(msg);
|
|
} /* end Query() */
|
|
|
|
|
|
static void gatetoviaheard(const char b[], uint32_t b_len,
|
|
const MONCALL fromcall, const MONCALL tocall)
|
|
{
|
|
pUDPSOCK u;
|
|
uint32_t void0;
|
|
uint32_t po;
|
|
if (!aprsstr_StrCmp(fromcall, 10ul, tocall, 10ul) && FindHeard(heardvia,
|
|
tocall, &po)>0UL) {
|
|
u = porttosock(po);
|
|
if ((u && u->torfradius>0.0f) && FindHeard(hearddir, tocall,
|
|
&void0)==0UL) NetToRf(b, b_len, po);
|
|
}
|
|
} /* end gatetoviaheard() */
|
|
|
|
|
|
static char iscall(const char b[], uint32_t b_len,
|
|
uint32_t p)
|
|
{
|
|
uint32_t i0;
|
|
uint32_t nu;
|
|
uint32_t li;
|
|
char c;
|
|
li = 0UL;
|
|
nu = 0UL;
|
|
for (i0 = 0UL; i0<=2UL; i0++) {
|
|
c = b[p+i0];
|
|
if ((uint8_t)c>='A' && (uint8_t)c<='Z') ++li;
|
|
else if ((uint8_t)c>='0' && (uint8_t)c<='9') {
|
|
if (i0==0UL) ++li;
|
|
else ++nu;
|
|
}
|
|
} /* end for */
|
|
/*
|
|
IO.WrCard(li,9);IO.WrCard(nu,9); IO.WrStrLn("<3>");
|
|
*/
|
|
return (nu+li==3UL && nu>=1UL) && nu<=2UL;
|
|
} /* end iscall() */
|
|
|
|
|
|
static void getack(const char s[], uint32_t s_len, uint32_t p,
|
|
ACKTEXT a)
|
|
{
|
|
uint32_t i0;
|
|
i0 = 0UL;
|
|
while ((p<=s_len-1 && (uint8_t)s[p]>' ') && (uint8_t)s[p]<(uint8_t)
|
|
'\200') {
|
|
a[i0] = s[p];
|
|
++p;
|
|
++i0;
|
|
if (i0>4UL) return;
|
|
}
|
|
a[i0] = 0;
|
|
} /* end getack() */
|
|
|
|
#define udpgate4_HEADEREND ":"
|
|
|
|
#define udpgate4_FROMEND ">"
|
|
|
|
#define udpgate4_USERACK "{"
|
|
|
|
#define udpgate4_NOARCHIVE "!x!"
|
|
|
|
|
|
static void Getmsg(const char b[], uint32_t b_len, uint32_t rxport,
|
|
char goodpath, char * ungate)
|
|
/* get user msg and ack out of aprsis stream */
|
|
{
|
|
uint32_t po;
|
|
uint32_t void0;
|
|
uint32_t p;
|
|
uint32_t len;
|
|
uint32_t pf;
|
|
uint32_t pm;
|
|
MSGTEXT msg;
|
|
ACKTEXT ack;
|
|
MONCALL hfrom;
|
|
MONCALL tocall;
|
|
MONCALL fromcall;
|
|
char c;
|
|
char tomh;
|
|
char dir;
|
|
char trust;
|
|
char isrej;
|
|
char isack;
|
|
uint8_t path;
|
|
*ungate = 0;
|
|
if ((b[0UL]==0 || rxport && !iscall(b, b_len, 0UL)) || aprsstr_InStr(b,
|
|
b_len, "!x!", 4ul)>=0L) return;
|
|
dir = Heard(b, b_len, hfrom, &trust);
|
|
if (hfrom[0U]) {
|
|
if (rxport) {
|
|
if ((heardtime>0UL && dir) && trust) {
|
|
AddHeard(&hearddir, Max(heardtime, heardtimew), hfrom, rxport, b,
|
|
b_len, ungate, 0);
|
|
}
|
|
else if (heardtimevia>0UL) {
|
|
AddHeard(&heardvia, heardtimevia, hfrom, rxport, b, b_len,
|
|
ungate, 0);
|
|
}
|
|
}
|
|
}
|
|
if (maxmsg==0UL && viacall[0U]==0) return;
|
|
/* mh server only */
|
|
len = aprsstr_Length(b, b_len);
|
|
pm = 0UL;
|
|
do {
|
|
pf = pm;
|
|
for (;;) {
|
|
if (pm>=len) return;
|
|
if (b[pm]==':') break;
|
|
++pm;
|
|
}
|
|
pm += 2UL;
|
|
} while (!(pm>len || b[pm-1UL]!='}'));
|
|
/* skip thirdparty headers */
|
|
--pm;
|
|
tomh = sendnetmsg;
|
|
if (((pm+10UL<len && b[pm]==':') && b[pm+10UL]==':') && iscall(b, b_len,
|
|
pm+1UL)) {
|
|
/* user message */
|
|
/* to */
|
|
cpcall(tocall, 10ul, b, b_len, pm+1UL);
|
|
if (iscall(b, b_len, pf) && maxmsg) {
|
|
/* mail storage on & not from a special (no)call */
|
|
/* from */
|
|
cpcall(fromcall, 10ul, b, b_len, pf);
|
|
/* text */
|
|
p = 0UL;
|
|
pm += 11UL;
|
|
for (;;) {
|
|
if (pm>=len) break;
|
|
c = b[pm];
|
|
if ((p>=67UL || (uint8_t)c<' ') || c=='{') break;
|
|
msg[p] = c;
|
|
++p;
|
|
++pm;
|
|
}
|
|
msg[p] = 0;
|
|
/* ack */
|
|
isack = 0;
|
|
ack[0U] = 0;
|
|
isrej = (msg[0U]=='r' && msg[1U]=='e') && msg[2U]=='j';
|
|
if ((msg[0U]=='a' && msg[1U]=='c') && msg[2U]=='k' || isrej) {
|
|
/* is ack or rej */
|
|
getack(msg, 68ul, 3UL, ack);
|
|
msg[0U] = 0;
|
|
isack = 1;
|
|
}
|
|
else if (pm<len && b[pm]=='{') getack(b, b_len, pm+1UL, ack);
|
|
path = udpgate4_NET;
|
|
if (rxport) {
|
|
path = udpgate4_INDIR;
|
|
if ((dir && goodpath) && FindHeard(hearddir, fromcall,
|
|
&void0)>0UL) path = udpgate4_DIR;
|
|
}
|
|
if (msg[0U]=='?') {
|
|
if (aprsstr_StrCmp(tocall, 10ul, viacall,
|
|
10ul) || aprsstr_StrCmp(tocall, 10ul, servercall, 10ul)) {
|
|
Query(fromcall, msg, 68ul, b, b_len, path);
|
|
tomh = 1;
|
|
}
|
|
}
|
|
else if (isack) {
|
|
Stomsg(tocall, fromcall, msg, ack, 1, isrej, 0, path);
|
|
}
|
|
else if (rxport || goodpath) {
|
|
Stomsg(fromcall, tocall, msg, ack, 0, isrej, 0, path);
|
|
}
|
|
gatetoviaheard(b, b_len, fromcall, tocall);
|
|
}
|
|
else if (goodpath && FindHeard(hearddir, tocall, &po)>0UL) {
|
|
NetToRf(b, b_len, po); /* not call from to local user */
|
|
}
|
|
if (verb) {
|
|
osi_WrStr(" <", 3ul);
|
|
p = 0UL;
|
|
while (p<b_len-1 && b[p]) {
|
|
if ((uint8_t)b[p]>=' ') {
|
|
osi_WrStr((char *) &b[p], 1u/1u);
|
|
}
|
|
++p;
|
|
}
|
|
osi_WrStrLn(">", 2ul);
|
|
}
|
|
}
|
|
if (((tomh && hfrom[0U]) && rxport==0UL) && (netmhin+1UL)%100UL!=netmhout)
|
|
{
|
|
memcpy(netmh[netmhin],hfrom,10u);
|
|
netmhin = (netmhin+1UL)%100UL;
|
|
}
|
|
} /* end Getmsg() */
|
|
|
|
|
|
static void getportname(uint32_t n, char s[], uint32_t s_len)
|
|
/* if not found return port number */
|
|
{
|
|
pUDPSOCK u;
|
|
uint32_t i0;
|
|
if (n==0UL) aprsstr_Assign(s, s_len, "TCPIP", 6ul);
|
|
else {
|
|
u = udpsocks;
|
|
i0 = 1UL;
|
|
while (u && i0<n) {
|
|
++i0;
|
|
u = u->next;
|
|
}
|
|
if (u==0 || u->portname[0U]==0) {
|
|
aprsstr_IntToStr((int32_t)n, 1UL, s, s_len);
|
|
}
|
|
else aprsstr_Assign(s, s_len, u->portname, 10ul);
|
|
}
|
|
} /* end getportname() */
|
|
|
|
#define udpgate4_SEP "|"
|
|
/* field separator */
|
|
|
|
#define udpgate4_SEPESC " "
|
|
/* set instead of SEP */
|
|
|
|
#define udpgate4_TEMPFN "~"
|
|
/* append to filename for temp file */
|
|
|
|
#define udpgate4_LINELEN 99
|
|
/* fill up lines to equal size */
|
|
|
|
|
|
static void App(uint32_t * p, char h[256], char s[],
|
|
uint32_t s_len)
|
|
{
|
|
uint32_t i0;
|
|
X2C_PCOPY((void **)&s,s_len);
|
|
i0 = 0UL;
|
|
while (i0<=s_len-1 && s[i0]) {
|
|
if (s[i0]!='|') h[*p] = s[i0];
|
|
else h[*p] = ' ';
|
|
++*p;
|
|
++i0;
|
|
}
|
|
X2C_PFREE(s);
|
|
} /* end App() */
|
|
|
|
|
|
static void MHtoFile(void)
|
|
{
|
|
char h[256];
|
|
char h1[16];
|
|
FILENAME fn;
|
|
pHEARD hn;
|
|
uint32_t t;
|
|
int32_t fd;
|
|
uint32_t cnt;
|
|
uint32_t p;
|
|
aprsstr_Assign(fn, 1024ul, mhfilename, 1024ul);
|
|
aprsstr_Append(fn, 1024ul, "~", 2ul);
|
|
fd = osi_OpenWrite(fn, 1024ul);
|
|
if (fd<0L) return;
|
|
cnt = mhfilelines;
|
|
hn = hearddir;
|
|
while (cnt>0UL && hn) {
|
|
p = 0UL;
|
|
if (hn->time0+heardtimew>systime && !hn->ungate) {
|
|
App(&p, h, hn->call, 10ul);
|
|
h[p] = '|';
|
|
++p;
|
|
App(&p, h, (char *) &hn->symt, 1u/1u);
|
|
App(&p, h, (char *) &hn->sym, 1u/1u);
|
|
h[p] = '|';
|
|
++p;
|
|
/* IntToStr(hn^.fromrx, 1, h1); App(h1); */
|
|
getportname(hn->fromrx, h1, 16ul);
|
|
App(&p, h, h1, 16ul);
|
|
h[p] = '|';
|
|
++p;
|
|
t = hn->time0;
|
|
if (systime<t || t==0UL) t = 0UL;
|
|
else t = systime-t;
|
|
aprsstr_IntToStr((int32_t)t, 1UL, h1, 16ul);
|
|
App(&p, h, h1, 16ul);
|
|
h[p] = '|';
|
|
++p;
|
|
aprsstr_IntToStr((int32_t)MHcount(hn, heardtimew), 1UL, h1, 16ul);
|
|
App(&p, h, h1, 16ul);
|
|
h[p] = '|';
|
|
++p;
|
|
if (aprspos_posvalid(hn->position) && aprspos_posvalid(home)) {
|
|
aprsstr_FixToStr(aprspos_distance(home, hn->position)+0.05f, 2UL,
|
|
h1, 16ul);
|
|
App(&p, h, h1, 16ul);
|
|
}
|
|
h[p] = '|';
|
|
++p;
|
|
if (hn->datatyp=='C') {
|
|
aprsstr_FixToStr(hn->data, 2UL, h1, 16ul);
|
|
aprsstr_Append(h1, 16ul, "\260C", 3ul);
|
|
}
|
|
else if (hn->datatyp=='S') {
|
|
aprsstr_FixToStr(hn->data, 0UL, h1, 16ul);
|
|
aprsstr_Append(h1, 16ul, "kmh", 4ul);
|
|
}
|
|
else h1[0] = 0;
|
|
App(&p, h, h1, 16ul);
|
|
h[p] = '|';
|
|
++p;
|
|
App(&p, h, hn->head, 41ul);
|
|
h[p] = '\012';
|
|
++p;
|
|
osi_WrBin(fd, (char *)h, 256u/1u, p);
|
|
}
|
|
hn = hn->next;
|
|
--cnt;
|
|
}
|
|
osic_Close(fd);
|
|
osi_Rename(fn, 1024ul, mhfilename, 1024ul);
|
|
} /* end MHtoFile() */
|
|
|
|
/*
|
|
PROCEDURE finddupe(s-:DUPESTRING):BOOLEAN;
|
|
VAR i, sum:CARDINAL;
|
|
t:TIME;
|
|
BEGIN
|
|
i:=0;
|
|
sum:=0;
|
|
WHILE (i<=HIGH(s)) & (s[i]<>0C) DO INC(sum, ORD(s[i]); INC(i) END;
|
|
(* make simple hash *)
|
|
|
|
sum:=sum MOD (HIGH(dupehashs)+1);
|
|
t:=dupehashs[sum].time;
|
|
IF systime>=t+dupetime THEN
|
|
WITH dupestrings[dupewrite] DO
|
|
str:=s;
|
|
time:=systime;
|
|
next:=dupewrite;
|
|
END;
|
|
dupehashs[sum].hash:=dupewrite;
|
|
dupehashs[sum].time:=systime;
|
|
dupewrite:=(dupewrite+1) MOD (HIGH(dupestrings)+1);
|
|
ELSE
|
|
DEC(i);
|
|
LOOP
|
|
IF dupestrings[i]=s THEN RETURN TRUE END;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
END finddupe;
|
|
|
|
*/
|
|
|
|
static int32_t callchk(uint32_t * qpos, uint8_t * unset,
|
|
char buf[], uint32_t buf_len, uint32_t * p,
|
|
uint32_t * pssid, char withstar,
|
|
char iscall0)
|
|
{
|
|
uint32_t lit;
|
|
uint32_t num;
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
char c;
|
|
uint8_t u;
|
|
*pssid = 0UL;
|
|
for (u = udpgate4_gUNGATE;; u++) {
|
|
j = 0UL;
|
|
i0 = *p;
|
|
while (ungates[u][j]==buf[i0]) {
|
|
++i0;
|
|
++j;
|
|
if (ungates[u][j]==0) *unset |= (1U<<u);
|
|
}
|
|
if (u==udpgate4_gQ) break;
|
|
} /* end for */
|
|
if (iscall0) {
|
|
/* we want a callsign */
|
|
num = 0UL;
|
|
lit = 0UL;
|
|
c = buf[*p];
|
|
if ((uint8_t)c>='A' && (uint8_t)c<='Z') ++lit;
|
|
else if ((uint8_t)c<'0' || (uint8_t)c>'9') return -1L;
|
|
++*p;
|
|
for (;;) {
|
|
c = buf[*p];
|
|
if ((uint8_t)c>='0' && (uint8_t)c<='9') ++num;
|
|
else if ((uint8_t)c>='A' && (uint8_t)c<='Z') ++lit;
|
|
else break;
|
|
++*p;
|
|
}
|
|
if ((lit<2UL || num==0UL) || num>2UL) return -1L;
|
|
*pssid = *p;
|
|
if (buf[*p]=='-') {
|
|
++*p;
|
|
if (buf[*p]=='1') {
|
|
++*p;
|
|
if ((uint8_t)buf[*p]>='0' && (uint8_t)buf[*p]<='5') ++*p;
|
|
}
|
|
else {
|
|
if ((uint8_t)buf[*p]<'1' || (uint8_t)buf[*p]>'9') return -1L;
|
|
++*p;
|
|
}
|
|
}
|
|
}
|
|
else if ((buf[*p]=='q' && buf[*p+1UL]=='A') && (uint8_t)
|
|
buf[*p+2UL]>='A') {
|
|
/* qAx */
|
|
*qpos = *p+2UL;
|
|
*p += 3UL;
|
|
}
|
|
else {
|
|
/* we skip any text */
|
|
for (;;) {
|
|
c = buf[*p];
|
|
if (c=='-') *pssid = *p;
|
|
if (((((uint8_t)c<=' ' || c=='>') || c=='*') || c==',') || c==':')
|
|
break;
|
|
++*p;
|
|
}
|
|
}
|
|
if (*pssid==0UL) *pssid = *p;
|
|
if (buf[*p]=='*' && withstar) ++*p;
|
|
return 0L;
|
|
} /* end callchk() */
|
|
|
|
|
|
static void Iconstruct(char qtext[32], uint32_t * pins,
|
|
char logcall[], uint32_t logcall_len, char buf[],
|
|
uint32_t buf_len, uint32_t * p)
|
|
{
|
|
uint32_t k;
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
if (*p<=4UL || buf[*p-2UL]!='I') return;
|
|
/* ,CALL,I: */
|
|
i0 = *p-4UL;
|
|
while (buf[i0]!=',') {
|
|
/* hop back call */
|
|
if (i0==0UL) return;
|
|
--i0;
|
|
}
|
|
k = i0; /* "," before call */
|
|
++i0;
|
|
j = 0UL;
|
|
while (j<=logcall_len-1 && logcall[j]) {
|
|
if (logcall[j]!=buf[i0]) return;
|
|
++i0;
|
|
++j;
|
|
}
|
|
/* logcall = call,I */
|
|
*pins = k;
|
|
i0 = *p-1UL;
|
|
*p = k+1UL; /* payload */
|
|
for (;;) {
|
|
buf[k] = buf[i0];
|
|
if (i0>=buf_len-1 || buf[i0]==0) break;
|
|
++k;
|
|
++i0;
|
|
}
|
|
/* delete ,call,I */
|
|
strncpy(qtext,",qAR,",32u); /* insert ,qAR,call */
|
|
aprsstr_Append(qtext, 32ul, logcall, logcall_len);
|
|
/*
|
|
OE0AAA-9>T8SV40,WIDE1-1,DB0WGS,I:test
|
|
OE0AAA-9>T8SV40,WIDE1-1:test
|
|
OE0AAA-9>T8SV40,WIDE1-1,qAR,DB0WGS:test
|
|
*/
|
|
} /* end Iconstruct() */
|
|
|
|
|
|
static int32_t AprsIs(char buf[], uint32_t buf_len,
|
|
uint8_t datafilt, uint8_t msgfilt,
|
|
const char logcall[], uint32_t logcall_len,
|
|
uint32_t udpchan, char valid,
|
|
struct POSCALL * poscall0)
|
|
{
|
|
uint32_t qpos;
|
|
uint32_t micedest;
|
|
uint32_t payload;
|
|
uint32_t ha;
|
|
uint32_t ilen;
|
|
uint32_t psum1;
|
|
uint32_t psum0;
|
|
uint32_t pssid;
|
|
uint32_t pins;
|
|
uint32_t len;
|
|
uint32_t p;
|
|
uint32_t i0;
|
|
uint8_t hashh;
|
|
uint8_t hashl;
|
|
char qtext[32];
|
|
char ungat;
|
|
char postyp;
|
|
uint8_t unset;
|
|
FRAMEBUF com;
|
|
uint32_t tmp;
|
|
hashl = 0U;
|
|
hashh = 0U;
|
|
p = 0UL;
|
|
pins = 0UL;
|
|
pssid = 0UL; /* for savety */
|
|
len = 0UL;
|
|
poscall0->pos.lat = 0.0f;
|
|
poscall0->pos.long0 = 0.0f;
|
|
while ((len<buf_len-1 && buf[len]) && buf[len]!='\015') ++len;
|
|
if (len==0UL || len+35UL>buf_len-1) return -2L;
|
|
unset = 0U;
|
|
qpos = 0UL;
|
|
for (;;) {
|
|
/* thirdparty loop */
|
|
psum0 = p;
|
|
if (callchk(&qpos, &unset, buf, buf_len, &p, &pssid, 0,
|
|
udpchan || callsrc)) return -3L;
|
|
/* src call */
|
|
if (buf[p]!='>') return -4L;
|
|
i0 = 0UL;
|
|
while (i0<9UL && i0<p) {
|
|
poscall0->call[i0] = buf[i0];
|
|
++i0;
|
|
}
|
|
poscall0->call[i0] = 0;
|
|
++p;
|
|
micedest = p;
|
|
if (callchk(&qpos, &unset, buf, buf_len, &p, &pssid, 0, 0)) return -3L;
|
|
/* dest call */
|
|
psum1 = pssid;
|
|
while (buf[p]==',') {
|
|
++p;
|
|
if (callchk(&qpos, &unset, buf, buf_len, &p, &pssid, 1, 0)) {
|
|
return -3L;
|
|
}
|
|
}
|
|
/* via calls */
|
|
if (buf[p]!=':') return -4L;
|
|
if (pins==0UL) pins = p;
|
|
++p;
|
|
if (buf[p]!='}') break;
|
|
++p;
|
|
}
|
|
if (p>=len) return -2L;
|
|
qtext[0U] = 0;
|
|
if (qpos>0UL) {
|
|
/* qA */
|
|
if (X2C_CAP(buf[qpos])=='Z') return -5L;
|
|
/* qAZ */
|
|
if (X2C_CAP(buf[qpos])=='I') {
|
|
aprsstr_Append(qtext, 32ul, ",", 2ul); /* qAI */
|
|
aprsstr_Append(qtext, 32ul, servercall, 10ul);
|
|
}
|
|
}
|
|
else if (udpchan) {
|
|
aprsstr_Append(qtext, 32ul, ",qAU,", 6ul);
|
|
aprsstr_Append(qtext, 32ul, servercall, 10ul);
|
|
}
|
|
else if (logcall[0UL]) {
|
|
if (cmpfrom(buf, buf_len, 0UL, logcall, logcall_len)) {
|
|
strncpy(qtext,",qAC,",32u);
|
|
}
|
|
else strncpy(qtext,",qAS,",32u);
|
|
aprsstr_Append(qtext, 32ul, servercall, 10ul);
|
|
Iconstruct(qtext, &pins, logcall, logcall_len, buf, buf_len, &p);
|
|
}
|
|
/*
|
|
IO.WrStr(" <");FOR i:=0 TO Length(buf)-1 DO IO.WrHex(ORD(buf[i]),3) END;
|
|
IO.WrStr("> "); IO.WrLn; IO.WrCard(pins, 10); IO.WrCard(p, 10); IO.WrLn;
|
|
*/
|
|
payload = p;
|
|
poscall0->typ0 = buf[p];
|
|
if (buf[p]=='?') return -5L;
|
|
if (udpchan || valid) {
|
|
Getmsg(buf, buf_len, udpchan, (unset&msgfilt)==0U, &ungat);
|
|
if (ungat) return -6L;
|
|
}
|
|
if ((unset&datafilt)!=0U) return -3L;
|
|
tmp = psum1-1UL;
|
|
i0 = psum0;
|
|
if (i0<=tmp) for (;; i0++) {
|
|
aprsstr_HashCh(buf[i0], &hashl, &hashh);
|
|
if (i0==tmp) break;
|
|
} /* end for */
|
|
while ((p<len && buf[p]!='\015') && buf[p]!='\012') {
|
|
aprsstr_HashCh(buf[p], &hashl, &hashh);
|
|
++p;
|
|
}
|
|
ha = (uint32_t)(uint8_t)(char)hashl+(uint32_t)(uint8_t)
|
|
(char)hashh*256UL&65535UL;
|
|
if (timehash[ha]+dupetime>systime) return -5L;
|
|
/* a duplicate */
|
|
if (udpchan || valid) timehash[ha] = systime;
|
|
aprspos_GetPos(&poscall0->pos, &vspeed, &vcourse, &valt, &vsym, &vsymt,
|
|
buf, buf_len, micedest, payload, com, 512ul, &postyp);
|
|
if (udpchan==0UL && !valid) return -1L;
|
|
buf[p] = '\015';
|
|
++p;
|
|
buf[p] = '\012';
|
|
++p;
|
|
buf[p] = 0;
|
|
++p;
|
|
ilen = aprsstr_Length(qtext, 32ul);
|
|
if (ilen>0UL) {
|
|
while (p>pins) {
|
|
--p;
|
|
buf[p+ilen] = buf[p];
|
|
}
|
|
i0 = 0UL;
|
|
while (i0<ilen) {
|
|
buf[p] = qtext[i0];
|
|
++p;
|
|
++i0;
|
|
}
|
|
}
|
|
return 0L;
|
|
} /* end AprsIs() */
|
|
|
|
|
|
static char getfix(uint32_t * p, char s[], uint32_t s_len,
|
|
float * x, float mul)
|
|
{
|
|
uint32_t i0;
|
|
FRAMEBUF h;
|
|
if (s[*p]=='/') {
|
|
++*p;
|
|
i0 = 0UL;
|
|
while (((uint8_t)s[*p]>' ' && s[*p]!='/') && i0<511UL) {
|
|
h[i0] = s[*p];
|
|
++i0;
|
|
++*p;
|
|
}
|
|
h[i0] = 0;
|
|
if (aprsstr_StrToFix(x, h, 512ul)) {
|
|
/*
|
|
IO.WrFixed(x, 4,10); IO.WrStr(" fix<"); IO.WrStr(h);
|
|
IO.WrStrLn(">");
|
|
*/
|
|
*x = *x*mul;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
} /* end getfix() */
|
|
|
|
|
|
static void getcalls(char s[], uint32_t s_len, uint32_t * p,
|
|
MONCALL table[], uint32_t table_len)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
++*p;
|
|
j = 0UL;
|
|
while (s[*p]=='/') {
|
|
++*p;
|
|
i0 = 0UL;
|
|
while ((*p<=s_len-1 && (uint8_t)s[*p]>' ') && s[*p]!='/') {
|
|
if (j<=table_len-1 && i0<=9UL) table[j][i0] = s[*p];
|
|
++*p;
|
|
++i0;
|
|
}
|
|
++j;
|
|
}
|
|
} /* end getcalls() */
|
|
|
|
typedef uint32_t CHSET0[4];
|
|
|
|
static CHSET0 _cnst0 = {0x00000000UL,0x00080000UL,0x00000000UL,0x00BBE200UL}
|
|
;
|
|
|
|
static void gettyps(char s[], uint32_t s_len, uint32_t * p,
|
|
char t[], uint32_t t_len)
|
|
{
|
|
uint32_t j;
|
|
++*p;
|
|
j = 0UL;
|
|
t[0UL] = 0;
|
|
if (s[*p]=='/') {
|
|
++*p;
|
|
while ((j<t_len-1 && *p<=s_len-1) && (uint8_t)s[*p]>' ') {
|
|
if (X2C_INL((int32_t)(uint8_t)s[*p],128,
|
|
_cnst0) && aprsstr_InStr(t, t_len, (char *) &s[*p],
|
|
1u/1u)<0L) {
|
|
t[j] = s[*p];
|
|
t[j+1UL] = 0;
|
|
++j;
|
|
}
|
|
++*p;
|
|
}
|
|
}
|
|
} /* end gettyps() */
|
|
|
|
|
|
static void GetFilters(struct FILTERS * filters, const char s[],
|
|
uint32_t s_len, uint32_t p, pTCPSOCK pongto)
|
|
{
|
|
char not;
|
|
FRAMEBUF pongstr;
|
|
skipblank(s, s_len, &p);
|
|
if (cmpfrom(s, s_len, p, "filter", 7ul)) {
|
|
p += 6UL;
|
|
not = 0;
|
|
filters->typ0 = 0; /* re-init if new filter comes */
|
|
memset((char *)filters->viacalls,(char)0,80UL);
|
|
memset((char *)filters->entrycalls,(char)0,80UL);
|
|
memset((char *)filters->prefixes,(char)0,80UL);
|
|
memset((char *)filters->typs,(char)0,13UL);
|
|
memset((char *)filters->destcalls,(char)0,80UL);
|
|
if (s[p]==' ') {
|
|
skipblank(s, s_len, &p);
|
|
while ((uint8_t)s[p]>=' ') {
|
|
if (s[p]==' ') not = 0;
|
|
skipblank(s, s_len, &p);
|
|
if (s[p]=='m') {
|
|
++p;
|
|
if (getfix(&p, s, s_len, &filters->radius, 1.0f)) {
|
|
filters->typ0 = 'm';
|
|
}
|
|
else return;
|
|
}
|
|
else if (s[p]=='r') {
|
|
++p;
|
|
if (!getfix(&p, s, s_len, &filters->base.lat,
|
|
1.7453292519444E-2f)) return;
|
|
if (!getfix(&p, s, s_len, &filters->base.long0,
|
|
1.7453292519444E-2f)) return;
|
|
if (!getfix(&p, s, s_len, &filters->radius, 1.0f)) return;
|
|
if (!aprspos_posvalid(filters->base)) return;
|
|
filters->typ0 = 'r';
|
|
}
|
|
else if (s[p]=='a') {
|
|
++p;
|
|
if (!getfix(&p, s, s_len, &filters->base.lat,
|
|
1.7453292519444E-2f)) return;
|
|
if (!getfix(&p, s, s_len, &filters->base.long0,
|
|
1.7453292519444E-2f)) return;
|
|
if (!getfix(&p, s, s_len, &filters->edge.lat,
|
|
1.7453292519444E-2f)) return;
|
|
if (!getfix(&p, s, s_len, &filters->edge.long0,
|
|
1.7453292519444E-2f)) return;
|
|
if (!aprspos_posvalid(filters->base)) return;
|
|
if (!aprspos_posvalid(filters->edge)) return;
|
|
filters->typ0 = 'a';
|
|
}
|
|
else if (s[p]=='d') {
|
|
getcalls(s, s_len, &p, filters->viacalls, 8ul);
|
|
filters->notvia = not;
|
|
}
|
|
else if (s[p]=='e') {
|
|
getcalls(s, s_len, &p, filters->entrycalls, 8ul);
|
|
filters->notentry = not;
|
|
}
|
|
else if (s[p]=='u') {
|
|
getcalls(s, s_len, &p, filters->destcalls, 8ul);
|
|
filters->notdestcall = not;
|
|
}
|
|
else if (s[p]=='p') {
|
|
getcalls(s, s_len, &p, filters->prefixes, 8ul);
|
|
filters->notprefix = not;
|
|
}
|
|
else if (s[p]=='t') {
|
|
gettyps(s, s_len, &p, filters->typs, 13ul);
|
|
filters->nottyps = not;
|
|
}
|
|
else if (s[p]=='-') {
|
|
not = 1;
|
|
++p;
|
|
}
|
|
else return;
|
|
}
|
|
}
|
|
}
|
|
else if (pongto && cmpfrom(s, s_len, p, "ping ", 6ul)) {
|
|
aprsstr_Assign(pongstr, 512ul, s, s_len);
|
|
pongstr[p+1UL] = 'o'; /* ping -> pong */
|
|
while (p<513UL && (uint8_t)pongstr[p]>=' ') {
|
|
++p;
|
|
}
|
|
pongstr[p] = '\015';
|
|
pongstr[p+1UL] = '\012';
|
|
pongstr[p+2UL] = 0;
|
|
Sendtcp(pongto, pongstr);
|
|
if (maxpongtime>0UL) {
|
|
if (pongto->pongtime+maxpongtime>systime) pongto->pingout = 0;
|
|
pongto->pongtime = systime+maxpongtime;
|
|
}
|
|
}
|
|
} /* end GetFilters() */
|
|
|
|
|
|
static void saypongout(pTCPSOCK pt)
|
|
{
|
|
FRAMEBUF h;
|
|
FRAMEBUF s;
|
|
strncpy(s,"# ping timeout ",512u);
|
|
aprsstr_IntToStr((int32_t)((systime+maxpongtime)-pt->pongtime), 0UL, h,
|
|
512ul);
|
|
aprsstr_Append(s, 512ul, h, 512ul);
|
|
aprsstr_Append(s, 512ul, "s - data forwarding stopped\015\012", 30ul);
|
|
Sendtcp(pt, s);
|
|
} /* end saypongout() */
|
|
|
|
|
|
static char Auth(const char mbuf0[], uint32_t mbuf_len,
|
|
pTCPSOCK pu)
|
|
{
|
|
uint32_t vport;
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
FRAMEBUF h1;
|
|
FRAMEBUF h;
|
|
pHEARD pmh;
|
|
struct TCPSOCK * anonym;
|
|
{ /* with */
|
|
struct TCPSOCK * anonym = pu;
|
|
i0 = 0UL;
|
|
while ((uint8_t)mbuf0[i0]<=' ') ++i0;
|
|
if (mbuf0[i0]=='#') {
|
|
GetFilters(&anonym->filters, mbuf0, mbuf_len, i0+1UL, 0);
|
|
return 1;
|
|
}
|
|
if (mbuf0[i0]!='u') return 0;
|
|
/* quick test */
|
|
if (cmpfrom(mbuf0, mbuf_len, i0, "user ", 6ul)) {
|
|
i0 += 5UL;
|
|
skipblank(mbuf0, mbuf_len, &i0);
|
|
j = 0UL;
|
|
while (j<9UL && (uint8_t)mbuf0[i0]>' ') {
|
|
anonym->user.call[j] = X2C_CAP(mbuf0[i0]);
|
|
++i0;
|
|
++j;
|
|
}
|
|
anonym->user.call[j] = 0;
|
|
skipblank(mbuf0, mbuf_len, &i0);
|
|
if (cmpfrom(mbuf0, mbuf_len, i0, "pass ", 6ul)) {
|
|
i0 += 5UL;
|
|
skipblank(mbuf0, mbuf_len, &i0);
|
|
j = 0UL;
|
|
while (((uint8_t)mbuf0[i0]>='0' && (uint8_t)mbuf0[i0]<='9')
|
|
&& j<32768UL) {
|
|
j = (j*10UL+(uint32_t)(uint8_t)mbuf0[i0])-48UL;
|
|
++i0;
|
|
}
|
|
anonym->valid = aprsstr_Length(anonym->user.call,
|
|
10ul)>=3UL && j==call2pass(anonym->user.call, 10ul);
|
|
skipblank(mbuf0, mbuf_len, &i0);
|
|
}
|
|
if (cmpfrom(mbuf0, mbuf_len, i0, "vers ", 6ul)) {
|
|
i0 += 5UL;
|
|
skipblank(mbuf0, mbuf_len, &i0);
|
|
j = 0UL;
|
|
while ((uint8_t)mbuf0[i0]>=' ' && !cmpfrom(mbuf0, mbuf_len, i0,
|
|
"filter", 7ul)) {
|
|
if (j<20UL) {
|
|
anonym->vers[j] = mbuf0[i0];
|
|
++j;
|
|
}
|
|
++i0;
|
|
}
|
|
while (j>0UL && anonym->vers[j-1UL]==' ') --j;
|
|
anonym->vers[j] = 0;
|
|
}
|
|
GetFilters(&anonym->filters, mbuf0, mbuf_len, i0, 0);
|
|
pmh = heardtcp;
|
|
if ((!aprspos_posvalid(anonym->user.pos) && FindUserHeard(&pmh,
|
|
anonym->user.call, &vport)>0UL) && pmh) {
|
|
anonym->user.pos = pmh->position;
|
|
}
|
|
aprsstr_Assign(h, 512ul, "# logresp ", 11ul);
|
|
aprsstr_Append(h, 512ul, anonym->user.call, 10ul);
|
|
if (anonym->valid) aprsstr_Append(h, 512ul, " verified", 10ul);
|
|
aprsstr_Append(h, 512ul, " server ", 9ul);
|
|
aprsstr_Append(h, 512ul, servercall, 10ul);
|
|
FiltToStr(anonym->filters, h1, 512ul);
|
|
if (h1[0U]) {
|
|
aprsstr_Append(h, 512ul, " filter ", 9ul);
|
|
aprsstr_Append(h, 512ul, h1, 512ul);
|
|
}
|
|
aprsstr_Assign(h1, 512ul, h, 512ul);
|
|
if (anonym->vers[0U]) {
|
|
aprsstr_Append(h1, 512ul, " vers: ", 8ul);
|
|
aprsstr_Append(h1, 512ul, anonym->vers, 21ul);
|
|
}
|
|
logline(1L, h1, 512ul);
|
|
aprsstr_Append(h, 512ul, "\015\012", 3ul);
|
|
Sendtcp(pu, h);
|
|
}
|
|
}
|
|
return 1;
|
|
} /* end Auth() */
|
|
|
|
|
|
static void closetcp(pTCPSOCK * w, char fin)
|
|
{
|
|
pWWWBUF pb;
|
|
struct TCPSOCK * anonym;
|
|
{ /* with */
|
|
struct TCPSOCK * anonym = *w;
|
|
while (anonym->txbuf) {
|
|
pb = anonym->txbuf;
|
|
anonym->txbuf = anonym->txbuf->next;
|
|
/*
|
|
IO.WrStrLn("deallocw");
|
|
*/
|
|
osic_free((char * *) &pb, sizeof(struct WWWBUF));
|
|
if (!fin && anonym->txbuf) return;
|
|
}
|
|
if (anonym->fd>=0L) osic_Close(anonym->fd);
|
|
anonym->fd = -1L;
|
|
}
|
|
} /* end closetcp() */
|
|
|
|
|
|
static void sendwww(pTCPSOCK * w, WWWB b, int32_t len, char push)
|
|
{
|
|
pWWWBUF pp;
|
|
pWWWBUF pb;
|
|
if (len==0L) return;
|
|
/*
|
|
IO.WrStrLn("allocw");
|
|
*/
|
|
osic_alloc((char * *) &pb, sizeof(struct WWWBUF));
|
|
if (pb==0) return;
|
|
memcpy(pb->buf,b,1401u);
|
|
pb->tlen = len;
|
|
pb->push = push;
|
|
pb->next = 0;
|
|
if ((*w)->txbuf==0) (*w)->txbuf = pb;
|
|
else {
|
|
pp = (*w)->txbuf;
|
|
while (pp->next) pp = pp->next;
|
|
pp->next = pb;
|
|
}
|
|
} /* end sendwww() */
|
|
|
|
#define udpgate4_RELURL "?reload="
|
|
|
|
#define udpgate4_SORTURL "?sort="
|
|
|
|
#define udpgate4_sortTIME "t"
|
|
|
|
#define udpgate4_sortCALL "c"
|
|
|
|
#define udpgate4_sortPORT "p"
|
|
|
|
#define udpgate4_sortHEARD "h"
|
|
|
|
#define udpgate4_sortDIST "d"
|
|
|
|
#define udpgate4_sortUP "u"
|
|
|
|
#define udpgate4_sortDOWN "d"
|
|
|
|
|
|
static void Appwww(pTCPSOCK * wsock, WWWB wbuf, const char s[],
|
|
uint32_t s_len)
|
|
{
|
|
uint32_t i0;
|
|
uint32_t slen;
|
|
uint32_t wlen;
|
|
/*
|
|
len:=Length(wbuf);
|
|
IF len+Length(s)>=HIGH(wbuf) THEN
|
|
sendwww(wsock, wbuf, len, FALSE);
|
|
wbuf[0]:=0C;
|
|
END;
|
|
Append(wbuf, s);
|
|
*/
|
|
wlen = aprsstr_Length(wbuf, 1401ul);
|
|
slen = aprsstr_Length(s, s_len);
|
|
i0 = 0UL;
|
|
while (i0<slen) {
|
|
if (wlen>=1400UL) {
|
|
sendwww(wsock, wbuf, (int32_t)wlen, 0);
|
|
wlen = 0UL;
|
|
}
|
|
wbuf[wlen] = s[i0];
|
|
++i0;
|
|
++wlen;
|
|
}
|
|
wbuf[wlen] = 0;
|
|
} /* end Appwww() */
|
|
|
|
|
|
static void AppCall(WWWB wbuf, pTCPSOCK * wsock, char c[],
|
|
uint32_t c_len, char ungate, char center,
|
|
const char link[], uint32_t link_len)
|
|
{
|
|
char b[4096];
|
|
uint32_t k;
|
|
uint32_t j;
|
|
uint32_t i0;
|
|
X2C_PCOPY((void **)&c,c_len);
|
|
Appwww(wsock, wbuf, "<TD style=text-align:", 22ul);
|
|
if (center) Appwww(wsock, wbuf, "center>", 8ul);
|
|
else Appwww(wsock, wbuf, "left>", 6ul);
|
|
j = 0UL;
|
|
i0 = 0UL;
|
|
while ((uint8_t)link[i0]>=' ') {
|
|
if (link[i0]=='$') {
|
|
++i0;
|
|
if (link[i0]=='c') {
|
|
k = 0UL;
|
|
while ((k<=c_len-1 && c[k]) && j<4095UL) {
|
|
b[j] = c[k];
|
|
++j;
|
|
++k;
|
|
}
|
|
}
|
|
else if (link[i0]=='$') {
|
|
b[j] = '$';
|
|
if (j<4095UL) ++j;
|
|
}
|
|
}
|
|
else {
|
|
b[j] = link[i0];
|
|
if (j<4095UL) ++j;
|
|
}
|
|
++i0;
|
|
}
|
|
b[j] = 0;
|
|
if (b[0U]) {
|
|
Appwww(wsock, wbuf, "<a href=", 9ul);
|
|
Appwww(wsock, wbuf, b, 4096ul);
|
|
Appwww(wsock, wbuf, ">", 2ul);
|
|
}
|
|
if (ungate) {
|
|
Appwww(wsock, wbuf, "#", 2ul);
|
|
}
|
|
Appwww(wsock, wbuf, c, c_len);
|
|
if (b[0U]) Appwww(wsock, wbuf, "</a>", 5ul);
|
|
Appwww(wsock, wbuf, "</TD>", 6ul);
|
|
X2C_PFREE(c);
|
|
} /* end AppCall() */
|
|
|
|
|
|
static void AppTime(WWWB wbuf, pTCPSOCK * wsock, uint32_t t,
|
|
char tab)
|
|
{
|
|
char h1[256];
|
|
if (tab) Appwww(wsock, wbuf, "<td>", 5ul);
|
|
if (systime<t || t==0UL) t = 0UL;
|
|
else t = systime-t;
|
|
aprsstr_TimeToStr(t, h1, 256ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
if (tab) Appwww(wsock, wbuf, "</td>", 6ul);
|
|
} /* end AppTime() */
|
|
|
|
|
|
static void AppMinSec(WWWB wbuf, pTCPSOCK * wsock, uint32_t t)
|
|
{
|
|
char h1[21];
|
|
/*
|
|
Appwww("<td>");
|
|
*/
|
|
if (systime<t || t==0UL) t = 0UL;
|
|
else t = systime-t;
|
|
if (t/3600UL>0UL) {
|
|
aprsstr_IntToStr((int32_t)(t/3600UL), 1UL, h1, 21ul);
|
|
Appwww(wsock, wbuf, h1, 21ul);
|
|
Appwww(wsock, wbuf, "h", 2ul);
|
|
t = t%3600UL;
|
|
}
|
|
if (t/60UL>0UL) {
|
|
aprsstr_IntToStr((int32_t)(t/60UL), 1UL, h1, 21ul);
|
|
Appwww(wsock, wbuf, h1, 21ul);
|
|
Appwww(wsock, wbuf, "m", 2ul);
|
|
t = t%60UL;
|
|
}
|
|
aprsstr_IntToStr((int32_t)t, 1UL, h1, 21ul);
|
|
if (h1[1U]==0) {
|
|
Appwww(wsock, wbuf, " ", 7ul);
|
|
}
|
|
Appwww(wsock, wbuf, h1, 21ul);
|
|
Appwww(wsock, wbuf, "s", 2ul);
|
|
/*
|
|
Appwww("</td>");
|
|
*/
|
|
} /* end AppMinSec() */
|
|
|
|
|
|
static void AppInt(WWWB wbuf, pTCPSOCK * wsock, int32_t n)
|
|
{
|
|
char h1[256];
|
|
Appwww(wsock, wbuf, "<td>", 5ul);
|
|
aprsstr_IntToStr(n, 1UL, h1, 256ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
} /* end AppInt() */
|
|
|
|
|
|
static void AppTxt(WWWB wbuf, pTCPSOCK * wsock, const char style[],
|
|
uint32_t style_len, const char s[], uint32_t s_len)
|
|
{
|
|
char c;
|
|
int32_t i0;
|
|
char h1[256];
|
|
int32_t tmp;
|
|
Appwww(wsock, wbuf, style, style_len);
|
|
tmp = (int32_t)aprsstr_Length(s, s_len)-1L;
|
|
i0 = 0L;
|
|
if (i0<=tmp) for (;; i0++) {
|
|
c = s[i0];
|
|
switch ((unsigned)c) {
|
|
case ' ':
|
|
case '.':
|
|
case ',':
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
case 'A':
|
|
case 'B':
|
|
case 'C':
|
|
case 'D':
|
|
case 'E':
|
|
case 'F':
|
|
case 'G':
|
|
case 'H':
|
|
case 'I':
|
|
case 'J':
|
|
case 'K':
|
|
case 'L':
|
|
case 'M':
|
|
case 'N':
|
|
case 'O':
|
|
case 'P':
|
|
case 'Q':
|
|
case 'R':
|
|
case 'S':
|
|
case 'T':
|
|
case 'U':
|
|
case 'V':
|
|
case 'W':
|
|
case 'X':
|
|
case 'Y':
|
|
case 'Z':
|
|
case 'a':
|
|
case 'b':
|
|
case 'c':
|
|
case 'd':
|
|
case 'e':
|
|
case 'f':
|
|
case 'g':
|
|
case 'h':
|
|
case 'i':
|
|
case 'j':
|
|
case 'k':
|
|
case 'l':
|
|
case 'm':
|
|
case 'n':
|
|
case 'o':
|
|
case 'p':
|
|
case 'q':
|
|
case 'r':
|
|
case 's':
|
|
case 't':
|
|
case 'u':
|
|
case 'v':
|
|
case 'w':
|
|
case 'x':
|
|
case 'y':
|
|
case 'z':
|
|
Appwww(wsock, wbuf, (char *) &c, 1u/1u);
|
|
break;
|
|
case 0:
|
|
case '\001':
|
|
case '\002':
|
|
case '\003':
|
|
case '\004':
|
|
case '\005':
|
|
case '\006':
|
|
case '\007':
|
|
case '\010':
|
|
case '\011':
|
|
case '\012':
|
|
case '\013':
|
|
case '\014':
|
|
case '\015':
|
|
case '\016':
|
|
case '\017':
|
|
case '\020':
|
|
case '\021':
|
|
case '\022':
|
|
case '\023':
|
|
case '\024':
|
|
case '\025':
|
|
case '\026':
|
|
case '\027':
|
|
case '\030':
|
|
case '\031':
|
|
case '\032':
|
|
case '\033':
|
|
case '\034':
|
|
case '\035':
|
|
case '\036':
|
|
case '\037':
|
|
break;
|
|
default:;
|
|
Appwww(wsock, wbuf, "&#", 3ul);
|
|
aprsstr_IntToStr((int32_t)(uint32_t)(uint8_t)c, 1UL, h1,
|
|
256ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, ";", 2ul);
|
|
break;
|
|
} /* end switch */
|
|
if (i0==tmp) break;
|
|
} /* end for */
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
} /* end AppTxt() */
|
|
|
|
|
|
static char hex(uint32_t n)
|
|
{
|
|
if (n>9UL) n += 7UL;
|
|
return (char)(n+48UL);
|
|
} /* end hex() */
|
|
|
|
|
|
static void setcol(char h1[256], uint32_t c, uint32_t n)
|
|
{
|
|
if (n>100UL) n = 100UL;
|
|
n += 155UL;
|
|
h1[c] = hex(n/16UL);
|
|
h1[c+1UL] = hex(n&15UL);
|
|
} /* end setcol() */
|
|
|
|
|
|
static void redgreen(char h1[256], int32_t c)
|
|
{
|
|
if (c<0L) c = 0L;
|
|
if (c<100L) {
|
|
setcol(h1, 0UL, (uint32_t)c);
|
|
setcol(h1, 2UL, 100UL);
|
|
}
|
|
else {
|
|
if (c>200L) c = 200L;
|
|
setcol(h1, 0UL, 100UL);
|
|
setcol(h1, 2UL, (uint32_t)(200L-c));
|
|
}
|
|
} /* end redgreen() */
|
|
|
|
|
|
static void green(char h1[256], uint32_t cnt, uint32_t maxt,
|
|
char driving)
|
|
{
|
|
uint32_t t;
|
|
t = systime-uptime;
|
|
if (t>maxt) t = maxt;
|
|
if (driving) cnt = cnt*2000UL;
|
|
else cnt = cnt*20000UL;
|
|
redgreen(h1, (int32_t)(cnt/(t+300UL)));
|
|
} /* end green() */
|
|
|
|
|
|
static void wcard64(WWWB wbuf, pTCPSOCK * wsock, uint32_t hi,
|
|
uint32_t lo)
|
|
{
|
|
char h1[16];
|
|
if (hi>0UL) {
|
|
aprsstr_CardToStr(lo/1024UL+hi*4194304UL, 1UL, h1, 16ul);
|
|
aprsstr_Append(h1, 16ul, "k", 2ul);
|
|
}
|
|
else aprsstr_CardToStr(lo, 1UL, h1, 16ul);
|
|
Appwww(wsock, wbuf, "<TD style=\"text-align:right\">", 30ul);
|
|
Appwww(wsock, wbuf, h1, 16ul);
|
|
Appwww(wsock, wbuf, "</TD>", 6ul);
|
|
} /* end wcard64() */
|
|
|
|
|
|
static void wint(WWWB wbuf, pTCPSOCK * wsock, int32_t n)
|
|
{
|
|
char h1[16];
|
|
aprsstr_IntToStr(n, 1UL, h1, 16ul);
|
|
Appwww(wsock, wbuf, "<TD style=\"text-align:right\">", 30ul);
|
|
Appwww(wsock, wbuf, h1, 16ul);
|
|
Appwww(wsock, wbuf, "</TD>", 6ul);
|
|
} /* end wint() */
|
|
|
|
|
|
static void wintint(WWWB wbuf, pTCPSOCK * wsock, int32_t n, int32_t k)
|
|
{
|
|
char h1[16];
|
|
aprsstr_IntToStr(n, 1UL, h1, 16ul);
|
|
Appwww(wsock, wbuf, "<TD style=\"text-align:right\">", 30ul);
|
|
Appwww(wsock, wbuf, h1, 16ul);
|
|
Appwww(wsock, wbuf, "<BR>", 5ul);
|
|
aprsstr_IntToStr(k, 1UL, h1, 16ul);
|
|
Appwww(wsock, wbuf, h1, 16ul);
|
|
Appwww(wsock, wbuf, "</TD>", 6ul);
|
|
} /* end wintint() */
|
|
|
|
|
|
static char openfile(char fn[], uint32_t fn_len, int32_t * fd,
|
|
int32_t * flen)
|
|
{
|
|
char h[4097];
|
|
char hh[2];
|
|
/*
|
|
s:stat_t;
|
|
*/
|
|
uint32_t i0;
|
|
char openfile_ret;
|
|
X2C_PCOPY((void **)&fn,fn_len);
|
|
if (fn[0UL]=='/') {
|
|
openfile_ret = 0;
|
|
goto label;
|
|
}
|
|
i0 = 0UL;
|
|
for (;;) {
|
|
if (i0+2UL>=fn_len-1 || fn[i0]==0) break;
|
|
if ((uint8_t)fn[i0]<=' ' || (uint8_t)fn[i0]>=(uint8_t)'\200') {
|
|
openfile_ret = 0;
|
|
goto label;
|
|
}
|
|
if ((fn[i0]=='.' && fn[i0+1UL]=='.') && fn[i0+2UL]=='/') {
|
|
openfile_ret = 0;
|
|
goto label;
|
|
}
|
|
++i0;
|
|
}
|
|
aprsstr_Assign(h, 4097ul, wwwdir, 1024ul);
|
|
aprsstr_Append(h, 4097ul, fn, fn_len);
|
|
*fd = osi_OpenRead(h, 4097ul);
|
|
if (*fd<0L || osi_RdBin(*fd, (char *)hh, 2u/1u, 1UL)!=1L) {
|
|
openfile_ret = 0;
|
|
goto label;
|
|
}
|
|
/* test read if regular file */
|
|
osic_Seek(*fd, 0UL);
|
|
/*
|
|
fstat(fd, s);
|
|
IF CAST(BITSET, s.st_mode)*CAST(BITSET,170000B)<>CAST(BITSET,
|
|
100000B) THEN RETURN FALSE END;
|
|
*/
|
|
*flen = osic_Size(*fd);
|
|
if (*flen<=0L || *flen>=wwwsizelimit) {
|
|
openfile_ret = 0;
|
|
goto label;
|
|
}
|
|
openfile_ret = 1;
|
|
label:;
|
|
X2C_PFREE(fn);
|
|
return openfile_ret;
|
|
} /* end openfile() */
|
|
|
|
|
|
static void appsorturl(WWWB wbuf, pTCPSOCK * wsock, const char sortby[],
|
|
uint32_t sortby_len)
|
|
{
|
|
char h[3];
|
|
if (sortby[0UL]) {
|
|
Appwww(wsock, wbuf, "?sort=", 7ul);
|
|
h[0U] = sortby[0UL];
|
|
h[1U] = sortby[1UL];
|
|
h[2U] = 0;
|
|
Appwww(wsock, wbuf, h, 3ul);
|
|
}
|
|
} /* end appsorturl() */
|
|
|
|
|
|
static void appreloadurl(WWWB wbuf, pTCPSOCK * wsock, uint32_t time0)
|
|
{
|
|
char h[32];
|
|
if (time0) {
|
|
Appwww(wsock, wbuf, "?reload=", 9ul);
|
|
aprsstr_IntToStr((int32_t)time0, 1UL, h, 32ul);
|
|
Appwww(wsock, wbuf, h, 32ul);
|
|
}
|
|
} /* end appreloadurl() */
|
|
|
|
|
|
static void klick(WWWB wbuf, pTCPSOCK * wsock, char path[],
|
|
uint32_t path_len, char text[], uint32_t text_len,
|
|
char sort)
|
|
{
|
|
char s[2];
|
|
X2C_PCOPY((void **)&path,path_len);
|
|
X2C_PCOPY((void **)&text,text_len);
|
|
aprsstr_Assign(s, 2ul, (*wsock)->sortby, 2ul);
|
|
if (sort) {
|
|
if (s[0U]==sort) {
|
|
if (s[1U]!='u') s[1U] = 'u';
|
|
else if (s[1U]!='d') s[1U] = 'd';
|
|
}
|
|
else {
|
|
s[0U] = sort;
|
|
s[1U] = 'u';
|
|
}
|
|
}
|
|
Appwww(wsock, wbuf, "<a href=\"", 10ul);
|
|
Appwww(wsock, wbuf, path, path_len);
|
|
appsorturl(wbuf, wsock, s, 2ul);
|
|
appreloadurl(wbuf, wsock, (*wsock)->reload);
|
|
Appwww(wsock, wbuf, "\">", 3ul);
|
|
Appwww(wsock, wbuf, text, text_len);
|
|
Appwww(wsock, wbuf, "</a> ", 6ul);
|
|
X2C_PFREE(path);
|
|
X2C_PFREE(text);
|
|
} /* end klick() */
|
|
|
|
|
|
static char iconf(char sym, char symt, char fn[],
|
|
uint32_t fn_len, char * overlay)
|
|
{
|
|
char h[256];
|
|
uint32_t i0;
|
|
i0 = (uint32_t)(uint8_t)sym;
|
|
if (i0<33UL || i0>127UL) return 0;
|
|
aprsstr_Assign(fn, fn_len, "icon/", 6ul);
|
|
aprsstr_IntToStr((int32_t)(i0+67UL), 3UL, h, 256ul);
|
|
*overlay = 0;
|
|
switch ((unsigned)symt) {
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
case 'A':
|
|
case 'B':
|
|
case 'C':
|
|
case 'D':
|
|
case 'E':
|
|
case 'F':
|
|
case 'G':
|
|
case 'H':
|
|
case 'I':
|
|
case 'J':
|
|
case 'K':
|
|
case 'L':
|
|
case 'M':
|
|
case 'N':
|
|
case 'O':
|
|
case 'P':
|
|
case 'Q':
|
|
case 'R':
|
|
case 'S':
|
|
case 'T':
|
|
case 'U':
|
|
case 'V':
|
|
case 'W':
|
|
case 'X':
|
|
case 'Y':
|
|
case 'Z':
|
|
h[0U] = '2';
|
|
*overlay = symt;
|
|
break;
|
|
case '\\':
|
|
h[0U] = '2';
|
|
break;
|
|
case '/':
|
|
break;
|
|
default:;
|
|
return 0;
|
|
} /* end switch */
|
|
aprsstr_Append(fn, fn_len, h, 256ul);
|
|
aprsstr_Append(fn, fn_len, ".gif", 5ul);
|
|
aprsstr_Assign(h, 256ul, wwwdir, 1024ul);
|
|
aprsstr_Append(h, 256ul, fn, fn_len);
|
|
return osi_Exists(h, 256ul);
|
|
} /* end iconf() */
|
|
|
|
|
|
static void sortindex(pHEARD ph, uint32_t maxtime, const char sortby[],
|
|
uint32_t sortby_len, char * withqual)
|
|
/* make LONGREAL of sort key */
|
|
{
|
|
char homevalid;
|
|
uint32_t i0;
|
|
char c;
|
|
char s;
|
|
double xs;
|
|
*withqual = 0;
|
|
xs = 0.0;
|
|
homevalid = aprspos_posvalid(home);
|
|
s = sortby[0UL];
|
|
while (ph) {
|
|
switch ((unsigned)s) {
|
|
case 't': /* sort by time as it is */
|
|
xs = xs+1.0;
|
|
break;
|
|
case 'c': /* sort by call */
|
|
xs = 0.0;
|
|
for (i0 = 0UL; i0<=9UL; i0++) {
|
|
c = ph->call[i0];
|
|
xs = xs*128.0+(double)(float)(uint32_t)(uint8_t)c;
|
|
} /* end for */
|
|
break;
|
|
case 'p': /* sort by port */
|
|
xs = (double)(float)ph->fromrx;
|
|
break;
|
|
case 'h': /* sort by count */
|
|
xs = (double)(float)MHcount(ph, maxtime);
|
|
break;
|
|
case 'd': /* sort by km */
|
|
if (homevalid && aprspos_posvalid(ph->position)) {
|
|
xs = (double)aprspos_distance(home, ph->position);
|
|
}
|
|
else xs = 0.0;
|
|
break;
|
|
} /* end switch */
|
|
if (sortby[1UL]=='d') ph->sortval = -xs;
|
|
else ph->sortval = xs;
|
|
if ((ph->txd || ph->level) || ph->quali) *withqual = 1;
|
|
ph = ph->next;
|
|
}
|
|
} /* end sortindex() */
|
|
|
|
|
|
static void getlinkfile(char b[], uint32_t b_len, const char fn[],
|
|
uint32_t fn_len)
|
|
{
|
|
int32_t len;
|
|
int32_t fd;
|
|
aprsstr_Assign(b, b_len, wwwdir, 1024ul);
|
|
aprsstr_Append(b, b_len, fn, fn_len);
|
|
fd = osi_OpenRead(b, b_len);
|
|
b[0UL] = 0;
|
|
if (fd>=0L) {
|
|
len = osi_RdBin(fd, (char *)b, (b_len)/1u, b_len-1UL);
|
|
if (len<0L) len = 0L;
|
|
b[len] = 0;
|
|
osic_Close(fd);
|
|
}
|
|
} /* end getlinkfile() */
|
|
|
|
|
|
static void apppos(WWWB wbuf, pTCPSOCK * wsock, struct aprspos_POSITION pos,
|
|
char withloc)
|
|
{
|
|
char h[32];
|
|
if (aprspos_posvalid(pos)) {
|
|
aprsstr_FixToStr(X2C_DIVR(pos.lat,1.7453292519444E-2f), 5UL, h, 32ul);
|
|
Appwww(wsock, wbuf, " ", 2ul);
|
|
Appwww(wsock, wbuf, h, 32ul);
|
|
aprsstr_FixToStr(X2C_DIVR(pos.long0,1.7453292519444E-2f), 5UL, h,
|
|
32ul);
|
|
Appwww(wsock, wbuf, "/", 2ul);
|
|
Appwww(wsock, wbuf, h, 32ul);
|
|
if (withloc) {
|
|
postoloc(h, 32ul, pos);
|
|
Appwww(wsock, wbuf, " ", 2ul);
|
|
Appwww(wsock, wbuf, h, 32ul);
|
|
}
|
|
}
|
|
else Appwww(wsock, wbuf, " (NoPos)", 9ul);
|
|
} /* end apppos() */
|
|
|
|
|
|
static void showmh(WWWB wbuf, pTCPSOCK * wsock, char h1[256], pHEARD ph0,
|
|
char dir, char net, uint32_t maxtime,
|
|
char title0[], uint32_t title_len,
|
|
const char sortby[], uint32_t sortby_len)
|
|
{
|
|
char withqual;
|
|
char withicon;
|
|
char withport;
|
|
uint32_t ci;
|
|
char hch;
|
|
pHEARD phs;
|
|
pHEARD ph;
|
|
double xs;
|
|
char callink[1024];
|
|
X2C_PCOPY((void **)&title0,title_len);
|
|
getlinkfile(callink, 1024ul, "calllink.txt", 13ul);
|
|
sortindex(ph0, maxtime, sortby, sortby_len, &withqual);
|
|
withport = udpsocks && udpsocks->next;
|
|
aprsstr_Assign(h1, 256ul, wwwdir, 1024ul);
|
|
aprsstr_Append(h1, 256ul, "icon", 5ul);
|
|
withicon = osi_Exists(h1, 256ul);
|
|
Appwww(wsock, wbuf, "<table id=mheard border=0 align=center CELLPADDING=3 \
|
|
CELLSPACING=1 BGCOLOR=#FFFFFF><tr class=tab-mh-titel BGCOLOR=#A9EEFF><th cols\
|
|
pan=", 135ul);
|
|
aprsstr_IntToStr((int32_t)(6UL+(uint32_t)withicon+(uint32_t)
|
|
withport+(uint32_t)(dir && withqual)*3UL+(uint32_t)net),
|
|
1UL, h1, 256ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, ">", 2ul);
|
|
Appwww(wsock, wbuf, title0, title_len);
|
|
if (maxtime%3600UL==0UL) {
|
|
aprsstr_IntToStr((int32_t)(maxtime/3600UL), 1UL, h1, 256ul);
|
|
aprsstr_Append(h1, 256ul, "h", 2ul);
|
|
}
|
|
else {
|
|
aprsstr_IntToStr((int32_t)(maxtime/60UL), 1UL, h1, 256ul);
|
|
aprsstr_Append(h1, 256ul, "min", 4ul);
|
|
}
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
/* Appwww('</th></tr><tr class=tab-mh-head BGCOLOR=#E0C080><th>Call</th>'
|
|
); */
|
|
Appwww(wsock, wbuf, "</th></tr><tr class=tab-mh-head BGCOLOR=#E0C080><th>",
|
|
53ul);
|
|
klick(wbuf, wsock, "mh", 3ul, "Call", 5ul, 'c');
|
|
Appwww(wsock, wbuf, "</th>", 6ul);
|
|
if (withicon) Appwww(wsock, wbuf, "<th>Icon</th>", 14ul);
|
|
/* IF withport THEN Appwww('<th>Port</th>') END; */
|
|
if (withport) {
|
|
Appwww(wsock, wbuf, "<th>", 5ul);
|
|
klick(wbuf, wsock, "mh", 3ul, "Port", 5ul, 'p');
|
|
Appwww(wsock, wbuf, "</th>", 6ul);
|
|
}
|
|
/* Appwww('<th>Last Heard</th><th>Pack</th><th>QRB km</th><th>Data</th><th>Path</th></tr>'
|
|
); */
|
|
Appwww(wsock, wbuf, "<th>", 5ul);
|
|
klick(wbuf, wsock, "mh", 3ul, "Last Heard", 11ul, 't');
|
|
if (dir && withqual) {
|
|
Appwww(wsock, wbuf, "</th><th>Txd</th><th>Lev</th><th>q%", 40ul);
|
|
}
|
|
if (net) Appwww(wsock, wbuf, "</th><th>Position", 18ul);
|
|
Appwww(wsock, wbuf, "</th><th>", 10ul);
|
|
klick(wbuf, wsock, "mh", 3ul, "Pack", 5ul, 'h');
|
|
Appwww(wsock, wbuf, "</th><th>", 10ul);
|
|
klick(wbuf, wsock, "mh", 3ul, "QRB km", 7ul, 'd');
|
|
Appwww(wsock, wbuf, "</th><th>Data</th><th>Path</th></tr>", 37ul);
|
|
for (;;) {
|
|
phs = ph0;
|
|
xs = X2C_max_longreal;
|
|
ph = 0;
|
|
while (phs) {
|
|
if (phs->sortval<xs) {
|
|
xs = phs->sortval;
|
|
ph = phs;
|
|
}
|
|
phs = phs->next;
|
|
}
|
|
if (ph==0) break;
|
|
ph->sortval = X2C_max_longreal;
|
|
if (ph->time0+maxtime>systime) {
|
|
ci = MHcount(ph, maxtime);
|
|
Appwww(wsock, wbuf, "<tr style=\"background-color:#90FF90; text-alig\
|
|
n:right\">", 56ul);
|
|
AppCall(wbuf, wsock, ph->call, 10ul, ph->ungate, 0, callink,
|
|
1024ul);
|
|
if (withicon) {
|
|
Appwww(wsock, wbuf, "<td", 4ul);
|
|
if (iconf(ph->sym, ph->symt, h1, 256ul, &hch)) {
|
|
Appwww(wsock, wbuf, " style=\"background-image:url(/", 31ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, "); background-repeat:no-repeat;background\
|
|
-position:center center;", 66ul);
|
|
if (hch) {
|
|
Appwww(wsock, wbuf, "text-align:center\">", 20ul);
|
|
Appwww(wsock, wbuf, (char *) &hch, 1u/1u);
|
|
}
|
|
else Appwww(wsock, wbuf, "\">", 3ul);
|
|
}
|
|
else Appwww(wsock, wbuf, ">", 2ul);
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
}
|
|
if (withport) {
|
|
Appwww(wsock, wbuf, "<td>", 5ul);
|
|
getportname(ph->fromrx, h1, 256ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
}
|
|
Appwww(wsock, wbuf, "<td>", 5ul);
|
|
AppMinSec(wbuf, wsock, ph->time0);
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
if (dir && withqual) {
|
|
/* txdel */
|
|
Appwww(wsock, wbuf, "<td style=\"background-color:#", 30ul);
|
|
strncpy(h1,"80FF80",256u);
|
|
redgreen(h1, (int32_t)ph->txd-50L);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, "\">", 3ul);
|
|
if (ph->txd) {
|
|
aprsstr_IntToStr((int32_t)ph->txd, 1UL, h1, 256ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
}
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
/* level */
|
|
Appwww(wsock, wbuf, "<td style=\"background-color:#", 30ul);
|
|
strncpy(h1,"80FF80",256u);
|
|
if (ph->level) {
|
|
redgreen(h1, ((int32_t)Min((uint32_t)(uint8_t)abs(ph->level+15),
|
|
15UL)-5L)*10L);
|
|
}
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, "\">", 3ul);
|
|
if (ph->level) {
|
|
aprsstr_IntToStr((int32_t)ph->level, 1UL, h1, 256ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
}
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
/*quality */
|
|
Appwww(wsock, wbuf, "<td>", 5ul);
|
|
if (ph->quali) {
|
|
aprsstr_IntToStr((int32_t)ph->quali, 1UL, h1, 256ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
}
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
}
|
|
if (net) {
|
|
Appwww(wsock, wbuf, "<td>", 5ul);
|
|
apppos(wbuf, wsock, ph->position, 0);
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
}
|
|
Appwww(wsock, wbuf, "<td style=\"background-color:#", 30ul);
|
|
strncpy(h1,"80FF80",256u);
|
|
green(h1, ci, maxtime, ph->datatyp=='S');
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, "\">", 3ul);
|
|
aprsstr_IntToStr((int32_t)ci, 1UL, h1, 256ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
h1[0U] = 0;
|
|
if (aprspos_posvalid(ph->position) && aprspos_posvalid(home)) {
|
|
aprsstr_FixToStr(aprspos_distance(home, ph->position)+0.05f, 2UL,
|
|
h1, 256ul);
|
|
}
|
|
Appwww(wsock, wbuf, "<td>", 5ul);
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
Appwww(wsock, wbuf, "<td>", 5ul);
|
|
if (ph->datatyp=='C') {
|
|
aprsstr_FixToStr(ph->data, 2UL, h1, 256ul);
|
|
aprsstr_Append(h1, 256ul, "\260C", 3ul);
|
|
}
|
|
else if (ph->datatyp=='S') {
|
|
aprsstr_FixToStr(ph->data, 0UL, h1, 256ul);
|
|
aprsstr_Append(h1, 256ul, "kmh", 4ul);
|
|
}
|
|
else h1[0] = 0;
|
|
Appwww(wsock, wbuf, h1, 256ul);
|
|
Appwww(wsock, wbuf, "</td>", 6ul);
|
|
AppTxt(wbuf, wsock, "<td style=text-align:left>", 27ul, ph->head,
|
|
41ul);
|
|
Appwww(wsock, wbuf, "</tr>\015\012", 8ul);
|
|
}
|
|
}
|
|
Appwww(wsock, wbuf, "</table> ", 15ul);
|
|
X2C_PFREE(title0);
|
|
} /* end showmh() */
|
|
|
|
|
|
static void getreload(char s[], uint32_t s_len, uint32_t * r)
|
|
{
|
|
int32_t len;
|
|
int32_t j;
|
|
int32_t i0;
|
|
uint32_t n;
|
|
n = 0UL;
|
|
i0 = aprsstr_InStr(s, s_len, "?reload=", 9ul);
|
|
if (i0>=0L) {
|
|
len = (int32_t)aprsstr_Length(s, s_len);
|
|
j = i0;
|
|
i0 += (int32_t)aprsstr_Length("?reload=", 9ul);
|
|
while ((i0<len && (uint8_t)s[i0]>='0') && (uint8_t)s[i0]<='9') {
|
|
n = (n*10UL+(uint32_t)(uint8_t)s[i0])-48UL;
|
|
++i0;
|
|
}
|
|
while (i0<=len) {
|
|
s[j] = s[i0];
|
|
++i0;
|
|
++j;
|
|
}
|
|
}
|
|
if (n>0UL) *r = n;
|
|
} /* end getreload() */
|
|
|
|
|
|
static void getmh(char s[], uint32_t s_len, char sortby[],
|
|
uint32_t sortby_len)
|
|
{
|
|
int32_t len;
|
|
int32_t j;
|
|
int32_t i0;
|
|
sortby[0UL] = 0;
|
|
sortby[1UL] = 0;
|
|
i0 = aprsstr_InStr(s, s_len, "?sort=", 7ul);
|
|
if (i0>=0L) {
|
|
len = (int32_t)aprsstr_Length(s, s_len);
|
|
j = i0;
|
|
i0 += (int32_t)aprsstr_Length("?sort=", 7ul);
|
|
sortby[0UL] = s[i0];
|
|
++i0;
|
|
sortby[1UL] = s[i0];
|
|
++i0;
|
|
while (i0<=len) {
|
|
s[j] = s[i0];
|
|
++i0;
|
|
++j;
|
|
}
|
|
}
|
|
} /* end getmh() */
|
|
|
|
|
|
static void appreload(WWWB wbuf, pTCPSOCK * wsock, uint32_t time0)
|
|
{
|
|
char h[32];
|
|
if (time0) {
|
|
Appwww(wsock, wbuf, "<meta http-equiv=\"refresh\" content=\"", 37ul);
|
|
aprsstr_IntToStr((int32_t)(time0*60UL), 1UL, h, 32ul);
|
|
Appwww(wsock, wbuf, h, 32ul);
|
|
Appwww(wsock, wbuf, "\">", 3ul);
|
|
}
|
|
} /* end appreload() */
|
|
|
|
|
|
static void reloadklick(WWWB wbuf, pTCPSOCK * wsock)
|
|
{
|
|
char h1[16];
|
|
/*
|
|
Appwww('<form method="get">reload min:<input type="text" value="');
|
|
*/
|
|
Appwww(wsock, wbuf, "Reload (min):<input type=\"text\" value=\"", 40ul);
|
|
aprsstr_IntToStr((int32_t)(*wsock)->reload, 1UL, h1, 16ul);
|
|
Appwww(wsock, wbuf, h1, 16ul);
|
|
Appwww(wsock, wbuf, "\" name=\"reload\" size=\"4\" maxlength=\"3\"><input \
|
|
type=\"submit\" value=\"set reload time\"/></form>", 93ul);
|
|
} /* end reloadklick() */
|
|
|
|
|
|
static void klicks(WWWB wbuf, pTCPSOCK * wsock)
|
|
{
|
|
/*
|
|
Appwww('<div style="text-align:center" class="nav">');
|
|
*/
|
|
Appwww(wsock, wbuf, "<div style=\"text-align:center\" class=\"nav\"><form \
|
|
method=\"get\">", 63ul);
|
|
klick(wbuf, wsock, "/", 2ul, "CONNECTS", 9ul, 0);
|
|
klick(wbuf, wsock, "mh", 3ul, "HEARD", 6ul, 0);
|
|
if (maxmsg>0UL) klick(wbuf, wsock, "msg", 4ul, "MSGRELAY", 9ul, 0);
|
|
klick(wbuf, wsock, "info.html", 10ul, "INFO", 5ul, 0);
|
|
reloadklick(wbuf, wsock);
|
|
Appwww(wsock, wbuf, "</div>", 7ul);
|
|
} /* end klicks() */
|
|
|
|
|
|
static void conthead(pTCPSOCK * wsock, WWWB wbuf)
|
|
{
|
|
strncpy(wbuf,"HTTP/1.0 200 OK\015\012Content-Type: text/html; charset=iso-\
|
|
8859-1\015\012\015\012",1401u);
|
|
sendwww(wsock, wbuf, (int32_t)aprsstr_Length(wbuf, 1401ul), 1);
|
|
strncpy(wbuf,"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//\
|
|
EN\"\015\012\"http://www.w3.org/TR/html4/loose.dtd\">\015\012<HTML><HEAD>",
|
|
1401u);
|
|
appreload(wbuf, wsock, (*wsock)->reload);
|
|
} /* end conthead() */
|
|
|
|
|
|
static void title(WWWB wbuf, pTCPSOCK * wsock, uint32_t * cnt)
|
|
{
|
|
char h[32];
|
|
++*cnt;
|
|
Appwww(wsock, wbuf, "<TITLE>", 8ul);
|
|
Appwww(wsock, wbuf, viacall, 10ul);
|
|
Appwww(wsock, wbuf, " Message Relay</TITLE><link href=\"style.css\" rel=\"\
|
|
stylesheet\" type=\"text/css\"></HEAD>\015\012<BODY><div style=\"text-align:c\
|
|
enter\"><H3>\015\012", 131ul);
|
|
if (viacall[0U]) {
|
|
Appwww(wsock, wbuf, " MsgCall ", 10ul);
|
|
Appwww(wsock, wbuf, viacall, 10ul);
|
|
}
|
|
apppos(wbuf, wsock, home, 1);
|
|
Appwww(wsock, wbuf, " [udpgate(c) 0.63] http#", 25ul);
|
|
aprsstr_IntToStr((int32_t)*cnt, 1UL, h, 32ul);
|
|
Appwww(wsock, wbuf, h, 32ul);
|
|
Appwww(wsock, wbuf, " Uptime ", 9ul);
|
|
AppTime(wbuf, wsock, uptime, 0);
|
|
Appwww(wsock, wbuf, "</H3></div>\015\012", 14ul);
|
|
} /* end title() */
|
|
|
|
|
|
static void Www(pTCPSOCK wsock)
|
|
{
|
|
WWWB wbuf;
|
|
char h1[256];
|
|
int32_t res0;
|
|
int32_t flen;
|
|
int32_t fdw;
|
|
uint32_t ut;
|
|
uint32_t tt;
|
|
pTCPSOCK ss;
|
|
pUDPSOCK us;
|
|
uint32_t i0;
|
|
char serverlink[1024];
|
|
pMESSAGE mp;
|
|
uint8_t tp;
|
|
char hok;
|
|
struct TCPSOCK * anonym;
|
|
struct TCPSOCK * anonym0;
|
|
struct _0 * anonym1;
|
|
struct TCPSOCK * anonym2;
|
|
/* Www */
|
|
res0 = readsock(wsock->fd, wbuf, 1401L);
|
|
i0 = 0UL;
|
|
for (;;) {
|
|
if ((int32_t)i0>=res0) {
|
|
if (res0<=0L) {
|
|
osic_Close(wsock->fd);
|
|
wsock->fd = -1L;
|
|
}
|
|
return;
|
|
}
|
|
{ /* with */
|
|
struct TCPSOCK * anonym = wsock;
|
|
anonym->get[anonym->wwwst] = wbuf[i0];
|
|
if (anonym->wwwst<255UL) ++anonym->wwwst;
|
|
else {
|
|
anonym->get[anonym->wwwst-4UL] = anonym->get[anonym->wwwst-3UL];
|
|
anonym->get[anonym->wwwst-3UL] = anonym->get[anonym->wwwst-2UL];
|
|
anonym->get[anonym->wwwst-2UL] = anonym->get[anonym->wwwst-1UL];
|
|
anonym->get[anonym->wwwst-1UL] = anonym->get[anonym->wwwst];
|
|
}
|
|
anonym->get[anonym->wwwst] = 0;
|
|
/*
|
|
IO.WrCard(wwwst, 10); FOR tt:=0 TO wwwst DO IO.WrHex(ORD(get[tt]), 3);
|
|
END; IO.WrLn;
|
|
*/
|
|
if (((((anonym->wwwst>=4UL && anonym->get[anonym->wwwst-4UL]
|
|
=='\015') && anonym->get[anonym->wwwst-3UL]=='\012')
|
|
&& anonym->get[anonym->wwwst-2UL]=='\015')
|
|
&& anonym->get[anonym->wwwst-1UL]=='\012')
|
|
&& cmpfrom(anonym->get, 256ul, 0UL, "GET /", 6ul)) break;
|
|
++i0;
|
|
}
|
|
}
|
|
{ /* with */
|
|
struct TCPSOCK * anonym0 = wsock;
|
|
i0 = 5UL;
|
|
while (i0<=255UL && (uint8_t)anonym0->get[i0]>' ') {
|
|
anonym0->get[i0-5UL] = anonym0->get[i0];
|
|
++i0;
|
|
}
|
|
anonym0->get[i0-5UL] = 0;
|
|
getreload(anonym0->get, 256ul, &anonym0->reload);
|
|
getmh(anonym0->get, 256ul, anonym0->sortby, 2ul);
|
|
}
|
|
if (wsock->get[0U]==0) {
|
|
++httpcount;
|
|
conthead(&wsock, wbuf);
|
|
Appwww(&wsock, wbuf, "<TITLE>", 8ul);
|
|
Appwww(&wsock, wbuf, servercall, 10ul);
|
|
Appwww(&wsock, wbuf, " Status Report</TITLE><link href=\"style.css\" re\
|
|
l=\"stylesheet\" type=\"text/css\"></HEAD>\015\012<BODY><div style=\"text-ali\
|
|
gn:center\"><H3>\015\012", 131ul);
|
|
if (servercall[0U]) {
|
|
Appwww(&wsock, wbuf, "Server ", 8ul);
|
|
Appwww(&wsock, wbuf, servercall, 10ul);
|
|
}
|
|
if (tcpbindport[0U]) {
|
|
Appwww(&wsock, wbuf, " Port ", 8ul);
|
|
Appwww(&wsock, wbuf, tcpbindport, 6ul);
|
|
}
|
|
Appwww(&wsock, wbuf, " [udpgate(c) 0.63] Maxusers ", 29ul);
|
|
aprsstr_IntToStr((int32_t)maxusers, 1UL, h1, 256ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
Appwww(&wsock, wbuf, " http#", 7ul);
|
|
aprsstr_IntToStr((int32_t)httpcount, 1UL, h1, 256ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
/*
|
|
IF QWatch.qsize>0 THEN
|
|
Appwww(" txq ");
|
|
IntToStr(QWatch.qsize, 1, h1); Appwww(h1); Appwww("s");
|
|
END;
|
|
*/
|
|
Appwww(&wsock, wbuf, " Uptime ", 9ul);
|
|
AppTime(wbuf, &wsock, uptime, 0);
|
|
Appwww(&wsock, wbuf, "</H3></div>\015\012", 14ul);
|
|
klicks(wbuf, &wsock);
|
|
/* udp ports*/
|
|
Appwww(&wsock, wbuf, "<TABLE id=connections BORDER=\"0\" CELLPADDING=3 \
|
|
CELLSPACING=1 BGCOLOR=#000000 align=center SUMMARY=\"Connection Table\">\015\01\
|
|
2<TR class=tab-con-titel VALIGN=\"BASELINE\" BGCOLOR=\"#A999CC\"><TH COLSPAN=\
|
|
14 style=\"text-align:center\">Server Connections</TH></TR>\015\012<TR class=\
|
|
tab-con-head BGCOLOR=\"#CCCCFF\">\015\012<TH>Dir</TH><TH>IPnum</TH><TH>Port</\
|
|
TH><TH>Call/Port</TH><TH>V</TH> <TH>Software</TH> <TH NOWRAP>Range Filter</TH\
|
|
><TH>TxByte</TH> <TH>TxFr</TH><TH NOWRAP>bit/s</TH><TH>RxByte</TH> <TH>RxFr</\
|
|
TH><TH NOWRAP>bit/s</TH><TH>Up</TH></TR>", 524ul);
|
|
us = udpsocks;
|
|
while (us) {
|
|
if (us->txbytes>0UL) {
|
|
showpip(us->ip, 0UL, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "<TR class=tab-con-udp BGCOLOR=#E0E0F0 style\
|
|
=\"text-align:center\">\015\012<TD>udp</TD><TD>", 83ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "</TD>", 6ul);
|
|
wint(wbuf, &wsock, (int32_t)us->dport);
|
|
Appwww(&wsock, wbuf, "<TD style=\"text-align:left\">T:", 31ul);
|
|
Appwww(&wsock, wbuf, us->portname, 10ul);
|
|
Appwww(&wsock, wbuf, "</TD><TD></TD><TD></TD>", 24ul);
|
|
if (us->torfradius>=1.0f || us->maxbytes>0UL) {
|
|
Appwww(&wsock, wbuf, "<td>", 5ul);
|
|
if (us->torfradius>=1.0f) {
|
|
aprsstr_IntToStr((int32_t)(uint32_t)
|
|
X2C_TRUNCC(us->torfradius,0UL,X2C_max_longcard), 1UL, h1,
|
|
256ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "km ", 4ul);
|
|
}
|
|
if (us->maxbytes>0UL) {
|
|
aprsstr_IntToStr((int32_t)us->maxbytes, 1UL, h1, 256ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "B/s", 4ul);
|
|
}
|
|
Appwww(&wsock, wbuf, "</td>", 6ul);
|
|
}
|
|
else Appwww(&wsock, wbuf, "<TD></TD>", 10ul);
|
|
wint(wbuf, &wsock, (int32_t)us->txbytes);
|
|
wint(wbuf, &wsock, (int32_t)us->txframes);
|
|
if (uptime<systime) ut = systime-uptime;
|
|
else ut = 1UL;
|
|
wint(wbuf, &wsock, (int32_t)((us->txbytes*8UL)/ut));
|
|
wint(wbuf, &wsock, 0L);
|
|
wint(wbuf, &wsock, 0L);
|
|
wint(wbuf, &wsock, 0L);
|
|
Appwww(&wsock, wbuf, "<TD>", 5ul);
|
|
aprsstr_TimeToStr(ut, h1, 256ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "</TD></TR>", 11ul);
|
|
}
|
|
for (i0 = 0UL; i0<=15UL; i0++) {
|
|
{ /* with */
|
|
struct _0 * anonym1 = &us->stat[i0];
|
|
if (anonym1->utime+600UL>systime) {
|
|
showpip(anonym1->uip, 0UL, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "<TR class=tab-con-udp BGCOLOR=#E0E0F0\
|
|
style=\"text-align:center\">\015\012<TD>udp</TD><TD>", 83ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "</TD>", 6ul);
|
|
wint(wbuf, &wsock, (int32_t)anonym1->uport);
|
|
Appwww(&wsock, wbuf, "<TD style=\"text-align:left\">R:",
|
|
31ul);
|
|
Appwww(&wsock, wbuf, us->portname, 10ul);
|
|
Appwww(&wsock, wbuf, "</TD><TD></TD><TD></TD><TD></TD>",
|
|
33ul);
|
|
wint(wbuf, &wsock, 0L);
|
|
wint(wbuf, &wsock, 0L);
|
|
if (anonym1->dtime<systime) ut = systime-anonym1->dtime;
|
|
else ut = 1UL;
|
|
wint(wbuf, &wsock, 0L);
|
|
wint(wbuf, &wsock, (int32_t)anonym1->rxbytes);
|
|
wint(wbuf, &wsock, (int32_t)anonym1->rxframes);
|
|
wint(wbuf, &wsock, (int32_t)((anonym1->rxbytes*8UL)/ut));
|
|
Appwww(&wsock, wbuf, "<TD>", 5ul);
|
|
aprsstr_TimeToStr(ut, h1, 256ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "</TD></TR>", 11ul);
|
|
}
|
|
}
|
|
} /* end for */
|
|
us = us->next;
|
|
}
|
|
/* tcp ports */
|
|
getlinkfile(serverlink, 1024ul, "serverlink.txt", 15ul);
|
|
ss = tcpsocks;
|
|
while (ss) {
|
|
{ /* with */
|
|
struct TCPSOCK * anonym2 = ss;
|
|
if (anonym2->service=='S' || anonym2->service=='G') {
|
|
if (anonym2->connt>0UL && anonym2->connt<systime) {
|
|
tt = systime-anonym2->connt;
|
|
}
|
|
else tt = 1UL;
|
|
/*
|
|
Appwww('<TR class=tab-con-tcp style="
|
|
text-align:center" ');
|
|
*/
|
|
if (anonym2->service=='S') {
|
|
Appwww(&wsock, wbuf, "<TR class=tab-con-in style=\"text-ali\
|
|
gn:center\" BGCOLOR=\"#C0E0C0\"><TD>in", 72ul);
|
|
}
|
|
else {
|
|
Appwww(&wsock, wbuf, "<TR class=tab-con-out style=\"text-al\
|
|
ign:center\" BGCOLOR=\"#D0C0C0\"><TD>out", 74ul);
|
|
}
|
|
Appwww(&wsock, wbuf, "</TD>", 6ul);
|
|
if (serverlink[0U]==0) {
|
|
/* make klickable link */
|
|
Appwww(&wsock, wbuf, "<TD style=\"text-align:center\">",
|
|
31ul);
|
|
Appwww(&wsock, wbuf, anonym2->ipnum, 64ul);
|
|
Appwww(&wsock, wbuf, "</TD>", 6ul);
|
|
}
|
|
else {
|
|
AppCall(wbuf, &wsock, anonym2->ipnum, 64ul, 0, 1,
|
|
serverlink, 1024ul);
|
|
}
|
|
Appwww(&wsock, wbuf, "<TD style=\"text-align:right\">", 30ul);
|
|
if (anonym2->service=='S') {
|
|
Appwww(&wsock, wbuf, tcpbindport, 6ul);
|
|
}
|
|
else Appwww(&wsock, wbuf, anonym2->port, 6ul);
|
|
Appwww(&wsock, wbuf, "</TD><TD style=\"text-align:left\">",
|
|
34ul);
|
|
Appwww(&wsock, wbuf, anonym2->user.call, 10ul);
|
|
if (anonym2->service=='G' && anonym2->qwatch.qsize>0L) {
|
|
Appwww(&wsock, wbuf, " q=", 4ul);
|
|
aprsstr_IntToStr(anonym2->qwatch.qsize, 1UL, h1, 256ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "s", 2ul);
|
|
}
|
|
Appwww(&wsock, wbuf, "</TD><TD>", 10ul);
|
|
if (anonym2->connt>0UL) {
|
|
if (anonym2->valid) Appwww(&wsock, wbuf, "v", 2ul);
|
|
if (aprspos_posvalid(anonym2->user.pos)) {
|
|
Appwww(&wsock, wbuf, "p", 2ul);
|
|
}
|
|
}
|
|
Appwww(&wsock, wbuf, "</TD><TD WIDTH=50>", 19ul);
|
|
Appwww(&wsock, wbuf, anonym2->vers, 21ul);
|
|
Appwww(&wsock, wbuf, "</TD><TD WIDTH=50>", 19ul);
|
|
if (anonym2->service=='S') {
|
|
FiltToStr(anonym2->filters, h1, 256ul);
|
|
}
|
|
else aprsstr_Assign(h1, 256ul, anonym2->outfilterst, 256ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "</TD>", 6ul);
|
|
wcard64(wbuf, &wsock, anonym2->txbytesh, anonym2->txbytes);
|
|
if (anonym2->losttxframes>0UL) {
|
|
wintint(wbuf, &wsock, (int32_t)anonym2->txframes,
|
|
-(int32_t)anonym2->losttxframes);
|
|
}
|
|
else wint(wbuf, &wsock, (int32_t)anonym2->txframes);
|
|
wint(wbuf, &wsock, (int32_t)bitsec64(anonym2->txbytesh,
|
|
anonym2->txbytes, tt));
|
|
wcard64(wbuf, &wsock, anonym2->rxbytesh, anonym2->rxbytes);
|
|
if (anonym2->lostrxframes>0UL) {
|
|
wintint(wbuf, &wsock, (int32_t)anonym2->rxframes,
|
|
-(int32_t)anonym2->lostrxframes);
|
|
}
|
|
else wint(wbuf, &wsock, (int32_t)anonym2->rxframes);
|
|
wint(wbuf, &wsock, (int32_t)bitsec64(anonym2->rxbytesh,
|
|
anonym2->rxbytes, tt));
|
|
Appwww(&wsock, wbuf, "<TD>", 5ul);
|
|
if (anonym2->connt>0UL) {
|
|
aprsstr_TimeToStr(tt, h1, 256ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
}
|
|
Appwww(&wsock, wbuf, "</TD></TR>", 11ul);
|
|
}
|
|
ss = anonym2->next;
|
|
}
|
|
}
|
|
Appwww(&wsock, wbuf, "</TABLE></BODY></HTML>\015\012", 25ul);
|
|
}
|
|
else if (aprsstr_StrCmp(wsock->get, 256ul, "mh", 3ul)) {
|
|
conthead(&wsock, wbuf);
|
|
title(wbuf, &wsock, &mhhttpcount);
|
|
klicks(wbuf, &wsock);
|
|
if (heardtimew>0UL) {
|
|
showmh(wbuf, &wsock, h1, hearddir, 1, 0, heardtimew, "Heard Stations\
|
|
Since Last ", 27ul, wsock->sortby, 2ul);
|
|
}
|
|
if (heardtimevia>0UL) {
|
|
showmh(wbuf, &wsock, h1, heardvia, 0, 0, heardtimevia, "Via RF Heard\
|
|
Stations Since Last ", 34ul, wsock->sortby, 2ul);
|
|
}
|
|
if (heardtimetcp>0UL) {
|
|
showmh(wbuf, &wsock, h1, heardtcp, 0, 1, heardtimetcp, "Via TCP Conn\
|
|
ected Stations Since Last ", 39ul, wsock->sortby, 2ul);
|
|
}
|
|
}
|
|
else if (aprsstr_StrCmp(wsock->get, 256ul, "msg", 4ul)) {
|
|
conthead(&wsock, wbuf);
|
|
title(wbuf, &wsock, &msghttpcount);
|
|
klicks(wbuf, &wsock);
|
|
for (tp = udpgate4_DIR; tp>=udpgate4_NET; tp--) {
|
|
Appwww(&wsock, wbuf, "<table id=msg border=0 align=center CELLPADDIN\
|
|
G=3 CELLSPACING=1 BGCOLOR=\"#FFFFFF\">", 83ul);
|
|
if (viacall[0U]==0) {
|
|
if (tp==udpgate4_DIR) {
|
|
strncpy(h1,"Heard Messages (tx off)",256u);
|
|
}
|
|
else if (tp==udpgate4_INDIR) {
|
|
strncpy(h1,"Via Digi Heard Messages (tx off)",256u);
|
|
}
|
|
else strncpy(h1,"Via Net Heard Messages (tx off)",256u);
|
|
}
|
|
else if (tp==udpgate4_DIR) {
|
|
strncpy(h1,"Heard Messages (Relayed to direct heard and Net)",
|
|
256u);
|
|
}
|
|
else if (tp==udpgate4_INDIR) {
|
|
strncpy(h1,"Via Digi Heard Messages (Relayed to direct heard)",
|
|
256u);
|
|
}
|
|
else {
|
|
strncpy(h1,"Via Net Heard Messages (Relayed to direct heard)",
|
|
256u);
|
|
}
|
|
Appwww(&wsock, wbuf, "<tr class=tab-msg-titel BGCOLOR=\"#A9EEFF\"><t\
|
|
h colspan=13>", 58ul);
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
Appwww(&wsock, wbuf, "</th></tr>", 11ul);
|
|
hok = 0;
|
|
mp = messages;
|
|
while (mp) {
|
|
if (mp->src==tp) {
|
|
if (!hok) {
|
|
Appwww(&wsock, wbuf, "<tr class=tab-msg-head BGCOLOR=\"#F0A\
|
|
070\"><th>From</th><th>To</th><th>hms ago</th><th>hms tx</th><th>po</th><th>r\
|
|
etr</th><th>m>r</th><th>m>n</th><th>a>r</th><th>a>n</th><th>A</th><th>Ack</th\
|
|
><th>Text</th></tr>", 209ul);
|
|
hok = 1;
|
|
}
|
|
Appwww(&wsock, wbuf, "<tr class=tab-msg-body BGCOLOR=\"#DDCC88\\
|
|
">", 42ul);
|
|
AppCall(wbuf, &wsock, mp->from, 10ul, 0, 0, "", 1ul);
|
|
AppCall(wbuf, &wsock, mp->to, 10ul, 0, 0, "", 1ul);
|
|
AppTime(wbuf, &wsock, mp->gentime, 1);
|
|
if (mp->retryc>0UL && mp->txtime>0UL) {
|
|
AppTime(wbuf, &wsock, mp->txtime, 1);
|
|
}
|
|
else if (!mp->acked && mp->gentime+msgsendtime<=systime) {
|
|
Appwww(&wsock, wbuf, "<td>timed out</td>", 19ul);
|
|
}
|
|
else Appwww(&wsock, wbuf, "<td></td>", 10ul);
|
|
AppInt(wbuf, &wsock, (int32_t)mp->txport);
|
|
AppInt(wbuf, &wsock, (int32_t)mp->retryc);
|
|
AppInt(wbuf, &wsock, (int32_t)mp->msg2rf);
|
|
AppInt(wbuf, &wsock, (int32_t)mp->msg2net);
|
|
AppInt(wbuf, &wsock, (int32_t)mp->ack2rf);
|
|
AppInt(wbuf, &wsock, (int32_t)mp->ack2net);
|
|
Appwww(&wsock, wbuf, "<td>", 5ul);
|
|
if (mp->acked) {
|
|
if (mp->acksrc==udpgate4_DIR) strncpy(h1,"D",256u);
|
|
else if (mp->acksrc==udpgate4_INDIR) strncpy(h1,"V",256u);
|
|
else if (mp->acksrc==udpgate4_NET) strncpy(h1,"N",256u);
|
|
else strncpy(h1,"X",256u);
|
|
if (mp->reject) aprsstr_Append(h1, 256ul, "R", 2ul);
|
|
if (!mp->ackackt) {
|
|
h1[0U] = (char)((uint32_t)(uint8_t)h1[0U]+32UL);
|
|
}
|
|
Appwww(&wsock, wbuf, h1, 256ul);
|
|
}
|
|
Appwww(&wsock, wbuf, "</td>", 6ul);
|
|
aprsstr_Assign(h1, 256ul, mp->ack, 5ul);
|
|
aprsstr_Append(h1, 256ul, mp->replyack, 2ul);
|
|
AppTxt(wbuf, &wsock, "<td>", 5ul, h1, 256ul);
|
|
AppTxt(wbuf, &wsock, "<td>", 5ul, mp->text, 68ul);
|
|
Appwww(&wsock, wbuf, "</tr>\015\012", 8ul);
|
|
}
|
|
mp = mp->next;
|
|
}
|
|
if (hok) {
|
|
Appwww(&wsock, wbuf, "</table> ", 15ul);
|
|
}
|
|
} /* end for */
|
|
Appwww(&wsock, wbuf, "</BODY></HTML>\015\012", 17ul);
|
|
}
|
|
else if (wwwdir[0U] && openfile(wsock->get, 256ul, &fdw, &flen)) {
|
|
strncpy(wbuf,"HTTP/1.0 200 OK\015\012Content-Length: ",1401u);
|
|
/*
|
|
+'Content-Type: text/html;
|
|
charset=iso-8859-1'+CR+LF+'Content-Length: ';
|
|
*/
|
|
aprsstr_IntToStr(flen, 1UL, h1, 256ul);
|
|
aprsstr_Append(wbuf, 1401ul, h1, 256ul);
|
|
aprsstr_Append(wbuf, 1401ul, "\015\012\015\012", 5ul);
|
|
sendwww(&wsock, wbuf, (int32_t)aprsstr_Length(wbuf, 1401ul), 1);
|
|
while (flen>0L) {
|
|
res0 = osi_RdBin(fdw, (char *)wbuf, 1401u/1u, 1401UL);
|
|
if (res0>0L) {
|
|
sendwww(&wsock, wbuf, res0, 0);
|
|
flen -= res0;
|
|
}
|
|
else flen = 0L;
|
|
}
|
|
osic_Close(fdw);
|
|
wbuf[0U] = 0;
|
|
}
|
|
else strncpy(wbuf,"HTTP/1.1 404\015\012",1401u);
|
|
if (wbuf[0U]) {
|
|
sendwww(&wsock, wbuf, (int32_t)aprsstr_Length(wbuf, 1401ul), 0);
|
|
}
|
|
} /* end Www() */
|
|
|
|
|
|
static void Wwwtx(pTCPSOCK * w)
|
|
{
|
|
int32_t i0;
|
|
int32_t len;
|
|
struct TCPSOCK * anonym;
|
|
int32_t tmp;
|
|
{ /* with */
|
|
struct TCPSOCK * anonym = *w;
|
|
if (anonym->txbuf) {
|
|
if (anonym->txbuf->push) {
|
|
len = sendsock(anonym->fd, anonym->txbuf->buf,
|
|
anonym->txbuf->tlen);
|
|
}
|
|
else {
|
|
len = sendmore(anonym->fd, anonym->txbuf->buf,
|
|
anonym->txbuf->tlen);
|
|
}
|
|
if (len>0L) {
|
|
tmp = anonym->txbuf->tlen-1L;
|
|
i0 = len;
|
|
if (i0<=tmp) for (;; i0++) {
|
|
anonym->txbuf->buf[i0-len] = anonym->txbuf->buf[i0];
|
|
/* delete the sent */
|
|
if (i0==tmp) break;
|
|
} /* end for */
|
|
anonym->txbuf->tlen -= len;
|
|
if (anonym->connt==0UL) anonym->connt = systime;
|
|
}
|
|
else anonym->txbuf->tlen = 0L;
|
|
if (anonym->txbuf->tlen<=0L) closetcp(w, 0);
|
|
}
|
|
}
|
|
} /* end Wwwtx() */
|
|
|
|
|
|
static void saybusy(int32_t * fd, char s[], uint32_t s_len)
|
|
{
|
|
int32_t res0;
|
|
X2C_PCOPY((void **)&s,s_len);
|
|
if (*fd>=0L) {
|
|
res0 = sendsock(*fd, s, (int32_t)aprsstr_Length(s, s_len));
|
|
osic_Close(*fd);
|
|
*fd = -1L;
|
|
}
|
|
X2C_PFREE(s);
|
|
} /* end saybusy() */
|
|
|
|
|
|
static void KillDoubleUser(pTCPSOCK u)
|
|
{
|
|
pTCPSOCK v;
|
|
v = u->next;
|
|
while (v) {
|
|
if ((v->service=='S' && v->user.call[0U])
|
|
&& aprsstr_StrCmp(u->user.call, 10ul, v->user.call, 10ul)) {
|
|
if (v->valid && !u->valid) {
|
|
saybusy(&u->fd, "# unvalidated double login\015\012", 29ul);
|
|
}
|
|
else {
|
|
saybusy(&v->fd, "# double login\015\012", 17ul);
|
|
/* kill older or the unvalid */
|
|
}
|
|
}
|
|
v = v->next;
|
|
}
|
|
} /* end KillDoubleUser() */
|
|
|
|
|
|
static char tcpconn(pTCPSOCK * sockchain, int32_t f,
|
|
char cservice)
|
|
{
|
|
pTCPSOCK cp;
|
|
FRAMEBUF h2;
|
|
FRAMEBUF h1;
|
|
FRAMEBUF h;
|
|
int32_t res0;
|
|
struct TCPSOCK * anonym;
|
|
if (f<0L) return 0;
|
|
osic_alloc((char * *) &cp, sizeof(struct TCPSOCK));
|
|
if (cp==0) {
|
|
osic_Close(f);
|
|
if (verb) osi_WrStrLn("tcp conn out of memory", 23ul);
|
|
return 0;
|
|
}
|
|
memset((char *)cp,(char)0,sizeof(struct TCPSOCK));
|
|
{ /* with */
|
|
struct TCPSOCK * anonym = cp;
|
|
anonym->fd = f;
|
|
anonym->valid = cservice=='G';
|
|
anonym->service = cservice;
|
|
res0 = socknonblock(f);
|
|
anonym->txbuf = 0;
|
|
}
|
|
cp->next = *sockchain;
|
|
*sockchain = cp;
|
|
if (cservice=='G') {
|
|
if (servercall[0U]) {
|
|
aprsstr_Assign(h, 512ul, "user ", 6ul);
|
|
aprsstr_Append(h, 512ul, servercall, 10ul);
|
|
if (passwd[0U]) {
|
|
aprsstr_Append(h, 512ul, " pass ", 7ul);
|
|
aprsstr_Append(h, 512ul, passwd, 6ul);
|
|
}
|
|
aprsstr_Append(h, 512ul, " vers ", 7ul);
|
|
aprsstr_Append(h, 512ul, "udpgate(c) 0.63", 16ul);
|
|
if (actfilter[0U]) {
|
|
aprsstr_Append(h, 512ul, " filter ", 9ul);
|
|
aprsstr_Append(h, 512ul, actfilter, 256ul);
|
|
}
|
|
aprsstr_Append(h, 512ul, "\015\012", 3ul);
|
|
Sendtcp(cp, h);
|
|
}
|
|
}
|
|
else if (cservice=='S') {
|
|
/*
|
|
cp^.txbytes:=4294967200;
|
|
cp^.txbytesh:=0;
|
|
cp^.rxbytes:=4294965296;
|
|
cp^.rxbytesh:=0;
|
|
*/
|
|
res0 = 512L;
|
|
res0 = getpeeripnum(f, h1, &res0);
|
|
if (res0>=0L) {
|
|
/*
|
|
tcp.ipnum2str(h1, h, SIZE(h));
|
|
*/
|
|
ipnumport2str(h1, 512UL, h, 512UL, h2, 512UL);
|
|
aprsstr_Assign(cp->ipnum, 64ul, h, 512ul);
|
|
aprsstr_Assign(cp->port, 6ul, h2, 512ul);
|
|
strncpy(h1,"T:connect to: ",512u);
|
|
aprsstr_Append(h1, 512ul, h, 512ul);
|
|
aprsstr_Append(h1, 512ul, " ", 2ul);
|
|
aprsstr_Append(h1, 512ul, h2, 512ul);
|
|
logline(1L, h1, 512ul);
|
|
}
|
|
aprsstr_Assign(h, 512ul, "# udpgate(c) 0.63\015\012", 20ul);
|
|
Sendtcp(cp, h);
|
|
}
|
|
return 1;
|
|
} /* end tcpconn() */
|
|
|
|
|
|
static void Gateconn(pTCPSOCK * cp)
|
|
{
|
|
int32_t fd;
|
|
pTCPSOCK kill;
|
|
pTCPSOCK try0;
|
|
pTCPSOCK act;
|
|
pTCPSOCK p;
|
|
FRAMEBUF h;
|
|
char hh[21];
|
|
uint32_t max0;
|
|
struct _1 * anonym;
|
|
act = 0;
|
|
try0 = 0;
|
|
p = *cp;
|
|
while (p) {
|
|
if (p->service=='G') {
|
|
if (p->connt>0UL) {
|
|
/* we have gate connect */
|
|
if (act) {
|
|
/* we have 2 connects */
|
|
if (act->gatepri>p->gatepri) {
|
|
/* stop second best */
|
|
kill = act;
|
|
act = p;
|
|
}
|
|
else kill = p;
|
|
saybusy(&kill->fd, "# remove double connect\015\012", 26ul);
|
|
}
|
|
else act = p;
|
|
}
|
|
else try0 = p;
|
|
}
|
|
p = p->next;
|
|
}
|
|
if (try0==0) {
|
|
if (gatesfn[0U]) readurlsfile(gatesfn, 1024ul);
|
|
if (act==0) max0 = 20UL;
|
|
else max0 = act->gatepri;
|
|
if ((trygate>=max0 || trygate>20UL) || gateways[trygate].url[0U]==0) {
|
|
trygate = 0UL; /* loop thru table */
|
|
}
|
|
if (lastdnstime>systime) lastdnstime = systime;
|
|
if ((trygate<max0 && Watchclock(&gateways[trygate].connecttime,
|
|
gateconndelay)) && lastdnstime+gateways[trygate].resolvtime*5UL<=systime)
|
|
{
|
|
{ /* with */
|
|
struct _1 * anonym = &gateways[trygate];
|
|
if (anonym->url[0U]) {
|
|
/*check dns time */
|
|
spintime();
|
|
lastdnstime = systime;
|
|
/*WrStrLn("start resolve"); */
|
|
fd = connectto(anonym->url, anonym->port);
|
|
spintime();
|
|
anonym->resolvtime = systime-lastdnstime;
|
|
if (anonym->resolvtime>5UL) {
|
|
strncpy(h,"T:slow DNS ",512u);
|
|
aprsstr_IntToStr((int32_t)anonym->resolvtime, 1UL, hh,
|
|
21ul);
|
|
aprsstr_Append(h, 512ul, hh, 21ul);
|
|
aprsstr_Append(h, 512ul, "s", 2ul);
|
|
logline(1L, h, 512ul);
|
|
if (anonym->resolvtime>300UL) anonym->resolvtime = 120UL;
|
|
}
|
|
/*check dns time */
|
|
if (fd>=0L) {
|
|
if (anonym->filterst[0U]) {
|
|
aprsstr_Assign(actfilter, 256ul, anonym->filterst,
|
|
256ul);
|
|
}
|
|
else {
|
|
aprsstr_Assign(actfilter, 256ul, serverrangefilter,
|
|
256ul);
|
|
}
|
|
if (tcpconn(cp, fd, 'G')) {
|
|
aprsstr_Assign((*cp)->ipnum, 64ul, anonym->url, 256ul);
|
|
aprsstr_Assign((*cp)->port, 6ul, anonym->port, 6ul);
|
|
aprsstr_Assign((*cp)->outfilterst, 256ul,
|
|
anonym->filterst, 256ul);
|
|
(*cp)->gatepri = trygate;
|
|
strncpy(h,"T:connect to: ",512u);
|
|
aprsstr_Append(h, 512ul, anonym->url, 256ul);
|
|
aprsstr_Append(h, 512ul, " ", 2ul);
|
|
aprsstr_Append(h, 512ul, anonym->port, 6ul);
|
|
logline(1L, h, 512ul);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
++trygate;
|
|
}
|
|
} /* end Gateconn() */
|
|
|
|
|
|
static void WatchTXQ(pTCPSOCK sock)
|
|
{
|
|
int32_t sent;
|
|
int32_t j;
|
|
int32_t i0;
|
|
int32_t rb;
|
|
int32_t acked;
|
|
int32_t qb;
|
|
char rest;
|
|
int32_t tmp;
|
|
qb = getunack(sock->fd); /* tcp unack sendqueue in byte */
|
|
sent = (int32_t)(sock->txbytes-sock->qwatch.lasttb);
|
|
/* last second sent bytes */
|
|
if (qb<=0L || sent<0L) sock->qwatch.qsize = 0L;
|
|
else {
|
|
/* we have unack bytes */
|
|
acked = (sock->qwatch.lastqb-qb)+sent; /* acked bytes in last s */
|
|
j = 0L;
|
|
rest = 0;
|
|
tmp = sock->qwatch.qsize-1L;
|
|
i0 = 0L;
|
|
if (i0<=tmp) for (;; i0++) {
|
|
rb = sock->qwatch.txbyte[i0]-acked;
|
|
sock->qwatch.txbyte[j] = rb;
|
|
if (rb>0L) rest = 1;
|
|
else acked = -rb;
|
|
if (rest) {
|
|
acked = 0L;
|
|
++j;
|
|
}
|
|
if (i0==tmp) break;
|
|
} /* end for */
|
|
sock->qwatch.qsize = j;
|
|
if (sock->qwatch.qsize<=59L) {
|
|
sock->qwatch.txbyte[sock->qwatch.qsize] = sent;
|
|
++sock->qwatch.qsize;
|
|
if (sock->qwatch.qsize>qmaxtime) {
|
|
stoptxrx(sock->fd, 2L); /* delete unsent data */
|
|
saybusy(&sock->fd, "\015\012", 3ul); /* close tcp immediately */
|
|
sock->slowlink = 1; /* for log message */
|
|
}
|
|
}
|
|
}
|
|
sock->qwatch.lastqb = qb;
|
|
sock->qwatch.lasttb = sock->txbytes;
|
|
} /* end WatchTXQ() */
|
|
|
|
static int32_t listensock;
|
|
|
|
static int32_t wwwsock;
|
|
|
|
static FRAMEBUF mbuf;
|
|
|
|
static int32_t res;
|
|
|
|
static int32_t i;
|
|
|
|
static pTCPSOCK acttcp;
|
|
|
|
static pTCPSOCK acttmp;
|
|
|
|
static pUDPSOCK actudp;
|
|
|
|
static uint32_t usercnt;
|
|
|
|
static uint32_t lenh;
|
|
|
|
static struct POSCALL poscall;
|
|
|
|
static char voidungate;
|
|
|
|
static char rfhered;
|
|
|
|
static uint32_t keepconn;
|
|
|
|
static uint32_t lasttime;
|
|
|
|
|
|
static void addsock(int32_t fd, char wtoo)
|
|
/* insert socket in fdset for select */
|
|
{
|
|
if (fd>=0L) {
|
|
fdsetr((uint32_t)fd);
|
|
if (wtoo) fdsetw((uint32_t)fd);
|
|
}
|
|
} /* end addsock() */
|
|
|
|
static CHSET _cnst1 = {0x30000000UL,0x20008092UL,0x80000001UL,0x00000001UL};
|
|
|
|
X2C_STACK_LIMIT(100000l)
|
|
extern int main(int argc, char **argv)
|
|
{
|
|
X2C_BEGIN(&argc,argv,1,4000000l,8000000l);
|
|
if (sizeof(MONCALL)!=10) X2C_ASSERT(0);
|
|
if (sizeof(FILENAME)!=1024) X2C_ASSERT(0);
|
|
if (sizeof(FRAMEBUF)!=512) X2C_ASSERT(0);
|
|
if (sizeof(FILTERST)!=256) X2C_ASSERT(0);
|
|
if (sizeof(WWWB)!=1401) X2C_ASSERT(0);
|
|
if (sizeof(MSGTEXT)!=68) X2C_ASSERT(0);
|
|
if (sizeof(ACKTEXT)!=5) X2C_ASSERT(0);
|
|
if (sizeof(REPLYACK)!=2) X2C_ASSERT(0);
|
|
aprsstr_BEGIN();
|
|
aprspos_BEGIN();
|
|
osi_BEGIN();
|
|
strncpy(rfdestcall,"RFONLY",10u);
|
|
strncpy(netdestcall,"NOGATE",10u);
|
|
viacall[0U] = 0;
|
|
nettorfpath[0U] = 0;
|
|
heardtime = 7200UL;
|
|
heardtimew = 86400UL;
|
|
heardtimevia = 1800UL;
|
|
heardtimetcp = 86400UL;
|
|
purgemsg = 86400UL;
|
|
purgeacked = 86400UL;
|
|
purgeunack = 3600UL;
|
|
purgeunacksent = 30UL;
|
|
gateconndelay = 30UL;
|
|
msgsendtime = 21600UL;
|
|
rfquiet = 10UL;
|
|
maxatonce = 2UL;
|
|
maxmsg = 1000UL;
|
|
messages = 0;
|
|
hearddir = 0;
|
|
heardvia = 0;
|
|
heardtcp = 0;
|
|
lastrfsent = 0UL;
|
|
sendnetmsg = 1;
|
|
mhfilelines = 0UL;
|
|
memset((char *)gateways,(char)0,sizeof(struct _1 [21]));
|
|
realtime = 0UL;
|
|
systime = 946728000UL; /* start of systime about 1.1.2000 */
|
|
qmaxtime = 15L;
|
|
ungates[udpgate4_gUNGATE][0] = 0;
|
|
strncpy(ungates[udpgate4_gRFONLY],"RFONLY",11u);
|
|
strncpy(ungates[udpgate4_gNOGATE],"NOGATE",11u);
|
|
strncpy(ungates[udpgate4_gTCPIP],"TCPIP",11u);
|
|
strncpy(ungates[udpgate4_gTCPXX],"TCPXX",11u);
|
|
strncpy(ungates[udpgate4_gQ],"q",11u);
|
|
dupetime = 60UL;
|
|
lastdnstime = 0UL;
|
|
netbeaconfn[0U] = 0;
|
|
maxusers = 50UL;
|
|
logframename[0U] = 0;
|
|
rawlogname[0U] = 0;
|
|
logframes = 6L;
|
|
tcpbindport[0U] = 0;
|
|
servercall[0U] = 0;
|
|
passwd[0U] = 0;
|
|
serverrangefilter[0U] = 0;
|
|
actfilter[0U] = 0;
|
|
rfhered = 0;
|
|
wwwbindport[0] = 0;
|
|
wwwdir[0U] = 0;
|
|
wwwsizelimit = 1048576L;
|
|
udpsocks = 0;
|
|
callsrc = 0;
|
|
mhperport = 0;
|
|
qas = 0UL;
|
|
qasc = 0UL;
|
|
maxpongtime = 30UL;
|
|
gatesfn[0U] = 0;
|
|
parms();
|
|
if (aprsstr_StrCmp(viacall, 10ul, "-", 2ul)) viacall[0U] = 0;
|
|
else if (viacall[0U]==0) memcpy(viacall,servercall,10u);
|
|
msghttpcount = 0UL;
|
|
mhhttpcount = 0UL;
|
|
netmhout = 0UL;
|
|
netmhin = 0UL;
|
|
aprsstr_Assign(ungates[udpgate4_gUNGATE], 11ul, servercall, 10ul);
|
|
uptime = systime;
|
|
udpdonetime = systime;
|
|
keepconn = 0UL;
|
|
trygate = 0UL;
|
|
httpcount = 0UL;
|
|
Netbeacon(mbuf, 512ul, 0, 1);
|
|
listensock = -1L;
|
|
wwwsock = -1L;
|
|
tcpsocks = 0;
|
|
for (;;) {
|
|
spintime();
|
|
if (systime!=lasttime) {
|
|
if (listensock<0L && tcpbindport[0U]) {
|
|
/* open listensocket tcp connects */
|
|
listensock = waitconnect(tcpbindport, 4UL);
|
|
if (verb && listensock<0L) {
|
|
osi_WrStr("cant bind to port ", 19ul);
|
|
osi_WrStrLn(tcpbindport, 6ul);
|
|
}
|
|
}
|
|
if (wwwsock<0L && wwwbindport[0U]) {
|
|
/* open listensocket www connects */
|
|
wwwsock = waitconnect(wwwbindport, 16UL);
|
|
if (verb && wwwsock<0L) {
|
|
osi_WrStr("cant bind to port ", 19ul);
|
|
osi_WrStrLn(wwwbindport, 6ul);
|
|
}
|
|
}
|
|
}
|
|
fdclr();
|
|
actudp = udpsocks;
|
|
while (actudp) {
|
|
addsock(actudp->fd, 0);
|
|
actudp = actudp->next;
|
|
}
|
|
addsock(listensock, 0);
|
|
addsock(wwwsock, 0);
|
|
if (systime!=lasttime) {
|
|
/* once a second is enough */
|
|
RfTimer();
|
|
SendNet();
|
|
if (mhfilelines>0UL) MHtoFile();
|
|
rfhered = keeptime==0UL || keepconn>systime;
|
|
acttcp = tcpsocks;
|
|
while (acttcp) {
|
|
{ /* with */
|
|
struct TCPSOCK * anonym = acttcp;
|
|
if (anonym->beacont<systime) Timebeacon(acttcp);
|
|
if (anonym->service=='G') {
|
|
if (keeptime>0UL && keepconn<=systime) {
|
|
saybusy(&anonym->fd, "# timeout\015\012", 12ul);
|
|
}
|
|
else if (qmaxtime>0L) WatchTXQ(acttcp);
|
|
}
|
|
else if (anonym->service=='W') {
|
|
if (anonym->connt==0UL) anonym->connt = systime;
|
|
else if (anonym->connt+60UL<systime) {
|
|
saybusy(&anonym->fd, "timeout\015\012", 10ul);
|
|
}
|
|
}
|
|
else if (anonym->service=='S') {
|
|
KillDoubleUser(acttcp);
|
|
keepconn = systime+keeptime; /* connect to gateway */
|
|
}
|
|
acttcp = anonym->next;
|
|
}
|
|
}
|
|
}
|
|
if (systime!=lasttime) {
|
|
if (rfhered) Gateconn(&tcpsocks);
|
|
else trygate = 0UL;
|
|
}
|
|
lasttime = systime;
|
|
usercnt = 0UL;
|
|
acttcp = tcpsocks;
|
|
while (acttcp) {
|
|
addsock(acttcp->fd, acttcp->tlen>0L || acttcp->txbuf);
|
|
++usercnt;
|
|
acttcp = acttcp->next;
|
|
}
|
|
mbuf[0U] = 0;
|
|
res = selectrw(2UL, 0UL);
|
|
if (listensock>=0L && issetr((uint32_t)listensock)) {
|
|
res = 512L;
|
|
res = acceptconnect(listensock, mbuf, &res);
|
|
if (res>=0L) {
|
|
if (usercnt>=maxusers || !tcpconn(&tcpsocks, res, 'S')) {
|
|
saybusy(&res, "# server full\015\012", 16ul);
|
|
}
|
|
}
|
|
}
|
|
if (wwwsock>=0L && issetr((uint32_t)wwwsock)) {
|
|
res = 512L;
|
|
res = acceptconnect(wwwsock, mbuf, &res);
|
|
if (res>=0L) {
|
|
if (usercnt>=maxusers+1UL || !tcpconn(&tcpsocks, res, 'W')) {
|
|
saybusy(&res, "server full\015\012", 14ul);
|
|
}
|
|
}
|
|
}
|
|
spintime();
|
|
actudp = udpsocks;
|
|
i = 1L;
|
|
while (actudp) {
|
|
if (issetr((uint32_t)actudp->fd)) {
|
|
while (getudp(actudp, mbuf, actudp->ghosts)) {
|
|
if (systime<udpdonetime+5UL) {
|
|
/* last time all data read is no too long */
|
|
res = AprsIs(mbuf, 512ul, 0x3FU, 0x3FU, "", 1ul,
|
|
(uint32_t)i, 0, &poscall);
|
|
if (res>=0L) {
|
|
Sendall(mbuf, 0L, poscall);
|
|
keepconn = systime+keeptime; /* connect to gateway */
|
|
}
|
|
}
|
|
else {
|
|
/*task was blocked too long */
|
|
if (verb) {
|
|
osi_WrStrLn("AXUDP-frames thrown away - too long program\
|
|
delay", 50ul);
|
|
}
|
|
logline(1L, "Frame discarded - too long program delay",
|
|
41ul);
|
|
}
|
|
if (verb || logframes>1L) {
|
|
showframe(res, 0, actudp, mbuf, 512ul, poscall.pos);
|
|
}
|
|
}
|
|
}
|
|
++i;
|
|
actudp = actudp->next;
|
|
}
|
|
spintime();
|
|
udpdonetime = systime; /* store fresh time of last all read input */
|
|
acttcp = tcpsocks;
|
|
while (acttcp) {
|
|
if (acttcp->fd>=0L && issetw((uint32_t)acttcp->fd)) {
|
|
{ /* with */
|
|
struct TCPSOCK * anonym0 = acttcp;
|
|
if (anonym0->service=='W') Wwwtx(&acttcp);
|
|
else {
|
|
sendtcpbuf(acttcp);
|
|
if (anonym0->connt==0UL) anonym0->connt = systime;
|
|
}
|
|
}
|
|
}
|
|
if (acttcp->fd>=0L && issetr((uint32_t)acttcp->fd)) {
|
|
if (acttcp->service=='W') Www(acttcp);
|
|
else {
|
|
for (;;) {
|
|
res = Gettcp(acttcp->fd, mbuf, acttcp->rbuf,
|
|
&acttcp->rpos);
|
|
if (res<0L) {
|
|
osic_Close(acttcp->fd);
|
|
acttcp->fd = -1L;
|
|
break;
|
|
}
|
|
if (res<=0L) break;
|
|
++acttcp->rxframes;
|
|
lenh = aprsstr_Length(mbuf, 512ul);
|
|
acttcp->rxbytes += lenh;
|
|
if (acttcp->rxbytes<lenh) ++acttcp->rxbytesh;
|
|
if (acttcp->pongtime>0UL && acttcp->service=='S') {
|
|
/* pingpong active */
|
|
if (acttcp->pongtime<systime) {
|
|
/* pinpong enabled - stop transfer */
|
|
saypongout(acttcp);
|
|
acttcp->pingout = 1;
|
|
++acttcp->lostrxframes;
|
|
}
|
|
}
|
|
if ((acttcp->valid || acttcp->service=='G') || !Auth(mbuf,
|
|
512ul, acttcp)) {
|
|
if (mbuf[0U]=='#') {
|
|
GetFilters(&acttcp->filters, mbuf, 512ul, 1UL,
|
|
acttcp);
|
|
res = -7L;
|
|
}
|
|
else {
|
|
res = AprsIs(mbuf, 512ul, 0x3U, 0x17U,
|
|
acttcp->user.call, 10ul, 0UL, acttcp->valid, &poscall);
|
|
}
|
|
if (((res>=-1L && aprspos_posvalid(poscall.pos))
|
|
&& aprsstr_StrCmp(poscall.call, 10ul, acttcp->user.call,
|
|
10ul)) && X2C_INL((int32_t)(uint8_t)poscall.typ0,128,
|
|
_cnst1)) {
|
|
acttcp->user.pos = poscall.pos;
|
|
if (heardtimetcp>0UL) {
|
|
AddHeard(&heardtcp, heardtimetcp, poscall.call,
|
|
0UL, mbuf, 512ul, &voidungate, 0);
|
|
/* store pos in mh to remember pos at next connect */
|
|
}
|
|
}
|
|
if (acttcp->valid && !acttcp->pingout) {
|
|
if (res>=0L) Sendall(mbuf, acttcp->fd, poscall);
|
|
if (verb || logframes>1L) {
|
|
showframe(res, acttcp, 0, mbuf, 512ul,
|
|
poscall.pos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (acttcp->fd<0L) {
|
|
/* connection lost */
|
|
if (acttcp->connt && acttcp->service!='W') showlogout(acttcp);
|
|
closetcp(&acttcp, 1); /* free www buffers */
|
|
if (acttcp==tcpsocks) tcpsocks = tcpsocks->next;
|
|
else {
|
|
acttmp = tcpsocks;
|
|
while (acttmp->next!=acttcp) acttmp = acttmp->next;
|
|
acttmp->next = acttcp->next;
|
|
}
|
|
osic_free((char * *) &acttcp, sizeof(struct TCPSOCK));
|
|
acttcp = tcpsocks;
|
|
}
|
|
else acttcp = acttcp->next;
|
|
}
|
|
}
|
|
X2C_EXIT();
|
|
return 0;
|
|
}
|
|
|
|
X2C_MAIN_DEFINITION
|