spdxl/src/aprsdecode.c

6926 wiersze
206 KiB
C

/*
* dxlAPRS toolchain
*
* Copyright (C) Christian Rabler <oe5dxl@oevsv.at>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#define X2C_int32
#define X2C_index32
#ifndef aprsdecode_H_
#include "aprsdecode.h"
#endif
#define aprsdecode_C_
#ifndef aprspos_H_
#include "aprspos.h"
#endif
#ifndef xosi_H_
#include "xosi.h"
#endif
#ifndef osi_H_
#include "osi.h"
#endif
#include <osic.h>
#ifndef tcp_H_
#include "tcp.h"
#endif
#ifndef udp_H_
#include "udp.h"
#endif
#ifndef aprsstr_H_
#include "aprsstr.h"
#endif
#ifndef useri_H_
#include "useri.h"
#endif
#ifndef aprstext_H_
#include "aprstext.h"
#endif
aprsdecode_SET256 aprsdecode_SYMTABLE = {0x00000000UL,0x03FF8000UL,
0x17FFFFFEUL,0x07FFFFFEUL,0x00000000UL,0x00000000UL,
0x00000000UL,0x00000000UL};
uint32_t aprsdecode_systime;
uint32_t aprsdecode_realtime;
uint32_t aprsdecode_lastlooped;
uint32_t aprsdecode_rxidle;
char aprsdecode_quit;
char aprsdecode_verb;
struct aprsdecode__D0 aprsdecode_click;
struct aprspos_POSITION aprsdecode_mappos;
int32_t aprsdecode_inittilex;
int32_t aprsdecode_inittiley;
int32_t aprsdecode_initxsize;
int32_t aprsdecode_initysize;
int32_t aprsdecode_parmzoom;
int32_t aprsdecode_initzoom;
float aprsdecode_finezoom;
float aprsdecode_parmfinezoom;
char aprsdecode_mapdir[1025];
aprsdecode_pMOUNTAIN aprsdecode_mountains;
struct aprsdecode__D1 aprsdecode_lums;
struct aprsdecode__D2 aprsdecode_tracenew;
aprsdecode_pTXMESSAGE aprsdecode_txmessages;
aprsdecode_pMSGFIFO aprsdecode_msgfifo0;
float aprsdecode_spikesens;
float aprsdecode_maxhop;
aprsdecode_pOPHIST aprsdecode_ophist2;
aprsdecode_pOPHIST aprsdecode_ophist0;
struct aprsdecode__D3 aprsdecode_gateways[10];
aprsdecode_pTCPSOCK aprsdecode_tcpsocks;
struct aprsdecode_UDPSOCK aprsdecode_udpsocks0[4];
uint32_t aprsdecode_lasttcptx;
uint32_t aprsdecode_lastanyudprx;
uint32_t aprsdecode_lastpurge;
uint32_t aprsdecode_lasttcprx;
aprsdecode_FRAMEBUF aprsdecode_testbeaconbuf;
struct xosi_PROCESSHANDLE aprsdecode_serialpid;
struct xosi_PROCESSHANDLE aprsdecode_serialpid2;
struct xosi_PROCESSHANDLE aprsdecode_maploadpid;
/* connect to aprs-is gateway and decode data for archive and map by OE5DXL */
/*FROM Storage IMPORT ALLOCATE, DEALLOCATE; */
/*FROM TimeConv IMPORT time; */
#define aprsdecode_CALLLEN 7
#define aprsdecode_HASHSIZE 65536
#define aprsdecode_GATECONNDELAY 30
#define aprsdecode_WATCH 180
#define aprsdecode_QMAXTIME 15
#define aprsdecode_MIDMOD 62
#define aprsdecode_HOLDT 0x0FFFFFFFF
#define aprsdecode_BEEPINVERVALL 5
/* min time between beeps */
#define aprsdecode_TICKEROFFTIME 60
/* switch off window headline ticker after no data*/
#define aprsdecode_cUSERMESSAGE ":"
#define aprsdecode_cTHIRDPARTY "}"
#define aprsdecode_DUPHASHSIZE 65536
#define aprsdecode_PINGTIMEOUT 10
/* ping-pong ping timeout */
#define aprsdecode_PINGINTERVALL 20
/* ping-pong ping intervall */
#define aprsdecode_DIRIN ">"
#define aprsdecode_DIROUT "<"
#define aprsdecode_DIRHAVIT "-"
#define aprsdecode_DIRJUNC "#"
#define aprsdecode_cMSGACK "{"
typedef uint32_t CHSET[4];
struct BEACON {
uint32_t bintervall;
aprsdecode_FILENAME bfile;
uint32_t btime;
};
typedef char TICKERCALL[31];
struct UDPSET;
struct UDPSET {
int32_t txd;
int32_t level;
int32_t quali;
};
static char sentemptymsg;
static uint32_t uptime;
static aprsdecode_FILENAME logframename;
/* netbeaconintervall, */
static uint32_t beaconrandomstart;
static uint32_t nextbeep;
static uint32_t rfbecondone;
static uint32_t lastmsgtx;
static uint32_t qwatchtime;
static uint32_t connecttime;
static uint32_t cycleservers;
static uint32_t qas;
static uint32_t qasc;
static int32_t logframes;
/* passwd : ARRAY[0..5] OF CHAR; */
static uint32_t trygate;
/* actudp : pUDPSOCK; */
static aprsdecode_MONCALL ungate[7];
static uint32_t timehash[65536];
static uint32_t rfbeacont;
static uint32_t dupetime;
static uint32_t msgmid;
static TICKERCALL frameticker[20];
/* calls in ticker headline */
static uint32_t tickertime;
static float maxspeed;
static uint16_t crctable12[256];
static void Err(const char text[], uint32_t text_len)
{
osi_WrStr("aprsmap: ", 10ul);
osi_WrStr(text, text_len);
osi_WrStrLn(" error abort", 13ul);
X2C_ABORT();
} /* end Err() */
extern uint32_t aprsdecode_trunc(float r)
{
if (r<=0.0f) return 0UL;
else if (r>=2.E+9f) return 2000000000UL;
else return (uint32_t)X2C_TRUNCC(r,0UL,X2C_max_longcard);
return 0;
} /* end trunc() */
extern float aprsdecode_floor(float r)
{
float f;
f = (float)osi_realint(r);
if (f>r) f = f-1.0f;
return f;
} /* end floor() */
static float sqr(float x)
{
return x*x;
} /* end sqr() */
extern void aprsdecode_posinval(struct aprspos_POSITION * pos)
{
pos->long0 = 0.0f;
pos->lat = 0.0f;
} /* end posinval() */
static char Watchclock(uint32_t * t, uint32_t intervall)
{
uint32_t tn;
if (intervall>0UL || *t==0UL) {
/* send once */
tn = aprsdecode_realtime;
if (*t<=tn) {
*t += intervall;
if (*t<=tn) *t = tn+intervall;
return 1;
}
if (*t>tn+intervall) *t = tn+intervall;
}
return 0;
} /* end Watchclock() */
extern void aprsdecode_beeplim(int32_t lev, uint32_t hz, uint32_t ms)
/* beep with minimum quiet time */
{
if (aprsdecode_realtime>=nextbeep) {
xosi_beep(lev, hz, ms);
nextbeep = aprsdecode_realtime+5UL;
}
} /* end beeplim() */
static void filepath(char s[], uint32_t s_len)
/* get path out of path + filename */
{
uint32_t j;
uint32_t i;
i = 0UL;
j = 0UL;
while (i<s_len-1 && s[i]) {
if (s[i]=='/' || s[i]=='/') j = i;
++i;
}
s[j] = 0;
} /* end filepath() */
static void alfanum(char s[], uint32_t s_len)
/* clean received call to filename */
{
uint32_t j;
uint32_t i;
char c;
i = 0UL;
j = 0UL;
while (i<s_len-1 && s[i]) {
c = X2C_CAP(s[i]);
if ((((((((uint8_t)c>='A' && (uint8_t)c<='Z' || (uint8_t)
c>='0' && (uint8_t)c<='9') || c=='-') || c=='+') || c=='_')
|| c=='(') || c==')') || c=='=') {
s[j] = c;
++j;
}
++i;
}
if (j<=s_len-1) s[j] = 0;
} /* end alfanum() */
static int32_t GetNum(char h[], uint32_t h_len, uint32_t * p,
uint32_t * n)
{
char ok0;
int32_t GetNum_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) {
GetNum_ret = -1L;
goto label;
}
GetNum_ret = 0L;
label:;
X2C_PFREE(h);
return GetNum_ret;
} /* end GetNum() */
static void parms(void)
{
char h[4096];
char err;
char lasth;
uint32_t n;
uint32_t i;
uint32_t gatecnt;
int32_t ii;
err = 0;
aprsdecode_verb = 0;
gatecnt = 0UL;
for (;;) {
osi_NextArg(h, 4096ul);
if (h[0U]==0) break;
if ((h[0U]=='-' && h[1U]) && h[2U]==0) {
lasth = h[1U];
if (lasth=='x') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n>=30UL) {
aprsdecode_initxsize = (int32_t)n;
}
else Err("-x xsize", 9ul);
}
else if (lasth=='y') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n>=20UL) {
aprsdecode_initysize = (int32_t)n;
}
else Err("-y xsize", 9ul);
}
else if (lasth=='z') {
osi_NextArg(h, 4096ul);
if (!aprsstr_StrToFix(&aprsdecode_parmfinezoom, h,
4096ul) || aprsdecode_parmfinezoom<=1.0f) {
Err("-z zoomlevel", 13ul);
}
n = aprsdecode_trunc(aprsdecode_parmfinezoom);
aprsdecode_parmfinezoom = (1.0f+aprsdecode_parmfinezoom)
-(float)n;
aprsdecode_parmzoom = (int32_t)n;
}
else if (lasth=='m') {
osi_NextArg(h, 4096ul);
if (!aprsstr_StrToFix(&aprsdecode_mappos.long0, h, 4096ul)) {
Err("-m long lat", 12ul);
}
osi_NextArg(h, 4096ul);
if (!aprsstr_StrToFix(&aprsdecode_mappos.lat, h, 4096ul)) {
Err("-m long lat", 12ul);
}
aprsdecode_mappos.long0 = aprspos_rad0(aprsdecode_mappos.long0);
aprsdecode_mappos.lat = aprspos_rad0(aprsdecode_mappos.lat);
}
else if (lasth=='c') osi_NextArg(aprsdecode_lums.configfn, 257ul);
else if (lasth=='g') {
osi_NextArg(h, 4096ul);
if (gatecnt>9UL) 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;
i = 1UL;
while (i<=4095UL) {
h[i-1UL] = h[i];
++i;
}
}
else ii = aprsstr_InStr(h, 4096ul, ":", 2ul);
if (ii>=0L) h[ii] = 0;
aprsstr_Assign(aprsdecode_gateways[gatecnt].url, 256ul, h,
4096ul);
if (ii>0L) {
/* port number */
++ii;
i = 0UL;
while (ii<=4095L) {
h[i] = h[ii];
++i;
++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(aprsdecode_gateways[gatecnt].port, 6ul, h,
4096ul);
if (ii>0L) {
/* we have a filter string */
++ii;
i = 0UL;
while (ii<=4095L) {
if (h[ii]==',') h[ii] = ' ';
h[i] = h[ii];
++i;
++ii;
}
aprsstr_Assign(aprsdecode_gateways[gatecnt].filterst, 256ul,
h, 4096ul);
}
++gatecnt;
}
else {
if (lasth=='h') {
osi_WrStrLn(" -c <configfilename>", 21ul);
osi_WrStrLn(" -g <url>:<port>#<filters> connect to APRS-IS gat\
eway, repeat -g to other", 74ul);
osi_WrStrLn(" gateways write favorites first fo\
r 1 activ link to the best", 76ul);
osi_WrStrLn(" reachable and a polling link to r\
evert immediately to preferred again", 86ul);
osi_WrStrLn(" -g www.db0anf.de:14580#m/300 -g 1\
27.0.0.1:3000 -g [::1]:3000", 77ul);
osi_WrStrLn(" <filters> text sent to out connec\
ted server -f m/50", 68ul);
osi_WrStrLn(" if blanks dont pass parameter set\
tings use , (-f m/30,-d/CW)", 77ul);
osi_WrStrLn(" ipv6 if enabled by kernel",
42ul);
osi_WrStrLn(" -h this", 21ul);
osi_WrStrLn(" -M <ip>:<dport>/<lport>[+<byte/s>[:<radius>]]",
47ul);
osi_WrStrLn(" udp rf port (monitor frame format\
) for local (t)rx", 67ul);
osi_WrStrLn(" <dport>:<lport> read from any ip,\
dport=0 no tx", 64ul);
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(" repeat -M for each radio port wit\
h a tx", 56ul);
osi_WrStrLn(" -o <outfile> out file, delete after read",
44ul);
osi_WrStrLn(" -R same as -M but axudp format",
44ul);
osi_WrStrLn(" -v show frames and analytics on stdo\
ut", 52ul);
osic_WrLn();
X2C_ABORT();
}
if (lasth=='C') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=100UL) {
aprsdecode_lums.centering = (int32_t)n;
}
else Err("-C center%", 11ul);
}
else if (lasth=='X') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
aprsdecode_lums.sym = (int32_t)n;
}
else Err("-X symbollumen", 15ul);
}
else if (lasth=='O') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
aprsdecode_lums.obj = (int32_t)n;
}
else Err("-O objectlumen", 15ul);
}
else if (lasth=='W') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
aprsdecode_lums.waypoint = (int32_t)n;
}
else Err("-W waypointlumen", 17ul);
}
else if (lasth=='A') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
aprsdecode_lums.text = (int32_t)n;
}
else Err("-A textlumen", 13ul);
}
else if (lasth=='T') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
aprsdecode_lums.track = (int32_t)n;
}
else Err("-T tracklumen", 14ul);
}
else if (lasth=='F') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n>0UL) {
aprsdecode_lums.firstdim = n*60UL;
}
else Err("-F fadetime (min)", 18ul);
}
else if (lasth=='V') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n>0UL) {
aprsdecode_lums.fps = (int32_t)n;
}
else Err("-V fps", 7ul);
}
else if (lasth=='B') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n>0UL) {
aprsdecode_lums.maxdim = n*60UL;
}
else Err("-B blanktime (min)", 19ul);
}
else if (lasth=='P') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n>0UL) {
aprsdecode_lums.purgetime = n*60UL;
}
else Err("-P purgetime (min)", 19ul);
}
else if (lasth=='r') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
aprsdecode_lums.rf = (int32_t)n;
}
else Err("-r rftracklumen", 16ul);
}
else if (lasth=='o') {
osi_NextArg(h, 4096ul);
i = 0UL;
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
aprsdecode_lums.map = (int32_t)n;
}
else Err("-o maplumen", 12ul);
}
else if (lasth=='v') aprsdecode_verb = 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);
}
} /* end parms() */
static void getval(const char s[], uint32_t s_len, uint32_t * i,
int32_t * v)
{
char m;
++*i;
*v = 0L;
m = s[*i]=='-';
if (m) ++*i;
while ((*i<s_len-1 && (uint8_t)s[*i]>='0') && (uint8_t)s[*i]<='9') {
*v = *v*10L+(int32_t)((uint32_t)(uint8_t)s[*i]-48UL);
++*i;
}
while (*i<s_len-1 && (uint8_t)s[*i]>' ') ++*i;
while (*i<s_len-1 && s[*i]==' ') ++*i;
if (m) *v = -*v;
} /* end getval() */
static void decodeudp2(const char ub[], uint32_t ub_len,
struct UDPSET * modeminfo)
{
uint32_t i;
int32_t res;
if (ub[0UL] && ub[1UL]) {
i = 2UL;
while (i<ub_len-1 && ub[i]) {
switch ((unsigned)ub[i]) {
case 'T':
getval(ub, ub_len, &i, &res);
modeminfo->txd = res;
break;
case 'V':
getval(ub, ub_len, &i, &res);
modeminfo->level = res;
break;
case 'Q':
getval(ub, ub_len, &i, &res);
modeminfo->quali = res;
break;
default:;
getval(ub, ub_len, &i, &res);
break;
} /* end switch */
}
}
} /* end decodeudp2() */
static char getudp(uint32_t usock, aprsdecode_FRAMEBUF buf,
struct UDPSET * modeminfo, aprsstr_GHOSTSET ghostset)
{
uint32_t fromport;
uint32_t ipn;
char crc2;
char crc1;
int32_t len;
uint32_t mlen;
aprsdecode_FRAMEBUF mbuf;
char udp2[100];
aprsstr_GHOSTSET tmp;
ghostset = (uint32_t *)memcpy(tmp,ghostset,36u);
if ((int32_t)aprsdecode_udpsocks0[usock].fd<0L) return 0;
len = udpreceive(aprsdecode_udpsocks0[usock].fd, buf, 512L, &fromport,
&ipn);
if ((len>2L && len<512L) && (!aprsdecode_udpsocks0[usock].checkip || aprsdecode_udpsocks0[usock].ip==ipn)
) {
/*WrInt(udpsend(usock^.fd, buf, len, usock^.dport, usock^.ip), 1);
WrStrLn(" us"); */
memset((char *)modeminfo,(char)0,sizeof(struct UDPSET));
buf[len] = 0;
if (aprsdecode_udpsocks0[usock].rawread) {
len -= 2L;
crc1 = buf[len];
crc2 = buf[len+1L];
aprsstr_AppCRC(buf, 512ul, len);
if (crc1!=buf[len] || crc2!=buf[len+1L]) {
if (aprsdecode_verb) osi_WrStrLn(" axudp crc error", 17ul);
buf[0UL] = 0;
}
else {
if (buf[0UL]=='\001') {
aprsstr_extrudp2(buf, 512ul, udp2, 100ul, &len);
decodeudp2(udp2, 100ul, modeminfo);
}
/*WrInt(modeminfo.txd, 5); WrInt(modeminfo.level, 5);
WrInt(modeminfo.quali, 5); WrStrLn(" modem"); */
aprsstr_raw2mon(buf, 512ul, mbuf, 512ul, (uint32_t)len, &mlen,
ghostset);
memcpy(buf,mbuf,512u);
}
}
}
else return 0;
return 1;
} /* end getudp() */
static int32_t Gettcp(int32_t fd, aprsdecode_FRAMEBUF line,
aprsdecode_FRAMEBUF buf, int32_t * pos)
{
int32_t j;
int32_t i;
int32_t len;
int32_t tmp;
i = *pos;
if (i>=512L) i = 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-i);
if (len<0L) return -1L;
if (*pos>=512L) {
/* hunt mode */
i = 0L;
while (i<len && line[i]!='\012') ++i;
if (i>=len) return 0L;
/* no line start found */
*pos = 0L;
++i;
j = 0L;
while (i<len) {
line[j] = line[i];
++j;
++i;
}
len = j;
}
if (*pos>0L) {
for (i = len-1L; i>=0L; i--) {
line[i+*pos] = line[i]; /* move up new */
} /* end for */
tmp = *pos-1L;
i = 0L;
if (i<=tmp) for (;; i++) {
line[i] = buf[i]; /* ins buf before */
if (i==tmp) break;
} /* end for */
len += *pos;
*pos = 0L;
}
i = 0L;
while (i<len && line[i]!='\012') ++i;
if (i>=len) {
/* no line end found */
while (*pos<len) {
buf[*pos] = line[*pos]; /* move to buf */
++*pos;
}
len = 0L;
}
else {
j = i+1L;
while (j<len) {
buf[*pos] = line[j]; /* move rest to buf */
++*pos;
++j;
}
len = i;
}
line[len] = 0;
return len;
} /* end Gettcp() */
static void saybusy(int32_t * fd, char s[], uint32_t s_len)
/* send good by text and close tcp */
{
int32_t res;
X2C_PCOPY((void **)&s,s_len);
if ((int32_t)*fd>=0L) {
res = sendsock(*fd, s, (int32_t)aprsstr_Length(s, s_len));
osic_CloseSock(*fd);
*fd = -1L;
}
X2C_PFREE(s);
} /* end saybusy() */
static void saylinkbad(int32_t s)
{
char hh[101];
char h[101];
strncpy(h,"AprsIs uplink delays ",101u);
aprsstr_IntToStr(s, 1UL, hh, 101ul);
aprsstr_Append(h, 101ul, hh, 101ul);
aprsstr_Append(h, 101ul, "s", 2ul);
useri_textautosize(0L, 5L, 4UL, 10UL, 'r', h, 101ul);
} /* end saylinkbad() */
static void WatchTXQ(aprsdecode_pTCPSOCK sock)
{
int32_t sent;
int32_t j;
int32_t i;
int32_t rb;
int32_t acked;
int32_t qb;
char rest;
int32_t tmp;
qb = getunack(sock->fd); /* tcp unack sendqueue in byte */
if (sock->lastping==0UL && qb==-1L) {
/* windoof */
sock->lastping = 1UL; /* switch on ping-pong mode */
return;
}
/*
configbool(fALLOWGATE, FALSE);
textautosize(0, 5, 6, 5, "r",
"TCP-Stack on this OS not usable for Igate,
gateing switched off");
END;
*/
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;
i = 0L;
if (i<=tmp) for (;; i++) {
rb = sock->qwatch.txbyte[i]-acked;
sock->qwatch.txbyte[j] = rb;
if (rb>0L) rest = 1;
else acked = -rb;
if (rest) {
acked = 0L;
++j;
}
if (i==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>1L) saylinkbad(sock->qwatch.qsize);
if (sock->qwatch.qsize>15L) {
stoptxrx(sock->fd, 2L); /* delete unsent data */
saybusy(&sock->fd, "\015\012", 3ul); /* close tcp immediately */
}
}
}
/* sock^.slowlink:=TRUE;
(* for log message *) */
sock->qwatch.lastqb = qb;
sock->qwatch.lasttb = sock->txbytes;
} /* end WatchTXQ() */
static void tickermon(const char port[], uint32_t port_len,
char dir, uint32_t ot, const char s[],
uint32_t s_len)
{
struct aprsdecode_DAT dat;
TICKERCALL h2;
TICKERCALL h1;
TICKERCALL h;
uint32_t cnt;
uint32_t i;
uint32_t tmp;
cnt = (uint32_t)useri_conf2int(useri_fWRTICKER, 0UL, 0L, 99L, 1L);
if (cnt==0UL && ot==0UL) cnt = 1UL;
if ((ot!=1UL && cnt>0UL) && aprsdecode_Decode(s, s_len, &dat)>=0L) {
h2[0] = 0;
if (cnt==1UL) {
if (ot==0UL) strncpy(h2,"New User: ",31u);
else if (ot<=aprsdecode_realtime) {
strncpy(h2,"since ",31u);
ot = aprsdecode_realtime-ot;
if (ot<180UL) {
aprsstr_IntToStr((int32_t)ot, 3UL, h1, 31ul);
aprsstr_Append(h1, 31ul, "s: ", 4ul);
}
else if (ot<10790UL) {
aprsstr_IntToStr((int32_t)((ot+10UL)/60UL), 3UL, h1, 31ul);
aprsstr_Append(h1, 31ul, "m: ", 4ul);
}
else {
aprsstr_IntToStr((int32_t)((ot+10UL)/3600UL), 3UL, h1,
31ul);
aprsstr_Append(h1, 31ul, "h: ", 4ul);
}
aprsstr_Append(h2, 31ul, h1, 31ul);
}
}
aprsstr_Assign(h1, 31ul, port, port_len);
h1[0U] = X2C_CAP(h1[0U]);
aprsstr_Append(h2, 31ul, h1, 31ul);
aprsstr_Append(h2, 31ul, (char *) &dir, 1u/1u);
aprsstr_Append(h2, 31ul, dat.symcall, 9ul);
if (dat.wx.temp!=1.E+6f) {
aprsstr_FixToStr(aprstext_FtoC(dat.wx.temp), 2UL, h, 31ul);
aprsstr_Append(h2, 31ul, " ", 2ul);
aprsstr_Append(h2, 31ul, h, 31ul);
aprsstr_Append(h2, 31ul, "C", 2ul);
}
else if ((dat.altitude<X2C_max_longint && dat.altitude>=1000L)
&& dat.altitude>=useri_conf2int(useri_fALTMIN, 0UL, -10000L,
65535L, -10000L)) {
aprsstr_Append(h2, 31ul, " ", 2ul);
aprsstr_IntToStr(dat.altitude, 1UL, h, 31ul);
aprsstr_Append(h2, 31ul, h, 31ul);
aprsstr_Append(h2, 31ul, "m", 2ul);
}
else if (dat.speed>0UL && dat.speed<2147483647UL) {
useri_confstr(useri_fKMH, h1, 31ul);
if (h1[0U]) {
aprsstr_IntToStr((int32_t)aprsdecode_trunc((float)
dat.speed*1.852f), 1UL, h, 31ul);
aprsstr_Append(h2, 31ul, " ", 2ul);
aprsstr_Append(h2, 31ul, h, 31ul);
aprsstr_Append(h2, 31ul, h1, 31ul);
}
}
for (i = 19UL; i>=1UL; i--) {
memcpy(frameticker[i],frameticker[i-1UL],31u);
} /* end for */
memcpy(frameticker[0U],h2,31u);
if (tickertime!=aprsdecode_realtime) {
aprsstr_Assign(xosi_headmh, 251ul, h2, 31ul);
if (cnt>19UL) cnt = 19UL;
tmp = cnt-1UL;
i = 1UL;
if (i<=tmp) for (;; i++) {
aprsstr_Append(xosi_headmh, 251ul, " * ", 6ul);
aprsstr_Append(xosi_headmh, 251ul, frameticker[i], 31ul);
if (i==tmp) break;
} /* end for */
tickertime = aprsdecode_realtime;
}
}
} /* end tickermon() */
static void Stopticker(void)
{
aprsstr_Assign(xosi_headmh, 251ul, "\015", 2ul);
tickertime = 0x0FFFFFFC3UL;
memset((char *)frameticker,(char)0,620UL);
} /* end Stopticker() */
static void wrmon(uint32_t port, char dir,
const struct UDPSET modeminfo, uint32_t oldtime,
const char s[], uint32_t s_len)
{
char mcon[10];
char ms[31];
if (port==0UL) strncpy(mcon,"n",10u);
else aprsstr_IntToStr((int32_t)port, 0UL, mcon, 10ul);
if ((dir=='>' || dir=='-') && useri_configon(useri_fWRTICKER)) {
tickermon(mcon, 10ul, dir, oldtime, s, s_len);
}
/*IF configon(fWRINCOM) THEN */
useri_confstr(useri_fWRINCOM, ms, 31ul);
if (aprsstr_InStr(ms, 31ul, mcon, 10ul)>=0L) {
aprsstr_Append(mcon, 10ul, "+", 2ul);
aprstext_listin(s, s_len, X2C_CAP(mcon[0U]), dir, aprsstr_InStr(ms,
31ul, mcon, 10ul)>=0L, modeminfo.quali, modeminfo.txd,
modeminfo.level);
}
/*END; */
} /* end wrmon() */
static char filtdupes(const char tb[], uint32_t tb_len,
uint32_t oport, uint32_t dt)
{
uint32_t n2;
uint32_t n1;
uint32_t n;
uint32_t p;
uint8_t hashh;
uint8_t hashl;
struct aprsdecode_UDPSOCK * anonym;
hashl = 0U;
hashh = 0U;
p = 0UL;
n1 = 0UL;
n2 = 0UL;
for (;;) {
while (tb[p] && tb[p]!=':') ++p;
if (tb[p]!=':') break;
n1 = p;
++p;
if (tb[p]!='}') break;
++p;
n2 = p;
}
p = n2;
while (p<n1 && tb[p]!='>') {
aprsstr_HashCh(tb[p], &hashl, &hashh);
++p;
}
while ((p<n1 && tb[p]!='-') && tb[p]!=',') {
aprsstr_HashCh(tb[p], &hashl, &hashh);
++p;
}
p = n1;
while (tb[p]) {
aprsstr_HashCh(tb[p], &hashl, &hashh);
++p;
}
n = (uint32_t)(uint8_t)(char)hashl+(uint32_t)(uint8_t)
(char)hashh*256UL&65535UL;
{ /* with */
struct aprsdecode_UDPSOCK * anonym = &aprsdecode_udpsocks0[oport];
if (anonym->pdupetimes==0) {
osic_alloc((char * *) &anonym->pdupetimes, 262144UL);
useri_debugmem.req = 262144UL;
useri_debugmem.mon += 262144UL;
if (anonym->pdupetimes==0) {
osi_WrStrLn("duptime out of memory", 22ul);
useri_wrheap();
return 0;
}
memset((char *)anonym->pdupetimes,(char)0,262144UL);
}
if (anonym->pdupetimes[n]+dt>aprsdecode_realtime) return 0;
/* it is a dupe */
anonym->pdupetimes[n] = aprsdecode_realtime;
}
return 1;
} /* end filtdupes() */
static char Sendtcp(aprsdecode_pTCPSOCK to,
const aprsdecode_FRAMEBUF buf)
{
int32_t i;
int32_t len;
char ok0;
struct UDPSET modeminfo;
struct aprsdecode_TCPSOCK * anonym;
int32_t tmp;
ok0 = 0;
if (to) {
if (to->connt>0UL) {
memset((char *) &modeminfo,(char)0,sizeof(struct UDPSET));
wrmon(0UL, '<', modeminfo, 1UL, buf, 512ul);
}
len = (int32_t)aprsstr_Length(buf, 512ul);
{ /* with */
struct aprsdecode_TCPSOCK * anonym = to;
if (anonym->tlen+len<512L) {
tmp = len-1L;
i = 0L;
if (i<=tmp) for (;; i++) {
anonym->tbuf[anonym->tlen] = buf[i];
++anonym->tlen;
if (i==tmp) break;
} /* end for */
++anonym->txframes;
anonym->txbytes += (uint32_t)len;
aprsdecode_lasttcptx = aprsdecode_realtime;
ok0 = 1;
}
else if (aprsdecode_verb) osi_WrStrLn("tx buf overflow", 16ul);
}
}
return ok0;
} /* end Sendtcp() */
static int32_t Sendudp(const char s[], uint32_t s_len,
uint32_t uport, uint32_t dupetime0)
{
int32_t len;
aprsdecode_FRAMEBUF raw;
struct UDPSET modeminfo;
struct aprsdecode_UDPSOCK * anonym;
len = -1L;
if ((uport<=3UL && (int32_t)aprsdecode_udpsocks0[uport].fd>=0L)
&& aprsdecode_udpsocks0[uport].dport>0UL) {
if (dupetime0==0UL || filtdupes(s, s_len, uport, dupetime0)) {
aprsstr_mon2raw(s, s_len, raw, 512ul, &len);
if (len>1L) {
len = udpsend(aprsdecode_udpsocks0[uport].fd, raw, len,
aprsdecode_udpsocks0[uport].dport,
aprsdecode_udpsocks0[uport].ip);
if (len>0L) {
memset((char *) &modeminfo,(char)0,
sizeof(struct UDPSET));
wrmon(uport+1UL, '<', modeminfo, 1UL, s, s_len);
{ /* with */
struct aprsdecode_UDPSOCK * anonym = &aprsdecode_udpsocks0[uport]
;
++anonym->txframes;
anonym->txbytes += (uint32_t)len;
anonym->lastudptx = aprsdecode_realtime;
if (anonym->starttime==0UL) {
anonym->starttime = aprsdecode_realtime;
}
}
}
}
else if (aprsdecode_verb) {
osi_WrStrLn("wrong rf monitor format", 24ul);
}
}
else len = 0L;
}
return len;
} /* end Sendudp() */
#define aprsdecode_MAXTXBIT 2000
/* clamp to +- bit */
#define aprsdecode_MSGPREF 1000
/* prefer msg time space */
static char Checkbps(uint32_t uport, uint32_t bps,
uint32_t bytes, char msgprefer)
/* check/set bit/s for net>rf*/
{
uint32_t t;
struct aprsdecode_UDPSOCK * anonym;
if (bps>0UL && uport<=3UL) {
t = 2000UL/bps;
{ /* with */
struct aprsdecode_UDPSOCK * anonym = &aprsdecode_udpsocks0[uport];
if (bytes==0UL) {
/* check */
/*WrInt(bpstime-realtime, 10); WrStrLn(" check tx"); */
if (anonym->bpstime<=aprsdecode_realtime+(1000UL/bps)
*(uint32_t)msgprefer) return 1;
t += aprsdecode_realtime;
if (anonym->bpstime>t) anonym->bpstime = t;
}
else {
/* set next tx time */
if (anonym->bpstime+t<aprsdecode_realtime) {
anonym->bpstime = aprsdecode_realtime-t;
/* limit transmission at once */
}
anonym->bpstime += (bytes*8UL)/bps;
}
}
}
/*WrInt(bpstime-realtime, 10); WrStrLn(" next tx"); */
return 0;
} /* end Checkbps() */
#define aprsdecode_RAININCH 3.9370078740157
#define aprsdecode_SEP ","
static char csvget(char w[], uint32_t w_len, const char s[],
uint32_t s_len, uint32_t n)
{
uint32_t j;
uint32_t i;
w[0UL] = 0;
i = 0UL;
while (n>0UL) {
if (i>s_len-1 || s[i]==0) return 0;
if (s[i]==',') --n;
++i;
}
j = 0UL;
while (((j<=w_len-1 && i<s_len-1) && s[i]) && s[i]!=',') {
w[j] = s[i];
++i;
++j;
}
if (j<=w_len-1) w[j] = 0;
return 1;
} /* end csvget() */
static char getreal(float * x, const char s[],
uint32_t s_len)
{
char val;
char dot;
float div0;
uint32_t i;
dot = 0;
val = 0;
*x = 0.0f;
div0 = 1.0f;
i = 0UL;
for (;;) {
if (div0>=0.0f && s[i]=='-') div0 = -div0;
else if ((uint8_t)s[i]>='0' && (uint8_t)s[i]<='9') {
*x = *x*10.0f+(float)((uint32_t)(uint8_t)s[i]-48UL);
if (*x>1.E+6f) {
val = 0;
break;
}
if (dot) div0 = div0*0.1f;
val = 1;
}
else if (!dot && s[i]=='.') dot = 1;
else break;
++i;
if (i>s_len-1) break;
}
*x = *x*div0;
return val;
} /* end getreal() */
static void apd(char ws[], uint32_t ws_len, char c, float v,
uint32_t f)
{
int32_t d;
int32_t n;
char tmp;
if (c) aprsstr_Append(ws, ws_len, (char *) &c, 1u/1u);
n = (int32_t)X2C_TRUNCI(v+0.5f,X2C_min_longint,X2C_max_longint);
if (n<0L) {
aprsstr_Append(ws, ws_len, "-", 2ul);
n = -n;
--f;
}
d = 1L;
while (f>1UL) {
d = d*10L;
--f;
}
do {
aprsstr_Append(ws, ws_len, (char *)(tmp = (char)((n/d)%10L+48L),
&tmp), 1u/1u);
d = d/10L;
} while (d);
} /* end apd() */
static void wxmacro(char ws[], uint32_t ws_len, char wms[],
uint32_t wms_len)
/* \\!wx.txt,,t,,h,b,,w3.6,d! */
{
struct aprsdecode_WX w;
uint32_t n;
int32_t payload;
int32_t len;
int32_t f;
float mul;
float v;
float winddir;
float wind;
char cb[1024];
char ns[1024];
char fn[1024];
char cn[21];
char c;
struct aprsdecode_DAT d;
X2C_PCOPY((void **)&wms,wms_len);
if (csvget(fn, 1024ul, wms, wms_len, 0UL)) {
/* csv filename */
len = 0L;
if (fn[0U]) {
f = osi_OpenRead(fn, 1024ul);
if (osic_FdValid(f)) {
n = (uint32_t)osic_Size(f);
if (n>1024UL) osic_Seek(f, n-1024UL);
len = osi_RdBin(f, (char *)cb, 1024u/1u, 1024UL);
}
if (len>0L) {
while (len>0L && (uint8_t)cb[len-1L]<=' ') {
--len; /* find first visable char from end */
}
if (len<=1023L) cb[len] = 0;
while (len>0L && (uint8_t)cb[len-1L]>=' ') {
--len; /* find begin of last csv line */
}
aprsstr_Delstr(cb, 1024ul, 0UL, (uint32_t)len);
}
else cb[0U] = 0;
if (cb[0U]==0) {
aprsstr_Assign(ns, 1024ul, "wx csv file not readable ", 26ul);
aprsstr_Append(ns, 1024ul, fn, 1024ul);
useri_xerrmsg(ns, 1024ul);
wms[0UL] = 0;
goto label;
}
w.temp = 1.E+6f;
winddir = 1.E+6f;
wind = 1.E+6f;
w.gust = 1.E+6f;
w.hygro = 1.E+6f;
w.baro = 1.E+6f;
w.lum = 1.E+6f;
w.rain1 = 1.E+6f;
w.rain24 = 1.E+6f;
w.raintoday = 1.E+6f;
n = 1UL;
while (csvget(cn, 21ul, wms, wms_len, n)) {
c = cn[0U]; /* w3.6 */
if (c) {
aprsstr_Delstr(cn, 21ul, 0UL, 1UL); /* 3.6 */
if (!getreal(&mul, cn, 21ul)) mul = 1.0f;
if (csvget(ns, 1024ul, cb, 1024ul, n-1UL) && getreal(&v, ns,
1024ul)) {
v = v*mul;
switch ((unsigned)c) {
case 't':
if (v>=(-60.0f) && v<=79.0f) w.temp = v;
break;
case 'g':
if (v>=0.0f && v<=500.0f) w.gust = v;
break;
case 'w':
if (v>=0.0f && v<=500.0f) wind = v;
break;
case 'd':
if (v>=0.0f && v<360.0f) winddir = v;
break;
case 'b':
if (v>=900.0f && v<=1100.0f) w.baro = v;
break;
case 'h':
if (v>=0.0f && v<=100.0f) w.hygro = v;
break;
case 'L':
if (v>=0.0f && v<=1500.0f) w.lum = v;
break;
case 'r':
if (v>=0.0f && v<=500.0f) w.rain1 = v;
break;
case 'P':
if (v>=0.0f && v<=500.0f) w.rain24 = v;
break;
case 'p':
if (v>=0.0f && v<=500.0f) w.raintoday = v;
break;
} /* end switch */
}
}
++n;
}
d.postyp = 'g';
payload = aprsstr_InStr(ws, ws_len, ":", 2ul);
if (payload>0L) {
aprspos_GetPos(&d.pos, &d.speed, &d.course, &d.altitude, &d.sym,
&d.symt, ws, ws_len, 0UL, (uint32_t)(payload+1L),
d.comment0, 256ul, &d.postyp);
/* exchange spd/dir */
if (d.postyp=='c') {
aprsstr_Delstr(ws, ws_len, (uint32_t)(payload+2L), ws_len);
d.speed = aprsdecode_trunc(X2C_DIVR(wind,1.609f));
d.course = aprsdecode_trunc(winddir);
cb[0U] = d.symt;
cb[1U] = d.sym;
cb[2U] = 0;
aprstext_compressdata(d.pos, d.speed, d.course, 0L, cb,
1024ul, cb, 1024ul);
aprsstr_Append(ws, ws_len, cb, 1024ul);
}
else if (d.postyp!='g') {
aprsstr_Assign(ns, 1024ul, "wx beacon not MICE encodable",
29ul);
useri_xerrmsg(ns, 1024ul);
}
}
if (d.postyp!='c') {
if (winddir!=1.E+6f) apd(ws, ws_len, 0, winddir+1.0f, 3UL);
else aprsstr_Append(ws, ws_len, "...", 4ul);
if (wind!=1.E+6f) {
apd(ws, ws_len, '/', X2C_DIVR(wind,1.609f), 3UL);
}
else aprsstr_Append(ws, ws_len, "/...", 5ul);
}
if (w.gust!=1.E+6f) {
apd(ws, ws_len, 'g', X2C_DIVR(w.gust,1.609f), 3UL);
}
else aprsstr_Append(ws, ws_len, "g...", 5ul);
if (w.temp!=1.E+6f) {
apd(ws, ws_len, 't', aprstext_CtoF(w.temp), 3UL);
}
else aprsstr_Append(ws, ws_len, "t...", 5ul);
if (w.rain1!=1.E+6f) {
apd(ws, ws_len, 'r', w.rain1*3.9370078740157f, 3UL);
}
if (w.rain24!=1.E+6f) {
apd(ws, ws_len, 'P', w.rain24*3.9370078740157f, 3UL);
}
if (w.raintoday!=1.E+6f) {
apd(ws, ws_len, 'p', w.raintoday*3.9370078740157f, 3UL);
}
if (w.hygro!=1.E+6f) apd(ws, ws_len, 'h', w.hygro, 2UL);
if (w.baro!=1.E+6f) apd(ws, ws_len, 'b', w.baro*10.0f, 5UL);
if (w.lum!=1.E+6f) {
if (w.lum>=1000.0f) apd(ws, ws_len, 'l', w.lum-1000.0f, 3UL);
else apd(ws, ws_len, 'L', w.lum, 3UL);
}
}
else {
aprsstr_Assign(ns, 1024ul, "wx beacon macro needs valid filename ",
38ul);
useri_xerrmsg(ns, 1024ul);
ws[0UL] = 0;
}
}
else {
aprsstr_Assign(ns, 1024ul, "wx beacon macro \\\\!filename,...! ",
34ul);
useri_xerrmsg(ns, 1024ul);
ws[0UL] = 0;
}
label:;
X2C_PFREE(wms);
} /* end wxmacro() */
#define aprsdecode_MSYM "\\"
#define aprsdecode_INSOPEN "<"
#define aprsdecode_INSCLOSE ">"
#define aprsdecode_DELOPEN "["
#define aprsdecode_DELCLOSE "]"
#define aprsdecode_WROPEN ">"
#define aprsdecode_WRCLOSE "<"
#define aprsdecode_WXOPEN "!"
#define aprsdecode_WXCLOSE "!"
static void beaconmacros(char s[], uint32_t s_len,
const char path[], uint32_t path_len, char wdata[],
uint32_t wdata_len, char all)
{
uint32_t i;
int32_t j;
int32_t len;
char ns[256];
char ds[256];
char fn[1024];
int32_t f;
char ok0;
char rwc;
char rw;
struct aprspos_POSITION pos;
X2C_PCOPY((void **)&wdata,wdata_len);
i = 0UL;
ns[0U] = 0;
while (i<s_len-1 && s[i]) {
if (s[i]=='\\' && s[i+1UL]=='\\') {
i += 2UL;
if (s[i]=='z' && all || s[i]=='Z') {
/* insert day, hour, min */
aprsstr_DateToStr(aprsdecode_realtime, 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[i]=='h' && all || s[i]=='H') {
/* insert hour, min, s */
aprsstr_DateToStr(aprsdecode_realtime, 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 (all) {
rw = s[i];
if (rw=='<') rwc = '>';
else if (rw=='>') rwc = '<';
else if (rw=='[') rwc = ']';
else if (rw=='!') rwc = '!';
else rwc = 0;
if (rwc) {
/* insert or write file or insert and delete */
fn[0U] = 0;
++i;
while ((i<s_len-1 && s[i]) && s[i]!=rwc) {
aprsstr_Append(fn, 1024ul, (char *) &s[i], 1u/1u);
++i;
}
if (rw=='<' || rw=='[') {
/* read file */
f = osi_OpenRead(fn, 1024ul);
if (osic_FdValid(f)) {
len = osi_RdBin(f, (char *)ds, 256u/1u, 255UL);
osic_Close(f);
if (rw=='[') osi_Erase(fn, 1024ul, &ok0);
j = 0L;
while (((j<len && ds[j]!='\015') && ds[j]!='\012')
&& ds[j]) {
aprsstr_Append(ns, 256ul, (char *) &ds[j],
1u/1u);
++j;
}
}
else {
aprsstr_Assign(s, s_len, "beacon macro file not readable\
", 32ul);
aprsstr_Append(s, s_len, fn, 1024ul);
useri_xerrmsg(s, s_len);
s[0UL] = 0;
goto label;
}
}
else if (rw=='>') {
if (wdata[0UL]) {
/* write file */
f = osi_OpenWrite(fn, 1024ul);
if (osic_FdValid(f)) {
osi_WrBin(f, (char *)wdata, (wdata_len)/1u,
aprsstr_Length(wdata, wdata_len));
osic_Close(f);
}
}
}
else if (rw=='!') wxmacro(ns, 256ul, fn, 1024ul);
}
else if (s[i]=='\\') {
aprsstr_Append(ns, 256ul, "\\\\", 3ul);
}
else if (s[i]=='v') {
aprsstr_Append(ns, 256ul, "aprsmap(cu) 0.66", 17ul);
}
else if (s[i]=='l') {
if (aprstext_getmypos(&pos)) {
aprstext_postostr(pos, '2', ds, 256ul);
aprsstr_Append(ns, 256ul, ds, 256ul);
}
}
else if (s[i]=='p') aprsstr_Append(ns, 256ul, path, path_len);
else {
aprsstr_Assign(s, s_len, "bad beacon macro ", 18ul);
aprsstr_Append(s, s_len, ns, 256ul);
aprsstr_Append(s, s_len, "???", 4ul);
useri_xerrmsg(s, s_len);
s[0UL] = 0;
goto label;
}
}
else {
aprsstr_Append(ns, 256ul, "\\\\", 3ul);
aprsstr_Append(ns, 256ul, (char *) &s[i], 1u/1u);
}
}
else aprsstr_Append(ns, 256ul, (char *) &s[i], 1u/1u);
++i;
}
aprsstr_Assign(s, s_len, ns, 256ul);
label:;
X2C_PFREE(wdata);
} /* end beaconmacros() */
static void BuildNetBeacon(char h[], uint32_t h_len)
/* "!ddmm.mmNsdddmm.mms....." */
{
struct aprspos_POSITION mypos;
char h3[301];
char h2[301];
char h1[301];
useri_confstr(useri_fMYSYM, h3, 301ul);
useri_confstr(useri_fNBTEXT, h2, 301ul);
if (!aprstext_getmypos(&mypos)) {
useri_xerrmsg("netbeacon: wrong my position", 29ul);
h[0UL] = 0;
return;
}
if (aprsstr_Length(h3, 301ul)!=2UL) {
useri_xerrmsg("netbeacon: wrong symbol", 24ul);
h[0UL] = 0;
return;
}
aprstext_postostr(mypos, '2', h1, 301ul);
aprsstr_Assign(h, h_len, "=", 2ul);
h1[8U] = h3[0U];
h1[18U] = h3[1U];
h1[19U] = 0;
aprsstr_Append(h, h_len, h1, 301ul);
beaconmacros(h2, 301ul, "", 1ul, "", 1ul, 1);
aprsstr_Append(h, h_len, h2, 301ul);
} /* end BuildNetBeacon() */
static void SendNetBeacon(aprsdecode_pTCPSOCK cp,
const aprsdecode_FRAMEBUF b, char manual,
char errtxt[], uint32_t errtxt_len)
{
int32_t ret;
struct aprsdecode_DAT dat;
uint32_t t;
if (b[0UL]==0 || aprsdecode_Decode(b, 512ul, &dat)<0L) {
aprsstr_Assign(errtxt, errtxt_len, "Net Beacon not Decodable", 25ul);
return;
}
if (!Sendtcp(cp, b)) {
if (manual) {
aprsstr_Assign(errtxt, errtxt_len, "Netport not connected", 22ul);
}
return;
}
if (aprsdecode_lums.logmode) {
ret = aprsdecode_Stoframe(&aprsdecode_ophist2, b, 512ul,
aprsdecode_realtime, 0, &t, dat);
}
else {
ret = aprsdecode_Stoframe(&aprsdecode_ophist0, b, 512ul,
aprsdecode_realtime, 0, &t, dat);
}
} /* end SendNetBeacon() */
static void SendNet(aprsdecode_pTCPSOCK cp, char mycall[],
uint32_t mycall_len, const char data[],
uint32_t data_len, char manual, char errtxt[],
uint32_t errtxt_len)
/* make net header append string and send */
{
aprsdecode_FRAMEBUF s;
char pass[51];
char h[51];
uint32_t i;
X2C_PCOPY((void **)&mycall,mycall_len);
errtxt[0UL] = 0;
if (!useri_configon(useri_fALLOWNETTX) || !useri_configon(useri_fCONNECT))
{
if (manual) {
aprsstr_Assign(errtxt, errtxt_len,
"Net Port not configured to Send", 32ul);
}
goto label;
}
if (mycall[0UL]) aprsstr_Assign(s, 512ul, mycall, mycall_len);
else useri_confstr(useri_fMYCALL, s, 512ul);
i = 0UL;
while (i<511UL && s[i]) {
if ((uint8_t)s[i]<=' ' || (uint8_t)s[i]>='\177') s[0UL] = 0;
++i;
}
if (aprstext_callwrong(s, 512ul)) {
aprsstr_Assign(errtxt, errtxt_len, "netbeacon: no valid mycall", 27ul);
goto label;
}
useri_confstr(useri_fMSGNETDEST, h, 51ul);
if (h[0U]==0) {
aprsstr_Assign(errtxt, errtxt_len, "netbeacon: no destination call",
31ul);
goto label;
}
if (manual) {
useri_confstr(useri_fPW, pass, 51ul);
if (pass[0U]==0) {
useri_xerrmsg("sending to Net without Passcode", 32ul);
}
}
aprsstr_Append(s, 512ul, ">", 2ul);
aprsstr_Append(s, 512ul, h, 51ul);
aprsstr_Append(s, 512ul, ",TCPIP*:", 9ul);
aprsstr_Append(s, 512ul, data, data_len);
aprsstr_Append(s, 512ul, "\015\012", 3ul);
SendNetBeacon(cp, s, manual, errtxt, errtxt_len);
label:;
X2C_PFREE(mycall);
} /* end SendNet() */
static void makeping(uint32_t t, char pong, char b[],
uint32_t b_len)
{
char s[21];
if (pong) aprsstr_Assign(b, b_len, "pong ", 6ul);
else aprsstr_Assign(b, b_len, "ping ", 6ul);
aprsstr_IntToStr((int32_t)(t%86400UL), 0UL, s, 21ul);
aprsstr_Append(b, b_len, s, 21ul);
} /* end makeping() */
static void sendping(aprsdecode_pTCPSOCK tp)
{
char h[21];
aprsdecode_FRAMEBUF s;
char ok0;
if (aprsdecode_realtime<tp->lastping) tp->lastping = aprsdecode_realtime;
if (aprsdecode_realtime>=tp->lastping+20UL) {
tp->lastping = aprsdecode_realtime;
if (tp->waitpong<=1U) ++tp->waitpong;
strncpy(s,"#",512u);
makeping(tp->lastping, 0, h, 21ul);
aprsstr_Append(s, 512ul, h, 21ul);
aprsstr_Append(s, 512ul, "\015\012", 3ul);
ok0 = Sendtcp(tp, s);
}
} /* end sendping() */
static void getpong(aprsdecode_pTCPSOCK tp, const char mb[],
uint32_t mb_len)
{
char s[21];
makeping(tp->lastping, 1, s, 21ul);
if (aprsdecode_realtime<=tp->lastping+10UL && aprsstr_InStr(mb, mb_len, s,
21ul)>=1L) {
tp->lastpong = aprsdecode_realtime;
tp->waitpong = 0U;
}
} /* end getpong() */
static void Timebeacon(aprsdecode_pTCPSOCK cp)
{
aprsdecode_FRAMEBUF h;
uint32_t bt;
char err[100];
if (useri_configon(useri_fALLOWNETTX) && useri_configon(useri_fCONNECT)) {
bt = (uint32_t)useri_conf2int(useri_fNETBTIME, 0UL, 0L,
X2C_max_longint, 0L);
if ((bt>=1UL || cp->beacont==0UL) && Watchclock(&cp->beacont, bt)) {
if ((bt<60UL && bt>0UL) && cp->connt>0UL) {
useri_xerrmsg("Netbeacon: too fast", 20ul);
}
BuildNetBeacon(h, 512ul);
SendNet(cp, "", 1ul, h, 512ul, 0, err, 100ul);
useri_xerrmsg(err, 100ul);
}
if (cp->lastping>0UL && useri_configon(useri_fALLOWGATE)) sendping(cp);
}
} /* end Timebeacon() */
/*
PROCEDURE nibb(n:CARDINAL; VAR s:ARRAY OF CHAR);
BEGIN IF n<=9 THEN Append(s, CHR(n+ORD("0"))) ELSE Append(s,
CHR(n+(ORD("a")-10))) END END nibb;
*/
extern int32_t aprsdecode_knottokmh(int32_t kn)
{
if (kn>=0L && kn<50000L) {
return (int32_t)aprsdecode_trunc((float)kn*1.852f+0.5f);
}
else return 0L;
return 0;
} /* end knottokmh() */
static void NoWX(struct aprsdecode_WX * wx)
{
wx->gust = 1.E+6f;
wx->temp = 1.E+6f;
wx->rain1 = 1.E+6f;
wx->rain24 = 1.E+6f;
wx->raintoday = 1.E+6f;
wx->hygro = 1.E+6f;
wx->baro = 1.E+6f;
wx->lum = 1.E+6f;
wx->sievert = 1.E+6f;
wx->storm = aprsdecode_WXNOWX;
wx->sustaind = 0.0f;
wx->radiushurr = 0.0f;
wx->radiusstorm = 0.0f;
wx->wholegale = 0.0f;
} /* end NoWX() */
static void wpar(uint32_t * p, char buf[], uint32_t buf_len,
float * v, int32_t mindig, int32_t maxdig)
{
char empty;
char dot;
char sn;
char c;
float x;
float div0;
dot = 0;
empty = 1;
sn = buf[*p]=='t';
x = 0.0f;
div0 = 1.0f;
for (;;) {
++*p;
c = buf[*p];
if (sn && c=='-') {
div0 = -div0;
empty = 0;
--mindig;
--maxdig;
}
else if ((uint8_t)c>='0' && (uint8_t)c<='9') {
if (!dot && maxdig<=0L) {
x = 0.0f;
break;
}
x = x*10.0f+(float)((uint32_t)(uint8_t)buf[*p]-48UL);
if (x>1.E+5f) return;
if (dot) div0 = div0*0.1f;
else {
--mindig;
--maxdig;
}
empty = 0;
}
else if (empty) {
if (c!=' ' && c!='.') break;
}
else if (c=='.') {
if (dot) break;
dot = 1;
}
else break;
sn = 0;
}
if (!empty && mindig<=0L) *v = x*div0;
} /* end wpar() */
static void wexp(char buf[], uint32_t buf_len, uint32_t * p,
float * v, float mul)
{
uint32_t n;
float x;
x = 0.0f;
++*p;
if ((uint8_t)buf[*p]>='0' && (uint8_t)buf[*p]<='9') {
x = 10.0f*(float)((uint32_t)(uint8_t)buf[*p]-48UL);
}
else return;
++*p;
if ((uint8_t)buf[*p]>='0' && (uint8_t)buf[*p]<='9') {
x = x+(float)((uint32_t)(uint8_t)buf[*p]-48UL);
}
else return;
++*p;
if ((uint8_t)buf[*p]>='0' && (uint8_t)buf[*p]<='9') {
n = (uint32_t)(uint8_t)buf[*p]-48UL;
while (n>0UL) {
x = x*10.0f; /* exponent */
--n;
}
++*p;
}
else return;
*v = x*mul;
} /* end wexp() */
static void GetWX(struct aprsdecode_WX * wx, uint32_t * course,
uint32_t * speed, char buf[], uint32_t buf_len,
char storm)
{
float wdir;
float wwind;
uint32_t p;
p = 0UL;
NoWX(wx);
wwind = 1.E+6f;
wdir = 1.E+6f;
/* IF buf[p]="_" THEN INC(p, 9) END; (* positionless wx *) */
if (storm) {
/* storm data */
/*4903.50N\07202.75W@088/036/HC/150^200/0980>090&030%040 */
if (((buf[0UL]=='/' && buf[3UL]=='/') && buf[7UL]=='^')
&& buf[11UL]=='/') {
++p;
if (buf[1UL]=='T' && buf[2UL]=='S') wx->storm = aprsdecode_WXTS;
else if (buf[1UL]=='H' && buf[2UL]=='C') {
wx->storm = aprsdecode_WXHC;
}
else if (buf[1UL]=='T' && buf[2UL]=='D') {
wx->storm = aprsdecode_WXTD;
}
if (wx->storm) {
p += 2UL;
wpar(&p, buf, buf_len, &wx->sustaind, 3L, 3L);
wpar(&p, buf, buf_len, &wx->gust, 3L, 3L);
wpar(&p, buf, buf_len, &wx->baro, 4L, 4L);
if (buf[p]=='>') wpar(&p, buf, buf_len, &wx->radiushurr, 3L, 3L);
if (buf[p]=='&') {
wpar(&p, buf, buf_len, &wx->radiusstorm, 3L, 3L);
}
if (buf[p]=='%') wpar(&p, buf, buf_len, &wx->wholegale, 3L, 3L);
}
}
}
else {
/* normal wx */
for (;;) {
switch ((unsigned)buf[p]) {
case 'g':
wpar(&p, buf, buf_len, &wx->gust, 3L, 3L);
break;
case 't':
wpar(&p, buf, buf_len, &wx->temp, 3L, 3L);
break;
case 'r':
wpar(&p, buf, buf_len, &wx->rain1, 3L, 3L);
break;
case 'p':
wpar(&p, buf, buf_len, &wx->rain24, 3L, 3L);
break;
case 'P':
wpar(&p, buf, buf_len, &wx->raintoday, 3L, 3L);
break;
case 'h':
wpar(&p, buf, buf_len, &wx->hygro, 2L, 3L);
break;
case 'b':
wpar(&p, buf, buf_len, &wx->baro, 5L, 5L);
break;
case 'L':
wpar(&p, buf, buf_len, &wx->lum, 3L, 3L);
break;
case 'l':
wpar(&p, buf, buf_len, &wx->lum, 3L, 3L);
wx->lum = wx->lum+1000.0f;
break;
case 'c':
wpar(&p, buf, buf_len, &wdir, 3L, 3L);
break;
case 's':
wpar(&p, buf, buf_len, &wwind, 3L, 3L);
break;
case 'X':
wexp(buf, buf_len, &p, &wx->sievert, 1.E-9f);
break;
default:;
goto loop_exit;
} /* end switch */
}
loop_exit:;
wx->storm = aprsdecode_WXNORMAL;
}
wdir = wdir+0.5f;
if (wdir>=1.0f && wdir<361.0f) *course = aprsdecode_trunc(wdir);
if (wwind>=0.0f && wwind<1000.0f) *speed = aprsdecode_trunc(wwind);
aprsstr_Delstr(buf, buf_len, 0UL, p);
/* X123 is 12 * 10^3 nanosieverts/hr*/
} /* end GetWX() */
#define aprsdecode_DATELEN 15
static char wrlog(const char b[], uint32_t b_len,
uint32_t time0, char wfn[], uint32_t wfn_len,
int32_t good)
{
int32_t f;
char h[1001];
uint32_t i;
uint32_t l;
char wrlog_ret;
X2C_PCOPY((void **)&wfn,wfn_len);
if (wfn[0UL]==0) {
wrlog_ret = 0;
goto label;
}
l = aprsstr_Length(b, b_len);
while (l>0UL && (uint8_t)b[l-1UL]<='\015') --l;
if (l>0UL) {
aprsstr_cleanfilename(wfn, wfn_len);
f = osi_OpenAppendLong(wfn, wfn_len);
if (!osic_FdValid(f)) f = osi_OpenWrite(wfn, wfn_len);
if (!osic_FdValid(f)) {
wrlog_ret = 0;
goto label;
}
aprsstr_DateToStr(time0, h, 1001ul);
h[4U] = h[5U];
h[5U] = h[6U];
h[6U] = h[8U];
h[7U] = h[9U];
h[8U] = ':';
h[9U] = h[11U];
h[10U] = h[12U];
h[11U] = h[14U];
h[12U] = h[15U];
h[13U] = h[17U];
h[14U] = h[18U];
if (good>=0L) h[15U] = ' ';
else h[15U] = '-';
if (l>=984UL) l = 984UL;
i = 0UL;
do {
h[i+16UL] = b[i];
++i;
} while (i<l);
h[i+16UL] = '\012';
++i;
osi_WrBin(f, (char *)h, 1001u/1u, i+16UL);
osic_Close(f);
}
wrlog_ret = 1;
label:;
X2C_PFREE(wfn);
return wrlog_ret;
} /* end wrlog() */
static aprsdecode_pOPHIST findop(aprsdecode_MONCALL call,
char online)
{
aprsdecode_pOPHIST op;
aprsdecode_MONCALL tmp;
call = (char *)memcpy(tmp,call,9u);
if (online && aprsdecode_lums.logmode) op = aprsdecode_ophist2;
else op = aprsdecode_ophist0;
while (op && X2C_STRCMP(call,9u,op->call,9u)) op = op->next;
return op;
} /* end findop() */
static void poplogerr(char fn[], uint32_t fn_len)
{
char h[1001];
X2C_PCOPY((void **)&fn,fn_len);
strncpy(h,"\012logfile write error ",1001u);
aprsstr_Append(h, 1001ul, fn, fn_len);
aprsstr_Append(h, 1001ul, "\012", 2ul);
useri_textautosize(0L, 5L, 6UL, 4UL, 'e', h, 1001ul);
X2C_PFREE(fn);
} /* end poplogerr() */
extern void aprsdecode_savetrack(void)
{
aprsdecode_pOPHIST op;
aprsdecode_pFRAMEHIST pf;
char h[101];
char fn[1001];
char ap;
aprsdecode_MONCALL name;
name[0UL] = 0;
if (aprsdecode_click.mhop[0UL]) memcpy(name,aprsdecode_click.mhop,9u);
else if (aprsdecode_click.entries>0UL && aprsdecode_click.table[aprsdecode_click.selected]
.opf) {
memcpy(name,aprsdecode_click.table[aprsdecode_click.selected].opf->call,
9u);
}
if (name[0UL]) {
op = findop(name, 0);
if (op) {
aprsstr_Assign(fn, 1001ul, op->call, 9ul); /* make 0C terminated */
alfanum(fn, 1001ul); /* remove bad chars */
aprsdecode_makelogfn(fn, 1001ul);
ap = osi_Exists(fn, 1001ul);
pf = op->frames;
while (pf) {
if (!wrlog(pf->vardat->raw, 500ul, pf->time0, fn, 1001ul, 0L)) {
poplogerr(fn, 1001ul);
return;
}
pf = pf->next;
}
if (ap) strncpy(h,"Append to logfile ",101u);
else strncpy(h,"Write logfile ",101u);
aprsstr_Append(h, 101ul, fn, 1001ul);
useri_say(h, 101ul, 4UL, 'b');
}
}
} /* end savetrack() */
static char replyack(char rep[], uint32_t rep_len,
char restack[], uint32_t restack_len,
const char ack[], uint32_t ack_len)
{
aprsstr_Assign(rep, rep_len, ack, ack_len);
aprsstr_Assign(restack, restack_len, ack, ack_len);
if (aprsstr_Length(ack, ack_len)>2UL && ack[2UL]=='}') {
/* {xx}yy */
rep[0UL] = ack[3UL];
rep[1UL] = ack[4UL];
if (rep_len-1>=2UL) rep[2UL] = 0;
if (restack_len-1>=2UL) restack[2UL] = 0;
return 1;
}
return 0;
} /* end replyack() */
static char iscall(const aprsdecode_MONCALL b)
{
uint32_t i;
uint32_t nu;
uint32_t li;
char c;
li = 0UL;
nu = 0UL;
for (i = 0UL; i<=2UL; i++) {
c = b[i];
if ((uint8_t)c>='A' && (uint8_t)c<='Z') ++li;
else if ((uint8_t)c>='0' && (uint8_t)c<='9') {
if (i==0UL) ++li;
else ++nu;
}
} /* end for */
return (nu+li==3UL && nu>=1UL) && nu<=2UL;
} /* end iscall() */
static char viaghost(const char b[], uint32_t b_len)
/* n<>N */
{
uint32_t i;
char c;
i = aprsstr_Length(b, b_len);
if (i>3UL) {
c = b[i-1UL];
if (((uint8_t)c>='0' && (uint8_t)c<='9') && c!=b[i-3UL]) return 1;
}
return 0;
} /* end viaghost() */
/*
PROCEDURE viaghost(b-:ARRAY OF CHAR):BOOLEAN;
(* ECHO GATE RELAY n=n ELSE ghost *)
VAR i:CARDINAL;
c:CHAR;
BEGIN
IF (b[0]="E") & (b[1]="C") & (b[2]="H") & (b[3]="O") & (b[4]=0C)
THEN RETURN FALSE END;
IF (b[0]="G") & (b[1]="A") & (b[2]="T") & (b[3]="E") & (b[4]=0C)
THEN RETURN FALSE END;
IF (b[0]="R") & (b[1]="E") & (b[2]="L") & (b[3]="A") & (b[4]="Y")
& (b[5]=0C) THEN RETURN FALSE E
i:=Length(b);
c:=b[i-1];
IF (i>3) & (b[i-2]="-") & (c=b[i-3]) & (c>="1") & (c<="7")
THEN RETURN FALSE END;
RETURN TRUE
END viaghost;
*/
static float num(char buf[], uint32_t buf_len, uint32_t * p)
{
char c;
char sig;
float f;
float r;
r = 0.0f;
sig = 0;
f = 1.0f;
for (;;) {
if (*p>buf_len-1 || (float)fabs(r)>=2.147483647E+9f) break;
c = buf[*p];
if (sig==0 && c=='-' || c=='+') sig = c;
else if (f>0.5f && c=='.') f = f*0.1f;
else if ((uint8_t)c>='0' && (uint8_t)c<='9') {
if (f>0.5f) r = r*10.0f+(float)((uint32_t)(uint8_t)c-48UL);
else {
r = r+(float)((uint32_t)(uint8_t)c-48UL)*f;
f = f*0.1f;
}
}
else break;
++*p;
if (sig==0) sig = '\001';
}
if (r>=2.147483647E+9f) r = 2.147483647E+9f;
if (sig=='-') r = -r;
return r;
} /* end num() */
static void skip(char buf[], uint32_t buf_len, uint32_t * p)
{
if (*p<=buf_len-1 && buf[*p]==',') ++*p;
} /* end skip() */
static uint32_t corrtime(uint32_t syst, uint32_t mt, uint32_t span)
/* complete modulo time to absolute */
{
mt = (span+mt%span)-syst%span;
if (mt<span/2UL) mt += span;
else if (mt>span+span/2UL) mt -= span;
mt += syst;
if (mt>=span) mt -= span;
return mt;
} /* end corrtime() */
#define aprsdecode_H 3600
#define aprsdecode_DAY 86400
#define aprsdecode_DEGUNIT 1.7453292519444E-7
/* 1/100000 deg = 1.1111m*/
static void GetHRT(struct aprspos_POSITION * pos, int32_t * altitude,
uint32_t * speed, const char buf[], uint32_t buf_len,
struct aprsdecode_HRTPOS hrtposes[],
uint32_t hrtposes_len, uint32_t * hrtlen,
uint32_t * hrttime)
{
uint32_t p;
char cmd;
uint32_t i;
uint32_t crc;
uint32_t duration;
uint32_t wcnt;
float r;
float unit;
uint32_t ts;
struct aprspos_POSITION posh;
struct aprspos_POSITION dao;
char newcompos;
struct aprsdecode_HRTPOS * anonym;
uint32_t tmp;
/* $HR[t46531u1.5p48.0235,13.1512a367d15,11w-479,622,33w-5,
2-4w7+2-3ww4-1-5wg435644353-10c27001]
t s utc modulo 24h modulo 1h or absolut since 1970
p deg lat/long
a m altitude
v m/s speed
y m/s climb
d deg lat/long dao
w deg,deg,m,s lat long alt time
u 0.00001 deg,m unit
g direct heard gateway
c crc
q qrv mhz
r rx freq mhz or hz
*/
/*WrStrLn(buf); */
*hrtlen = 0UL;
*hrttime = 0UL;
p = 0UL;
newcompos = 1;
/*WrInt(p, 10);WrStrLn(" compos"); */
for (;;) {
if (p+3UL>buf_len-1 || buf[p]==0) return;
if (((buf[p]=='$' && buf[p+1UL]=='H') && buf[p+2UL]=='R')
&& buf[p+3UL]=='[') break;
/*WrStrLn(" newcompos"); */
++p;
newcompos = 0;
}
p += 4UL;
ts = aprsdecode_systime;
unit = 1.0f;
duration = 0UL;
wcnt = 0UL;
dao.lat = 0.0f;
dao.long0 = 0.0f;
memset((char *)hrtposes,(char)0,
hrtposes_len*sizeof(struct aprsdecode_HRTPOS));
crc = 0UL;
for (;;) {
cmd = buf[p];
++p;
if (cmd==0 || p>buf_len-1) {
*hrtlen = 0UL; /* end of string? */
return;
}
if (cmd=='t') {
ts = aprsdecode_trunc(num(buf, buf_len, &p)+0.5f);
if (ts<3600UL) {
ts = corrtime(aprsdecode_systime, ts, 3600UL);
/* move system time max +-30min */
}
else if (ts<90000UL) {
ts = corrtime(aprsdecode_systime, ts-3600UL, 86400UL);
/* move system time max +-12h */
}
/* absolute time */
*hrttime = ts;
}
else if (cmd=='u') unit = num(buf, buf_len, &p);
else if (cmd=='p') {
/* take position from extension if correct */
posh.lat = aprspos_rad0(num(buf, buf_len, &p));
skip(buf, buf_len, &p);
posh.long0 = aprspos_rad0(num(buf, buf_len, &p));
if (aprspos_posvalid(posh)) *pos = posh;
}
else if (cmd=='a') {
/* take altitude from extension if correct */
r = num(buf, buf_len, &p);
if (r>(-1.E+4f) && r<50000.0f) {
*altitude = (int32_t)X2C_TRUNCI(r+0.5f,X2C_min_longint,
X2C_max_longint);
}
}
else if (cmd=='v') {
/* take speed from extension if correct */
r = num(buf, buf_len, &p);
if (r>0.0f && r<50000.0f) {
*speed = (uint32_t)(int32_t)X2C_TRUNCI(r+0.5f,
X2C_min_longint,X2C_max_longint);
}
}
else if (cmd=='d') {
/* ELSIF cmd="i" THEN (* define constant time intervall *)
*/
/* duration:=trunc(num()+0.5); */
/* DAO, correct position */
dao.lat = num(buf, buf_len, &p);
skip(buf, buf_len, &p);
dao.long0 = num(buf, buf_len, &p);
}
else if (cmd=='w') {
/* waypoints, first is difference from now */
if (wcnt<=hrtposes_len-1) {
{ /* with */
struct aprsdecode_HRTPOS * anonym = &hrtposes[wcnt];
anonym->dlat = num(buf, buf_len, &p);
skip(buf, buf_len, &p);
anonym->dlong = num(buf, buf_len, &p);
skip(buf, buf_len, &p);
anonym->dalt = num(buf, buf_len, &p);
anonym->notinterpolated = (anonym->dlat!=0.0f || anonym->dlong!=0.0f)
|| anonym->dalt!=0.0f;
skip(buf, buf_len, &p);
r = num(buf, buf_len, &p);
anonym->dtime = aprsdecode_trunc((float)fabs(r)+0.5f);
if (r<0.0f) anonym->dtime = 0UL-anonym->dtime;
}
++wcnt;
}
}
else if (cmd=='c') {
/* crc incl sender call and destination without ssid */
crc = aprsdecode_trunc(num(buf, buf_len, &p)+0.5f);
}
else if (cmd==']') break;
}
/*
IF (wcnt>0) & (hrtposes[0].dtime>0) THEN
r:=1.0/FLOAT(wcnt);
kt:=r*FLOAT(hrtposes[0].dtime);
kx:=r*hrtposes[0].dlong;
ky:=r*hrtposes[0].dlat;
kh:=r*hrtposes[0].dalt;
FOR i:=1 TO wcnt-1 DO
r:=FLOAT(wcnt-i);
hrtposes[i].dtime:=trunc(kt*r + 0.5)-hrtposes[i].dtime;
hrtposes[i].dlong:=hrtposes[i].dlong + kx*r;
hrtposes[i].dlat :=hrtposes[i].dlat + ky*r;
hrtposes[i].dalt :=hrtposes[i].dalt + kh*r;
END;
r:=unit*DEGUNIT;
pos.long:=pos.long + dao.long*r;
pos.lat :=pos.lat + dao.lat *r;
FOR i:=0 TO wcnt-1 DO
hrtposes[i].dtime:=ts - hrtposes[i].dtime;
hrtposes[i].dlong:=pos.long + hrtposes[i].dlong*r;
hrtposes[i].dlat :=pos.lat + hrtposes[i].dlat*r;
hrtposes[i].dalt :=VAL(REAL, altitude) + hrtposes[i].dalt*unit;
--WrInt(hrtposes[i].dtime, 6); WrFixed(r, 8,15); WrFixed(dao.lat*r, 8,15);
WrFixed(hrtposes[i].dlat*360.0/PI2, 8,15);
WrFixed(hrtposes[i].dlong*360.0/PI2, 8,15);
WrInt(VAL(INTEGER, hrtposes[i].dalt), 6);WrStrLn("");
END;
hrtlen:=wcnt;
END;
*/
if (wcnt>0UL && hrtposes[0UL].dtime>0UL) {
tmp = wcnt-1UL;
i = 1UL;
if (i<=tmp) for (;; i++) {
hrtposes[i].dtime += hrtposes[i-1UL].dtime-hrtposes[i-1UL]
.dtime/((wcnt-i)+1UL);
if (hrtposes[i-1UL].dtime>0UL) {
r = X2C_DIVR((float)hrtposes[i].dtime,
(float)hrtposes[i-1UL].dtime);
hrtposes[i].dlong = hrtposes[i].dlong+hrtposes[i-1UL].dlong*r;
hrtposes[i].dlat = hrtposes[i].dlat+hrtposes[i-1UL].dlat*r;
hrtposes[i].dalt = hrtposes[i].dalt+hrtposes[i-1UL].dalt*r;
}
if (i==tmp) break;
} /* end for */
r = unit*1.7453292519444E-7f;
pos->long0 = pos->long0+dao.long0*r;
pos->lat = pos->lat+dao.lat*r;
tmp = wcnt-1UL;
i = 0UL;
if (i<=tmp) for (;; i++) {
hrtposes[i].dtime = ts-hrtposes[i].dtime;
hrtposes[i].dlong = pos->long0+hrtposes[i].dlong*r;
hrtposes[i].dlat = pos->lat+hrtposes[i].dlat*r;
hrtposes[i].dalt = (float)*altitude+hrtposes[i].dalt*unit;
if (i==tmp) break;
} /* end for */
/*WrInt(hrtposes[i].dtime, 6); WrFixed(r, 8,15);
WrFixed(dao.lat*r, 8,15);
WrFixed(hrtposes[i].dlat*360.0/PI2, 8,15);
WrFixed(hrtposes[i].dlong*360.0/PI2, 8,15);
WrInt(VAL(INTEGER, hrtposes[i].dalt), 6);WrStrLn(""); */
*hrtlen = wcnt;
}
/* IF newcompos THEN compos:=p END; */
/*WrInt(compos, 10);WrStrLn(" composret"); */
} /* end GetHRT() */
static char r91(uint16_t * n, char c)
{
if ((uint8_t)c<'!' || (uint8_t)c>'|') return 0;
*n = (uint16_t)((uint32_t)( *n*91U)+((uint32_t)(uint8_t)c-33UL));
return 1;
} /* end r91() */
static void GetTLM(aprsdecode_TELEMETRY v, char b[], uint32_t b_len)
{
uint32_t ib;
uint32_t ia;
uint32_t j;
uint32_t i;
aprsdecode_TELEMETRY t;
uint32_t tmp;
ia = 0UL;
ib = 0UL;
i = 0UL;
while (i<b_len-1 && b[i]) {
if (b[i]=='|') {
ib = ia;
ia = i+1UL;
}
++i;
}
if (((ib>0UL && (ia-ib&1)) && ia-ib>=5UL) && ia-ib<=15UL) {
/*& (b[ia]=0C)*/
i = 0UL;
j = ib;
do {
t[i] = 0U;
if (!r91(&t[i], b[j]) || !r91(&t[i], b[j+1UL])) return;
++i;
j += 2UL;
} while (j+1UL<ia);
tmp = i-1UL;
ia = 0UL;
if (ia<=tmp) for (;; ia++) {
v[ia] = t[ia]+1U;
if (ia==tmp) break;
} /* end for */
/* b[ib-1]:=0C; */
aprsstr_Delstr(b, b_len, ib-1UL, (j-ib)+2UL);
}
} /* end GetTLM() */
/* === multiline */
extern void aprsdecode_GetMultiline(char buf[], uint32_t buf_len,
uint32_t * delfrom, struct aprsdecode_MULTILINE * md)
{
uint32_t idx;
uint32_t s;
uint32_t i;
char c;
float v;
float scale;
md->size = 0UL;
md->linetyp = 'a';
md->filltyp = '0';
i = 0UL;
s = 0UL;
*delfrom = (buf_len-1)+1UL;
while (i<buf_len-1 && buf[i]) {
c = buf[i];
if (s==0UL) {
if (c==' ') {
s = 1UL;
*delfrom = i;
}
}
else if (s==1UL) {
if (c=='}') s = 2UL;
else s = 0UL;
}
else if (s==2UL) {
if ((uint8_t)c>='a' && (uint8_t)c<='l') {
md->linetyp = c;
s = 3UL;
}
else s = 0UL;
}
else if (s==3UL) {
if ((uint8_t)c>='0' && (uint8_t)c<='9') {
md->filltyp = c;
s = 4UL;
}
else s = 0UL;
}
else if (s==4UL) {
if ((uint8_t)c>='!' && (uint8_t)c<='q') {
scale = osic_exp((float)((uint32_t)(uint8_t)c-33UL)
*1.15129255E-1f)*1.7453292519444E-6f;
/* 10^(x/20)*0.0001 deg */
s = 5UL;
idx = 0UL;
}
else s = 0UL;
}
else if (s==5UL || s==6UL) {
if ((uint8_t)c>='!' && (uint8_t)c<='z') {
if (idx<=40UL) {
v = ((float)(uint32_t)(uint8_t)c-78.0f)*scale;
/*WrFixed(v/RAD, 5, 10); WrStrLn(" deg"); */
if (s==5UL) {
md->vec[idx].lat = v;
s = 6UL;
}
else {
md->vec[idx].long0 = -v;
s = 5UL;
++idx;
}
}
else s = 0UL;
}
else if (s==5UL && c=='{') s = 7UL;
else s = 0UL;
/*
ELSIF (s>=7) & (s<=11) THEN
IF c>" " THEN INC(s) ELSE s:=0 END;
IF s=12 THEN
md.size:=idx;
RETURN (* protocol done *)
END;
*/
if (s==7UL) {
md->size = idx;
return;
}
}
else {
/* protocol done */
s = 0UL;
}
++i;
}
} /* end GetMultiline() */
extern char aprsdecode_ismultiline(char editing)
{
char s[251];
uint32_t i;
struct aprsdecode_MULTILINE ml;
if (editing) {
useri_confstr(useri_fRBPOSTYP, s, 251ul);
if (s[0U]!='L') return 0;
}
useri_confstr(useri_fRBCOMMENT, s, 251ul);
aprsdecode_GetMultiline(s, 251ul, &i, &ml);
return ml.size>=2UL;
} /* end ismultiline() */
#define aprsdecode_GRIDSIZE 88
#define aprsdecode_RA 3.4377467707849E+7
static void app(char buf[], uint32_t buf_len, float d)
{
char tmp;
/*WrFixed(d, 5, 8); WrStr(" "); */
d = d+78.5f;
if (d>=33.0f && d<=209.0f) {
aprsstr_Append(buf, buf_len,
(char *)(tmp = (char)aprsdecode_trunc(d),&tmp),
1u/1u);
}
} /* end app() */
static void EncMultiline(char buf[], uint32_t buf_len,
struct aprspos_POSITION * center,
struct aprsdecode_MULTILINE md)
{
uint32_t i;
uint32_t scaler;
float scale;
struct aprspos_POSITION max0;
struct aprspos_POSITION min0;
/* find size */
struct aprspos_POSITION * anonym;
char tmp;
min0.lat = 6.283185307f;
min0.long0 = 6.283185307f;
max0.lat = (-6.283185307f);
max0.long0 = (-6.283185307f);
i = 0UL;
while (i<md.size) {
{ /* with */
struct aprspos_POSITION * anonym = &md.vec[i];
if (anonym->lat<min0.lat) min0.lat = anonym->lat;
if (anonym->lat>max0.lat) max0.lat = anonym->lat;
if (anonym->long0<min0.long0) min0.long0 = anonym->long0;
if (anonym->long0>max0.long0) max0.long0 = anonym->long0;
}
++i;
}
center->lat = (max0.lat+min0.lat)*0.5f;
center->long0 = (max0.long0+min0.long0)*0.5f;
scale = max0.lat-min0.lat;
if (max0.long0-min0.long0>scale) scale = max0.long0-min0.long0;
/*WrFixed(scale, 10, 15); WrStrLn(" scaleo"); */
if (scale<1.57079632675f) {
if (scale>0.0f) {
scaler = aprsdecode_trunc(X2C_DIVR(osic_ln(X2C_DIVR(scale,
1.5358897417111E-4f)),1.15129255E-1f)+1.0f);
/*WrInt(scaler, 10);WrStrLn(" scaler"); */
scale = osic_exp((float)scaler*1.15129255E-1f)
*1.5358897417111E-4f; /* 10^(x/20)*0.0001 deg */
/*WrFixed(scale, 10, 15); WrStrLn(" scale"); */
scale = X2C_DIVR(88.0f,scale);
}
else {
scaler = 0UL;
scale = 0.0f;
}
aprsstr_Assign(buf, buf_len, " }", 3ul);
aprsstr_Append(buf, buf_len, (char *) &md.linetyp, 1u/1u);
aprsstr_Append(buf, buf_len, (char *) &md.filltyp, 1u/1u);
aprsstr_Append(buf, buf_len,
(char *)(tmp = (char)(33UL+scaler),&tmp), 1u/1u);
i = 0UL;
while (i<md.size) {
app(buf, buf_len, (md.vec[i].lat-center->lat)*scale);
app(buf, buf_len, (center->long0-md.vec[i].long0)*scale);
++i;
}
/* scale:=ln(scale/(0.0001*RAD))/(2.3025851/20.0); */
aprsstr_Append(buf, buf_len, "{", 2ul);
}
else {
/*
lati :=trunc(ABS(center.lat) *RA);
longi:=trunc(ABS(center.long)*RA);
latd :=VAL(CARDINAL, lati ) MOD 100;
longd:=VAL(CARDINAL, longi) MOD 100;
lati :=lati -latd;
longi:=longi-longd;
WrInt(latd,0); WrStrLn(" latd");
*/
/*WrStrLn(" <-appended"); */
buf[0UL] = 0;
}
} /* end EncMultiline() */
extern void aprsdecode_appendmultiline(struct aprspos_POSITION pos)
{
char h[251];
char cso[251];
char cs[251];
struct aprsdecode_MULTILINE ml;
struct aprspos_POSITION center;
uint32_t i;
char msgc;
/* make absolute */
struct aprspos_POSITION * anonym;
useri_confstr(useri_fRBPOS, cs, 251ul);
if (cs[0U]) aprstext_deganytopos(cs, 251ul, &center);
else aprsdecode_posinval(&center);
useri_confstr(useri_fRBCOMMENT, cso, 251ul);
aprsdecode_GetMultiline(cso, 251ul, &i, &ml);
if (i<=250UL) cso[i] = 0;
if (ml.size<2UL) aprsdecode_click.insreplaceline = 1;
/*WrStr("<<<");WrStr(cso);WrStrLn(">>> csodel"); */
i = 0UL;
while (i<ml.size) {
{ /* with */
struct aprspos_POSITION * anonym = &ml.vec[i];
anonym->lat = anonym->lat+center.lat;
anonym->long0 = anonym->long0+center.long0;
}
++i;
}
if (ml.size>40UL) ml.size = 41UL;
if (aprsdecode_click.polilinecursor>=ml.size) {
aprsdecode_click.polilinecursor = ml.size;
}
if (aprspos_posvalid(pos)) {
if (aprsdecode_click.insreplaceline) {
if (ml.size<40UL) {
/* insert line */
i = 40UL;
while (i>0UL && i>aprsdecode_click.polilinecursor) {
ml.vec[i] = ml.vec[i-1UL];
--i;
}
ml.vec[aprsdecode_click.polilinecursor] = pos;
if (aprsdecode_click.polilinecursor>=ml.size) {
++aprsdecode_click.polilinecursor;
}
++ml.size;
}
}
else ml.vec[aprsdecode_click.polilinecursor] = pos;
}
else {
/* delete line */
i = aprsdecode_click.polilinecursor;
while (i<40UL) {
ml.vec[i] = ml.vec[i+1UL];
++i;
}
if (ml.size>0UL) --ml.size;
}
if (ml.size<=33UL) msgc = 'b';
else if (ml.size<40UL) msgc = 'r';
else msgc = 'e';
aprsstr_IntToStr((int32_t)ml.size, 0UL, h, 251ul);
aprsstr_Append(h, 251ul, " elements", 10ul);
useri_textautosize(0L, 0L, 6UL, 2UL, msgc, h, 251ul);
EncMultiline(cs, 251ul, &center, ml);
aprsstr_Append(cso, 251ul, cs, 251ul);
useri_AddConfLine(useri_fRBCOMMENT, 1U, cso, 251ul);
/*WrInt(ml.size, 10); WrStr("<<<");WrStr(cso);WrStrLn(">>> csoapp"); */
aprstext_postostr(center, '3', cs, 251ul);
useri_AddConfLine(useri_fRBPOS, 1U, cs, 251ul); /* update new center */
aprsdecode_tracenew.winevent = 2000UL;
} /* end appendmultiline() */
extern void aprsdecode_modmultiline(uint32_t n)
{
struct aprspos_POSITION pos;
struct aprsdecode_MULTILINE ml;
uint32_t i;
char s[251];
uint32_t v;
if (n==1UL) {
/* del line */
aprsdecode_posinval(&pos);
aprsdecode_appendmultiline(pos);
}
else {
useri_confstr(useri_fRBCOMMENT, s, 251ul);
aprsdecode_GetMultiline(s, 251ul, &i, &ml);
if (n==2UL) {
/* colour */
if (ml.size>0UL) {
v = (uint32_t)(uint8_t)s[i+2UL];
v += 3UL;
if (v>108UL) v -= 12UL;
s[i+2UL] = (char)v;
}
}
else if (n==3UL) {
/* colour */
if (ml.size>0UL) {
v = (uint32_t)(uint8_t)s[i+2UL];
++v;
if (v%3UL==1UL) v -= 3UL;
s[i+2UL] = (char)v;
}
}
else if (n==4UL) {
/* poliline/poligone */
if (ml.size>0UL) {
s[i+3UL] = (char)((uint32_t)(uint8_t)s[i+3UL]+1UL);
if ((uint8_t)s[i+3UL]<'0' || (uint8_t)s[i+3UL]>'9') {
s[i+3UL] = '0';
}
}
}
useri_AddConfLine(useri_fRBCOMMENT, 1U, s, 251ul);
}
aprsdecode_tracenew.winevent = 2000UL;
} /* end modmultiline() */
/* === multiline */
/*
PROCEDURE checksymb(symt, symb:CHAR):BOOLEAN;
(* true for bad symbol *)
BEGIN
(*
RETURN (symt<>"/") & (symt<>"\") & ((InStr("#&0>AW^_acnsuvz", symb)<0)
OR ((symt<"0") OR (symt>"9")) & ((symt<"A") OR (symt>"Z")))
*)
RETURN (symt<>"/") & (symt<>"\") & (((symt<"0") OR (symt>"9"))
& ((symt<"A") OR (symt>"Z")) & ((symt<"a") OR (symt>"z")))
END checksymb;
*/
static aprsdecode_SET256 _cnst = {0x00000000UL,0x03FF8000UL,0x17FFFFFEUL,
0x07FFFFFEUL,0x00000000UL,0x00000000UL,0x00000000UL,
0x00000000UL};
extern int32_t aprsdecode_Decode(char buf[], uint32_t buf_len,
struct aprsdecode_DAT * dat)
{
uint32_t ia;
uint32_t iv;
uint32_t micedest;
uint32_t len;
uint32_t p;
uint32_t i;
char thirdparty;
memset((char *)dat,(char)0,sizeof(struct aprsdecode_DAT));
dat->speed = X2C_max_longcard;
dat->altitude = X2C_max_longint;
NoWX(&dat->wx);
len = 0UL;
while ((len<buf_len-1 && buf[len]) && buf[len]!='\015') ++len;
if (len==0UL || buf[0UL]=='#') return -1L;
i = 0UL;
do {
/* skip 3rd party headers */
p = i;
while (i<len && buf[i]!=':') ++i;
i += 2UL;
} while (!(i>len || buf[i-1UL]!='}'));
thirdparty = p!=0UL;
i = 0UL;
while (buf[p]!='>') {
/* source call */
if (p>=len || i>8UL) return -1L;
dat->symcall[i] = buf[p];
++p;
++i;
}
memcpy(dat->srcall,dat->symcall,9u);
++p;
micedest = p;
i = 0UL;
while (buf[p]!=',' && buf[p]!=':') {
/* dest call */
if (p>=len || i>8UL) return -1L;
dat->dstcall[i] = buf[p];
++p;
++i;
}
iv = 0UL;
while (buf[p]==',') {
if (iv>9UL) iv = 9UL;
++p;
if (((((thirdparty && buf[p]=='T') && buf[p+1UL]=='C')
&& buf[p+2UL]=='P') && buf[p+3UL]=='I')
&& buf[p+4UL]=='P' || ((buf[p]=='q' && buf[p+1UL]=='A')
&& buf[p+2UL]!='C') && iv<9UL) dat->igatep = iv+1UL;
if (dat->igatep==iv) dat->igaterawp = p;
i = 0UL;
while (buf[p]!=',' && buf[p]!=':') {
if (p>=len) return -1L;
if (buf[p]=='*') {
if (dat->igatep==0UL && dat->hbitp==0UL) dat->hbitp = iv+1UL;
}
else if (i<=8UL) {
dat->viacalls[iv][i] = buf[p];
++i;
}
++p;
}
/* IF dat.igatep=iv THEN dat.igatelen:=p-dat.igaterawp END; */
if (dat->igatep==iv) dat->igatelen = i;
++iv;
}
if (dat->hbitp>0UL || iv>(uint32_t)(dat->igatep!=0UL)
*2UL && viaghost(dat->viacalls[0UL], 9ul)) {
/* maybe not direct */
i = 0UL;
while ((i<9UL && i<dat->hbitp) && iscall(dat->viacalls[i])) ++i;
dat->hbitp = i+1UL;
}
else dat->hbitp = 0UL;
/*WrInt(dat.hbitp, 1);WrStrLn("=h"); */
if (p+1UL>=len || buf[p]!=':') return -1L;
++p;
dat->payload = p;
dat->typc = buf[dat->payload];
switch ((unsigned)dat->typc) {
case '\034':
case '\035':
case '\'':
case '`':
dat->type = aprsdecode_MICE;
break;
case '!':
case '$':
case '/':
case '=':
case '@':
dat->type = aprsdecode_POS;
break;
case '#':
case '*':
dat->type = aprsdecode_WETH;
break;
case '_':
dat->type = aprsdecode_PWETH;
dat->sym = '_'; /* positionless wx */
dat->symt = '/';
break;
case ':':
dat->type = aprsdecode_MSG;
break;
case ';':
dat->type = aprsdecode_OBJ;
break;
case ')':
dat->type = aprsdecode_ITEM;
break;
case '<':
dat->type = aprsdecode_SCAP;
break;
case '>':
dat->type = aprsdecode_STAT;
break;
case 'T':
dat->type = aprsdecode_TELE;
break;
case '?':
dat->type = aprsdecode_QUERY;
break;
default:;
dat->type = aprsdecode_UNKNOWN;
break;
} /* end switch */
++p;
if (dat->type==aprsdecode_OBJ) {
/* object */
if (buf[p+9UL]=='_' || buf[p+9UL]=='*') {
memcpy(dat->objectfrom,dat->symcall,9u);
i = 0UL;
while (i<=8UL) {
if (p+i>=len) return -1L;
dat->symcall[i] = buf[p+i];
++i;
}
if (buf[p+i]=='_') dat->objkill = '1';
else if (buf[p+i]!='*') dat->type = aprsdecode_UNKNOWN;
dat->timestamp = buf[p+16UL];
while (i>0UL && (uint8_t)dat->symcall[i-1UL]<=' ') {
dat->symcall[i-1UL] = 0;
--i;
}
}
else dat->type = aprsdecode_UNKNOWN;
}
else if (dat->typc==')') {
/* item */
memcpy(dat->objectfrom,dat->symcall,9u);
i = 0UL;
while (buf[p+i]!='!' && buf[p+i]!='_') {
if (p+i>=len) return -1L;
if (i<=8UL) dat->symcall[i] = buf[p+i];
++i;
}
if (i<=8UL) dat->symcall[i] = 0;
if (buf[p+i]=='_') dat->objkill = '1';
}
else if (dat->typc==':') {
/* msg, bulletin */
if (buf[p+9UL]==':') {
i = 0UL;
while (i<9UL && p<len) {
if (i<=8UL && (uint8_t)buf[p]>' ') dat->msgto[i] = buf[p];
++i;
++p;
}
if (X2C_STRCMP(dat->msgto,9u,dat->symcall,9u)==0) {
dat->type = aprsdecode_TELE; /* msg to itself */
}
++p;
i = 0UL;
if ((buf[p]=='r' && buf[p+1UL]=='e') && buf[p+2UL]=='j') {
dat->ackrej = aprsdecode_MSGREJ; /* reject */
}
else if ((buf[p]=='a' && buf[p+1UL]=='c') && buf[p+2UL]=='k') {
dat->ackrej = aprsdecode_MSGACK; /* ack */
}
if (dat->ackrej>aprsdecode_MSGMSG) {
p += 3UL;
while ((i<=4UL && (uint8_t)buf[p]>' ') && p<len) {
dat->acktext[i] = buf[p];
++i;
++p;
}
}
else {
i = p;
ia = len;
while (i<len) {
/* find last { */
if (buf[i]=='{') ia = i;
++i;
}
i = 0UL;
while (i<=66UL && p<ia) {
/* message text */
dat->msgtext[i] = buf[p];
++i;
++p;
}
dat->ackrej = aprsdecode_MSGMSG;
if (buf[p]=='{') {
/* message ack */
i = 0UL;
++p;
while ((i<=4UL && (uint8_t)buf[p]>' ') && p<len) {
dat->acktext[i] = buf[p];
++i;
++p;
}
}
}
}
}
else if (dat->typc=='?') {
/* general query */
i = 0UL;
while ((i<9UL && (uint8_t)buf[p]>' ') && p<len) {
if (i<=8UL) dat->msgto[i] = buf[p];
++i;
++p;
}
}
/* dat.course:=MAX(CARDINAL); */
dat->course = 0UL;
if (X2C_IN((int32_t)dat->type,12,0xCEU)) {
aprspos_GetPos(&dat->pos, &dat->speed, &dat->course, &dat->altitude,
&dat->sym, &dat->symt, buf, buf_len, micedest, dat->payload,
dat->comment0, 256ul, &dat->postyp);
aprspos_GetSym(dat->dstcall, 9ul, &dat->sym, &dat->symt);
if (!X2C_INL((uint8_t)dat->symt,256,_cnst)) {
dat->symt = 0; /* wrong symbol */
dat->sym = 0;
}
if (dat->postyp=='A' && dat->type==aprsdecode_OBJ) {
/* area object */
dat->areasymb.typ = (char)((dat->course/100UL)%10UL+48UL);
dat->areasymb.color = (uint8_t)(dat->speed/100UL);
dat->areasymb.dpos.lat = sqr((float)(dat->course%100UL))
*1.454441043287E-6f;
dat->areasymb.dpos.long0 = sqr((float)(dat->speed%100UL))
*1.454441043287E-6f;
if (dat->areasymb.typ=='6') {
dat->areasymb.dpos.long0 = -dat->areasymb.dpos.long0;
/* line to left down */
}
dat->pos.lat = dat->pos.lat-dat->areasymb.dpos.lat;
dat->pos.long0 = dat->pos.long0+dat->areasymb.dpos.long0;
/* shift pos to middle of area */
dat->speed = 0UL;
dat->course = 0UL;
}
if (dat->type==aprsdecode_OBJ || dat->type==aprsdecode_ITEM) {
aprsdecode_GetMultiline(dat->comment0, 256ul, &i, &dat->multiline);
if (dat->multiline.size>0UL) dat->postyp = 'L';
}
GetHRT(&dat->pos, &dat->altitude, &dat->speed, dat->comment0, 256ul,
dat->hrtposes, 32ul, &dat->hrtlen, &dat->hrttime);
GetTLM(dat->tlmvalues, dat->comment0, 256ul);
}
else {
i = 0UL;
p = dat->payload+(uint32_t)(dat->type!=aprsdecode_UNKNOWN);
while (p<len && i<=255UL) {
dat->comment0[i] = buf[p];
++p;
++i;
}
}
if (X2C_IN((int32_t)dat->type,12,0xCCU)) {
if (dat->sym=='_' || dat->type==aprsdecode_PWETH) {
if (dat->type==aprsdecode_PWETH) {
aprsstr_Delstr(dat->comment0, 256ul, 0UL, 8UL);
}
GetWX(&dat->wx, &dat->course, &dat->speed, dat->comment0, 256ul, 0);
}
else if (dat->sym=='@') {
GetWX(&dat->wx, &dat->course, &dat->speed, dat->comment0, 256ul, 1);
}
/*
IF dat.wx.storm>WXNORMAL THEN
dat.areasymb.typ:="5"; (* circle *)
dat.areasymb.color:=5;
dat.areasymb.dpos.lat :=0.006;
dat.areasymb.dpos.long:=0.0;
END;
*/
if (dat->course<1UL || dat->course>360UL) dat->course = 0UL;
}
return 0L;
} /* end Decode() */
static char getbeaconparm(char s[], uint32_t s_len,
uint32_t * time0, char * port)
/* time:port:rawframe */
{
uint32_t i;
*port = s[0UL];
if ((uint8_t)*port<' ' || s[1UL]!=':') return 0;
*time0 = 0UL;
i = 2UL;
while ((uint8_t)s[i]>='0' && (uint8_t)s[i]<='9') {
*time0 = ( *time0*10UL+(uint32_t)(uint8_t)s[i])-48UL;
++i;
}
if (s[i]!=':') return 0;
aprsstr_Delstr(s, s_len, 0UL, i+1UL);
return 1;
} /* end getbeaconparm() */
extern void aprsdecode_getbeaconname(char raw[], uint32_t raw_len,
char name[], uint32_t name_len, char symb[],
uint32_t symb_len, char * isobj,
char * isdel, char * isbad)
/* item object else src name */
{
struct aprsdecode_DAT dat;
char port;
uint32_t time0;
X2C_PCOPY((void **)&raw,raw_len);
*isobj = 0;
*isdel = 0;
*isbad = 1;
name[0UL] = 0;
if (getbeaconparm(raw, raw_len, &time0, &port)) {
beaconmacros(raw, raw_len, "", 1ul, "", 1ul, 0);
if (aprsdecode_Decode(raw, raw_len, &dat)==0L) {
aprsstr_Assign(name, name_len, dat.symcall, 9ul);
aprsstr_Assign(symb, symb_len, (char *) &dat.symt, 1u/1u);
aprsstr_Append(symb, symb_len, (char *) &dat.sym, 1u/1u);
*isobj = dat.type==aprsdecode_OBJ || dat.type==aprsdecode_ITEM;
*isdel = dat.objkill=='1';
*isbad = (uint8_t)dat.symt<' ' || (uint8_t)name[0UL]<=' ';
}
else *isbad = 1;
}
X2C_PFREE(raw);
} /* end getbeaconname() */
extern void aprsdecode_extractbeacon(char raw[], uint32_t raw_len,
char withparm, char macros)
/* monitor line to beacon config */
{
struct aprsdecode_DAT dat;
char port;
uint32_t i;
uint32_t time0;
int32_t j;
char s[1000];
X2C_PCOPY((void **)&raw,raw_len);
if (withparm) {
if (getbeaconparm(raw, raw_len, &time0, &port)) {
if (macros) beaconmacros(raw, raw_len, "", 1ul, "", 1ul, 0);
aprsstr_IntToStr((int32_t)time0, 0UL, s, 1000ul);
useri_AddConfLine(useri_fRBTIME, 1U, s, 1000ul);
useri_AddConfLine(useri_fRBPORT, 1U, (char *) &port, 1u/1u);
}
else {
useri_say("\012beacon syntax wrong, delete line!\012", 36ul, 4UL,
'e');
}
}
if (aprsdecode_Decode(raw, raw_len, &dat)==0L) {
if (dat.type==aprsdecode_OBJ || dat.type==aprsdecode_ITEM) {
aprsstr_Assign(s, 1000ul, dat.symcall, 9ul);
}
else {
useri_confstr(useri_fMYCALL, s, 1000ul);
if (aprstext_callwrong(s, 1000ul)) {
useri_xerrmsg("need legal \'My Call\' to build Beacon", 37ul);
}
}
useri_AddConfLine(useri_fRBNAME, 1U, s, 1000ul);
if (aprspos_posvalid(dat.pos)) {
if (dat.postyp=='A' && dat.type==aprsdecode_OBJ) {
/* area object */
dat.pos.lat = dat.pos.lat+dat.areasymb.dpos.lat;
dat.pos.long0 = dat.pos.long0-dat.areasymb.dpos.long0;
/* shift pos to upleft of area */
}
aprstext_postostr(dat.pos, '3', s, 1000ul);
useri_AddConfLine(useri_fRBPOS, 1U, s, 1000ul);
}
useri_AddConfLine(useri_fRBCOMMENT, 1U, dat.comment0, 256ul);
s[0U] = dat.symt;
s[1U] = dat.sym;
s[2U] = 0;
useri_AddConfLine(useri_fRBSYMB, 1U, s, 1000ul);
useri_AddConfLine(useri_fRBSPEED, 1U, "", 1ul);
useri_AddConfLine(useri_fRBDIR, 1U, "", 1ul);
if ((uint8_t)dat.areasymb.typ>='0') {
/* IntToStr(dat.areasymb.color*100+trunc(sqrt(dat.areasymb.dpos.long/(RAD/200.0/60.0)
)), 1, s); */
aprsstr_IntToStr((int32_t)((uint32_t)
dat.areasymb.color*100UL+aprsdecode_trunc(osic_sqrt(X2C_DIVR((float)
fabs(dat.areasymb.dpos.long0),1.454441043287E-6f)))), 1UL, s,
1000ul);
useri_AddConfLine(useri_fRBSPEED, 1U, s, 1000ul);
aprsstr_IntToStr((int32_t)(((uint32_t)(uint8_t)
dat.areasymb.typ-48UL)
*100UL+aprsdecode_trunc(osic_sqrt(X2C_DIVR((float)
fabs(dat.areasymb.dpos.lat),1.454441043287E-6f)))), 1UL, s,
1000ul);
useri_AddConfLine(useri_fRBDIR, 1U, s, 1000ul);
}
else if (dat.speed>0UL && dat.speed<2147483647UL) {
aprsstr_IntToStr((int32_t)aprsdecode_trunc((float)
dat.speed*1.852f), 1UL, s, 1000ul);
useri_AddConfLine(useri_fRBSPEED, 1U, s, 1000ul);
if (dat.course>0UL) {
aprsstr_IntToStr((int32_t)(dat.course%360UL), 1UL, s, 1000ul);
useri_AddConfLine(useri_fRBDIR, 1U, s, 1000ul);
}
}
if (dat.altitude<X2C_max_longint) {
aprsstr_IntToStr(dat.altitude, 1UL, s, 1000ul);
}
else s[0U] = 0;
useri_AddConfLine(useri_fRBALT, 1U, s, 1000ul);
s[1U] = 0;
s[0U] = 'b';
if (dat.type==aprsdecode_OBJ) {
if (dat.timestamp=='h') s[0U] = 'H';
else s[0U] = 'O';
if (dat.objkill=='1') s[0U] = 'P';
}
else if (dat.type==aprsdecode_ITEM) {
if (dat.objkill=='1') s[0U] = 'J';
else s[0U] = 'I';
}
useri_AddConfLine(useri_fRBTYP, 1U, s, 1000ul);
useri_AddConfLine(useri_fRBPOSTYP, 1U, (char *) &dat.postyp,
1u/1u);
if (withparm) {
s[0U] = 0;
j = aprsstr_InStr(dat.dstcall, 9ul, "-", 2ul);
/* move dest ssid to viapath */
if (j>=0L) {
aprsstr_Assign(s, 1000ul, dat.dstcall, 9ul);
aprsstr_Delstr(s, 1000ul, 0UL, (uint32_t)j);
dat.dstcall[j] = 0;
}
if (dat.type==aprsdecode_MICE) strncpy(dat.dstcall,"APLM01",9u);
useri_AddConfLine(useri_fRBDEST, 1U, dat.dstcall, 9ul);
useri_AddConfLine(useri_fRBNAME, 1U, dat.symcall, 9ul);
i = 0UL;
while (i<=9UL && dat.viacalls[i][0UL]) {
/* make via path */
if (s[0U]) aprsstr_Append(s, 1000ul, ",", 2ul);
aprsstr_Append(s, 1000ul, dat.viacalls[i], 9ul);
++i;
}
useri_AddConfLine(useri_fRBPATH, 1U, s, 1000ul);
}
else useri_AddConfLine(useri_fRBDEST, 1U, "APLM01", 7ul);
}
X2C_PFREE(raw);
} /* end extractbeacon() */
extern void aprsdecode_importbeacon(void)
{
/* op last pos frame to beacon config */
aprsdecode_pOPHIST opf;
aprsdecode_pOPHIST op;
aprsdecode_pFRAMEHIST pl;
aprsdecode_pFRAMEHIST pf;
struct aprsdecode_DAT dat;
if (useri_beaconediting && aprsdecode_click.entries>0UL) {
opf = aprsdecode_click.table[aprsdecode_click.selected].opf;
if (opf) {
op = aprsdecode_ophist0;
while (op && X2C_STRCMP(opf->call,9u,op->call,9u)) op = op->next;
if (op) {
pl = 0;
pf = op->frames;
while (pf) {
if (aprspos_posvalid(pf->vardat->pos)) pl = pf;
pf = pf->next;
}
if ((pl && pl->vardat) && aprsdecode_Decode(pl->vardat->raw,
500ul, &dat)==0L) {
aprsdecode_extractbeacon(pl->vardat->raw, 500ul, 0, 0);
useri_beaconed = 1;
useri_textautosize(0L, 0L, 5UL, 5UL, 'b', "Object Cloned to Be\
acon Editor!", 32ul);
}
}
}
}
} /* end importbeacon() */
static void beepmsg(char isack)
{
if (useri_configon(useri_fBEEPMSG)) {
aprsdecode_beeplim(100L, (uint32_t)useri_conf2int(useri_fBEEPMSG,
(uint32_t)isack*2UL, 20L, 8000L, 1000L),
(uint32_t)useri_conf2int(useri_fBEEPMSG,
(uint32_t)isack*2UL+1UL, 0L, 5000L, 250L));
}
} /* end beepmsg() */
static void popupmessage(const char from[], uint32_t from_len,
const char to[], uint32_t to_len, const char txt[],
uint32_t txt_len, const char ack[],
uint32_t ack_len, uint32_t time0, char port,
char isquery0, char kill,
struct aprspos_POSITION pos, const char item[],
uint32_t item_len)
{
aprsdecode_pMSGFIFO pl;
aprsdecode_pMSGFIFO pm;
int32_t cnt;
pm = aprsdecode_msgfifo0;
pl = 0;
while (pm) {
/* delete older same messages */
if (((aprsstr_StrCmp(pm->from, 9ul, from,
from_len) && aprsstr_StrCmp(pm->to, 9ul, to,
to_len)) && aprsstr_StrCmp(pm->txt, 67ul, txt,
txt_len)) && aprsstr_StrCmp(pm->ack, 5ul, ack, ack_len)) {
if (pl==0) aprsdecode_msgfifo0 = pm->next;
else pl->next = pm->next;
osic_free((char * *) &pm, sizeof(struct aprsdecode_MSGFIFO));
pm = aprsdecode_msgfifo0;
pl = 0;
}
else {
pl = pm;
pm = pm->next;
}
}
osic_alloc((char * *) &pm, sizeof(struct aprsdecode_MSGFIFO));
if (pm==0) {
osi_WrStrLn("msg out of memory", 18ul);
return;
}
aprsstr_Assign(pm->from, 9ul, from, from_len);
aprsstr_Assign(pm->to, 9ul, to, to_len);
aprsstr_Assign(pm->txt, 67ul, txt, txt_len);
aprsstr_Assign(pm->ack, 5ul, ack, ack_len);
aprsstr_Assign(pm->itemname, 9ul, item, item_len);
pm->itempos = pos;
pm->time0 = time0;
pm->port = port;
pm->query = isquery0;
pm->next = 0;
pm->deleteitem = kill;
cnt = 1L;
if (aprsdecode_msgfifo0==0) aprsdecode_msgfifo0 = pm;
else {
cnt = 2L;
pl = aprsdecode_msgfifo0;
while (pl->next) {
pl = pl->next;
++cnt;
}
pl->next = pm;
}
if (useri_nextmsg==0L) {
if (useri_configon(useri_fPOPUPMSG)) useri_nextmsg = -cnt;
}
else useri_nextmsg = -labs(useri_nextmsg);
} /* end popupmessage() */
extern void aprsdecode_getactack(aprsdecode_MONCALL call, char ack[],
uint32_t ack_len)
/* get actual message ack */
{
aprsdecode_pOPHIST op;
aprsdecode_pFRAMEHIST pf;
struct aprsdecode_DAT dat;
char mid[2];
char aa[2];
char ok0;
aprsdecode_MONCALL my;
ack[0UL] = 0;
op = findop(call, 0);
if (op) {
useri_confstr(useri_fMYCALL, my, 9ul);
pf = op->frames;
while (pf) {
if (((aprsdecode_Decode(pf->vardat->raw, 500ul,
&dat)>=0L && dat.type==aprsdecode_MSG)
&& dat.ackrej==aprsdecode_MSGMSG) && X2C_STRCMP(dat.msgto,9u,
my,9u)==0) {
ok0 = replyack(aa, 2ul, mid, 2ul, dat.acktext, 5ul);
if (mid[0U]) aprsstr_Assign(ack, ack_len, mid, 2ul);
}
pf = pf->next;
}
}
} /* end getactack() */
static char ch(uint32_t n)
{
if (n<10UL) n += 48UL;
else if (n<36UL) n += 55UL;
else n += 61UL;
return (char)n;
} /* end ch() */
extern void aprsdecode_acknumstr(char aa[], uint32_t aa_len,
uint32_t n)
{
aa[0UL] = ch((n/62UL)%62UL);
aa[1UL] = ch(n%62UL);
if (aa_len-1>=2UL) aa[2UL] = 0;
} /* end acknumstr() */
static char sendtxmsg(uint32_t acknum, const aprsdecode_MONCALL to,
const char txt[], uint32_t txt_len, char port,
char rfonly, uint32_t ackcnt, char errm[],
uint32_t errm_len)
{
uint32_t i;
aprsdecode_FRAMEBUF s;
aprsdecode_FRAMEBUF rfs;
char am[51];
char h1[51];
char h[51];
char tmp;
if (ackcnt==0UL) strncpy(am,"Ack ",51u);
else strncpy(am,"Msg ",51u);
errm[0UL] = 0;
if (to[0UL]==0) return 0;
useri_confstr(useri_fMYCALL, rfs, 512ul);
if (aprstext_callwrong(rfs, 512ul)) {
aprsstr_Assign(errm, errm_len, "Msg not sent (no valid Mycall)", 31ul);
return 0;
}
aprsstr_Append(rfs, 512ul, ">", 2ul);
if (rfonly) useri_confstr(useri_fMSGRFDEST, h, 51ul);
else useri_confstr(useri_fMSGNETDEST, h, 51ul);
aprsstr_Append(rfs, 512ul, h, 51ul);
if (h[0U]==0) {
aprsstr_Assign(errm, errm_len, am, 51ul);
aprsstr_Append(errm, errm_len, "not sent (no Port set)", 23ul);
return 0;
}
if (port=='A' || (uint8_t)port>='1' && (uint8_t)port<='9') {
/* radio so add via path */
useri_confstr(useri_fMSGPATH, h, 51ul);
if ((uint8_t)h[0U]>='1' && (uint8_t)h[0U]<='7') {
aprsstr_Append(rfs, 512ul, "-", 2ul);
aprsstr_Append(rfs, 512ul, (char *) &h[0U], 1u/1u);
}
else if (h[0U]) {
aprsstr_Append(rfs, 512ul, ",", 2ul);
aprsstr_Append(rfs, 512ul, h, 51ul);
}
}
aprsstr_Append(rfs, 512ul, ":", 2ul);
strncpy(s,":",512u);
aprsstr_Append(s, 512ul, to, 9ul);
for (i = aprsstr_Length(to, 9ul); i<=8UL; i++) {
aprsstr_Append(s, 512ul, " ", 2ul);
} /* end for */
aprsstr_Append(s, 512ul, ":", 2ul);
if (ackcnt==0UL) aprsstr_Append(s, 512ul, "ack", 4ul);
aprsstr_Append(s, 512ul, txt, txt_len);
if (acknum>0UL) {
aprsstr_Append(s, 512ul, "{", 2ul);
aprsdecode_acknumstr(h, 51ul, acknum);
aprsstr_Append(s, 512ul, h, 51ul);
aprsstr_Append(s, 512ul, "}", 2ul);
aprsdecode_getactack(to, h, 51ul);
if (h[0U]) aprsstr_Append(s, 512ul, h, 51ul);
}
/*WrInt(ORD(rfonly), 10);WrStrLn(port); */
aprsstr_Append(rfs, 512ul, s, 512ul);
for (i = 0UL; i<=3UL; i++) {
/* try the rf ports */
if ((useri_configon((uint8_t)(36UL+i))
&& (port=='A' || port==(char)(i+49UL))) && Sendudp(rfs,
512ul, i, 0UL)>0L) {
memcpy(h,am,51u);
if (ackcnt==1UL) aprsstr_Append(h, 51ul, "sent", 5ul);
else {
aprsstr_Append(h, 51ul, "resent(", 8ul);
aprsstr_IntToStr((int32_t)ackcnt, 0UL, h1, 51ul);
aprsstr_Append(h, 51ul, h1, 51ul);
aprsstr_Append(h, 51ul, ")", 2ul);
}
aprsstr_Append(h, 51ul, " to ", 5ul);
aprsstr_Append(h, 51ul, to, 9ul);
aprsstr_Append(h, 51ul, " on Port ", 10ul);
aprsstr_Append(h, 51ul, (char *)(tmp = (char)(i+49UL),&tmp),
1u/1u);
useri_say(h, 51ul, 2UL, 'b');
return 1;
}
} /* end for */
/* make it better */
if (!rfonly && port=='N') {
SendNet(aprsdecode_tcpsocks, "", 1ul, s, 512ul, 1, errm, errm_len);
if (errm[0UL]) {
memcpy(h,am,51u);
aprsstr_Append(h, 51ul, "not sent ", 10ul);
aprsstr_Append(h, 51ul, errm, errm_len);
aprsstr_Assign(errm, errm_len, h, 51ul);
}
else {
memcpy(h,am,51u);
aprsstr_Append(h, 51ul, "(re)sent to ", 13ul);
aprsstr_Append(h, 51ul, to, 9ul);
aprsstr_Append(h, 51ul, " on Net", 8ul);
useri_say(h, 51ul, 2UL, 'b');
}
return 1;
}
else {
aprsstr_Assign(errm, errm_len, am, 51ul);
aprsstr_Append(errm, errm_len, "not sent (delete Msg or open outgoing P\
ort)", 44ul);
return 0;
}
return 0;
} /* end sendtxmsg() */
static void iteminmsg(const char from[], uint32_t from_len,
const char to[], uint32_t to_len, const char txt[],
uint32_t txt_len, struct aprspos_POSITION * pos,
char name[], uint32_t name_len, char * del)
/* test for and draw item in a message */
{
char h[1000];
char s[1000];
struct aprsdecode_DAT dat;
aprsdecode_posinval(pos);
aprsstr_Assign(s, 1000ul, from, from_len);
aprsstr_Append(s, 1000ul, ">", 2ul);
aprsstr_Append(s, 1000ul, to, to_len);
aprsstr_Append(s, 1000ul, ":", 2ul);
aprsstr_Append(s, 1000ul, txt, txt_len);
if ((aprsdecode_Decode(s, 1000ul,
&dat)>=0L && dat.type==aprsdecode_ITEM)
&& aprspos_posvalid(dat.pos)) {
aprsstr_Assign(h, 1000ul, "0:0:", 5ul);
aprsstr_Append(h, 1000ul, s, 1000ul);
aprsdecode_drawbeacon(h, 1000ul);
*pos = dat.pos;
aprsstr_Assign(name, name_len, dat.symcall, 9ul);
*del = dat.objkill=='1';
}
} /* end iteminmsg() */
static void ackmsg(const char from[], uint32_t from_len,
const char rep[], uint32_t rep_len, uint8_t rej)
{
aprsdecode_pTXMESSAGE pm;
char bb[2];
char aa[2];
/*
WrStr("replyack:");
WrStr(from);
WrStr("|");
WrStr(rep);
WrStr("|");
WrLn;
*/
if (rej==aprsdecode_MSGMSG) {
if (!replyack(bb, 2ul, aa, 2ul, rep, rep_len)) return;
}
else {
/* message only */
aprsstr_Assign(bb, 2ul, rep, rep_len);
}
pm = aprsdecode_txmessages;
while (pm) {
if (pm->acktime==0UL && X2C_STRCMP(from,from_len,pm->to,9u)==0) {
aprsdecode_acknumstr(aa, 2ul, pm->acknum);
if (X2C_STRCMP(aa,2u,bb,2u)==0) {
/* message acked now */
pm->acktime = aprsdecode_realtime;
pm->rej = rej==aprsdecode_MSGREJ;
useri_refresh = 1;
/*WrInt(ORD(rej), 10); WrStrLn("=rej"); */
beepmsg(1);
}
}
pm = pm->next;
}
} /* end ackmsg() */
#define aprsdecode_QUERYRESPONSEWINDOW 30
/* time after sending a msg to display already received query response */
static void showmsg(const char from[], uint32_t from_len,
const char to[], uint32_t to_len, const char txt[],
uint32_t txt_len, const char ack[],
uint32_t ack_len, uint8_t rej, char my,
char query, char port)
{
aprsdecode_pOPHIST op;
aprsdecode_pFRAMEHIST opf;
aprsdecode_ACKTEXT aack;
aprsdecode_ACKTEXT rep;
aprsdecode_MONCALL call;
struct aprsdecode_DAT dat;
struct aprspos_POSITION itempos;
aprsdecode_MONCALL itemname;
char delitem;
char s[501];
opf = 0;
if (ack[0UL]) {
aprsstr_Assign(call, 9ul, from, from_len);
op = findop(call, 1); /* find sender of msg */
if (op) {
opf = op->frames;
for (;;) {
if (opf==0) break;
if ((((aprsdecode_Decode(opf->vardat->raw, 500ul,
&dat)>=0L && dat.type==aprsdecode_MSG)
&& dat.ackrej==aprsdecode_MSGMSG) && X2C_STRCMP(dat.msgto,9u,
to,to_len)==0) && X2C_STRCMP(txt,txt_len,dat.msgtext,
67u)==0) {
if (ack[0UL]==0) {
if (lastmsgtx+30UL<aprsdecode_realtime) {
break; /* we do not wait for a query response */
}
}
else if (X2C_STRCMP(dat.acktext,5u,ack,
ack_len)==0 || replyack(rep, 5ul, aack, 5ul, dat.acktext,
5ul) && X2C_STRCMP(aack,5u,ack,ack_len)==0) {
break; /* we have this msg got before */
}
}
opf = opf->next;
}
}
}
if (opf==0) {
if (my || useri_configon(useri_fMSGALLSSID) && (!aprsstr_StrCmp(from,
from_len, to, to_len) || useri_configon(useri_fPASSSELFMSG))) {
if (!useri_configon(useri_fPOPUPMSG)) {
if (query) strncpy(s,"Query from ",501u);
else strncpy(s,"Message from ",501u);
aprsstr_Append(s, 501ul, from, from_len);
aprsstr_Append(s, 501ul, " to ", 5ul);
aprsstr_Append(s, 501ul, to, to_len);
aprsstr_Append(s, 501ul, " (click on M Button)", 21ul);
useri_textautosize(0L, 5L, 6UL, 0UL, 'y', s, 501ul);
}
iteminmsg(from, from_len, to, to_len, txt, txt_len, &itempos,
itemname, 9ul, &delitem);
popupmessage(from, from_len, to, to_len, txt, txt_len, ack, ack_len,
aprsdecode_realtime, port, query, delitem, itempos,
itemname, 9ul);
++aprsdecode_tracenew.winevent;
beepmsg(0);
}
}
else if (aprsdecode_verb) {
osi_WrStr("seen msg:", 10ul);
osi_WrStr(from, from_len);
osi_WrStr(">", 2ul);
osi_WrStr(to, to_len);
osi_WrStr("|", 2ul);
osi_WrStr(txt, txt_len);
osi_WrStr("|", 2ul);
osi_WrStr(ack, ack_len);
osi_WrStr("|", 2ul);
osi_WrStr((char *) &port, 1u/1u);
osic_WrLn();
}
} /* end showmsg() */
static char isquery(const struct aprsdecode_DAT dat, char port)
{
uint32_t j;
uint32_t i;
char err[201];
char wdata[201];
char key[201];
char path[201];
char s[201];
/* IF dat.msgtext[0]<>"?" THEN RETURN FALSE END; */
aprsstr_Assign(path, 201ul, dat.symcall, 9ul);
aprsstr_Append(path, 201ul, ">", 2ul);
aprsstr_Append(path, 201ul, dat.dstcall, 9ul);
i = 0UL;
while (dat.viacalls[i][0UL]) {
aprsstr_Append(path, 201ul, ",", 2ul);
aprsstr_Append(path, 201ul, dat.viacalls[i], 9ul);
if (i+2UL==dat.hbitp) aprsstr_Append(path, 201ul, "*", 2ul);
++i;
}
i = 0UL;
for (;;) {
useri_confstrings(useri_fQUERYS, i, 0, s, 201ul);
if (s[0U]==0) break;
j = (uint32_t)aprsstr_InStr(s, 201ul, ":", 2ul);
if (j>0UL) {
aprsstr_Assign(key, 201ul, s, 201ul);
key[j] = 0;
aprsstr_Delstr(s, 201ul, 0UL, j+1UL);
if (aprsstr_InStr(dat.msgtext, 67ul, key, 201ul)==0L) {
aprsstr_Assign(wdata, 201ul, dat.msgtext, 67ul);
aprsstr_Delstr(wdata, 201ul, 0UL, aprsstr_Length(key, 201ul));
beaconmacros(s, 201ul, path, 201ul, wdata, 201ul, 1);
if (s[0U]==0) return 1;
if (!sendtxmsg(0UL, dat.symcall, s, 201ul, port, port!='N', 1UL,
err, 201ul)) {
useri_xerrmsg(err, 201ul);
return 0;
}
else {
useri_xerrmsg(err, 201ul);
return 1;
}
}
}
++i;
}
/*WrStrLn(port);WrStrLn(dat.symcall);WrStrLn(dat.msgtext); */
return 0;
} /* end isquery() */
static void getmessage(aprsdecode_pTCPSOCK cp, uint32_t up,
const struct aprsdecode_DAT dat)
/* if first: popup, if full match & lastack>10s: send ack */
{
uint32_t i;
char void0;
char query;
char fit;
char my[100];
char h[100];
char port;
/* my:MONCALL; */
char ch0;
useri_confstr(useri_fMYCALL, my, 100ul);
if (aprstext_callwrong(my, 100ul)) return;
aprsstr_Assign(h, 100ul, dat.msgto, 9ul);
fit = 0;
i = 0UL;
while (h[i]==my[i] && h[i]) {
if (h[i]=='-' || my[i]=='-') fit = 1;
++i;
}
if (i==0UL) return;
ch0 = my[i];
if (h[i]==0 && ch0=='-' || h[i]=='-' && ch0==0) fit = 1;
if (cp) port = 'N';
else port = (char)(up+48UL);
if (ch0==0 && h[i]==0) {
/* WrStr("my message "); */
if (dat.ackrej==aprsdecode_MSGMSG) {
/*FOR i:=0 TO HIGH(dat.acktext) DO WrInt(ORD(dat.acktext[i]), 4);
END; WrStrLn("=ack"); */
query = isquery(dat, port);
showmsg(dat.symcall, 9ul, dat.msgto, 9ul, dat.msgtext, 67ul,
dat.acktext, 5ul, dat.ackrej, 1, query, port);
if (!query && dat.acktext[0UL]) {
void0 = sendtxmsg(0UL, dat.symcall, dat.acktext, 5ul, port,
port!='N', 0UL, h, 100ul);
useri_xerrmsg(h, 100ul);
}
}
if (dat.acktext[0UL]) {
ackmsg(dat.symcall, 9ul, dat.acktext, 5ul, dat.ackrej);
}
}
else if (fit && dat.ackrej==aprsdecode_MSGMSG) {
/* WrStr("other ssid message "); */
showmsg(dat.symcall, 9ul, dat.msgto, 9ul, dat.msgtext, 67ul,
dat.acktext, 5ul, dat.ackrej, 0, 0, port);
}
} /* end getmessage() */
#define aprsdecode_SETPORT 2
#define aprsdecode_DEL 6
#define aprsdecode_KICK 5
#define aprsdecode_RESTART 4
#define aprsdecode_HOLD 3
#define aprsdecode_EDIT 1
extern void aprsdecode_deltxmsg(uint32_t cmd, uint32_t n)
/* delete/edit tx message number */
{
aprsdecode_pTXMESSAGE po;
aprsdecode_pTXMESSAGE pm;
pm = aprsdecode_txmessages;
if (pm) {
if (cmd==6UL || cmd==1UL) {
if (n==0UL) aprsdecode_txmessages = aprsdecode_txmessages->next;
else {
do {
po = pm;
pm = pm->next;
--n;
} while (!(n==0UL || pm==0));
if (pm) po->next = pm->next;
}
if (pm) {
if (cmd==1UL) {
useri_AddConfLine(useri_fMSGTEXT, 0U, pm->msgtext, 67ul);
useri_AddConfLine(useri_fMSGTO, 0U, pm->to, 9ul);
useri_AddConfLine(useri_fMSGPORT, 0U, (char *) &pm->port,
1u/1u);
}
osic_free((char * *) &pm,
sizeof(struct aprsdecode_TXMESSAGE));
}
}
else {
while (n>0UL && pm) {
pm = pm->next;
--n;
}
if (pm && pm->acktime==0UL) {
if (cmd==5UL) pm->txtime = 0UL;
else if (cmd==4UL) {
pm->txtime = 0UL;
pm->acktime = 0UL;
pm->txcnt = 0UL;
pm->heard = 0;
}
else if (cmd==3UL) pm->txtime = X2C_max_longcard;
else if (cmd==2UL) {
useri_confstr(useri_fMSGPORT, (char *) &pm->port, 1u/1u);
}
}
}
}
} /* end deltxmsg() */
extern void aprsdecode_makemsg(char ack)
{
aprsdecode_pTXMESSAGE pn;
aprsdecode_pTXMESSAGE pm;
char po;
char ht[101];
char hm[101];
char mes[101];
int32_t i;
char c;
struct aprsdecode_TXMESSAGE * anonym;
int32_t tmp;
mes[0U] = 0;
useri_confstr(useri_fMSGPORT, (char *) &po, 1u/1u);
if (po==' ' || X2C_CAP(po)=='A') po = 'A';
else if (X2C_CAP(po)=='N' || X2C_CAP(po)=='I') po = 'N';
else if ((uint8_t)po<'0' || (uint8_t)po>'9') {
strncpy(mes,"need Port where to send",101u);
}
useri_confstr(useri_fMSGTO, ht, 101ul); /* no destination call */
if (ht[0U]==0) strncpy(mes,"need call to send to",101u);
useri_confstr(useri_fMSGTEXT, hm, 101ul);
if (hm[0U]==0) {
/* empty message line */
if (!sentemptymsg) {
strncpy(mes,"send empty line? if so, enter again",101u);
sentemptymsg = 1;
}
else sentemptymsg = 0;
}
else sentemptymsg = 0;
pn = aprsdecode_txmessages; /* look for same msg pending */
while (pn) {
if (((((ack && pn->acknum>0UL) && pn->acktime==0UL)
&& aprsstr_StrCmp(pn->to, 9ul, ht,
101ul)) && aprsstr_StrCmp(pn->msgtext, 67ul, hm,
101ul)) && pn->port==po) {
strncpy(mes,"same message pending, try [kick] or delete",101u);
}
pn = pn->next;
}
if (mes[0U]==0) {
osic_alloc((char * *) &pm, sizeof(struct aprsdecode_TXMESSAGE));
if (pm==0) Err("out of memory", 14ul);
memset((char *)pm,(char)0,sizeof(struct aprsdecode_TXMESSAGE));
{ /* with */
struct aprsdecode_TXMESSAGE * anonym = pm;
anonym->port = po;
useri_confstr(useri_fMSGTO, anonym->to, 9ul);
aprsstr_Caps(anonym->to, 9ul);
useri_confstr(useri_fMSGTEXT, anonym->msgtext, 67ul);
tmp = (int32_t)aprsstr_Length(anonym->msgtext, 67ul)-1L;
i = 0L;
if (i<=tmp) for (;; i++) {
c = anonym->msgtext[i];
if (c=='|' || c=='~') {
/* OR (c=cMSGACK) */
anonym->msgtext[i] = ' ';
}
if (i==tmp) break;
} /* end for */
if (ack) {
if (msgmid==0UL) {
msgmid = (aprsdecode_realtime%68400UL)/30UL;
/* init msg number with 30s daytime */
}
msgmid = (msgmid+1UL)%3843UL;
anonym->acknum = msgmid+1UL; /* 0 is query with no ack */
}
}
pn = aprsdecode_txmessages;
if (pn==0) aprsdecode_txmessages = pm;
else {
while (pn->next) pn = pn->next;
pn->next = pm;
}
useri_clrmsgtext("", 1ul);
useri_textautosize(0L, 5L, 6UL, 5UL, 'b', "Msg Stored", 11ul);
}
useri_xerrmsg(mes, 101ul);
} /* end makemsg() */
#define aprsdecode_MAXMSGTXTIME 3600
#define aprsdecode_MAXMSGRETRY 20
#define aprsdecode_MAXNOACKRETRY 1
#define aprsdecode_MSGNOTXTIME 10
#define aprsdecode_MSGTXTIME 15
/* my:MONCALL; */
static void sendmsg(void)
{
aprsdecode_pTXMESSAGE pn;
aprsdecode_pTXMESSAGE pm;
uint32_t t;
uint32_t maxret;
uint32_t tc;
char port;
char sent;
char err[101];
if (lastmsgtx>aprsdecode_realtime) lastmsgtx = aprsdecode_realtime;
/* confstr(fMYCALL, my); */
/* IF (lastmsgtx+MSGNOTXTIME<realtime) & (Length(my)>=3) THEN */
if (lastmsgtx+10UL<aprsdecode_realtime) {
err[0U] = 0;
pm = aprsdecode_txmessages;
for (;;) {
if (pm==0) break;
if (pm->acknum>0UL) maxret = 20UL;
else maxret = 1UL;
if ((pm->acktime==0UL && pm->txtime!=X2C_max_longcard)
&& (pm->txcnt<maxret || pm->txtime==0UL)) {
tc = pm->txcnt;
t = 15UL;
for (;;) {
if (tc<=1UL) break;
t += t;
--tc;
if (t>3600UL) {
t = 3600UL;
break;
}
}
if (pm->txtime+t<=aprsdecode_realtime) {
pn = aprsdecode_txmessages;
while (pn!=pm && ((((pn->acknum==0UL || pn->acktime>0UL)
|| pn->txcnt>=20UL) || !aprsstr_StrCmp(pn->to, 9ul, pm->to,
9ul)) || pn->txtime==X2C_max_longcard)) pn = pn->next;
if (pn==pm) {
/* not older unacked msg to this call */
port = pm->port;
sent = 0;
if ((pm->txcnt<=(uint32_t)pm->heard || pm->txtime==0UL)
&& (port=='N' || port=='A')) {
if (sendtxmsg(pm->acknum, pm->to, pm->msgtext, 67ul,
'N', 0, pm->txcnt+1UL, err, 101ul) && err[0U]==0) sent = 1;
}
if (port=='A' || (uint8_t)port>='1' && (uint8_t)
port<='9') {
if (sendtxmsg(pm->acknum, pm->to, pm->msgtext, 67ul,
port, sent || port!='A', pm->txcnt+1UL, err,
101ul) && err[0U]==0) sent = 1;
else if (sent || pm->txcnt>0UL) err[0U] = 0;
}
if (sent) {
++pm->txcnt;
pm->txtime = aprsdecode_realtime;
lastmsgtx = aprsdecode_realtime;
useri_refresh = 1;
break; /* send 1 msg a time */
}
}
}
}
pm = pm->next;
}
useri_xerrmsg(err, 101ul);
}
} /* end sendmsg() */
static void setmsgheard(const aprsdecode_MONCALL us)
/* set heard flag in tx msg if user heard now */
{
aprsdecode_pTXMESSAGE pm;
pm = aprsdecode_txmessages;
for (;;) {
if (pm==0) break;
if ((pm->acktime==0UL && pm->txcnt==1UL) && aprsstr_StrCmp(pm->to, 9ul,
us, 9ul)) pm->heard = 1;
pm = pm->next;
}
} /* end setmsgheard() */
extern aprsdecode_pOPHIST aprsdecode_selop(void)
{
if (aprsdecode_click.entries>0UL) {
return aprsdecode_click.table[aprsdecode_click.selected].opf;
}
else return 0;
return 0;
} /* end selop() */
/*
PROCEDURE objsender(op:pOPHIST; VAR s:ARRAY OF CHAR);
(* find (last) sender of an item/object *)
VAR dat:DAT;
f:pFRAMEHIST;
BEGIN
s[0]:=0C;
IF (op<>NIL) & (ISOBJECT IN op^.drawhints) THEN
f:=op^.frames;
IF f<>NIL THEN
WHILE f^.next<>NIL DO f:=f^.next END;
(* goto last frame *)
IF (Decode(f^.vardat^.raw, dat)>=0) & ((dat.type=OBJ) OR (dat.type=ITEM))
THEN Assign(s, dat.objectfrom) END;
END;
END;
END objsender;
*/
extern void aprsdecode_objsender(aprsdecode_pOPHIST op, char s[],
uint32_t s_len)
/* find (last) sender of an item/object */
{
struct aprsdecode_DAT dat;
aprsdecode_pFRAMEHIST f;
aprsdecode_pOPHIST o;
s[0UL] = 0;
if (op) {
if ((0x2U & op->drawhints)) {
f = op->frames;
if (f) {
while (f->next) f = f->next;
if (aprsdecode_Decode(f->vardat->raw, 500ul,
&dat)>=0L && (dat.type==aprsdecode_OBJ || dat.type==aprsdecode_ITEM)
) aprsstr_Assign(s, s_len, dat.objectfrom, 9ul);
}
}
else {
o = aprsdecode_ophist0;
for (;;) {
if (o==0) break;
f = o->frames;
if (((f && aprsdecode_Decode(f->vardat->raw, 500ul,
&dat)>=0L) && (dat.type==aprsdecode_OBJ || dat.type==aprsdecode_ITEM)
) && X2C_STRCMP(dat.objectfrom,9u,op->call,9u)==0) {
aprsstr_Assign(s, s_len, op->call, 9ul);
break;
}
o = o->next;
}
}
}
} /* end objsender() */
#define aprsdecode_MAXDELAY 30
/* add seconds to time */
static void timespeed(aprsdecode_pFRAMEHIST lastf,
struct aprspos_POSITION pos1, uint32_t time1,
uint8_t * err)
{
float d;
uint32_t t;
if (((((*err&0xFU)!=0U || lastf==0) || (lastf->nodraw&0xFU)!=0U)
|| !aprspos_posvalid(lastf->vardat->pos))
|| !aprspos_posvalid(pos1)) return;
d = aprspos_distance(lastf->vardat->pos, pos1);
/*
IF d>50.0 THEN INCL(err, eDIST) END;
*/
if (lastf->time0>=time1) t = 0UL;
else t = time1-lastf->time0;
if (X2C_DIVR(d*3600.0f,(float)(t+30UL))>maxspeed) *err |= 0x10U;
} /* end timespeed() */
#define aprsdecode_MINHOP 20.0
#define aprsdecode_HOPPART 0.5
/* MINSPIKE=0.02; (* min distance to mark as spike *) */
#define aprsdecode_SPIKEANGLE 30.0
/* min deg spanned by 3 waypoints for no SPIKE */
/* 1 wayout, delete before, 2 wayout join last good with last else delete before */
static void joinchunk(aprsdecode_pOPHIST op)
{
aprsdecode_pFRAMEHIST lbad;
aprsdecode_pFRAMEHIST bad;
aprsdecode_pFRAMEHIST lllpf;
aprsdecode_pFRAMEHIST llpf;
aprsdecode_pFRAMEHIST lpf;
aprsdecode_pFRAMEHIST pf;
aprsdecode_pVARDAT v;
float kml;
float km;
float ang;
float waylen;
waylen = (float)op->lastkmh*0.03f+20.0f;
lllpf = 0;
llpf = 0;
lpf = 0;
pf = op->frames;
lbad = 0;
while (pf) {
v = pf->vardat;
if (aprspos_posvalid(v->pos) && (pf->nodraw&0xCU)==0U) {
if (lpf) {
km = aprspos_distance(lpf->vardat->pos, v->pos);
if (llpf && km!=0.0f) {
/* we have 3 waypoints */
kml = aprspos_distance(lpf->vardat->pos, llpf->vardat->pos);
if (kml!=0.0f) {
ang = (float)fabs(aprspos_azimuth(lpf->vardat->pos,
v->pos)-aprspos_azimuth(lpf->vardat->pos,
llpf->vardat->pos));
if (ang>180.0f) ang = 360.0f-ang;
if (ang<30.0f) {
/* a spike */
if (lllpf==0) {
/* first spike */
lpf->nodraw = lpf->nodraw&~0x10U|0x2U;
pf->nodraw &= ~0x10U;
lllpf = llpf;
}
else {
/* second spike */
if (km>aprspos_distance(llpf->vardat->pos, v->pos)) {
lpf->nodraw = lpf->nodraw&~0x10U|0x2U;
pf->nodraw &= ~0x10U;
llpf->nodraw &= ~0x2U; /* the second is bad */
}
lllpf = 0;
}
}
else lllpf = 0;
}
}
if (aprsdecode_maxhop>0.0f) {
if (km>waylen) lbad = pf;
else {
waylen = waylen+km*0.5f;
/* inc max hop if there are some steps */
if (waylen>aprsdecode_maxhop) waylen = aprsdecode_maxhop;
}
}
}
if ((pf->nodraw&0xCU)==0U) {
/* use only until now ok waypoints */
llpf = lpf;
lpf = pf;
}
}
pf = pf->next;
}
if (lbad) {
/* there is a dist */
bad = 0;
lpf = 0;
pf = op->frames;
for (;;) {
/* find last long hop in track */
if (pf==0) break;
if (aprspos_posvalid(pf->vardat->pos) && (pf->nodraw&0x1EU)==0U) {
if (lpf && aprspos_distance(lpf->vardat->pos,
pf->vardat->pos)>waylen) bad = pf;
lpf = pf;
}
if (lpf==lbad) break;
pf = pf->next;
}
if (bad) {
/* hide path until last bad */
pf = op->frames;
while (pf!=bad) {
pf->nodraw |= 0x20U;
pf = pf->next;
}
}
}
} /* end joinchunk() */
extern void aprsdecode_makelogfn(char s[], uint32_t s_len)
{
aprsdecode_FILENAME fn;
useri_confstr(useri_fLOGWFN, fn, 1024ul);
filepath(fn, 1024ul);
if (fn[0UL]) aprsstr_Append(fn, 1024ul, "/", 2ul);
aprsstr_Append(fn, 1024ul, s, s_len);
aprsstr_Assign(s, s_len, fn, 1024ul);
/*WrStr("<"); WrStr(s);WrStrLn(">"); */
} /* end makelogfn() */
static void inwindow(aprsdecode_pOPHIST op, const char rawbuf[],
uint32_t rawbuf_len)
{
uint32_t matchlen;
uint32_t j;
uint32_t ii;
uint32_t i;
char in;
aprsdecode_pFRAMEHIST pf;
char wc[100];
aprsdecode_FILENAME fn;
aprsdecode_pVARDAT pv;
uint8_t doset;
struct aprspos_POSITION * anonym;
in = 0;
aprsdecode_tracenew.call[0UL] = 0;
doset = 0U;
if (op) {
setmsgheard(op->call);
pf = op->frames;
while (pf && !in) {
/* find waypoint inside screen */
pv = pf->vardat;
if (aprspos_posvalid(pv->pos)) {
{ /* with */
struct aprspos_POSITION * anonym = &pv->pos;
if (((anonym->long0>aprsdecode_tracenew.winpos0.long0 && anonym->lat<aprsdecode_tracenew.winpos0.lat)
&& anonym->long0<aprsdecode_tracenew.winpos1.long0)
&& anonym->lat>aprsdecode_tracenew.winpos1.lat) in = 1;
}
}
pf = pf->next;
}
if (in) ++aprsdecode_tracenew.winevent;
/*find user in watchlist */
/* IF posvalid(op^.lastpos) THEN */
j = 0UL;
matchlen = 0UL;
for (;;) {
useri_confstrings(useri_fWATCH, j, 1, wc, 100ul);
if (wc[0U]==0) break;
i = 0UL;
ii = 0UL;
for (;;) {
if (((i>99UL || ii>8UL) || wc[i]==0) || op->call[ii]==0) {
if ((ii>8UL || op->call[ii]==0) && (wc[i]==0 || wc[i]=='*')) {
if (i>=matchlen) {
memcpy(aprsdecode_tracenew.call,op->call,9u);
doset = useri_confflags(useri_fWATCH, j);
matchlen = i;
}
}
break;
}
if (wc[i]=='*') {
if (wc[i+1UL]) ++i;
}
else {
if (X2C_CAP(wc[i])!=X2C_CAP(op->call[ii])) break;
++i;
}
++ii;
}
++j;
}
/* END; */
aprsdecode_tracenew.beep = (char)(doset&1);
aprsdecode_tracenew.follow = (char)(doset/2U&1);
if ((!aprsdecode_tracenew.follow && aprsdecode_click.watchmhop)
&& X2C_STRCMP(op->call,9u,aprsdecode_click.mhop,9u)==0) {
aprsdecode_tracenew.follow = 1;
memcpy(aprsdecode_tracenew.call,op->call,9u);
}
/*WrStrLn(op^.call); WrStrLn(click.mhop);
WrInt(ORD(click.watchmhop), 1);
WrInt(ORD(tracenew.follow), 1); WrStrLn(""); */
if ((doset/4U&1)) {
/* append to watchcall file */
aprsstr_Assign(fn, 1024ul, op->call, 9ul);
alfanum(fn, 1024ul); /* remove bad chars */
/*
confstr(fLOGWFN, fn);
filepath(fn);
IF fn[0]<>0C THEN Append(fn, DIRSEP) END;
Append(fn, wc);
*/
aprsdecode_makelogfn(fn, 1024ul);
if (!wrlog(rawbuf, rawbuf_len, aprsdecode_realtime, fn, 1024ul,
0L)) poplogerr(op->call, 9ul);
}
}
} /* end inwindow() */
extern uint32_t aprsdecode_finddup(aprsdecode_pFRAMEHIST pf,
aprsdecode_pFRAMEHIST frame)
/* return delay time if dupe found */
{
struct aprspos_POSITION apos;
uint32_t ret;
uint32_t dupedelay;
uint32_t speed;
uint32_t course;
int32_t altitude;
struct aprsdecode_DAT dat;
/* search from begin to 1 frame before */
struct aprsdecode_VARDAT * anonym;
apos = frame->vardat->pos;
ret = 0UL;
if ((pf!=frame && aprspos_posvalid(apos))
&& aprsdecode_Decode(frame->vardat->raw, 500ul, &dat)>=0L) {
speed = dat.speed;
course = dat.course;
altitude = dat.altitude;
dupedelay = frame->time0-aprsdecode_lums.dupemaxtime;
while (pf->next!=frame) {
{ /* with */
struct aprsdecode_VARDAT * anonym = pf->vardat;
if (pf->time0>=dupedelay && (frame->vardat==pf->vardat || ((((apos.lat==anonym->pos.lat && apos.long0==anonym->pos.long0)
&& aprsdecode_Decode(anonym->raw, 500ul,
&dat)>=0L) && speed==dat.speed) && course==dat.course)
&& altitude==dat.altitude)) {
/* dupe pos found */
ret = frame->time0-pf->time0;
}
else if (ret>0UL) return ret;
}
/* pos changed so we have real dupe */
pf = pf->next;
}
}
return 0UL;
} /* end finddup() */
#define aprsdecode_POLY13 0x112D
#define aprsdecode_TOPBIT 12
static void initcrc12(void)
{
uint16_t remainder;
uint32_t bit;
uint32_t dividend;
for (dividend = 0UL; dividend<=255UL; dividend++) {
remainder = X2C_LSH((uint16_t)dividend,16,4);
for (bit = 8UL;; bit--) {
if ((0x1000U & remainder)) {
remainder = X2C_LSH(remainder,16,1)^0x112DU;
}
else remainder = X2C_LSH(remainder,16,1);
if (bit==0UL) break;
} /* end for */
crctable12[dividend] = remainder&0x1FFFU;
} /* end for */
} /* end initcrc12() */
typedef uint8_t * RAW;
#define aprsdecode_TOPBIT0 12
static void crca12(const RAW data, int32_t len, uint16_t * rem)
{
int32_t i;
int32_t tmp;
tmp = len-1L;
i = 0L;
if (i<=tmp) for (;; i++) {
*rem = X2C_LSH(*rem,16,8)^crctable12[(uint16_t)(X2C_LSH(*rem,16,
-5)&0xFFU)]^(uint16_t)data[i];
if (i==tmp) break;
} /* end for */
} /* end crca12() */
struct _0;
struct _0 {
aprsdecode_pFRAMEHIST wayp;
uint16_t next;
};
static char lookup(uint32_t * wridx, struct _0 table[4096],
uint16_t index[8192], aprsdecode_pFRAMEHIST waypoint)
{
uint32_t sum;
uint16_t ojp;
uint16_t jp;
uint16_t ip;
struct aprsdecode_DAT dat1;
struct aprsdecode_DAT dat;
uint16_t rem;
struct aprsdecode_FRAMEHIST * anonym;
if (aprsdecode_Decode(waypoint->vardat->raw, 500ul,
&dat)>=0L && aprspos_posvalid(dat.pos)) {
rem = 0U;
crca12((RAW) &dat.speed, 2L, &rem);
crca12((RAW) &dat.course, 2L, &rem);
crca12((RAW) &dat.altitude, 2L, &rem);
crca12((RAW) &dat.pos.lat, (int32_t)sizeof(float), &rem);
crca12((RAW) &dat.pos.long0, (int32_t)sizeof(float), &rem);
sum = (uint32_t)(rem&0x1FFFU);
ip = index[sum];
/*WrInt(sum, 10);WrInt(ip, 10);WrStrLn("=ip"); */
if (ip) {
/* starts with 1, not found */
--ip;
jp = ip;
for (;;) {
{ /* with */
struct aprsdecode_FRAMEHIST * anonym = table[jp].wayp;
if (anonym->vardat==waypoint->vardat || ((((anonym->vardat->pos.lat==dat.pos.lat && anonym->vardat->pos.long0==dat.pos.long0)
&& aprsdecode_Decode(anonym->vardat->raw, 500ul,
&dat1)>=0L) && dat1.speed==dat.speed)
&& dat1.course==dat.course) && dat1.altitude==dat.altitude) {
if (anonym->time0+aprsdecode_lums.dupemaxtime>waypoint->time0)
return 1;
else break;
}
}
ojp = jp;
jp = table[jp].next;
if (jp>4095U || ojp<=jp==((uint32_t)ojp<*wridx==(uint32_t)
jp<*wridx)) {
/*WrInt(ORD(jp>HIGH(table)), 2); WrInt(ojp, 6); WrInt(jp, 6);
WrInt(wridx, 6); WrStr("o"); */
break;
}
}
}
else {
/*INC(collis); */
ip = 65535U;
}
index[sum] = (uint16_t)(*wridx+1UL);
table[*wridx].wayp = waypoint;
table[*wridx].next = ip;
*wridx = *wridx+1UL&4095UL;
}
return 0;
} /* end lookup() */
extern void aprsdecode_Checktrack(aprsdecode_pOPHIST op,
aprsdecode_pFRAMEHIST lastf)
{
aprsdecode_pFRAMEHIST f;
aprsdecode_pFRAMEHIST frame;
struct aprspos_POSITION last2;
struct aprspos_POSITION last;
struct aprspos_POSITION apos;
uint32_t starttime;
char cmp;
uint32_t wridx;
uint16_t index[8192];
struct _0 table[4096];
struct aprsdecode_OPHIST * anonym;
if (lastf) frame = lastf->next;
else {
op->margin0.long0 = 3.1415926535f;
op->margin0.lat = (-1.57079632675f);
op->margin1.long0 = (-3.1415926535f);
op->margin1.lat = 1.57079632675f;
frame = op->frames;
while (frame) {
frame->vardat->refcnt = 0UL;
frame = frame->next;
}
frame = op->frames;
while (frame) {
++frame->vardat->refcnt;
frame = frame->next;
}
frame = op->frames;
}
if (frame==0) return;
starttime = frame->time0; /* from this waypoint dupes will be set */
f = op->frames;
while (f && f->time0+aprsdecode_lums.dupemaxtime<starttime) f = f->next;
memset((char *)index,(char)0,16384UL);
wridx = 0UL;
lastf = 0;
cmp = 0;
aprsdecode_posinval(&last);
aprsdecode_posinval(&last2);
while (f) {
if (f==frame) cmp = 1;
apos = f->vardat->pos;
if (aprspos_posvalid(apos)) {
if (cmp) {
{ /* with */
struct aprsdecode_OPHIST * anonym = op;
if (apos.long0<anonym->margin0.long0) {
anonym->margin0.long0 = apos.long0;
}
if (apos.long0>anonym->margin1.long0) {
anonym->margin1.long0 = apos.long0;
}
if (apos.lat>anonym->margin0.lat) {
anonym->margin0.lat = apos.lat;
}
if (apos.lat<anonym->margin1.lat) {
anonym->margin1.lat = apos.lat;
}
}
f->nodraw &= ~0x8U;
}
if (lookup(&wridx, table, index, f) && cmp) {
if (apos.lat!=last.lat || apos.long0!=last.long0) {
if (apos.lat!=last2.lat || apos.long0!=last2.long0) {
f->nodraw |= 0x8U;
}
}
}
if (maxspeed>0.0f) timespeed(lastf, apos, f->time0, &f->nodraw);
if (!(f->nodraw&~0x14U) || !aprspos_posvalid(op->lastpos)) {
op->lastpos = apos;
}
last2 = last;
last = apos;
}
else f->nodraw |= 0x40U;
lastf = f;
f = f->next;
}
joinchunk(op);
} /* end Checktrack() */
static char strcmp0(const char a[], uint32_t a_len,
const char b[], uint32_t b_len)
/* faster but needs 0 termination */
{
uint32_t i;
i = 0UL;
for (;;) {
if (a[i]!=b[i]) return 0;
if (a[i]==0) return 1;
++i;
}
return 0;
} /* end strcmp() */
static char callfilt(uint8_t v, const char str[],
uint32_t str_len, char fullmatch)
{
uint32_t j;
uint32_t i;
char s[31];
if (str[0UL]==0) return 0;
i = 0UL;
for (;;) {
useri_confstrings(v, i, 0, s, 31ul);
if (s[0U]==0) return 0;
s[30U] = 0;
/* IF fullmatch THEN IF StrCmp(s, str) THEN RETURN TRUE END; */
if (fullmatch) {
j = 0UL;
for (;;) {
if (s[j]=='*') {
if (s[j+1UL]==0 || str[j]==0) return 1;
}
else {
if (s[j]!=str[j]) break;
if (str[j]==0) return 1;
}
++j;
if (j>str_len-1) return 1;
}
}
else if (aprsstr_InStr(str, str_len, s, 31ul)>=0L) return 1;
/* comment filter */
++i;
}
return 0;
} /* end callfilt() */
static void inserthrt(const struct aprsdecode_DAT dat,
aprsdecode_pOPHIST * op, uint8_t errs)
{
aprsdecode_pFRAMEHIST lastf;
aprsdecode_pFRAMEHIST f;
aprsdecode_pVARDAT v;
uint32_t len;
uint32_t ih;
uint32_t i;
uint32_t stime;
char s[51];
char rb[51];
struct aprsdecode_VARDAT * anonym;
uint32_t tmp;
f = (*op)->frames;
lastf = 0;
tmp = dat.hrtlen-1UL;
ih = 0UL;
if (ih<=tmp) for (;; ih++) {
if (dat.hrtposes[ih].notinterpolated) {
/* interpolating does vector drawer */
stime = dat.hrtposes[ih].dtime;
while (f && f->time0<stime) {
lastf = f;
f = f->next;
}
if (f==0 || f->time0!=stime) {
/* not a redundant same time frame */
osic_alloc((char * *) &f,
sizeof(struct aprsdecode_FRAMEHIST));
useri_debugmem.req = sizeof(struct aprsdecode_FRAMEHIST);
useri_debugmem.mon += useri_debugmem.req;
if (f==0) return;
memset((char *)f,(char)0,
sizeof(struct aprsdecode_FRAMEHIST));
if ((float)fabs(dat.hrtposes[ih].dalt)<2.147483646E+9f) {
aprsstr_IntToStr((int32_t)X2C_TRUNCI(dat.hrtposes[ih].dalt,
X2C_min_longint,X2C_max_longint), 0UL, s, 51ul);
strncpy(rb,">:$HR[a",51u);
aprsstr_Append(rb, 51ul, s, 51ul);
aprsstr_Append(rb, 51ul, "]", 2ul);
}
else rb[0U] = 0;
len = (sizeof(struct aprsdecode_VARDAT)-499UL)+aprsstr_Length(rb,
51ul);
osic_alloc((char * *) &v, len);
useri_debugmem.req = len;
useri_debugmem.mon += len;
if (v==0) return;
memset((char *)v,(char)0,len);
{ /* with */
struct aprsdecode_VARDAT * anonym = v;
anonym->pos.long0 = dat.hrtposes[ih].dlong;
anonym->pos.lat = dat.hrtposes[ih].dlat;
i = 0UL;
do {
anonym->raw[i] = rb[i];
++i;
} while (rb[i]);
}
v->lastref = f;
f->vardat = v;
f->time0 = stime;
f->nodraw = errs;
if (lastf==0) {
f->next = (*op)->frames;
(*op)->frames = f; /* new track */
}
else {
f->next = lastf->next; /* not nil if insert older frame */
lastf->next = f; /* append waypoint */
}
}
}
if (ih==tmp) break;
} /* end for */
} /* end inserthrt() */
static void settempspeed(aprsdecode_pOPHIST op,
const struct aprsdecode_DAT dat)
{
float rv;
op->drawhints = op->drawhints&~0x3U;
if (dat.objectfrom[0UL]) op->drawhints |= 0x2U;
/* EXCL(op^.drawhints, MIRRORSYM); */
if (dat.sym=='_') {
op->lastinftyp = 0U;
op->lasttempalt = -32768;
rv = aprstext_FtoC(dat.wx.temp);
if (rv>=(-99.0f) && rv<=99.0f) {
op->lasttempalt = (short)X2C_TRUNCI(rv,-32768,32767);
op->temptime = aprsdecode_systime;
op->lastinftyp = 100U;
}
if (dat.course>=1UL && dat.course<=360UL) {
op->lastinftyp = (uint8_t)(110UL+(dat.course%360UL)/4UL);
op->temptime = aprsdecode_systime;
}
else op->lastinftyp = 100U;
if (dat.speed<500UL) {
op->lastkmh = (short)X2C_TRUNCI((float)dat.speed*1.609f+0.5f,
-32768,32767);
if (op->lastinftyp<100U) op->lastinftyp = 100U;
op->temptime = aprsdecode_systime;
}
else op->lastkmh = 0;
}
else if (dat.speed<30000UL) {
op->lastkmh = (short)X2C_TRUNCI((float)dat.speed*1.852f+0.5f,
-32768,32767);
if (dat.speed>0UL && dat.course>180UL) op->drawhints |= 0x1U;
if (dat.course<=360UL) {
op->lastinftyp = (uint8_t)(10UL+dat.course/4UL);
}
else op->lastinftyp = 1U;
}
else if (op->lastinftyp<100U) op->lastinftyp = 0U;
if (op->lastinftyp<100U) {
if (dat.altitude>-10000L && dat.altitude<55535L) {
op->lasttempalt = (short)(dat.altitude+(-22768L));
}
else op->lasttempalt = -32768;
}
} /* end settempspeed() */
static char widefilt(void)
{
char s[101];
useri_confstr(useri_fFINGERPRINT, s, 101ul);
return aprsstr_InStr(s, 101ul, "0:2", 4ul)>=0L;
} /* end widefilt() */
#define aprsdecode_SAMETIME 27
/* max time diff for merged in frames */
static CHSET _cnst0 = {0x30000000UL,0x280086BAUL,0x80000001UL,0x00000001UL};
extern int32_t aprsdecode_Stoframe(aprsdecode_pOPHIST * optab,
char rawbuf[], uint32_t rawbuf_len, uint32_t stime,
char logmode, uint32_t * oldtime,
struct aprsdecode_DAT dat)
{
aprsdecode_pOPHIST opo;
aprsdecode_pOPHIST op;
aprsdecode_pFRAMEHIST lastf;
aprsdecode_pFRAMEHIST frame;
aprsdecode_pVARDAT same;
aprsdecode_MONCALL igate;
uint32_t cnt;
uint32_t len;
uint32_t i;
uint16_t ch0;
uint16_t hash;
struct aprsdecode_VARDAT * anonym;
int32_t aprsdecode_Stoframe_ret;
X2C_PCOPY((void **)&rawbuf,rawbuf_len);
*oldtime = 1UL; /* say not "new user" if filtered out */
i = 0UL;
hash = 0U;
do {
ch0 = (uint16_t)(uint8_t)rawbuf[i];
hash += ch0;
++i;
} while (ch0);
do {
--i;
} while (!(i==0UL || (rawbuf[i]!='\015' && rawbuf[i]!='\012') && rawbuf[i]));
rawbuf[i+1UL] = 0; /* remove trailing CR LF */
/*FOR len:=0 TO i DO WrInt(ORD(rawbuf[len]), 4) END; WrLn; */
/* IF NOT logmode THEN */
if (dat.igatep>0UL && dat.igatep<=9UL) {
memcpy(igate,dat.viacalls[dat.igatep],9u);
}
else igate[0UL] = 0;
if (((((callfilt(useri_fOPFILT, dat.symcall, 9ul,
1) || callfilt(useri_fIGATEFILT, igate, 9ul,
1)) || callfilt(useri_fOBJSRCFILT, dat.objectfrom, 9ul,
1)) || callfilt(useri_fDESTFILT, dat.dstcall, 9ul,
0)) || callfilt(useri_fSTRFILT, dat.comment0, 256ul,
0)) || callfilt(useri_fRAWFILT, rawbuf, rawbuf_len, 0)) {
aprsdecode_Stoframe_ret = -1L;
goto label;
}
if (useri_configon(useri_fMUSTBECALL)) {
if (dat.type==aprsdecode_OBJ || dat.type==aprsdecode_ITEM) {
if (!aprstext_isacall(dat.objectfrom, 9ul)) {
aprsdecode_Stoframe_ret = -1L;
goto label;
}
}
else if (!aprstext_isacall(dat.symcall, 9ul)) {
aprsdecode_Stoframe_ret = -1L;
goto label;
}
}
/* END; */
*oldtime = 0UL;
cnt = 0UL; /* check for 2 WIDE chunk */
if (widefilt()) {
i = 0UL;
while (((cnt<2UL && i<=9UL) && dat.viacalls[i][0UL])
&& (dat.igatep==0UL || i<dat.igatep)) {
if (aprsstr_InStr(dat.viacalls[i], 9ul, "WIDE", 5ul)==0L) ++cnt;
++i;
}
}
opo = 0;
op = *optab;
while (op && X2C_STRCMP(dat.symcall,9u,op->call,9u)) {
opo = op;
op = op->next;
}
if (op==0) {
osic_alloc((char * *) &op, sizeof(struct aprsdecode_OPHIST));
useri_debugmem.req = sizeof(struct aprsdecode_OPHIST);
useri_debugmem.mon += useri_debugmem.req;
if (op==0) {
aprsdecode_Stoframe_ret = -2L;
goto label;
}
memset((char *)op,(char)0,sizeof(struct aprsdecode_OPHIST));
memcpy(op->call,dat.symcall,9u);
if (logmode || opo==0) {
/* store it at begin of list for quick find */
op->next = *optab;
*optab = op;
}
else opo->next = op;
}
else if (logmode && opo) {
/* move it to begin of list */
opo->next = op->next;
op->next = *optab;
*optab = op;
}
else *oldtime = op->lasttime;
if (dat.hrttime>0UL) stime = dat.hrttime;
if (op->lasttime<=stime) {
/* new waypoint */
settempspeed(op, dat);
op->lasttime = stime;
}
frame = op->frames;
lastf = 0;
same = 0;
if (logmode) {
/* refcnt used as raw string hash */
while (frame && (frame->vardat->refcnt!=(uint32_t)
hash || !strcmp0(frame->vardat->raw, 500ul, rawbuf,
rawbuf_len))) {
lastf = frame;
frame = frame->next;
}
}
else {
/* online data find without hash */
while (frame && !strcmp0(frame->vardat->raw, 500ul, rawbuf,
rawbuf_len)) {
lastf = frame;
frame = frame->next;
}
}
if (frame) {
/* found same frame */
same = frame->vardat;
lastf = same->lastref;
while (lastf->next) lastf = lastf->next;
}
if (lastf && lastf->time0>stime) {
/* older frame to insert */
lastf = 0;
frame = op->frames;
while (frame && frame->time0<stime) {
lastf = frame;
frame = frame->next;
}
if (frame && frame->time0-stime<27UL) {
aprsdecode_Stoframe_ret = -2L;
goto label;
}
}
/* not insert same frame */
osic_alloc((char * *) &frame, sizeof(struct aprsdecode_FRAMEHIST));
useri_debugmem.req = sizeof(struct aprsdecode_FRAMEHIST);
useri_debugmem.mon += useri_debugmem.req;
if (frame==0) {
aprsdecode_Stoframe_ret = -2L;
goto label;
}
memset((char *)frame,(char)0,sizeof(struct aprsdecode_FRAMEHIST));
if (same==0) {
/* found new data */
len = (sizeof(struct aprsdecode_VARDAT)-499UL)+aprsstr_Length(rawbuf,
rawbuf_len);
osic_alloc((char * *) &same, len);
useri_debugmem.req = len;
useri_debugmem.mon += len;
if (same==0) {
aprsdecode_Stoframe_ret = -2L;
goto label;
}
memset((char *)same,(char)0,len);
{ /* with */
struct aprsdecode_VARDAT * anonym = same;
anonym->pos = dat.pos;
/* altitude:=dat.altitude; */
if (dat.hbitp==0UL && dat.igaterawp<=255UL) {
/* direct to igate */
anonym->igatepos = (uint8_t)dat.igaterawp;
anonym->igatelen = (uint8_t)dat.igatelen;
}
i = 0UL;
do {
anonym->raw[i] = rawbuf[i];
++i;
} while (rawbuf[i]);
if (logmode) anonym->refcnt = (uint32_t)hash;
}
}
else if (!logmode) ++same->refcnt;
if (same->lastref==0 || same->lastref->time0<=stime) {
same->lastref = frame;
}
frame->vardat = same;
frame->time0 = stime;
if (X2C_INL((int32_t)(uint8_t)dat.typc,128,_cnst0)) {
if (((X2C_INL((uint8_t)dat.symt,256,
_cnst) && (uint8_t)dat.sym>' ') && (uint8_t)
dat.sym<'\177') && op->sym.tab!='\001') {
op->sym.tab = dat.symt;
op->sym.pic = dat.sym;
}
else frame->nodraw |= 0x4U;
if (cnt>=2UL || dat.objkill=='1') {
op->sym.tab = '\001';
op->sym.pic = 0;
}
}
op->areasymb = dat.areasymb;
op->poligon = dat.multiline.size>2UL;
op->lastrxport = dat.lastrxport;
if (lastf==0) {
frame->next = op->frames;
op->frames = frame; /* new track */
}
else {
frame->next = lastf->next; /* not nil if insert older frame */
lastf->next = frame; /* append waypoint */
}
if (dat.hrtlen>0UL) {
inserthrt(dat, &op, frame->nodraw);
}
if (!logmode) {
/* read log check whole track at end */
aprsdecode_Checktrack(op, lastf);
inwindow(op, rawbuf, rawbuf_len);
}
if (!(frame->nodraw&~0x1U)) aprsdecode_Stoframe_ret = 0L;
else aprsdecode_Stoframe_ret = -1L;
label:;
X2C_PFREE(rawbuf);
return aprsdecode_Stoframe_ret;
} /* end Stoframe() */
static char locked(aprsdecode_pOPHIST op)
/* prevent entries in click table from purge */
{
uint32_t i;
i = 0UL;
while (i<aprsdecode_click.entries) {
if (aprsdecode_click.table[i].opf==op) return 1;
++i;
}
return 0;
} /* end locked() */
static void freevardat(aprsdecode_pVARDAT v)
{
uint32_t alen;
alen = (sizeof(struct aprsdecode_VARDAT)-499UL)+aprsstr_Length(v->raw,
500ul);
osic_free((char * *) &v, alen);
useri_debugmem.mon -= alen;
} /* end freevardat() */
#define aprsdecode_CHKINTERVALL 120
/* seconds to next check track */
extern void aprsdecode_purge(aprsdecode_pOPHIST * ops, uint32_t oldt,
uint32_t oldobj)
{
aprsdecode_pOPHIST opx;
aprsdecode_pOPHIST lastop;
aprsdecode_pOPHIST op;
aprsdecode_pFRAMEHIST frame;
aprsdecode_pVARDAT v;
uint32_t old;
char chk;
/*chkptr(ops); */
/*
WrInt(ORD(lums.logmode), 1);
IF ops=ophist THEN WrStrLn("purge oph")
ELSIF ops=ophist2 THEN WrStrLn("purge oph2")
ELSE WrStrLn("purge error") END;
*/
op = *ops;
lastop = 0;
while (op) {
/*WrStr("op:"); WrStr(op^.call); WrStr(" "); */
if (op->sym.tab=='\001') old = X2C_max_longcard;
else if ((0x2U & op->drawhints) && op->lastinftyp<100U) {
old = oldobj; /* object but no wx obj for wx graphs */
}
else old = oldt;
chk = 0;
for (;;) {
frame = op->frames;
if (frame==0) break;
/*WrCard(systime-frame^.time, 6);
IF frame^.next<>NIL THEN WrStr("+") END; */
if (frame->time0>=old || locked(op)) break;
if (frame->next && frame->time0/120UL!=frame->next->time0/120UL) {
chk = 1;
}
v = frame->vardat;
if (v->lastref==frame) freevardat(v);
else --v->refcnt;
op->frames = frame->next;
/*WrStr("(purge)"); */
useri_debugmem.mon -= sizeof(struct aprsdecode_FRAMEHIST);
osic_free((char * *) &frame,
sizeof(struct aprsdecode_FRAMEHIST));
}
if (op->frames==0 && !locked(op)) {
/* empty op */
opx = op;
op = op->next;
if (lastop==0) *ops = op;
else lastop->next = op;
/*WrStr(opx^.call); WrStrLn("(purgop) "); */
useri_debugmem.mon -= sizeof(struct aprsdecode_OPHIST);
osic_free((char * *) &opx, sizeof(struct aprsdecode_OPHIST));
}
else {
if (chk) {
aprsdecode_Checktrack(op, 0); /*WrStr(op^.call); WrStr(" ")*/
}
lastop = op;
op = op->next;
}
}
/*WrLn; */
/*WrStrLn(" --purge"); */
} /* end purge() */
extern void aprsdecode_delwaypoint(aprsdecode_pOPHIST op,
aprsdecode_pFRAMEHIST * frame)
{
aprsdecode_pFRAMEHIST lastf;
aprsdecode_pFRAMEHIST lf;
aprsdecode_pFRAMEHIST f;
int32_t mi;
int32_t di;
int32_t i;
struct aprsdecode_DAT dat;
if (op==0 || *frame==0) return;
i = 0L;
di = 0L;
mi = 0L;
lf = 0;
f = op->frames;
while (f) {
if (f->next==*frame) {
lf = f; /* next frame is to delete */
di = mi;
}
if (f->vardat==(*frame)->vardat) ++i;
f->vardat->refcnt = 0UL;
++mi;
f = f->next;
}
if (i==1L) freevardat((*frame)->vardat);
if (lf==0) op->frames = (*frame)->next;
else lf->next = (*frame)->next;
useri_debugmem.mon -= sizeof(struct aprsdecode_FRAMEHIST);
osic_free((char * *)frame, sizeof(struct aprsdecode_FRAMEHIST));
f = op->frames;
while (f) {
if (f->vardat->refcnt<65535UL) ++f->vardat->refcnt;
f->vardat->lastref = f;
f->nodraw = 0U; /* mark errors new later */
f = f->next;
}
aprsdecode_Checktrack(op, 0);
i = 0L; /* set new marker to the nearest from deleted with error */
mi = X2C_max_longint;
*frame = 0;
lf = 0;
lastf = 0;
f = op->frames;
while (f) {
if ((!aprsdecode_lums.errorstep || (f->nodraw&~0x40U)!=0U)
&& labs(i-di)<mi) {
mi = labs(i-di);
*frame = f;
}
if (i==di) lf = f;
++i;
lastf = f;
f = f->next;
}
if (*frame==0) *frame = lf;
if (lastf) {
if (aprsdecode_Decode(lastf->vardat->raw, 500ul, &dat)>=0L) {
settempspeed(op, dat);
}
op->lasttime = lastf->time0;
/* deleted last frame so correct op time */
}
} /* end delwaypoint() */
static char cmpfrom(const char a[], uint32_t a_len,
uint32_t from, const char b[], uint32_t b_len)
{
uint32_t i;
i = 0UL;
while (from<=a_len-1 && b[i]) {
if (a[from]!=b[i]) return 0;
++i;
++from;
}
return 1;
} /* end cmpfrom() */
/*
PROCEDURE AppQ(VAR h:ARRAY OF CHAR; q-:ARRAY OF CHAR; appcall:BOOLEAN);
BEGIN
Append(h, ">"+TOCALL+",");
Append(h, q);
IF appcall THEN Append(h, servercall) END;
Append(h, ":");
END AppQ;
*/
static char callchk(uint32_t * qpos, char * tablechk,
char buf[], uint32_t buf_len, uint32_t * p,
uint32_t tablen, uint32_t * pssid, char withstar,
char iscall0)
{
uint32_t lit;
uint32_t num1;
uint32_t u;
uint32_t j;
uint32_t i;
char c;
*pssid = 0UL;
u = 0UL;
for (;;) {
if (u>=tablen) break;
j = 0UL;
i = *p;
while (ungate[u][j]==buf[i]) {
++i;
++j;
if (ungate[u][j]==0) {
*tablechk = 1;
goto loop_exit;
}
}
++u;
}
loop_exit:;
if (iscall0) {
/* we want a callsign */
num1 = 0UL;
lit = 0UL;
for (;;) {
c = buf[*p];
if ((uint8_t)c>='0' && (uint8_t)c<='9') ++num1;
else if ((uint8_t)c>='A' && (uint8_t)c<='Z') ++lit;
else break;
++*p;
}
if ((lit<2UL || num1==0UL) || num1>2UL) return 0;
*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 0;
++*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 1;
} /* 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 i;
if (*p<=4UL || buf[*p-2UL]!='I') return;
/* ,CALL,I: */
i = *p-4UL;
while (buf[i]!=',') {
/* hop back call */
if (i==0UL) return;
--i;
}
k = i; /* "," before call */
++i;
j = 0UL;
while (j<=logcall_len-1 && logcall[j]) {
if (logcall[j]!=buf[i]) return;
++i;
++j;
}
/* logcall = call,I */
*pins = k;
i = *p-1UL;
*p = k+1UL; /* payload */
for (;;) {
buf[k] = buf[i];
if (i>=buf_len-1 || buf[i]==0) break;
++k;
++i;
}
/* 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,
uint32_t tablen, const char logcall[],
uint32_t logcall_len, uint32_t udpchan,
char valid, char chkrfcall,
char * tablechk)
{
uint32_t qpos;
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 i;
uint8_t hashh;
uint8_t hashl;
char qtext[32];
uint32_t tmp;
hashl = 0U;
hashh = 0U;
p = 0UL;
pins = 0UL;
pssid = 0UL; /* for savety */
len = 0UL;
while ((len<buf_len-1 && buf[len]) && buf[len]!='\015') ++len;
if (len==0UL || len+35UL>buf_len-1) return -2L;
qpos = 0UL;
*tablechk = 0;
for (;;) {
psum0 = p;
if (!callchk(&qpos, tablechk, buf, buf_len, &p, tablen, &pssid, 0,
udpchan && chkrfcall)) return -3L;
if (buf[p]!='>') return -1L;
++p;
if (!callchk(&qpos, tablechk, buf, buf_len, &p, tablen, &pssid, 0, 0)) {
return -3L;
}
psum1 = pssid;
while (buf[p]==',') {
++p;
if (!callchk(&qpos, tablechk, buf, buf_len, &p, tablen, &pssid, 1,
0)) return -3L;
}
if (buf[p]!=':') return -1L;
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 -3L;
if (X2C_CAP(buf[qpos])=='I') {
aprsstr_Append(qtext, 32ul, ",", 2ul); /* qAI */
useri_confappend(useri_fMYCALL, qtext, 32ul);
}
}
else if (udpchan) {
aprsstr_Append(qtext, 32ul, ",qAU,", 6ul);
useri_confappend(useri_fMYCALL, qtext, 32ul);
}
else if (logcall[0UL]) {
if (cmpfrom(buf, buf_len, 0UL, logcall, logcall_len)) {
strncpy(qtext,",qAC,",32u);
}
else strncpy(qtext,",qAS,",32u);
useri_confappend(useri_fMYCALL, qtext, 32ul);
Iconstruct(qtext, &pins, logcall, logcall_len, buf, buf_len, &p);
}
if (buf[p]=='?') return -4L;
tmp = psum1-1UL;
i = psum0;
if (i<=tmp) for (;; i++) {
aprsstr_HashCh(buf[i], &hashl, &hashh);
if (i==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>aprsdecode_realtime) return -5L;
/* a duplicate */
if (udpchan || valid) timehash[ha] = aprsdecode_realtime;
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];
}
i = 0UL;
while (i<ilen) {
buf[p] = qtext[i];
++p;
++i;
}
}
return 0L;
} /* end AprsIs() */
static void connstr(aprsdecode_pTCPSOCK cp, char s[], uint32_t s_len)
{
struct aprsdecode_TCPSOCK * anonym;
{ /* with */
struct aprsdecode_TCPSOCK * anonym = cp;
useri_confstr(useri_fMYCALL, s, s_len);
aprsstr_Append(s, s_len, " connected to ", 15ul);
aprsstr_Append(s, s_len, anonym->ipnum, 64ul);
aprsstr_Append(s, s_len, ":", 2ul);
aprsstr_Append(s, s_len, anonym->port, 6ul);
}
} /* end connstr() */
static void wrconnected(aprsdecode_pTCPSOCK cp)
{
char h[301];
connstr(cp, h, 301ul);
useri_textautosize(0L, 5L, 6UL, 5UL, 'b', h, 301ul);
} /* end wrconnected() */
extern void aprsdecode_tcpconnstat(char s[], uint32_t s_len)
{
aprsdecode_pTCPSOCK tcp0;
char h[100];
struct aprsdecode_TCPSOCK * anonym;
tcp0 = aprsdecode_tcpsocks;
while (tcp0) {
{ /* with */
struct aprsdecode_TCPSOCK * anonym = tcp0;
if (anonym->connt>0UL && anonym->connt<aprsdecode_realtime) {
if (s[0UL]) aprsstr_Append(s, s_len, "\012", 2ul);
aprsstr_Append(s, s_len, "TCP:", 5ul);
aprsstr_Append(s, s_len, anonym->ipnum, 64ul);
aprsstr_Append(s, s_len, ":", 2ul);
aprsstr_Append(s, s_len, anonym->port, 6ul);
aprsstr_Append(s, s_len, "\012 Connecttime:", 16ul);
aprsstr_TimeToStr(aprsdecode_realtime-anonym->connt, h, 100ul);
aprsstr_Append(s, s_len, h, 100ul);
if (aprsdecode_lasttcprx<=aprsdecode_realtime && aprsdecode_realtime-aprsdecode_lasttcprx<3600UL)
{
aprsstr_Append(s, s_len, "\012 No rx since:", 16ul);
aprsstr_TimeToStr(aprsdecode_realtime-aprsdecode_lasttcprx, h,
100ul);
aprsstr_Append(s, s_len, h, 100ul);
}
aprsstr_Append(s, s_len, "\012 Rx Frames:", 14ul);
aprsstr_IntToStr((int32_t)anonym->rxframes, 1UL, h, 100ul);
aprsstr_Append(s, s_len, h, 100ul);
aprsstr_Append(s, s_len, "\012 Rx Bytes:", 13ul);
aprsstr_IntToStr((int32_t)anonym->rxbytes, 1UL, h, 100ul);
aprsstr_Append(s, s_len, h, 100ul);
aprsstr_Append(s, s_len, "\012 Tx Frames:", 14ul);
aprsstr_IntToStr((int32_t)anonym->txframes, 1UL, h, 100ul);
aprsstr_Append(s, s_len, h, 100ul);
aprsstr_Append(s, s_len, "\012 Tx Bytes:", 13ul);
aprsstr_IntToStr((int32_t)anonym->txbytes, 1UL, h, 100ul);
aprsstr_Append(s, s_len, h, 100ul);
}
tcp0 = anonym->next;
}
}
} /* end tcpconnstat() */
extern void aprsdecode_udpconnstat(uint32_t port, char s[],
uint32_t s_len)
{
char h[51];
uint32_t i;
struct aprsdecode_UDPSOCK * anonym;
if (port<=3UL) {
{ /* with */
struct aprsdecode_UDPSOCK * anonym = &aprsdecode_udpsocks0[port];
if (anonym->starttime>0UL) {
if (aprsdecode_realtime<anonym->starttime) {
anonym->starttime = aprsdecode_realtime;
}
if (s[0UL]) aprsstr_Append(s, s_len, "\012", 2ul);
aprsstr_Append(s, s_len, "Rf ", 4ul);
aprsstr_IntToStr((int32_t)(port+1UL), 1UL, h, 51ul);
aprsstr_Append(s, s_len, h, 51ul);
aprsstr_Append(s, s_len, ":", 2ul);
i = 1UL;
for (;;) {
useri_conf2str((uint8_t)(36UL+port), i, h, 51ul);
if (h[0U]==0) break;
if (i>1UL) aprsstr_Append(s, s_len, " ", 2ul);
aprsstr_Append(s, s_len, h, 51ul);
++i;
}
aprsstr_Append(s, s_len, "\012 ", 4ul);
aprsstr_ipv4tostr(anonym->ip, h, 51ul);
aprsstr_Append(s, s_len, h, 51ul);
aprsstr_Append(s, s_len, ":", 2ul);
aprsstr_IntToStr((int32_t)anonym->dport, 0UL, h, 51ul);
aprsstr_Append(s, s_len, h, 51ul);
if (anonym->checkip) aprsstr_Append(s, s_len, "/", 2ul);
else aprsstr_Append(s, s_len, ":", 2ul);
aprsstr_IntToStr((int32_t)anonym->bindport, 0UL, h, 51ul);
aprsstr_Append(s, s_len, h, 51ul);
aprsstr_Append(s, s_len, "\012 Uptime :", 12ul);
aprsstr_TimeToStr(aprsdecode_realtime-anonym->starttime, h,
51ul);
aprsstr_Append(s, s_len, h, 51ul);
if (anonym->lastudprx>0UL && anonym->lastudprx<=aprsdecode_realtime)
{
aprsstr_Append(s, s_len, "\012 Last rx:", 12ul);
aprsstr_TimeToStr(aprsdecode_realtime-anonym->lastudprx, h,
51ul);
aprsstr_Append(s, s_len, h, 51ul);
}
if (anonym->lastudptx>0UL && anonym->lastudptx<=aprsdecode_realtime)
{
aprsstr_Append(s, s_len, "\012 Last tx:", 12ul);
aprsstr_TimeToStr(aprsdecode_realtime-anonym->lastudptx, h,
51ul);
aprsstr_Append(s, s_len, h, 51ul);
}
if (aprsdecode_realtime<anonym->bpstime && anonym->bpstime-aprsdecode_realtime<3600UL)
{
aprsstr_Append(s, s_len, "\012 Next net>rf(s):", 19ul);
aprsstr_IntToStr((int32_t)
(anonym->bpstime-aprsdecode_realtime), 1UL, h, 51ul);
aprsstr_Append(s, s_len, h, 51ul);
}
aprsstr_Append(s, s_len, "\012 Rx Frames:", 14ul);
aprsstr_IntToStr((int32_t)anonym->rxframes, 1UL, h, 51ul);
aprsstr_Append(s, s_len, h, 51ul);
aprsstr_Append(s, s_len, "\012 Rx Bytes:", 13ul);
aprsstr_IntToStr((int32_t)anonym->rxbytes, 1UL, h, 51ul);
aprsstr_Append(s, s_len, h, 51ul);
aprsstr_Append(s, s_len, "\012 Tx Frames:", 14ul);
aprsstr_IntToStr((int32_t)anonym->txframes, 1UL, h, 51ul);
aprsstr_Append(s, s_len, h, 51ul);
aprsstr_Append(s, s_len, "\012 Tx Bytes:", 13ul);
aprsstr_IntToStr((int32_t)anonym->txbytes, 1UL, h, 51ul);
aprsstr_Append(s, s_len, h, 51ul);
}
}
}
} /* end udpconnstat() */
extern void aprsdecode_tcpclose(aprsdecode_pTCPSOCK w, char fin)
{
char h[201];
struct aprsdecode_TCPSOCK * anonym;
{ /* with */
struct aprsdecode_TCPSOCK * anonym = w;
if ((int32_t)anonym->fd>=0L) osic_CloseSock(anonym->fd);
anonym->fd = -1L;
aprsdecode_lasttcprx = 0UL;
strncpy(h,"\012TCP Close ",201u);
aprsstr_Append(h, 201ul, anonym->ipnum, 64ul);
aprsstr_Append(h, 201ul, ":", 2ul);
aprsstr_Append(h, 201ul, anonym->port, 6ul);
aprsstr_Append(h, 201ul, "\012", 2ul);
useri_textautosize(0L, 5L, 6UL, 4UL, 'e', h, 201ul);
}
} /* end tcpclose() */
static void Watchbeacon(aprsdecode_pTCPSOCK cp)
{
char ok0;
aprsdecode_FRAMEBUF tmp;
ok0 = Sendtcp(cp, *(aprsdecode_FRAMEBUF *)memcpy(&tmp,"# watchbeacon\015\01\
2",16u));
cp->watchtime = aprsdecode_realtime;
} /* end Watchbeacon() */
static void appfilter(char s[], uint32_t s_len, char nulltoo)
/* build string "filter m/300" */
{
char h[1000];
useri_confstr(useri_fSERVERFILT, h, 1000ul);
if (nulltoo || h[0U]) {
aprsstr_Append(s, s_len, " filter ", 9ul);
aprsstr_Append(s, s_len, h, 1000ul);
}
} /* end appfilter() */
static void updatefilters(aprsdecode_pTCPSOCK cp)
{
char ok0;
aprsdecode_FRAMEBUF s;
strncpy(s,"#",512u);
appfilter(s, 512ul, 1);
aprsstr_Append(s, 512ul, "\015\012", 3ul);
ok0 = Sendtcp(cp, s);
strncpy(s,"Sent to Server",512u);
appfilter(s, 512ul, 1);
useri_textautosize(0L, 5L, 6UL, 4UL, 'b', s, 512ul);
} /* end updatefilters() */
static char tcpconn(aprsdecode_pTCPSOCK * sockchain, int32_t f)
{
aprsdecode_pTCPSOCK cp;
aprsdecode_FRAMEBUF h;
int32_t res;
char ok0;
char s[100];
struct aprsdecode_TCPSOCK * anonym;
if ((int32_t)f<0L) return 0;
osic_alloc((char * *) &cp, sizeof(struct aprsdecode_TCPSOCK));
useri_debugmem.req = sizeof(struct aprsdecode_TCPSOCK);
useri_debugmem.mon += useri_debugmem.req;
if (cp==0) {
osic_CloseSock(f);
if (aprsdecode_verb) osi_WrStrLn("tcp conn out of memory", 23ul);
return 0;
}
memset((char *)cp,(char)0,sizeof(struct aprsdecode_TCPSOCK));
{ /* with */
struct aprsdecode_TCPSOCK * anonym = cp;
anonym->fd = f;
res = socknonblock(f);
/* txbuf:=NIL; */
anonym->watchtime = aprsdecode_realtime;
}
cp->next = *sockchain;
*sockchain = cp;
useri_confstr(useri_fMYCALL, s, 100ul);
if (s[0U]) {
if (aprstext_callwrong(s, 100ul)) {
useri_xerrmsg("illegal \'My Call\' in login", 27ul);
}
aprsstr_Assign(h, 512ul, "user ", 6ul);
aprsstr_Append(h, 512ul, s, 100ul);
useri_confstr(useri_fPW, s, 100ul);
if (s[0U]) {
/* & configon(fPW)*/
aprsstr_Append(h, 512ul, " pass ", 7ul);
aprsstr_Append(h, 512ul, s, 100ul);
}
aprsstr_Append(h, 512ul, " vers ", 7ul);
aprsstr_Append(h, 512ul, "aprsmap(cu) 0.66", 17ul);
appfilter(h, 512ul, 0);
/* IF filter[0]<>0C THEN Append(h, " filter ");
Append(h, filter) END; */
aprsstr_Append(h, 512ul, "\015\012", 3ul);
ok0 = Sendtcp(cp, h);
}
cp->txframes = 0UL;
cp->txbytes = 0UL;
return 1;
} /* end tcpconn() */
/*
PROCEDURE Gateconn(VAR cp:pTCPSOCK);
VAR fd:SOCKET;
p, act, try, kill:pTCPSOCK;
max:CARDINAL;
BEGIN
--WrStrLn(" gateconn");
(*
IF cp<>NIL THEN
IF (cp^.fd<>CAST(SOCKET,-1)) & NOT configon(fSERVERURL) THEN
saybusy(kill^.fd, "");
END;
ELSIF
*)
act:=NIL;
try:=NIL;
p:=cp;
WHILE p<>NIL DO
IF p^.connt>0 THEN (* we have gate connect *)
IF act<>NIL THEN (* we have 2 connects *)
IF act^.gatepri>p^.gatepri THEN (* stop second best *)
kill:=act;
act:=p;
ELSE kill:=p END; (* stop second best *)
saybusy(kill^.fd, "# remove double connect"+CR+LF)
ELSE act:=p END;
ELSE try:=p END; (* trying to connect *)
p:=p^.next;
END;
IF (try=NIL) & Watchclock(connecttime,
GATECONNDELAY) THEN (* no trials *)
IF act=NIL THEN max:=HIGH(gateways) ELSE max:=act^.gatepri END;
(* try only better *)
IF (trygate>=max) OR (trygate>HIGH(gateways))
OR (gateways[trygate].url[0]=0C) THEN trygate:=0 END;
(* loop thru table *)
IF trygate<max THEN
WITH gateways[trygate] DO
IF url[0]<>0C THEN
fd:=connectto(url, port);
--WrInt(fd, 1);WrStrLn(" connfd");
IF CAST(INTEGER,fd)>=0 THEN
IF tcpconn(cp, fd, filterst) THEN
Assign(cp^.ipnum, url);
Assign(cp^.port, port);
cp^.gatepri:=trygate;
-- Assign(h, servercall);
-- Append(h, " connected to "); Append(h, url); Append(h, ":");
Append(h, port);
-- xerrmsg(h);
END;
END;
END;
END;
END;
INC(trygate);
END;
END Gateconn;
*/
static void urlport(char s[], uint32_t s_len, char url[],
uint32_t url_len, char port[], uint32_t port_len)
/* url:port to url port */
{
int32_t i;
X2C_PCOPY((void **)&s,s_len);
aprsstr_Assign(url, url_len, s, s_len);
i = aprsstr_InStr(url, url_len, ":", 2ul);
if (i>0L) {
url[i] = 0;
aprsstr_Delstr(s, s_len, 0UL, (uint32_t)(i+1L));
aprsstr_Assign(port, port_len, s, s_len);
}
else port[0UL] = 0;
X2C_PFREE(s);
} /* end urlport() */
#define aprsdecode_DEFAULTPORT "14580"
static void Gateconn(aprsdecode_pTCPSOCK * cp)
{
int32_t fd;
char port[1000];
char ip[1000];
char s[1000];
/*WrInt(cycleservers, 5); WrStrLn(" gateconn"); */
if (*cp) {
if ((int32_t)(*cp)->fd>=0L && !useri_configon(useri_fCONNECT)) {
saybusy(&(*cp)->fd, "", 1ul);
}
}
else if (useri_configon(useri_fCONNECT) && Watchclock(&connecttime,
30UL)) {
for (;;) {
useri_confstrings(useri_fSERVERURL, cycleservers, 0, s, 1000ul);
if (s[0U] || cycleservers==0UL) break;
cycleservers = 0UL;
}
if (s[0U]) {
++cycleservers;
urlport(s, 1000ul, ip, 1000ul, port, 1000ul);
if (port[0U]==0) strncpy(port,"14580",1000u);
/*WrInt(cycleservers, 5);WrStr(" <"); WrStr(ip);WrStr("><");
WrStr(port);WrStrLn(">"); */
fd = connectto(ip, port);
if ((int32_t)fd>=0L) {
if (tcpconn(cp, fd)) {
aprsstr_Assign((*cp)->ipnum, 64ul, ip, 1000ul);
aprsstr_Assign((*cp)->port, 6ul, port, 1000ul);
(*cp)->beacont = 0UL; /* send next beacon now */
}
}
}
else useri_xerrmsg("Net: No Online/Server URL configured", 37ul);
}
} /* end Gateconn() */
static void porttext(uint32_t p, char s[], uint32_t s_len)
{
char h[31];
aprsstr_IntToStr((int32_t)(p+1UL), 1UL, h, 31ul);
aprsstr_Assign(s, s_len, "UDP ", 5ul);
aprsstr_Append(s, s_len, h, 31ul);
} /* end porttext() */
static void rfbeacons(void)
{
uint32_t i;
uint32_t nb;
int32_t j;
uint32_t shift;
uint32_t bshift;
uint32_t bn;
uint32_t bt;
aprsdecode_FRAMEBUF s;
char h[101];
char says[101];
char port;
struct aprsdecode_DAT dat;
char tmp;
nb = 0UL;
shift = beaconrandomstart;
bshift = (uint32_t)useri_conf2int(useri_fRFBTSHIFT, 0UL, 0L, 86400L,
120L);
if (rfbecondone==0UL || rfbecondone>aprsdecode_realtime) {
rfbecondone = aprsdecode_realtime;
}
for (;;) {
if (aprsdecode_testbeaconbuf[0UL]) {
/* manual sent beacon */
aprsstr_Assign(s, 512ul, aprsdecode_testbeaconbuf, 512ul);
aprsdecode_testbeaconbuf[0UL] = 0;
strncpy(says,"Sent: ",101u);
aprsstr_Append(says, 101ul, s, 512ul);
if (getbeaconparm(s, 512ul, &bt, &port)) bt = 1UL;
else bt = 0UL;
}
else {
useri_confstrings(useri_fRBTEXT, nb, 0, s, 512ul);
if (s[0UL]==0) break;
if (!getbeaconparm(s, 512ul, &bt, &port)) bt = 0UL;
says[0U] = 0;
}
if (bt>0UL) {
/* valid time */
bn = (aprsdecode_realtime+shift)%bt;
/*WrInt(realtime MOD 86400, 10); WrInt(realtime-rfbecondone, 4);
WrInt(bshift, 4); WrInt(shift, 14); WrStrLn(" bshift"); */
if (bn<aprsdecode_realtime-rfbecondone) {
beaconmacros(s, 512ul, "", 1ul, "", 1ul, 1);
if (s[0UL]) {
if (aprsdecode_Decode(s, 512ul, &dat)>=0L) {
if ((uint8_t)dat.symt<' ') {
strncpy(h,"beacon warning: no symbol: ",101u);
aprsstr_Append(h, 101ul, s, 512ul);
useri_xerrmsg(h, 101ul);
}
if (X2C_CAP(port)=='N') {
/* beacon to net */
if (dat.type!=aprsdecode_MICE) {
j = aprsstr_InStr(s, 512ul, ":", 2ul);
if (j>=0L) {
aprsstr_Delstr(s, 512ul, 0UL, (uint32_t)(j+1L));
/* remove rf adress */
SendNet(aprsdecode_tcpsocks, dat.srcall, 9ul, s,
512ul, 1, h, 101ul);
if (h[0U]) {
strncpy(says,"beacon: not sent ",101u);
aprsstr_Append(says, 101ul, h, 101ul);
}
}
}
else strncpy(says,"beacon: not sent mic-e to Net",101u);
}
else if ((uint8_t)port>='1') {
if (s[0UL]) {
i = (uint32_t)(uint8_t)port-49UL;
if (i<4UL && useri_configon((uint8_t)(36UL+i))) {
if (Sendudp(s, 512ul, i, 1UL)<0L) {
strncpy(says,"beacon: Rfport ",101u);
aprsstr_Append(says, 101ul,
(char *)(tmp = (char)(i+49UL),&tmp), 1u/1u);
aprsstr_Append(says, 101ul, " not configured to\
send", 24ul);
}
}
else {
strncpy(says,"beacon: Rfport ",101u);
aprsstr_Append(says, 101ul,
(char *)(tmp = (char)(i+49UL),&tmp), 1u/1u);
aprsstr_Append(says, 101ul, " not enabled", 13ul);
}
}
}
if (says[0U]) useri_say(says, 101ul, 2UL, 'b');
}
else {
strncpy(h,"rfbeacon not decodeable: ",101u);
aprsstr_Append(h, 101ul, s, 512ul);
useri_xerrmsg(h, 101ul);
}
}
}
shift += bshift; /* delay next beacon by shift time to before beacon */
}
++nb;
}
rfbecondone = aprsdecode_realtime;
} /* end rfbeacons() */
static void startserial(struct xosi_PROCESSHANDLE * pid, uint8_t cfg)
{
char h[1001];
char s[1001];
if (useri_configon(cfg)) {
if (!(pid->runs || pid->started)) {
useri_confstr(cfg, s, 1001ul);
if (s[0U]) {
xosi_StartProg(s, 1001ul, pid);
pid->started = 1;
if (pid->runs) {
useri_say("Start Serial Interface", 23ul, 3UL, 'g');
}
else {
strncpy(h,"can not start ",1001u);
aprsstr_Append(h, 1001ul, s, 1001ul);
useri_xerrmsg(h, 1001ul);
useri_configbool(cfg, 0);
useri_refresh = 1;
}
}
}
}
else pid->started = 0;
} /* end startserial() */
extern void aprsdecode_tcpjobs(void)
{
aprsdecode_pTCPSOCK acttcp;
int32_t i;
int32_t len;
char ok0;
char s[1000];
struct aprsdecode_TCPSOCK * anonym;
struct aprsdecode_UDPSOCK * anonym0;
if (qwatchtime!=aprsdecode_realtime) {
acttcp = aprsdecode_tcpsocks;
while (acttcp) {
{ /* with */
struct aprsdecode_TCPSOCK * anonym = acttcp;
Timebeacon(acttcp);
if (anonym->watchtime+180UL<aprsdecode_realtime) {
Watchbeacon(acttcp);
}
if (useri_configon(useri_fALLOWGATE)) WatchTXQ(acttcp);
if (useri_isupdated(useri_fSERVERFILT)) updatefilters(acttcp);
acttcp = anonym->next;
}
}
qwatchtime = aprsdecode_realtime;
Gateconn(&aprsdecode_tcpsocks);
rfbeacons();
}
/*UDP */
for (i = 0L; i<=3L; i++) {
{ /* with */
struct aprsdecode_UDPSOCK * anonym0 = &aprsdecode_udpsocks0[i];
if (useri_configon((uint8_t)(36UL+(uint32_t)i))
&& !useri_isupdated((uint8_t)(36UL+(uint32_t)i))) {
if ((int32_t)anonym0->fd<0L) {
ok0 = 0;
useri_confstr((uint8_t)(36UL+(uint32_t)i), s, 1000ul);
if (s[0U]) {
memset((char *) &aprsdecode_udpsocks0[i],(char)0,
sizeof(struct aprsdecode_UDPSOCK));
anonym0->fd = -1L;
if (aprsstr_GetIp2(s, 1000ul, &anonym0->ip,
&anonym0->dport, &anonym0->bindport, &anonym0->checkip)<0L) {
anonym0->rawread = 1;
porttext((uint32_t)i, s, 1000ul);
aprsstr_Append(s, 1000ul, " Config Error <IPNumber:TxPor\
t:RxPort>", 39ul);
/* textautosize(0, 5, 6, 10, "e", s); */
useri_xerrmsg(s, 1000ul);
}
else {
anonym0->fd = openudp();
anonym0->rawread = 1;
porttext((uint32_t)i, s, 1000ul);
if ((int32_t)anonym0->fd<0L || bindudp(anonym0->fd,
anonym0->bindport)<0L) {
aprsstr_Append(s, 1000ul, " Bindport Error, Illegal (\
Rx)Port or in Use", 44ul);
/* textautosize(0, 5, 6, 10, "e", s);
*/
useri_xerrmsg(s, 1000ul);
osic_CloseSock(anonym0->fd);
anonym0->fd = -1L;
}
else {
aprsstr_Append(s, 1000ul, " Open", 6ul);
len = socknonblock(anonym0->fd);
useri_textautosize(0L, 5L, 6UL, 5UL, 'b', s, 1000ul);
ok0 = 1;
}
}
}
else {
porttext((uint32_t)i, s, 1000ul);
aprsstr_Append(s, 1000ul, " Not Configured", 16ul);
/* textautosize(0, 5, 6, 10, "e", s); */
useri_xerrmsg(s, 1000ul);
}
if (!ok0) {
useri_configbool((uint8_t)(36UL+(uint32_t)i), 0);
}
}
}
else if ((int32_t)anonym0->fd>=0L) {
osic_CloseSock(anonym0->fd);
anonym0->fd = -1L;
anonym0->starttime = 0UL;
porttext((uint32_t)i, s, 1000ul);
aprsstr_Append(s, 1000ul, " Close", 7ul);
/* textautosize(0, 5, 6, 4, "e", s); */
useri_xerrmsg(s, 1000ul);
}
}
} /* end for */
startserial(&aprsdecode_serialpid, useri_fSERIALTASK);
startserial(&aprsdecode_serialpid2, useri_fSERIALTASK2);
sendmsg();
/*WrInt(tickertime, 15); WrInt(realtime, 15); WrLn; */
if (tickertime+60UL<aprsdecode_realtime) Stopticker();
} /* end tcpjobs() */
static void beepprox(float d, float km)
{
if ((useri_configon(useri_fBEEPPROX) && km!=0.0f) && d<km) {
d = 1.0f-X2C_DIVR(d,km);
d = d*d;
d = d*d;
aprsdecode_beeplim(100L, aprsdecode_trunc((1.0f-d)*(float)useri_conf2int(useri_fBEEPPROX,
0UL, 20L, 8000L,
400L)+d*(float)useri_conf2int(useri_fBEEPPROX, 2UL, 20L,
8000L, 400L)), aprsdecode_trunc((1.0f-d)*(float)useri_conf2int(useri_fBEEPPROX,
1UL, 0L, 5000L, 40L)+d*(float)useri_conf2int(useri_fBEEPPROX,
3UL, 0L, 5000L, 1000L)));
}
} /* end beepprox() */
#define aprsdecode_WARNFN "proxwarn"
#define aprsdecode_LOOKBACK 180
/* last s look if nearest pos is last */
static void approxywarn(struct aprspos_POSITION pos, const char call[],
uint32_t call_len)
{
char s[31];
char h[101];
float d;
float mino;
float mind;
float km;
struct aprspos_POSITION mypos;
aprsdecode_pOPHIST op;
aprsdecode_pFRAMEHIST pf;
int32_t fd;
km = useri_conf2real(useri_fAPPROXY, 0UL, 0.0f, 30000.0f, 0.0f);
if (km!=0.0f) {
if (aprstext_getmypos(&mypos)) {
d = aprspos_distance(pos, mypos);
if (d<=km) {
/* quick check if it is in radius */
op = aprsdecode_ophist0;
while (op && X2C_STRCMP(op->call,9u,call,call_len)) {
op = op->next;
}
if (op) {
mino = 30000.0f;
mind = 30000.0f;
pf = op->frames;
while (pf) {
if (pf->time0+180UL>aprsdecode_realtime && (pf->nodraw&0x4FU)
==0U) {
d = aprspos_distance(pf->vardat->pos, mypos);
/*
FixToStr(distance(pf^.vardat^.pos, mypos), 4, s);
WrStr(s); WrStr(" ");
FixToStr(distance(mypos, pf^.vardat^.pos), 4, s);
WrStr(s); WrStr(" ");
postostr(pf^.vardat^.pos, s); WrStr(s); WrStr(" ");
postostr(mypos, s); WrStrLn(s);
*/
mino = mind;
if (d<mind) mind = d;
}
pf = pf->next;
}
if ((mino<29000.0f && mino!=d) && mino>d) {
beepprox(d, km);
strncpy(h,"approach ",101u);
aprsstr_FixToStr(d, 3UL, s, 31ul);
aprsstr_Append(h, 101ul, s, 31ul);
aprsstr_Append(h, 101ul, "km ", 4ul);
aprsstr_Append(h, 101ul, call, call_len);
useri_textautosize(0L, 5L, 6UL, 120UL, 'r', h, 101ul);
if (!osi_Exists("proxwarn", 9ul)) {
fd = osi_OpenWrite("proxwarn", 9ul);
if (osic_FdValid(fd)) {
aprsstr_Assign(h, 101ul, call, call_len);
aprsstr_IntToStr((int32_t)
aprsdecode_trunc(d*1000.0f), 0UL, s, 31ul);
aprsstr_Append(h, 101ul, " p ", 4ul);
aprsstr_Append(h, 101ul, s, 31ul);
osi_WrBin(fd, (char *)h, 101u/1u,
aprsstr_Length(h, 101ul));
osic_Close(fd);
}
}
}
}
}
}
}
} /* end approxywarn() */
#define aprsdecode_DUPTIME 27
#define aprsdecode_NN "n"
#define aprsdecode_BAD "x"
#define aprsdecode_VIA "v"
static void app0(uint32_t * viac, aprsdecode_FRAMEBUF tb, uint32_t * tp,
char c)
{
if (*tp<511UL) {
tb[*tp] = c;
++*tp;
}
if (c==',') ++*viac;
} /* end app() */
static char via(char words[], uint32_t words_len,
aprsdecode_FRAMEBUF b, char typ, uint32_t from,
uint32_t to)
{
uint32_t i;
char h[31];
if (from>=to) return 0;
h[0U] = typ;
i = 1UL;
while (i<28UL && from<to) {
h[i] = b[from];
++from;
++i;
}
h[i] = ' ';
h[i+1UL] = 0;
return aprsstr_InStr(words, words_len, h, 31ul)>=0L;
} /* end via() */
static char num0(aprsdecode_FRAMEBUF b, uint32_t i, uint32_t * n)
{
if ((i<511UL && (uint8_t)b[i]>='0') && (uint8_t)b[i]<='9') {
*n = (uint32_t)(uint8_t)b[i]-48UL;
return 1;
}
return 0;
} /* end num() */
static char scanpath(char words[], uint32_t words_len,
uint32_t * tp, aprsdecode_FRAMEBUF tb, uint32_t * viac,
aprsdecode_FRAMEBUF b, uint32_t * p, uint32_t to,
char store)
{
uint32_t hp;
hp = *p;
while (*p<to) {
if (store) app0(viac, tb, tp, b[*p]);
if (*p+1UL>=to || b[*p]==',') {
if (via(words, words_len, b, 'x', hp+1UL,
*p+(uint32_t)(*p+1UL>=to))) return 0;
/* bad word */
hp = *p;
}
++*p;
}
return 1;
} /* end scanpath() */
static void digi(const aprsdecode_FRAMEBUF b, char fromrf,
uint32_t outport, char directonly,
char appendrest, uint32_t nomovetime,
uint32_t radius, char words[], uint32_t words_len,
int32_t * txbyte)
{
struct aprsdecode_DAT dat;
uint32_t pn;
uint32_t viac;
uint32_t n2;
uint32_t n1;
uint32_t n;
uint32_t ssid;
uint32_t len;
uint32_t tp;
uint32_t p;
aprsdecode_FRAMEBUF tb;
/* hashl, hashh:SET8; */
uint32_t dt;
char norout;
struct aprspos_POSITION mypos;
char s2[31];
char s1[31];
char mycall[31];
*txbyte = 0L;
if (nomovetime<27UL) nomovetime = 27UL;
if (fromrf) {
tp = 0UL;
p = 0UL;
len = 0UL;
ssid = 0UL;
viac = 0UL;
useri_confstr(useri_fMYCALL, mycall, 31ul);
if (aprstext_callwrong(mycall, 31ul)) {
useri_xerrmsg("Digi needs \'My Call\'", 21ul); /* no mycall */
return;
}
norout = aprsstr_InStr(words, words_len, " x-", 4ul)>=0L;
/* ssid routing off */
if (aprsstr_InStr(words, words_len, " xi", 4ul)<0L) {
aprsstr_Append(words, words_len, " v", 3ul);
/* if not disabled append mycall for via */
aprsstr_Append(words, words_len, mycall, 31ul);
}
aprsstr_Append(words, words_len, " x", 3ul); /* mycall as badword */
aprsstr_Append(words, words_len, mycall, 31ul);
aprsstr_Append(words, words_len, " ", 2ul);
while ((len<511UL && b[len]) && b[len]!=':') ++len;
while (p<len && b[p]!='>') {
app0(&viac, tb, &tp, b[p]); /* end of src call */
++p;
}
if (via(words, words_len, b, 'x', 0UL, p)) return;
/* bad src call */
if (useri_configon(useri_fMUSTBECALL)) {
tb[tp] = 0;
if (!aprstext_isacall(tb, 512ul)) return;
}
n = p+1UL;
while ((p<len && b[p]!='-') && b[p]!=',') {
app0(&viac, tb, &tp, b[p]); /* ssid or end of dst call */
++p;
}
if (via(words, words_len, b, 'x', n, p)) return;
/* bad dest call */
if (b[p]=='-') {
/* we have a ssid */
++p;
if (num0(b, p, &n)) {
ssid = n;
++p;
if (num0(b, p, &n)) {
ssid = ssid*10UL+n;
++p;
}
}
}
if (ssid==0UL || ssid>7UL) norout = 1;
n = p;
while (n<len && b[n]!='*') ++n;
if (n+1UL<len) norout = 1;
if (!norout) {
/* use ssid routing */
if (appendrest) --ssid;
else ssid = 0UL;
}
if (ssid>0UL) {
/* write old or new ssid */
app0(&viac, tb, &tp, '-');
if (ssid>=10UL) app0(&viac, tb, &tp, '1');
app0(&viac, tb, &tp, (char)(ssid%10UL+48UL));
}
if (n<len) {
if (directonly) return;
/* not direct heard */
if (!scanpath(words, words_len, &tp, tb, &viac, b, &p, n, 1)) {
return;
}
/* append path till * and find badwords */
++p;
}
app0(&viac, tb, &tp, ',');
n = 0UL;
while (mycall[n]) {
app0(&viac, tb, &tp, mycall[n]); /* append mycall */
++n;
}
app0(&viac, tb, &tp, '*');
if (p<len) {
/* look for via routing */
norout = 1;
if (b[p]==',') ++p;
n = p;
while (p<len && b[p]!=',') ++p;
if (((((((via(words, words_len, b, 'n', n, p-3UL) && num0(b, p-3UL,
&n1)) && n1>0UL) && n1<=7UL) && b[p-2UL]=='-') && num0(b,
p-1UL, &n2)) && n2>0UL) && n2<=n1) {
if (directonly && n1!=n2) {
return;
}
/* not direct heard */
if (appendrest && n2>1UL) {
/* append not n-0 */
app0(&viac, tb, &tp, ',');
pn = n;
while (pn+3UL<p) {
app0(&viac, tb, &tp, b[pn]); /* append via word */
++pn;
}
app0(&viac, tb, &tp, (char)(n1+48UL)); /* append n-n */
app0(&viac, tb, &tp, '-');
app0(&viac, tb, &tp, (char)(n2+47UL));
}
norout = 0; /* append rest path later*/
}
else if (via(words, words_len, b, 'v', n, p)) norout = 0;
}
if (norout) return;
/* nothing to digipeat */
if (!scanpath(words, words_len, &tp, tb, &viac, b, &p, len,
appendrest)) return;
/* append rest path and find badwords */
if (viac>7UL) return;
/* too much via */
p = len;
while (p<511UL && b[p]) {
app0(&viac, tb, &tp, b[p]);
++p;
}
app0(&viac, tb, &tp, 0);
}
else memcpy(tb,b,512u);
if (aprsdecode_Decode(tb, 512ul, &dat)<0L) return;
/*radius */
if (dat.type!=aprsdecode_MSG && radius>0UL) {
if (!aprstext_getmypos(&mypos)) {
useri_xerrmsg("Digi with Radius needs MY Position", 35ul);
return;
}
if (!aprspos_posvalid(dat.pos) || aprspos_distance(mypos,
dat.pos)>(float)radius) return;
}
if (dat.type==aprsdecode_MSG && aprstext_isacall(dat.msgto, 9ul)) {
dt = 27UL; /* real messages fast dupetime */
}
else dt = nomovetime;
if (outport>0UL && outport-1UL<=3UL) {
*txbyte = Sendudp(tb, 512ul, outport-1UL, dt);
if (*txbyte<0L) {
strncpy(s1,"aprsdigi:can not send to port ",31u);
aprsstr_IntToStr((int32_t)outport, 0UL, s2, 31ul);
aprsstr_Append(s1, 31ul, s2, 31ul);
useri_xerrmsg(s1, 31ul);
}
}
} /* end digi() */
#define aprsdecode_MAXPAYLOAD 200
/* spare min 36 byte for 3rd party header */
#define aprsdecode_MSGMHTIME 3600
/* last heard age for msgs sending */
static void digitorf(const aprsdecode_FRAMEBUF b, uint32_t outport,
uint32_t nomovetime, uint32_t radius, int32_t maxbps,
char words[], uint32_t words_len)
{
uint32_t j;
uint32_t i;
int32_t sentbytes;
aprsdecode_pOPHIST op;
char ok0;
aprsdecode_FRAMEBUF tb;
struct aprsdecode_DAT dat;
char via0[201];
char ww[201];
char w[201];
/*"OH4ZZZ-5>APZ123,WIDE2-2:}OH2XYZ-11>APZYXW-4,TCPIP,OH4ZZZ-5*:>packet "*/
/*WrStr(words); WrStrLn(b); */
if (aprsdecode_Decode(b, 512ul, &dat)<0L || dat.igatep==0UL) return;
aprsstr_Assign(w, 201ul, words, words_len);
do {
aprsstr_Extractword(w, 201ul, ww, 201ul);
} while (!(ww[0U]==0 || ww[0U]=='n'));
if (ww[0U]==0) return;
aprsstr_Delstr(ww, 201ul, 0UL, 1UL);
if (!aprsstr_StrToInt(ww, 201ul, &maxbps)) return;
aprsstr_Extractword(w, 201ul, via0, 201ul); /* via path */
if (via0[0U]=='n') aprsstr_Delstr(via0, 201ul, 0UL, 1UL);
else via0[0U] = 0;
if (maxbps<0L) {
if (dat.type!=aprsdecode_MSG) return;
/* if neg bps send msg only */
/*WrStr(dat.msgto); WrStrLn(" msgto"); */
op = findop(dat.msgto, 1);
/*IF (op<>NIL) THEN WrStr(op^.lastrxport); WrStrLn(" opok") END; */
if ((op==0 || op->lastrxport!=(char)(outport+48UL))
|| op->lasttime+3600UL<aprsdecode_realtime) return;
}
/* user not heard on this port */
if (!Checkbps(outport-1UL, (uint32_t)labs(maxbps), 0UL,
dat.type==aprsdecode_MSG)) return;
/* -bps only msg */
useri_confstr(useri_fMYCALL, tb, 512ul);
if (aprstext_callwrong(tb, 512ul)) {
useri_xerrmsg("Gate to rf needs valid \'My Call\'", 33ul);
return;
}
aprsstr_Append(tb, 512ul, ">APLM01", 8ul);
if (via0[0U]) {
if (via0[0U]!='-') aprsstr_Append(tb, 512ul, ",", 2ul);
else if (((uint8_t)via0[1U]<'1' || (uint8_t)via0[1U]>'9')
|| via0[2U]) return;
/* not correct ssid */
aprsstr_Append(tb, 512ul, via0, 201ul);
}
aprsstr_Append(tb, 512ul, ":}", 3ul);
aprsstr_Append(tb, 512ul, dat.srcall, 9ul);
aprsstr_Append(tb, 512ul, ">", 2ul);
aprsstr_Append(tb, 512ul, dat.dstcall, 9ul);
aprsstr_Append(tb, 512ul, ",TCPIP,", 8ul);
aprsstr_Append(tb, 512ul, dat.viacalls[dat.igatep], 9ul);
aprsstr_Append(tb, 512ul, "*:", 3ul);
i = dat.payload;
j = aprsstr_Length(tb, 512ul);
while (((i<=511UL && b[i]) && b[i]!='\015') && j<511UL) {
tb[j] = b[i];
++j;
++i;
}
tb[j] = 0;
if (i-dat.payload>200UL) return;
/* frame too long */
w[0] = 0;
digi(tb, 0, outport, 0, 1, nomovetime, radius, w, 201ul, &sentbytes);
if (sentbytes>0L) {
ok0 = Checkbps(outport-1UL, (uint32_t)labs(maxbps),
(uint32_t)sentbytes, 0); /* sum up txbytes */
}
} /* end digitorf() */
static void digipeat(const aprsdecode_FRAMEBUF b, uint32_t udpch)
{
uint32_t line;
uint32_t outport;
uint32_t radius;
int32_t sentbytes;
uint32_t nomovetime;
char directonly;
char appendrest;
char words[201];
char word[11];
char cin;
char c;
line = 0UL;
for (;;) {
useri_confstrings(useri_fDIGI, line, 0, words, 201ul);
if (words[0U]==0) break;
cin = words[0U]; /* input port */
if ((cin=='*' && udpch>0UL || cin==(char)(udpch+48UL))
|| cin=='N' && udpch==0UL) {
/* input port, 0 is from net */
c = words[1U]; /* output port */
if ((uint8_t)c>='1') outport = (uint32_t)(uint8_t)c-48UL;
else outport = 0UL;
directonly = 1;
appendrest = 0;
switch ((unsigned)words[2U]) { /* direct/delpath */
case '1':
appendrest = 1;
break;
case '2':
directonly = 0;
break;
case '3':
directonly = 0;
appendrest = 1;
break;
} /* end switch */
aprsstr_Extractword(words, 201ul, word, 11ul);
aprsstr_Extractword(words, 201ul, word, 11ul);
if (aprsstr_StrToCard(word, 11ul, &nomovetime)) {
aprsstr_Extractword(words, 201ul, word, 11ul);
if (aprsstr_StrToCard(word, 11ul, &radius)) {
if (cin=='N') {
digitorf(b, outport, nomovetime, radius, -5L, words,
201ul);
}
else if (udpch>0UL) {
digi(b, 1, outport, directonly, appendrest, nomovetime,
radius, words, 201ul, &sentbytes);
}
}
}
}
++line;
}
} /* end digipeat() */
#define aprsdecode_PURGEINTERVALL 10
/* seconds+1 with no purge */
static void storedata(aprsdecode_FRAMEBUF mb, aprsdecode_pTCPSOCK cp,
uint32_t udpch, const struct UDPSET modeminfo,
char valid, char local)
{
int32_t res;
char fn[1000];
char s[21];
aprsdecode_MONCALL server;
char tabchk;
char ok0;
aprsdecode_pTCPSOCK tp;
struct aprsdecode_DAT dat;
char dir;
uint32_t otime;
char tmp;
if (aprsdecode_lastpurge!=aprsdecode_realtime/10UL) {
if (aprsdecode_lums.logmode) {
aprsdecode_purge(&aprsdecode_ophist2,
aprsdecode_realtime-aprsdecode_lums.purgetime,
aprsdecode_realtime-aprsdecode_lums.purgetimeobj);
}
else {
aprsdecode_purge(&aprsdecode_ophist0,
aprsdecode_realtime-aprsdecode_lums.purgetime,
aprsdecode_realtime-aprsdecode_lums.purgetimeobj);
}
aprsdecode_lastpurge = aprsdecode_realtime/10UL;
}
if (cp) memcpy(server,cp->user.call,9u);
else server[0UL] = 0;
/*WrInt(rxidle, 15); WrInt(lastlooped+IGATEMAXDELAY, 15);
WrInt(time(), 15); WrStrLn(" ig"); */
if (local) res = 0L;
else if (aprsdecode_rxidle>=3UL && aprsdecode_lastlooped+5UL>=osic_time())
{
/* not too long delayd data */
digipeat(mb, udpch);
res = AprsIs(mb, 512ul, 6UL, server, 9ul, udpch, valid,
useri_configon(useri_fMUSTBECALL), &tabchk);
if (((res>=0L && useri_configon(useri_fALLOWGATE)) && !tabchk)
&& udpch>0UL) {
useri_confstr(useri_fALLOWGATE, s, 21ul);
if (aprsstr_InStr(s, 21ul,
(char *)(tmp = (char)(udpch+48UL),&tmp), 1u/1u)>=0L) {
tp = aprsdecode_tcpsocks;
while (tp) {
if (tp->lastping>0UL && (tp->waitpong==1U && tp->lastping+10UL<aprsdecode_realtime || tp->waitpong>1U)
) {
if (tp->lastpong>0UL) {
saylinkbad((int32_t)(aprsdecode_realtime-tp->lastpong)
);
}
useri_xerrmsg("Ping-Timeout, Rf to AprsIs transfer stopped \
temporarily", 56ul);
}
else ok0 = Sendtcp(tp, mb);
tp = tp->next;
}
}
}
}
else {
/* delayed */
res = 0L;
if (aprsdecode_verb) {
osi_WrStrLn("---discarded delayed digpeat-frame", 35ul);
}
}
otime = 0UL;
if (aprsdecode_verb && udpch>0UL) {
osic_WrINT32((uint32_t)res, 3UL);
osi_WrStr(" udp ", 6ul);
osi_WrStrLn(mb, 512ul);
}
if (res>=0L && aprsdecode_Decode(mb, 512ul, &dat)>=0L) {
if (udpch>0UL) dat.lastrxport = (char)(udpch+48UL);
else dat.lastrxport = 'N';
if (dat.type==aprsdecode_MSG) {
if (udpch>0UL) getmessage(0, udpch, dat);
else getmessage(cp, 0UL, dat);
}
if (aprsdecode_lums.logmode) {
res = aprsdecode_Stoframe(&aprsdecode_ophist2, mb, 512ul,
aprsdecode_realtime, 0, &otime, dat);
}
else {
res = aprsdecode_Stoframe(&aprsdecode_ophist0, mb, 512ul,
aprsdecode_realtime, 0, &otime, dat);
}
if (!local) {
if (useri_configon(useri_fLOGWFN)) {
useri_confstr(useri_fLOGWFN, fn, 1000ul);
aprstext_logfndate(aprsdecode_realtime, fn, 1000ul);
if (!wrlog(mb, 512ul, aprsdecode_realtime, fn, 1000ul, res)) {
poplogerr(fn, 1000ul);
}
}
if (aprspos_posvalid(dat.pos) && useri_configon(useri_fAPPROXY)) {
approxywarn(dat.pos, dat.symcall, 9ul);
}
}
}
if (res==-2L) {
dir = '#';
}
else if (res<0L) dir = '-';
else dir = '>';
if (udpch>0UL) wrmon(udpch, dir, modeminfo, otime, mb, 512ul);
else wrmon(0UL, dir, modeminfo, otime, mb, 512ul);
} /* end storedata() */
extern void aprsdecode_drawbeacon(char raw[], uint32_t raw_len)
{
aprsdecode_FRAMEBUF b;
char port;
uint32_t time0;
struct UDPSET modeminfo;
aprsstr_Assign(b, 512ul, raw, raw_len);
if (getbeaconparm(b, 512ul, &time0, &port)) {
beaconmacros(b, 512ul, "", 1ul, "", 1ul, 1);
if (b[0UL]) {
memset((char *) &modeminfo,(char)0,sizeof(struct UDPSET));
storedata(b, 0, 0UL, modeminfo, 0, 1);
if (aprsdecode_lums.logmode) {
useri_say("drawn to Realtime Data not to imported Log!", 44ul,
5UL, 'r');
}
else if (aprsdecode_click.mhop[0UL]) {
useri_say("switch to \"show all\" to see new object", 39ul, 5UL,
'r');
}
}
}
else useri_xerrmsg("decode error", 13ul);
aprsdecode_tracenew.winevent = 2000UL;
} /* end drawbeacon() */
static aprsstr_GHOSTSET _cnst2 = {0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,
0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,
0xFFFFFFFFUL,0x00000001UL};
static aprsstr_GHOSTSET _cnst1 = {0x00000000UL,0x00000000UL,0x00000000UL,
0x00000000UL,0x00000000UL,0x00000000UL,0x00000000UL,
0x00000000UL,0x00000000UL};
static void getghostset(uint32_t port, aprsstr_GHOSTSET g)
{
uint32_t n;
uint32_t i;
char s[11];
char p;
p = (char)(port+49UL);
memcpy(g,_cnst1,36u);
i = 0UL;
for (;;) {
useri_conf2str(useri_fFINGERPRINT, i, s, 11ul);
if (s[0U]==0) break;
if (s[0U]==p) {
if (s[1U]==':') {
aprsstr_Delstr(s, 11ul, 0UL, 2UL);
if (aprsstr_StrToCard(s, 11ul, &n) && n<=256UL) {
X2C_INCL(g,n,257);
}
}
else if (s[1U]==0) memcpy(g,_cnst2,36u);
}
++i;
}
} /* end getghostset() */
extern void aprsdecode_udpin(uint32_t port)
{
aprsdecode_FRAMEBUF mbuf;
struct UDPSET modeminfo;
aprsstr_GHOSTSET gs;
struct aprsdecode_UDPSOCK * anonym;
getghostset(port, gs);
while (getudp(port, mbuf, &modeminfo, gs)) {
if (mbuf[0UL]) {
{ /* with */
struct aprsdecode_UDPSOCK * anonym = &aprsdecode_udpsocks0[port];
anonym->lastudprx = aprsdecode_realtime;
++anonym->rxframes;
anonym->rxbytes += aprsstr_Length(mbuf, 512ul);
if (anonym->starttime==0UL) {
anonym->starttime = aprsdecode_realtime;
}
}
aprsdecode_lastanyudprx = aprsdecode_realtime;
storedata(mbuf, 0, port+1UL, modeminfo, 0, 0);
}
else if (aprsdecode_verb) osi_WrStrLn("axudp decode error", 19ul);
}
} /* end udpin() */
extern int32_t aprsdecode_tcpout(aprsdecode_pTCPSOCK acttcp)
{
int32_t i;
int32_t res;
struct aprsdecode_TCPSOCK * anonym;
int32_t tmp;
if ((int32_t)acttcp->fd>=0L) {
{ /* with */
struct aprsdecode_TCPSOCK * anonym = acttcp;
res = sendsock(anonym->fd, anonym->tbuf, anonym->tlen);
if (res>0L) {
tmp = anonym->tlen-1L;
i = res;
if (i<=tmp) for (;; i++) {
anonym->tbuf[i-res] = anonym->tbuf[i];
if (i==tmp) break;
} /* end for */
anonym->tlen -= res;
if (anonym->connt==0UL) {
anonym->connt = aprsdecode_realtime;
wrconnected(acttcp);
}
anonym->watchtime = aprsdecode_realtime;
}
}
}
else {
/* ELSE tlen:=0; (* should not happen *) */
res = -1L;
}
return res;
} /* end tcpout() */
extern void aprsdecode_tcpin(aprsdecode_pTCPSOCK acttcp)
{
int32_t res;
aprsdecode_FRAMEBUF mbuf;
struct UDPSET modeminfo;
if ((int32_t)acttcp->fd>=0L) {
for (;;) {
res = Gettcp(acttcp->fd, mbuf, acttcp->rbuf, &acttcp->rpos);
/*WrInt(res, 1);WrStrLn(" gettcp"); */
if (res<0L) {
/*WrStrLn("closesock"); */
osic_CloseSock(acttcp->fd);
acttcp->fd = -1L;
break;
}
if (res<=0L) break;
++acttcp->rxframes;
acttcp->rxbytes += aprsstr_Length(mbuf, 512ul);
acttcp->watchtime = aprsdecode_realtime;
/* WrMon(mbuf); */
if (mbuf[0UL]=='#') getpong(acttcp, mbuf, 512ul);
memset((char *) &modeminfo,(char)0,sizeof(struct UDPSET));
storedata(mbuf, acttcp, 0UL, modeminfo, 1, 0);
aprsdecode_lasttcprx = aprsdecode_realtime;
}
}
} /* end tcpin() */
extern void aprsdecode_initparms(void)
{
uint32_t i;
struct aprsdecode__D1 * anonym;
initcrc12();
memset((char *)aprsdecode_gateways,(char)0,
sizeof(struct aprsdecode__D3 [10]));
memset((char *)aprsdecode_udpsocks0,(char)0,
sizeof(struct aprsdecode_UDPSOCK [4]));
for (i = 0UL; i<=3UL; i++) {
aprsdecode_udpsocks0[i].fd = -1L;
} /* end for */
connecttime = 0UL;
cycleservers = 0UL;
logframename[0UL] = 0;
logframes = 6L;
aprsdecode_testbeaconbuf[0UL] = 0;
/* servercall[0]:=0C; */
/* passwd[0]:=0C; */
/* igatedelay:=TRUE; */
rfbeacont = 0UL;
qas = 0UL;
qasc = 0UL;
aprsdecode_initxsize = 0L;
aprsdecode_initysize = 0L;
aprsdecode_initzoom = 0L;
aprsdecode_finezoom = 1.0f;
aprsdecode_posinval(&aprsdecode_mappos);
aprsdecode_spikesens = 2.0f;
aprsdecode_maxhop = 100.0f;
maxspeed = 1000.0f;
nextbeep = 0UL;
{ /* with */
struct aprsdecode__D1 * anonym = &aprsdecode_lums;
anonym->map = 350L;
anonym->rfbri = 350L;
anonym->track = 1000L;
anonym->waypoint = 800L;
anonym->sym = 1000L;
anonym->obj = 1000L;
anonym->text = 750L;
anonym->nomov = 90L;
anonym->maxdim = 3600UL;
anonym->firstdim = 82800UL;
anonym->purgetime = 90000UL;
anonym->purgetimeobj = 90000UL;
anonym->dupemaxtime = 10800UL;
anonym->fps = 0L;
/* mapmode:=REFLATER; */
strncpy(anonym->mapname,"tiles",41u);
anonym->maplumcorr = -128L;
anonym->gamma = 2.2f;
anonym->centering = 40L;
anonym->movestep = 10UL;
strncpy(anonym->configfn,"aprsmap.cfg",257u);
anonym->wxcol = 0;
}
aprsdecode_lastpurge = 0UL;
aprsdecode_lastanyudprx = 0UL;
aprsdecode_lasttcprx = 0UL;
strncpy(aprsdecode_mapdir,"osm",1025u);
parms();
aprsdecode_ophist0 = 0;
aprsdecode_ophist2 = 0;
aprsdecode_txmessages = 0;
aprsdecode_msgfifo0 = 0;
msgmid = 0UL;
aprsdecode_realtime = osic_time();
uptime = aprsdecode_realtime;
trygate = 0UL;
dupetime = 60UL;
ungate[0U][0] = 0;
strncpy(ungate[1U],"NOGATE",9u);
strncpy(ungate[2U],"RFONLY",9u);
strncpy(ungate[3U],"TCPIP",9u);
strncpy(ungate[4U],"TCPXX",9u);
strncpy(ungate[5U],"q",9u);
ungate[6U][0] = 0;
aprsdecode_tcpsocks = 0;
Stopticker();
tickertime = 0UL;
sentemptymsg = 0;
beaconrandomstart = osic_time();
/* set a beacon scheduler start second in minute */
beaconrandomstart = (beaconrandomstart/60UL)%60UL+(beaconrandomstart%60UL)
*60UL;
} /* end initparms() */
extern void aprsdecode_BEGIN(void)
{
static int aprsdecode_init = 0;
if (aprsdecode_init) return;
aprsdecode_init = 1;
if (sizeof(aprsdecode_SET256)!=32) X2C_ASSERT(0);
if (sizeof(aprsdecode_MONCALL)!=9) X2C_ASSERT(0);
if (sizeof(aprsdecode_FRAMEBUF)!=512) X2C_ASSERT(0);
if (sizeof(aprsdecode_WWWB)!=1401) X2C_ASSERT(0);
if (sizeof(aprsdecode_FILENAME)!=1024) X2C_ASSERT(0);
if (sizeof(aprsdecode_DUPETIMES)!=262144) X2C_ASSERT(0);
if (sizeof(aprsdecode_MSGTEXT)!=67) X2C_ASSERT(0);
if (sizeof(aprsdecode_ACKTEXT)!=5) X2C_ASSERT(0);
if (sizeof(aprsdecode_ACKREPTEXT)!=2) X2C_ASSERT(0);
if (sizeof(uint8_t)!=1) X2C_ASSERT(0);
if (sizeof(uint8_t)!=1) X2C_ASSERT(0);
if (sizeof(uint16_t)!=2) X2C_ASSERT(0);
if (sizeof(aprsdecode_TELEMETRY)!=14) X2C_ASSERT(0);
if (sizeof(uint16_t)!=2) X2C_ASSERT(0);
if (sizeof(aprsdecode_MAPNAME)!=41) X2C_ASSERT(0);
if (sizeof(aprsdecode_SYMBOLSET)!=24) X2C_ASSERT(0);
if (sizeof(CHSET)!=16) X2C_ASSERT(0);
if (sizeof(TICKERCALL)!=31) X2C_ASSERT(0);
aprstext_BEGIN();
useri_BEGIN();
aprspos_BEGIN();
aprsstr_BEGIN();
osi_BEGIN();
xosi_BEGIN();
}