mirror of https://github.com/wb2osz/direwolf.git
Better duplicate checking for IGate and debug option to see what is going on.
This commit is contained in:
parent
1376c0c2fb
commit
1053bc483f
|
@ -584,21 +584,21 @@ check : dtest ttest tttexttest pftest tlmtest lltest enctest kisstest check-mode
|
||||||
# Can we encode and decode at popular data rates?
|
# Can we encode and decode at popular data rates?
|
||||||
|
|
||||||
check-modem1200 : gen_packets atest
|
check-modem1200 : gen_packets atest
|
||||||
gen_packets -n 100 -o /tmp/test1.wav
|
./gen_packets -n 100 -o /tmp/test1.wav
|
||||||
atest -F0 -PE -L70 -G71 /tmp/test1.wav
|
./atest -F0 -PE -L70 -G71 /tmp/test1.wav
|
||||||
atest -F1 -PE -L73 -G75 /tmp/test1.wav
|
./atest -F1 -PE -L73 -G75 /tmp/test1.wav
|
||||||
#rm /tmp/test1.wav
|
#rm /tmp/test1.wav
|
||||||
|
|
||||||
check-modem300 : gen_packets atest
|
check-modem300 : gen_packets atest
|
||||||
gen_packets -B300 -n 100 -o /tmp/test3.wav
|
./gen_packets -B300 -n 100 -o /tmp/test3.wav
|
||||||
atest -B300 -F0 -L68 -G69 /tmp/test3.wav
|
./atest -B300 -F0 -L68 -G69 /tmp/test3.wav
|
||||||
atest -B300 -F1 -L73 -G75 /tmp/test3.wav
|
./atest -B300 -F1 -L73 -G75 /tmp/test3.wav
|
||||||
rm /tmp/test3.wav
|
rm /tmp/test3.wav
|
||||||
|
|
||||||
check-modem9600 : gen_packets atest
|
check-modem9600 : gen_packets atest
|
||||||
gen_packets -B9600 -n 100 -o /tmp/test9.wav
|
./gen_packets -B9600 -n 100 -o /tmp/test9.wav
|
||||||
atest -B9600 -F0 -L57 -G59 /tmp/test9.wav
|
./atest -B9600 -F0 -L57 -G59 /tmp/test9.wav
|
||||||
atest -B9600 -F1 -L66 -G67 /tmp/test9.wav
|
./atest -B9600 -F1 -L66 -G67 /tmp/test9.wav
|
||||||
rm /tmp/test9.wav
|
rm /tmp/test9.wav
|
||||||
|
|
||||||
|
|
||||||
|
@ -606,7 +606,8 @@ check-modem9600 : gen_packets atest
|
||||||
# Unit test for inner digipeater algorithm
|
# Unit test for inner digipeater algorithm
|
||||||
|
|
||||||
.PHONY : dtest
|
.PHONY : dtest
|
||||||
dtest : digipeater.c pfilter.o ax25_pad.o dedupe.o fcs_calc.o tq.o textcolor.o \
|
dtest : digipeater.c dedupe.c \
|
||||||
|
pfilter.o ax25_pad.o fcs_calc.o tq.o textcolor.o \
|
||||||
decode_aprs.o dwgpsnmea.o dwgps.o dwgpsd.o serial_port.o latlong.o telemetry.o symbols.o tt_text.o misc.a
|
decode_aprs.o dwgpsnmea.o dwgps.o dwgpsd.o serial_port.o latlong.o telemetry.o symbols.o tt_text.o misc.a
|
||||||
$(CC) $(CFLAGS) -DDIGITEST -o $@ $^ $(LDFLAGS)
|
$(CC) $(CFLAGS) -DDIGITEST -o $@ $^ $(LDFLAGS)
|
||||||
./dtest
|
./dtest
|
||||||
|
|
|
@ -283,7 +283,8 @@ atest9 : atest.c demod.c dsp.c demod_afsk.c demod_9600.c hdlc_rec.c hdlc_rec2.c
|
||||||
# Unit test for inner digipeater algorithm
|
# Unit test for inner digipeater algorithm
|
||||||
|
|
||||||
.PHONY: dtest
|
.PHONY: dtest
|
||||||
dtest : digipeater.c pfilter.o ax25_pad.o dedupe.o fcs_calc.o tq.o textcolor.o \
|
dtest : digipeater.c dedupe.c \
|
||||||
|
pfilter.o ax25_pad.o fcs_calc.o tq.o textcolor.o \
|
||||||
decode_aprs.o dwgpsnmea.o dwgps.o serial_port.o latlong.o telemetry.o symbols.o tt_text.o misc.a regex.a
|
decode_aprs.o dwgpsnmea.o dwgps.o serial_port.o latlong.o telemetry.o symbols.o tt_text.o misc.a regex.a
|
||||||
$(CC) $(CFLAGS) -DDIGITEST -o $@ $^
|
$(CC) $(CFLAGS) -DDIGITEST -o $@ $^
|
||||||
./dtest
|
./dtest
|
||||||
|
|
168
ax25_pad.c
168
ax25_pad.c
|
@ -476,7 +476,7 @@ packet_t ax25_from_text (char *monitor, int strict)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! ax25_parse_addr (pa, strict, atemp, &ssid_temp, &heard_temp)) {
|
if ( ! ax25_parse_addr (AX25_SOURCE, pa, strict, atemp, &ssid_temp, &heard_temp)) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Failed to create packet from text. Bad source address\n");
|
dw_printf ("Failed to create packet from text. Bad source address\n");
|
||||||
ax25_delete (this_p);
|
ax25_delete (this_p);
|
||||||
|
@ -500,7 +500,7 @@ packet_t ax25_from_text (char *monitor, int strict)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! ax25_parse_addr (pa, strict, atemp, &ssid_temp, &heard_temp)) {
|
if ( ! ax25_parse_addr (AX25_DESTINATION, pa, strict, atemp, &ssid_temp, &heard_temp)) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Failed to create packet from text. Bad destination address\n");
|
dw_printf ("Failed to create packet from text. Bad destination address\n");
|
||||||
ax25_delete (this_p);
|
ax25_delete (this_p);
|
||||||
|
@ -524,7 +524,7 @@ packet_t ax25_from_text (char *monitor, int strict)
|
||||||
|
|
||||||
// JWL 10:38 this_p->num_addr++;
|
// JWL 10:38 this_p->num_addr++;
|
||||||
|
|
||||||
if ( ! ax25_parse_addr (pa, strict, atemp, &ssid_temp, &heard_temp)) {
|
if ( ! ax25_parse_addr (k, pa, strict, atemp, &ssid_temp, &heard_temp)) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Failed to create packet from text. Bad digipeater address\n");
|
dw_printf ("Failed to create packet from text. Bad digipeater address\n");
|
||||||
ax25_delete (this_p);
|
ax25_delete (this_p);
|
||||||
|
@ -582,11 +582,8 @@ packet_t ax25_from_frame_debug (unsigned char *fbuf, int flen, alevel_t alevel,
|
||||||
packet_t ax25_from_frame (unsigned char *fbuf, int flen, alevel_t alevel)
|
packet_t ax25_from_frame (unsigned char *fbuf, int flen, alevel_t alevel)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
//unsigned char *pf;
|
|
||||||
packet_t this_p;
|
packet_t this_p;
|
||||||
|
|
||||||
//int a;
|
|
||||||
//int addr_bytes;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First make sure we have an acceptable length:
|
* First make sure we have an acceptable length:
|
||||||
|
@ -687,7 +684,10 @@ packet_t ax25_dup (packet_t copy_from)
|
||||||
*
|
*
|
||||||
* Purpose: Parse address with optional ssid.
|
* Purpose: Parse address with optional ssid.
|
||||||
*
|
*
|
||||||
* Inputs: in_addr - Input such as "WB2OSZ-15*"
|
* Inputs: position - AX25_DESTINATION, AX25_SOURCE, AX25_REPEATER_1...
|
||||||
|
* Used for more specific error message. -1 if not used.
|
||||||
|
*
|
||||||
|
* in_addr - Input such as "WB2OSZ-15*"
|
||||||
*
|
*
|
||||||
* strict - TRUE for strict checking (6 characters, no lower case,
|
* strict - TRUE for strict checking (6 characters, no lower case,
|
||||||
* SSID must be in range of 0 to 15).
|
* SSID must be in range of 0 to 15).
|
||||||
|
@ -710,8 +710,12 @@ packet_t ax25_dup (packet_t copy_from)
|
||||||
*
|
*
|
||||||
*------------------------------------------------------------------------------*/
|
*------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static const char *position_name[1 + AX25_MAX_ADDRS] = {
|
||||||
|
"", "Destination ", "Source ",
|
||||||
|
"Digi1 ", "Digi2 ", "Digi3 ", "Digi4 ",
|
||||||
|
"Digi5 ", "Digi6 ", "Digi7 ", "Digi8 " };
|
||||||
|
|
||||||
int ax25_parse_addr (char *in_addr, int strict, char *out_addr, int *out_ssid, int *out_heard)
|
int ax25_parse_addr (int position, char *in_addr, int strict, char *out_addr, int *out_ssid, int *out_heard)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
char sstr[8]; /* Should be 1 or 2 digits for SSID. */
|
char sstr[8]; /* Should be 1 or 2 digits for SSID. */
|
||||||
|
@ -722,22 +726,33 @@ int ax25_parse_addr (char *in_addr, int strict, char *out_addr, int *out_ssid, i
|
||||||
*out_ssid = 0;
|
*out_ssid = 0;
|
||||||
*out_heard = 0;
|
*out_heard = 0;
|
||||||
|
|
||||||
|
if (strict && strlen(in_addr) >= 2 && strncmp(in_addr, "qA", 2) == 0) {
|
||||||
|
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("%sAddress \"%s\" is a \"q-construct\" used for communicating\n", position_name[position], in_addr);
|
||||||
|
dw_printf ("with APRS Internet Servers. It was not expected here.\n");
|
||||||
|
}
|
||||||
|
|
||||||
//dw_printf ("ax25_parse_addr in: %s\n", in_addr);
|
//dw_printf ("ax25_parse_addr in: %s\n", in_addr);
|
||||||
|
|
||||||
|
if (position < -1) position = -1;
|
||||||
|
if (position > AX25_REPEATER_8) position = AX25_REPEATER_8;
|
||||||
|
position++; /* Adjust for position_name above. */
|
||||||
|
|
||||||
maxlen = strict ? 6 : (AX25_MAX_ADDR_LEN-1);
|
maxlen = strict ? 6 : (AX25_MAX_ADDR_LEN-1);
|
||||||
p = in_addr;
|
p = in_addr;
|
||||||
i = 0;
|
i = 0;
|
||||||
for (p = in_addr; isalnum(*p); p++) {
|
for (p = in_addr; isalnum(*p); p++) {
|
||||||
if (i >= maxlen) {
|
if (i >= maxlen) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Address is too long. \"%s\" has more than %d characters.\n", in_addr, maxlen);
|
dw_printf ("%sAddress is too long. \"%s\" has more than %d characters.\n", position_name[position], in_addr, maxlen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
out_addr[i++] = *p;
|
out_addr[i++] = *p;
|
||||||
out_addr[i] = '\0';
|
out_addr[i] = '\0';
|
||||||
if (strict && islower(*p)) {
|
if (strict && islower(*p)) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Address has lower case letters. \"%s\" must be all upper case.\n", in_addr);
|
dw_printf ("%sAddress has lower case letters. \"%s\" must be all upper case.\n", position_name[position], in_addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -748,21 +763,21 @@ int ax25_parse_addr (char *in_addr, int strict, char *out_addr, int *out_ssid, i
|
||||||
for (p++; isalnum(*p); p++) {
|
for (p++; isalnum(*p); p++) {
|
||||||
if (j >= 2) {
|
if (j >= 2) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("SSID is too long. SSID part of \"%s\" has more than 2 characters.\n", in_addr);
|
dw_printf ("%sSSID is too long. SSID part of \"%s\" has more than 2 characters.\n", position_name[position], in_addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
sstr[j++] = *p;
|
sstr[j++] = *p;
|
||||||
sstr[j] = '\0';
|
sstr[j] = '\0';
|
||||||
if (strict && ! isdigit(*p)) {
|
if (strict && ! isdigit(*p)) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("SSID must be digits. \"%s\" has letters in SSID.\n", in_addr);
|
dw_printf ("%sSSID must be digits. \"%s\" has letters in SSID.\n", position_name[position], in_addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
k = atoi(sstr);
|
k = atoi(sstr);
|
||||||
if (k < 0 || k > 15) {
|
if (k < 0 || k > 15) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("SSID out of range. SSID of \"%s\" not in range of 0 to 15.\n", in_addr);
|
dw_printf ("%sSSID out of range. SSID of \"%s\" not in range of 0 to 15.\n", position_name[position], in_addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*out_ssid = k;
|
*out_ssid = k;
|
||||||
|
@ -775,7 +790,7 @@ int ax25_parse_addr (char *in_addr, int strict, char *out_addr, int *out_ssid, i
|
||||||
|
|
||||||
if (*p != '\0') {
|
if (*p != '\0') {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Invalid character \"%c\" found in address \"%s\".\n", *p, in_addr);
|
dw_printf ("Invalid character \"%c\" found in %saddress \"%s\".\n", *p, position_name[position], in_addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,6 +801,73 @@ int ax25_parse_addr (char *in_addr, int strict, char *out_addr, int *out_ssid, i
|
||||||
} /* end ax25_parse_addr */
|
} /* end ax25_parse_addr */
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Name: ax25_check_addresses
|
||||||
|
*
|
||||||
|
* Purpose: Check addresses of given packet and print message if any issues.
|
||||||
|
* We call this when receiving and transmitting.
|
||||||
|
*
|
||||||
|
* Inputs: pp - packet object pointer.
|
||||||
|
*
|
||||||
|
* Errors: Print error message.
|
||||||
|
*
|
||||||
|
* Returns: 1 for all valid. 0 if not.
|
||||||
|
*
|
||||||
|
* Examples: I was surprised to get this from an APRS-IS server with
|
||||||
|
* a lower case source address.
|
||||||
|
*
|
||||||
|
* n1otx>APRS,TCPIP*,qAC,THIRD:@141335z4227.48N/07111.73W_348/005g014t044r000p000h60b10075.wview_5_20_2
|
||||||
|
*
|
||||||
|
* I haven't gotten to the bottom of this yet but it sounds
|
||||||
|
* like "q constructs" are somehow getting on to the air when
|
||||||
|
* they should only appear in conversations with IGate servers.
|
||||||
|
*
|
||||||
|
* https://groups.yahoo.com/neo/groups/direwolf_packet/conversations/topics/678
|
||||||
|
*
|
||||||
|
* WB0VGI-7>APDW12,W0YC-5*,qAR,AE0RF-10:}N0DZQ-10>APWW10,TCPIP,WB0VGI-7*:;145.230MN*080306z4607.62N/09230.58WrKE0ACL/R 145.230- T146.2 (Pine County ARES)
|
||||||
|
*
|
||||||
|
* Typical result:
|
||||||
|
*
|
||||||
|
* Digipeater WIDE2 (probably N3LEE-4) audio level = 28(10/6) [NONE] __|||||||
|
||||||
|
* [0.5] VE2DJE-9>P_0_P?,VE2PCQ-3,K1DF-7,N3LEE-4,WIDE2*:'{S+l <0x1c>>/
|
||||||
|
* Invalid character "_" in MIC-E destination/latitude.
|
||||||
|
* Invalid character "_" in MIC-E destination/latitude.
|
||||||
|
* Invalid character "?" in MIC-E destination/latitude.
|
||||||
|
* Invalid MIC-E N/S encoding in 4th character of destination.
|
||||||
|
* Invalid MIC-E E/W encoding in 6th character of destination.
|
||||||
|
* MIC-E, normal car (side view), Unknown manufacturer, Returning
|
||||||
|
* N 00 00.0000, E 005 55.1500, 0 MPH
|
||||||
|
* Invalid character "_" found in Destination address "P_0_P?".
|
||||||
|
*
|
||||||
|
* *** The origin and journey of this packet should receive some scrutiny. ***
|
||||||
|
*
|
||||||
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int ax25_check_addresses (packet_t pp)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
char addr[AX25_MAX_ADDR_LEN];
|
||||||
|
char ignore1[AX25_MAX_ADDR_LEN];
|
||||||
|
int ignore2, ignore3;
|
||||||
|
int all_ok = 1;
|
||||||
|
|
||||||
|
for (n = 0; n < ax25_get_num_addr(pp); n++) {
|
||||||
|
ax25_get_addr_with_ssid (pp, n, addr);
|
||||||
|
all_ok &= ax25_parse_addr (n, addr, 1, ignore1, &ignore2, &ignore3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! all_ok) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("\n");
|
||||||
|
dw_printf ("*** The origin and journey of this packet should receive some scrutiny. ***\n");
|
||||||
|
dw_printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (all_ok);
|
||||||
|
} /* end ax25_check_addresses */
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: ax25_unwrap_third_party
|
* Name: ax25_unwrap_third_party
|
||||||
|
@ -862,7 +944,7 @@ void ax25_set_addr (packet_t this_p, int n, char *ad)
|
||||||
/*
|
/*
|
||||||
* Set existing address position.
|
* Set existing address position.
|
||||||
*/
|
*/
|
||||||
ax25_parse_addr (ad, 0, atemp, &ssid_temp, &heard_temp);
|
ax25_parse_addr (n, ad, 0, atemp, &ssid_temp, &heard_temp);
|
||||||
|
|
||||||
memset (this_p->frame_data + n*7, ' ' << 1, 6);
|
memset (this_p->frame_data + n*7, ' ' << 1, 6);
|
||||||
|
|
||||||
|
@ -951,7 +1033,11 @@ void ax25_insert_addr (packet_t this_p, int n, char *ad)
|
||||||
|
|
||||||
SET_LAST_ADDR_FLAG;
|
SET_LAST_ADDR_FLAG;
|
||||||
|
|
||||||
ax25_parse_addr (ad, 0, atemp, &ssid_temp, &heard_temp);
|
// Why aren't we setting 'strict' here?
|
||||||
|
// Messages from IGate have q-constructs.
|
||||||
|
// We use this to parse it and later remove unwanted parts.
|
||||||
|
|
||||||
|
ax25_parse_addr (n, ad, 0, atemp, &ssid_temp, &heard_temp);
|
||||||
memset (this_p->frame_data + n*7, ' ' << 1, 6);
|
memset (this_p->frame_data + n*7, ' ' << 1, 6);
|
||||||
for (i=0; i<6 && atemp[i] != '\0'; i++) {
|
for (i=0; i<6 && atemp[i] != '\0'; i++) {
|
||||||
this_p->frame_data[n*7+i] = atemp[i] << 1;
|
this_p->frame_data[n*7+i] = atemp[i] << 1;
|
||||||
|
@ -1161,7 +1247,8 @@ void ax25_get_addr_with_ssid (packet_t this_p, int n, char *station)
|
||||||
snprintf (sstr, sizeof(sstr), "-%d", ssid);
|
snprintf (sstr, sizeof(sstr), "-%d", ssid);
|
||||||
strlcat (station, sstr, 10);
|
strlcat (station, sstr, 10);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} /* end ax25_get_addr_with_ssid */
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
|
@ -2065,6 +2152,27 @@ int ax25_get_pid (packet_t this_p)
|
||||||
* packets will result in the same checksum, and the
|
* packets will result in the same checksum, and the
|
||||||
* undesired dropping of the packet.
|
* undesired dropping of the packet.
|
||||||
*
|
*
|
||||||
|
* There is a 1 / 65536 chance of getting a false positive match
|
||||||
|
* which is good enough for this application.
|
||||||
|
* We could reduce that with a 32 bit CRC instead of reusing
|
||||||
|
* code from the AX.25 frame CRC calculation.
|
||||||
|
*
|
||||||
|
* Version 1.3: We exclude any trailing CR/LF at the end of the info part
|
||||||
|
* so we can detect duplicates that are received only over the
|
||||||
|
* air and those which have gone thru an IGate where the process
|
||||||
|
* removes any trailing CR/LF. Example:
|
||||||
|
*
|
||||||
|
* Original via RF only:
|
||||||
|
* W1TG-1>APU25N,N3LEE-10*,WIDE2-1:<IGATE,MSG_CNT=30,LOC_CNT=61<0x0d>
|
||||||
|
*
|
||||||
|
* When we get the same thing via APRS-IS:
|
||||||
|
* W1TG-1>APU25N,K1FFK,WIDE2*,qAR,WB2ZII-15:<IGATE,MSG_CNT=30,LOC_CNT=61
|
||||||
|
*
|
||||||
|
* (Actually there is a trailing space. Maybe some systems
|
||||||
|
* change control characters to space???)
|
||||||
|
* Hmmmm. I guess we should ignore trailing space as well for
|
||||||
|
* duplicate detection and suppression.
|
||||||
|
*
|
||||||
*------------------------------------------------------------------------------*/
|
*------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
unsigned short ax25_dedupe_crc (packet_t pp)
|
unsigned short ax25_dedupe_crc (packet_t pp)
|
||||||
|
@ -2079,6 +2187,20 @@ unsigned short ax25_dedupe_crc (packet_t pp)
|
||||||
ax25_get_addr_with_ssid(pp, AX25_DESTINATION, dest);
|
ax25_get_addr_with_ssid(pp, AX25_DESTINATION, dest);
|
||||||
info_len = ax25_get_info (pp, &pinfo);
|
info_len = ax25_get_info (pp, &pinfo);
|
||||||
|
|
||||||
|
while (info_len >= 1 && (pinfo[info_len-1] == '\r' ||
|
||||||
|
pinfo[info_len-1] == '\n' ||
|
||||||
|
pinfo[info_len-1] == ' ')) {
|
||||||
|
|
||||||
|
// Temporary for debugging!
|
||||||
|
|
||||||
|
// if (pinfo[info_len-1] == ' ') {
|
||||||
|
// text_color_set(DW_COLOR_ERROR);
|
||||||
|
// dw_printf ("DEBUG: ax25_dedupe_crc ignoring trailing space.\n");
|
||||||
|
// }
|
||||||
|
|
||||||
|
info_len--;
|
||||||
|
}
|
||||||
|
|
||||||
crc = 0xffff;
|
crc = 0xffff;
|
||||||
crc = crc16((unsigned char *)src, strlen(src), crc);
|
crc = crc16((unsigned char *)src, strlen(src), crc);
|
||||||
crc = crc16((unsigned char *)dest, strlen(dest), crc);
|
crc = crc16((unsigned char *)dest, strlen(dest), crc);
|
||||||
|
@ -2160,6 +2282,11 @@ unsigned short ax25_m_m_crc (packet_t pp)
|
||||||
* packet raw data is in hexadecimal but an extracted
|
* packet raw data is in hexadecimal but an extracted
|
||||||
* comment displays UTF-8? Or a command line option for only ASCII?
|
* comment displays UTF-8? Or a command line option for only ASCII?
|
||||||
*
|
*
|
||||||
|
* Trailing space:
|
||||||
|
* I recently noticed a case where a packet has space character
|
||||||
|
* at the end. If the last character of the line is a space,
|
||||||
|
* this will be displayed in hexadecimal to make it obvious.
|
||||||
|
*
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define MAXSAFE 500
|
#define MAXSAFE 500
|
||||||
|
@ -2184,7 +2311,12 @@ void ax25_safe_print (char *pstr, int len, int ascii_only)
|
||||||
{
|
{
|
||||||
ch = *((unsigned char *)pstr);
|
ch = *((unsigned char *)pstr);
|
||||||
|
|
||||||
if (ch < ' ' || ch == 0x7f || ch == 0xfe || ch == 0xff ||
|
if (ch == ' ' && (len == 1 || pstr[1] == '\0')) {
|
||||||
|
|
||||||
|
snprintf (safe_str + safe_len, sizeof(safe_str)-safe_len, "<0x%02x>", ch);
|
||||||
|
safe_len += 6;
|
||||||
|
}
|
||||||
|
else if (ch < ' ' || ch == 0x7f || ch == 0xfe || ch == 0xff ||
|
||||||
(ascii_only && ch >= 0x80) ) {
|
(ascii_only && ch >= 0x80) ) {
|
||||||
|
|
||||||
/* Control codes and delete. */
|
/* Control codes and delete. */
|
||||||
|
|
|
@ -307,7 +307,8 @@ extern void ax25_delete (packet_t pp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern int ax25_parse_addr (char *in_addr, int strict, char *out_addr, int *out_ssid, int *out_heard);
|
extern int ax25_parse_addr (int position, char *in_addr, int strict, char *out_addr, int *out_ssid, int *out_heard);
|
||||||
|
extern int ax25_check_addresses (packet_t pp);
|
||||||
|
|
||||||
extern packet_t ax25_unwrap_third_party (packet_t from_pp);
|
extern packet_t ax25_unwrap_third_party (packet_t from_pp);
|
||||||
|
|
||||||
|
|
27
config.c
27
config.c
|
@ -742,8 +742,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
memset (p_igate_config, 0, sizeof(struct igate_config_s));
|
memset (p_igate_config, 0, sizeof(struct igate_config_s));
|
||||||
p_igate_config->t2_server_port = DEFAULT_IGATE_PORT;
|
p_igate_config->t2_server_port = DEFAULT_IGATE_PORT;
|
||||||
p_igate_config->tx_chan = -1; /* IS->RF not enabled */
|
p_igate_config->tx_chan = -1; /* IS->RF not enabled */
|
||||||
p_igate_config->tx_limit_1 = 6;
|
p_igate_config->tx_limit_1 = IGATE_TX_LIMIT_1_DEFAULT;
|
||||||
p_igate_config->tx_limit_5 = 20;
|
p_igate_config->tx_limit_5 = IGATE_TX_LIMIT_5_DEFAULT;
|
||||||
|
|
||||||
|
|
||||||
/* People find this confusing. */
|
/* People find this confusing. */
|
||||||
|
@ -3165,7 +3165,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
if (islower(*p)) *p = toupper(*p);
|
if (islower(*p)) *p = toupper(*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! ax25_parse_addr(t, 1, method, &ssid, &heard)) {
|
if ( ! ax25_parse_addr(-1, t, 1, method, &ssid, &heard)) {
|
||||||
continue; // function above prints any error message
|
continue; // function above prints any error message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3409,18 +3409,22 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* limits of 20 and 100 are unfriendly but not insane. */
|
|
||||||
|
|
||||||
n = atoi(t);
|
n = atoi(t);
|
||||||
if (n >= 1 && n <= 20) {
|
if (n < 1) {
|
||||||
|
p_igate_config->tx_limit_1 = 1;
|
||||||
|
}
|
||||||
|
else if (n <= IGATE_TX_LIMIT_1_MAX) {
|
||||||
p_igate_config->tx_limit_1 = n;
|
p_igate_config->tx_limit_1 = n;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
p_igate_config->tx_limit_1 = IGATE_TX_LIMIT_1_MAX;
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Line %d: Invalid one minute transmit limit. Using %d.\n",
|
dw_printf ("Line %d: One minute transmit limit has been reduced to %d.\n",
|
||||||
line, p_igate_config->tx_limit_1);
|
line, p_igate_config->tx_limit_1);
|
||||||
|
dw_printf ("You won't make friends by setting a limit this high.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
t = split(NULL,0);
|
t = split(NULL,0);
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
@ -3429,13 +3433,18 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
}
|
}
|
||||||
|
|
||||||
n = atoi(t);
|
n = atoi(t);
|
||||||
if (n >= 1 && n <= 100) {
|
if (n < 1) {
|
||||||
|
p_igate_config->tx_limit_5 = 1;
|
||||||
|
}
|
||||||
|
else if (n <= IGATE_TX_LIMIT_5_MAX) {
|
||||||
p_igate_config->tx_limit_5 = n;
|
p_igate_config->tx_limit_5 = n;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
p_igate_config->tx_limit_5 = IGATE_TX_LIMIT_5_MAX;
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Line %d: Invalid one minute transmit limit. Using %d.\n",
|
dw_printf ("Line %d: Five minute transmit limit has been reduced to %d.\n",
|
||||||
line, p_igate_config->tx_limit_5);
|
line, p_igate_config->tx_limit_5);
|
||||||
|
dw_printf ("You won't make friends by setting a limit this high.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
|
||||||
A->g_footprint_radius = G_UNKNOWN;
|
A->g_footprint_radius = G_UNKNOWN;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract source and destination including the SSID.
|
* Extract source and destination including the SSID.
|
||||||
*/
|
*/
|
||||||
|
@ -4552,6 +4553,12 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
decode_aprs_print (&A);
|
decode_aprs_print (&A);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform validity check on each address.
|
||||||
|
* This should print an error message if any issues.
|
||||||
|
*/
|
||||||
|
(void)ax25_check_addresses(pp);
|
||||||
|
|
||||||
// Send to log file?
|
// Send to log file?
|
||||||
|
|
||||||
// if (logdir != NULL && *logdir != '\0') {
|
// if (logdir != NULL && *logdir != '\0') {
|
||||||
|
|
11
dedupe.c
11
dedupe.c
|
@ -108,6 +108,9 @@
|
||||||
#include "dedupe.h"
|
#include "dedupe.h"
|
||||||
#include "fcs_calc.h"
|
#include "fcs_calc.h"
|
||||||
#include "textcolor.h"
|
#include "textcolor.h"
|
||||||
|
#ifndef DIGITEST
|
||||||
|
#include "igate.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
|
@ -205,6 +208,14 @@ void dedupe_remember (packet_t pp, int chan)
|
||||||
if (insert_next >= HISTORY_MAX) {
|
if (insert_next >= HISTORY_MAX) {
|
||||||
insert_next = 0;
|
insert_next = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we send something by digipeater, we don't */
|
||||||
|
/* want to do it again if it comes from APRS-IS. */
|
||||||
|
/* Not sure about the other way around. */
|
||||||
|
|
||||||
|
#ifndef DIGITEST
|
||||||
|
ig_to_tx_remember (pp, chan, 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
28
direwolf.c
28
direwolf.c
|
@ -177,13 +177,14 @@ int main (int argc, char *argv[])
|
||||||
char input_file[80];
|
char input_file[80];
|
||||||
|
|
||||||
int t_opt = 1; /* Text color option. */
|
int t_opt = 1; /* Text color option. */
|
||||||
|
int a_opt = 0; /* "-a n" interval, in seconds, for audio statistics report. 0 for none. */
|
||||||
|
|
||||||
int d_k_opt = 0; /* "-d k" option for serial port KISS. Can be repeated for more detail. */
|
int d_k_opt = 0; /* "-d k" option for serial port KISS. Can be repeated for more detail. */
|
||||||
int d_n_opt = 0; /* "-d n" option for Network KISS. Can be repeated for more detail. */
|
int d_n_opt = 0; /* "-d n" option for Network KISS. Can be repeated for more detail. */
|
||||||
int d_t_opt = 0; /* "-d t" option for Tracker. Can be repeated for more detail. */
|
int d_t_opt = 0; /* "-d t" option for Tracker. Can be repeated for more detail. */
|
||||||
int d_g_opt = 0; /* "-d g" option for GPS. Can be repeated for more detail. */
|
int d_g_opt = 0; /* "-d g" option for GPS. Can be repeated for more detail. */
|
||||||
int d_o_opt = 0; /* "-d o" option for output control such as PTT and DCD. */
|
int d_o_opt = 0; /* "-d o" option for output control such as PTT and DCD. */
|
||||||
int a_opt = 0; /* "-a n" interval, in seconds, for audio statistics report. 0 for none. */
|
int d_i_opt = 0; /* "-d i" option for IGate. Repeat for more detail */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
strlcpy(l_opt, "", sizeof(l_opt));
|
strlcpy(l_opt, "", sizeof(l_opt));
|
||||||
|
@ -233,6 +234,14 @@ int main (int argc, char *argv[])
|
||||||
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "G", __DATE__);
|
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "G", __DATE__);
|
||||||
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
||||||
|
|
||||||
|
#if defined(ENABLE_GPSD) // later or hamlib ...
|
||||||
|
dw_printf ("Includes optional support for: ");
|
||||||
|
#if defined(ENABLE_GPSD)
|
||||||
|
dw_printf (" gpsd");
|
||||||
|
#endif
|
||||||
|
dw_printf ("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
SetConsoleCtrlHandler ((PHANDLER_ROUTINE)cleanup_win, TRUE);
|
SetConsoleCtrlHandler ((PHANDLER_ROUTINE)cleanup_win, TRUE);
|
||||||
|
@ -438,6 +447,7 @@ int main (int argc, char *argv[])
|
||||||
case 'w': nmea_set_debug (1); break; // not documented yet.
|
case 'w': nmea_set_debug (1); break; // not documented yet.
|
||||||
case 'p': d_p_opt = 1; break; // TODO: packet dump for xmit side.
|
case 'p': d_p_opt = 1; break; // TODO: packet dump for xmit side.
|
||||||
case 'o': d_o_opt++; ptt_set_debug(d_o_opt); break;
|
case 'o': d_o_opt++; ptt_set_debug(d_o_opt); break;
|
||||||
|
case 'i': d_i_opt++; break;
|
||||||
#if AX25MEMDEBUG
|
#if AX25MEMDEBUG
|
||||||
case 'm': ax25memdebug_set(); break; // Track down memory leak. Not documented.
|
case 'm': ax25memdebug_set(); break; // Track down memory leak. Not documented.
|
||||||
#endif
|
#endif
|
||||||
|
@ -653,7 +663,7 @@ int main (int argc, char *argv[])
|
||||||
* Initialize the digipeater and IGate functions.
|
* Initialize the digipeater and IGate functions.
|
||||||
*/
|
*/
|
||||||
digipeater_init (&audio_config, &digi_config);
|
digipeater_init (&audio_config, &digi_config);
|
||||||
igate_init (&audio_config, &igate_config, &digi_config);
|
igate_init (&audio_config, &igate_config, &digi_config, d_i_opt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Provide the AGW & KISS socket interfaces for use by a client application.
|
* Provide the AGW & KISS socket interfaces for use by a client application.
|
||||||
|
@ -681,18 +691,19 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable beaconing.
|
* Enable beaconing.
|
||||||
|
* Open log file first because "-dttt" (along with -l...) will
|
||||||
|
* log the tracker beacon transmissions with fake channel 999.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
log_init(misc_config.logdir);
|
||||||
beacon_init (&audio_config, &misc_config);
|
beacon_init (&audio_config, &misc_config);
|
||||||
|
|
||||||
log_init(misc_config.logdir);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get sound samples and decode them.
|
* Get sound samples and decode them.
|
||||||
* Use hot attribute for all functions called for every audio sample.
|
* Use hot attribute for all functions called for every audio sample.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
recv_init (&audio_config);
|
recv_init (&audio_config);
|
||||||
recv_process ();
|
recv_process ();
|
||||||
|
|
||||||
|
@ -898,6 +909,12 @@ void app_process_rec_packet (int chan, int subchan, packet_t pp, alevel_t alevel
|
||||||
|
|
||||||
decode_aprs_print (&A);
|
decode_aprs_print (&A);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform validity check on each address.
|
||||||
|
* This should print an error message if any issues.
|
||||||
|
*/
|
||||||
|
(void)ax25_check_addresses(pp);
|
||||||
|
|
||||||
// Send to log file.
|
// Send to log file.
|
||||||
|
|
||||||
log_write (chan, &A, pp, alevel, retries);
|
log_write (chan, &A, pp, alevel, retries);
|
||||||
|
@ -1038,6 +1055,7 @@ static void usage (char **argv)
|
||||||
dw_printf (" g g = GPS interface.\n");
|
dw_printf (" g g = GPS interface.\n");
|
||||||
dw_printf (" t t = Tracker beacon.\n");
|
dw_printf (" t t = Tracker beacon.\n");
|
||||||
dw_printf (" o o = output controls such as PTT and DCD.\n");
|
dw_printf (" o o = output controls such as PTT and DCD.\n");
|
||||||
|
dw_printf (" i i = IGate.\n");
|
||||||
dw_printf (" -q Quiet (suppress output) options:\n");
|
dw_printf (" -q Quiet (suppress output) options:\n");
|
||||||
dw_printf (" h h = Heard line with the audio level.\n");
|
dw_printf (" h h = Heard line with the audio level.\n");
|
||||||
dw_printf (" d d = Decoding of APRS packets.\n");
|
dw_printf (" d d = Decoding of APRS packets.\n");
|
||||||
|
|
|
@ -318,7 +318,7 @@ TBEACON delay=0:30 every=0:20 SYMBOL=car FREQ=146.955 OFFSET=-0.600 TONE=74.4
|
||||||
# the "#" from the beginning of the line below.
|
# the "#" from the beginning of the line below.
|
||||||
#
|
#
|
||||||
|
|
||||||
#DIGIPEAT 0 0 ^WIDE[3-7]-[1-7]$|^TEST$ ^WIDE[12]-[12]$ TRACE
|
DIGIPEAT 0 0 ^WIDE[3-7]-[1-7]$|^TEST$ ^WIDE[12]-[12]$ TRACE
|
||||||
|
|
||||||
# See User Guide for more explanation of what this means and how
|
# See User Guide for more explanation of what this means and how
|
||||||
# it can be customized for your particular needs.
|
# it can be customized for your particular needs.
|
||||||
|
@ -346,12 +346,12 @@ TBEACON delay=0:30 every=0:20 SYMBOL=car FREQ=146.955 OFFSET=-0.600 TONE=74.4
|
||||||
# asia.aprs2.net - for Asia
|
# asia.aprs2.net - for Asia
|
||||||
# aunz.aprs2.net - for Oceania
|
# aunz.aprs2.net - for Oceania
|
||||||
|
|
||||||
#IGSERVER noam.aprs2.net
|
IGSERVER noam.aprs2.net
|
||||||
|
|
||||||
# You also need to specify your login name and passcode.
|
# You also need to specify your login name and passcode.
|
||||||
# Contact the author if you can't figure out how to generate the passcode.
|
# Contact the author if you can't figure out how to generate the passcode.
|
||||||
|
|
||||||
#IGLOGIN WB2OSZ-5 123456
|
IGLOGIN WB2OSZ-14 17845
|
||||||
|
|
||||||
# That's all you need for a receive only IGate which relays
|
# That's all you need for a receive only IGate which relays
|
||||||
# messages from the local radio channel to the global servers.
|
# messages from the local radio channel to the global servers.
|
||||||
|
@ -361,26 +361,28 @@ TBEACON delay=0:30 every=0:20 SYMBOL=car FREQ=146.955 OFFSET=-0.600 TONE=74.4
|
||||||
# forward it to an IGate server. This is done by using sendto=IG rather
|
# forward it to an IGate server. This is done by using sendto=IG rather
|
||||||
# than a radio channel number. Overlay R for receive only, T for two way.
|
# than a radio channel number. Overlay R for receive only, T for two way.
|
||||||
|
|
||||||
#PBEACON sendto=IG delay=0:30 every=60:00 symbol="igate" overlay=R lat=42^37.14N long=071^20.83W
|
PBEACON sendto=IG delay=1:00 every=60:00 symbol="igate" overlay=R lat=42^37.14N long=071^20.83W
|
||||||
#PBEACON sendto=IG delay=0:30 every=60:00 symbol="igate" overlay=T lat=42^37.14N long=071^20.83W
|
#PBEACON sendto=IG delay=0:30 every=60:00 symbol="igate" overlay=T lat=42^37.14N long=071^20.83W
|
||||||
|
|
||||||
|
|
||||||
# To relay messages from the Internet to radio, you need to add
|
# To relay messages from the Internet to radio, you need to add
|
||||||
# one more option with the transmit channel number and a VIA path.
|
# one more option with the transmit channel number and a VIA path.
|
||||||
|
|
||||||
#IGTXVIA 0 WIDE1-1
|
IGTXVIA 0 WIDE1-1
|
||||||
|
|
||||||
# You might want to apply a filter for what packets will be obtained from the server.
|
# You might want to apply a filter for what packets will be obtained from the server.
|
||||||
# Read about filters here: http://www.aprs-is.net/javaprsfilter.aspx
|
# Read about filters here: http://www.aprs-is.net/javaprsfilter.aspx
|
||||||
# Example, positions and objects within 50 km of my location:
|
# Example, positions and objects within 50 km of my location:
|
||||||
|
|
||||||
#IGFILTER m/50
|
IGFILTER m/100
|
||||||
|
|
||||||
# That is known as a server-side filter. It is processed by the IGate server.
|
# That is known as a server-side filter. It is processed by the IGate server.
|
||||||
# You can also apply local filtering to limit what will be transmitted on the
|
# You can also apply local filtering to limit what will be transmitted on the
|
||||||
# RF side. For example, transmit only "messages" on channel 0 and weather
|
# RF side. For example, transmit only "messages" on channel 0 and weather
|
||||||
# reports on channel 1.
|
# reports on channel 1.
|
||||||
|
|
||||||
|
filter 0 ig t/p
|
||||||
|
|
||||||
#FILTER IG 0 t/m
|
#FILTER IG 0 t/m
|
||||||
#FILTER IG 1 t/wn
|
#FILTER IG 1 t/wn
|
||||||
|
|
||||||
|
@ -389,7 +391,7 @@ TBEACON delay=0:30 every=0:20 SYMBOL=car FREQ=146.955 OFFSET=-0.600 TONE=74.4
|
||||||
# during 1 minute and 5 minute intervals. If a limit would
|
# during 1 minute and 5 minute intervals. If a limit would
|
||||||
# be exceeded, the packet is dropped and message is displayed in red.
|
# be exceeded, the packet is dropped and message is displayed in red.
|
||||||
|
|
||||||
IGTXLIMIT 6 10
|
IGTXLIMIT 20 100
|
||||||
|
|
||||||
|
|
||||||
#############################################################
|
#############################################################
|
Binary file not shown.
2
dwgpsd.c
2
dwgpsd.c
|
@ -171,7 +171,7 @@ int dwgpsd_init (struct misc_config_s *pconfig, int debug)
|
||||||
dwgps_info_t info;
|
dwgps_info_t info;
|
||||||
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Unable to connect to GPSD stream.\n");
|
dw_printf ("Unable to connect to GPSD stream at %s:%s.\n", pconfig->gpsd_host, sport);
|
||||||
dw_printf ("%s\n", gps_errstr(errno));
|
dw_printf ("%s\n", gps_errstr(errno));
|
||||||
|
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
490
igate.c
490
igate.c
|
@ -107,16 +107,15 @@ static void * connnect_thread (void *arg);
|
||||||
static void * igate_recv_thread (void *arg);
|
static void * igate_recv_thread (void *arg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void send_msg_to_server (char *msg);
|
static void send_msg_to_server (const char *msg);
|
||||||
static void xmit_packet (char *message);
|
static void xmit_packet (char *message, int chan);
|
||||||
|
|
||||||
static void rx_to_ig_init (void);
|
static void rx_to_ig_init (void);
|
||||||
static void rx_to_ig_remember (packet_t pp);
|
static void rx_to_ig_remember (packet_t pp);
|
||||||
static int rx_to_ig_allow (packet_t pp);
|
static int rx_to_ig_allow (packet_t pp);
|
||||||
|
|
||||||
static void ig_to_tx_init (void);
|
static void ig_to_tx_init (void);
|
||||||
static void ig_to_tx_remember (packet_t pp);
|
static int ig_to_tx_allow (packet_t pp, int chan);
|
||||||
static int ig_to_tx_allow (packet_t pp);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -256,7 +255,7 @@ int main (int argc, char *argv[])
|
||||||
SLEEP_SEC (20);
|
SLEEP_SEC (20);
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf ("Send received packet\n");
|
dw_printf ("Send received packet\n");
|
||||||
send_msg_to_server ("W1ABC>APRS:?\r\n");
|
send_msg_to_server ("W1ABC>APRS:?");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -277,6 +276,8 @@ int main (int argc, char *argv[])
|
||||||
static struct audio_s *save_audio_config_p;
|
static struct audio_s *save_audio_config_p;
|
||||||
static struct igate_config_s *save_igate_config_p;
|
static struct igate_config_s *save_igate_config_p;
|
||||||
static struct digi_config_s *save_digi_config_p;
|
static struct digi_config_s *save_digi_config_p;
|
||||||
|
static int s_debug;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Statistics.
|
* Statistics.
|
||||||
|
@ -359,6 +360,13 @@ static int stats_rf_xmit_packets; /* Number of packets passed along to radio */
|
||||||
* p_digi_config - Digipeater configuration.
|
* p_digi_config - Digipeater configuration.
|
||||||
* All we care about here is the packet filtering options.
|
* All we care about here is the packet filtering options.
|
||||||
*
|
*
|
||||||
|
* debug_level - 0 print packets FROM APRS-IS,
|
||||||
|
* establishing connection with sergver, and
|
||||||
|
* and anything rejected by client side filtering.
|
||||||
|
* 1 plus packets sent TO server or why not.
|
||||||
|
* 2 plus duplicate detection overview.
|
||||||
|
* 3 plus duplicate detection details.
|
||||||
|
*
|
||||||
* Description: This starts two threads:
|
* Description: This starts two threads:
|
||||||
*
|
*
|
||||||
* * to establish and maintain a connection to the server.
|
* * to establish and maintain a connection to the server.
|
||||||
|
@ -367,7 +375,7 @@ static int stats_rf_xmit_packets; /* Number of packets passed along to radio */
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
void igate_init (struct audio_s *p_audio_config, struct igate_config_s *p_igate_config, struct digi_config_s *p_digi_config)
|
void igate_init (struct audio_s *p_audio_config, struct igate_config_s *p_igate_config, struct digi_config_s *p_digi_config, int debug_level)
|
||||||
{
|
{
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
HANDLE connnect_th;
|
HANDLE connnect_th;
|
||||||
|
@ -377,6 +385,7 @@ void igate_init (struct audio_s *p_audio_config, struct igate_config_s *p_igate_
|
||||||
pthread_t cmd_listen_tid;
|
pthread_t cmd_listen_tid;
|
||||||
int e;
|
int e;
|
||||||
#endif
|
#endif
|
||||||
|
s_debug = debug_level;
|
||||||
|
|
||||||
#if DEBUGx
|
#if DEBUGx
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
@ -738,7 +747,6 @@ static void * connnect_thread (void *arg)
|
||||||
strlcat (stemp, " filter ", sizeof(stemp));
|
strlcat (stemp, " filter ", sizeof(stemp));
|
||||||
strlcat (stemp, save_igate_config_p->t2_filter, sizeof(stemp));
|
strlcat (stemp, save_igate_config_p->t2_filter, sizeof(stemp));
|
||||||
}
|
}
|
||||||
strlcat (stemp, "\r\n", sizeof(stemp));
|
|
||||||
send_msg_to_server (stemp);
|
send_msg_to_server (stemp);
|
||||||
|
|
||||||
/* Delay until it is ok to start sending packets. */
|
/* Delay until it is ok to start sending packets. */
|
||||||
|
@ -766,7 +774,7 @@ static void * connnect_thread (void *arg)
|
||||||
|
|
||||||
char heartbeat[10];
|
char heartbeat[10];
|
||||||
|
|
||||||
strlcpy (heartbeat, "#\r\n", sizeof(heartbeat));
|
strlcpy (heartbeat, "#", sizeof(heartbeat));
|
||||||
|
|
||||||
/* This will close the socket if any error. */
|
/* This will close the socket if any error. */
|
||||||
send_msg_to_server (heartbeat);
|
send_msg_to_server (heartbeat);
|
||||||
|
@ -800,13 +808,15 @@ static void * connnect_thread (void *arg)
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define IGATE_MAX_MSG 520 /* Message to IGate max 512 characters. */
|
||||||
|
|
||||||
void igate_send_rec_packet (int chan, packet_t recv_pp)
|
void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
{
|
{
|
||||||
packet_t pp;
|
packet_t pp;
|
||||||
int n;
|
int n;
|
||||||
unsigned char *pinfo;
|
unsigned char *pinfo;
|
||||||
char *p;
|
char *p;
|
||||||
char msg[520]; /* Message to IGate max 512 characters. */
|
char msg[IGATE_MAX_MSG];
|
||||||
int info_len;
|
int info_len;
|
||||||
|
|
||||||
|
|
||||||
|
@ -826,11 +836,9 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
|
|
||||||
if (pfilter(chan, MAX_CHANS, save_digi_config_p->filter_str[chan][MAX_CHANS], recv_pp) != 1) {
|
if (pfilter(chan, MAX_CHANS, save_digi_config_p->filter_str[chan][MAX_CHANS], recv_pp) != 1) {
|
||||||
|
|
||||||
// TODO1.2: take out debug message.
|
text_color_set(DW_COLOR_INFO);
|
||||||
//#if DEBUG
|
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
|
||||||
dw_printf ("Packet from channel %d to IGate was rejected by filter: %s\n", chan, save_digi_config_p->filter_str[chan][MAX_CHANS]);
|
dw_printf ("Packet from channel %d to IGate was rejected by filter: %s\n", chan, save_digi_config_p->filter_str[chan][MAX_CHANS]);
|
||||||
//#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -862,19 +870,22 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
strcmp(via, "TCPXX") == 0 ||
|
strcmp(via, "TCPXX") == 0 ||
|
||||||
strcmp(via, "RFONLY") == 0 ||
|
strcmp(via, "RFONLY") == 0 ||
|
||||||
strcmp(via, "NOGATE") == 0) {
|
strcmp(via, "NOGATE") == 0) {
|
||||||
#if DEBUGx
|
|
||||||
|
if (s_debug >= 1) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("Rx IGate: Do not relay with TCPIP etc. in path.\n");
|
dw_printf ("Rx IGate: Do not relay with %s in path.\n", via);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
ax25_delete (pp);
|
ax25_delete (pp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUGx
|
if (s_debug >= 1) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("Rx IGate: Unwrap third party message.\n");
|
dw_printf ("Rx IGate: Unwrap third party message.\n");
|
||||||
#endif
|
}
|
||||||
|
|
||||||
inner_pp = ax25_unwrap_third_party(pp);
|
inner_pp = ax25_unwrap_third_party(pp);
|
||||||
if (inner_pp == NULL) {
|
if (inner_pp == NULL) {
|
||||||
ax25_delete (pp);
|
ax25_delete (pp);
|
||||||
|
@ -896,10 +907,12 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
strcmp(via, "TCPXX") == 0 ||
|
strcmp(via, "TCPXX") == 0 ||
|
||||||
strcmp(via, "RFONLY") == 0 ||
|
strcmp(via, "RFONLY") == 0 ||
|
||||||
strcmp(via, "NOGATE") == 0) {
|
strcmp(via, "NOGATE") == 0) {
|
||||||
#if DEBUGx
|
|
||||||
|
if (s_debug >= 1) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("Rx IGate: Do not relay with TCPIP etc. in path.\n");
|
dw_printf ("Rx IGate: Do not relay with %s in path.\n", via);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
ax25_delete (pp);
|
ax25_delete (pp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -909,10 +922,10 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
* Do not relay generic query.
|
* Do not relay generic query.
|
||||||
*/
|
*/
|
||||||
if (ax25_get_dti(pp) == '?') {
|
if (ax25_get_dti(pp) == '?') {
|
||||||
#if DEBUGx
|
if (s_debug >= 1) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("Rx IGate: Do not relay generic query.\n");
|
dw_printf ("Rx IGate: Do not relay generic query.\n");
|
||||||
#endif
|
}
|
||||||
ax25_delete (pp);
|
ax25_delete (pp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -926,18 +939,18 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
(void)(info_len);
|
(void)(info_len);
|
||||||
|
|
||||||
if ((p = strchr ((char*)pinfo, '\r')) != NULL) {
|
if ((p = strchr ((char*)pinfo, '\r')) != NULL) {
|
||||||
#if DEBUGx
|
if (s_debug >= 1) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("Rx IGate: Truncated information part at CR.\n");
|
dw_printf ("Rx IGate: Truncated information part at CR.\n");
|
||||||
#endif
|
}
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p = strchr ((char*)pinfo, '\n')) != NULL) {
|
if ((p = strchr ((char*)pinfo, '\n')) != NULL) {
|
||||||
#if DEBUGx
|
if (s_debug >= 1) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("Rx IGate: Truncated information part at LF.\n");
|
dw_printf ("Rx IGate: Truncated information part at LF.\n");
|
||||||
#endif
|
}
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -947,10 +960,10 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
*/
|
*/
|
||||||
if (strlen((char*)pinfo) == 0) {
|
if (strlen((char*)pinfo) == 0) {
|
||||||
|
|
||||||
#if DEBUGx
|
if (s_debug >= 1) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("Rx IGate: Information part length is zero.\n");
|
dw_printf ("Rx IGate: Information part length is zero.\n");
|
||||||
#endif
|
}
|
||||||
ax25_delete (pp);
|
ax25_delete (pp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -962,10 +975,10 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( ! rx_to_ig_allow(pp)) {
|
if ( ! rx_to_ig_allow(pp)) {
|
||||||
#if DEBUG
|
if (s_debug >= 1) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
dw_printf ("Rx IGate: Drop duplicate of same packet seen recently.\n");
|
dw_printf ("Rx IGate: Drop duplicate of same packet seen recently.\n");
|
||||||
#endif
|
}
|
||||||
ax25_delete (pp);
|
ax25_delete (pp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -980,7 +993,6 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
strlcat (msg, save_audio_config_p->achan[chan].mycall, sizeof(msg));
|
strlcat (msg, save_audio_config_p->achan[chan].mycall, sizeof(msg));
|
||||||
strlcat (msg, ":", sizeof(msg));
|
strlcat (msg, ":", sizeof(msg));
|
||||||
strlcat (msg, (char*)pinfo, sizeof(msg));
|
strlcat (msg, (char*)pinfo, sizeof(msg));
|
||||||
strlcat (msg, "\r\n", sizeof(msg));
|
|
||||||
|
|
||||||
send_msg_to_server (msg);
|
send_msg_to_server (msg);
|
||||||
stats_rx_igate_packets++;
|
stats_rx_igate_packets++;
|
||||||
|
@ -1006,7 +1018,7 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
* This one function should be used for login, hearbeats,
|
* This one function should be used for login, hearbeats,
|
||||||
* and packets.
|
* and packets.
|
||||||
*
|
*
|
||||||
* Inputs: msg - Message. Should end with CR/LF.
|
* Inputs: imsg - Message. We will add CR/LF.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Description: Send message to IGate Server if connected.
|
* Description: Send message to IGate Server if connected.
|
||||||
|
@ -1015,26 +1027,30 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
static void send_msg_to_server (char *msg)
|
static void send_msg_to_server (const char *imsg)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
char stemp[IGATE_MAX_MSG];
|
||||||
|
|
||||||
if (igate_sock == -1) {
|
if (igate_sock == -1) {
|
||||||
return; /* Silently discard if not connected. */
|
return; /* Silently discard if not connected. */
|
||||||
}
|
}
|
||||||
|
|
||||||
stats_uplink_bytes += strlen(msg);
|
strlcpy(stemp, imsg, sizeof(stemp));
|
||||||
|
|
||||||
#if DEBUG
|
if (s_debug >= 1) {
|
||||||
text_color_set(DW_COLOR_XMIT);
|
text_color_set(DW_COLOR_XMIT);
|
||||||
dw_printf ("[ig] ");
|
dw_printf ("[rx>ig] ");
|
||||||
ax25_safe_print (msg, strlen(msg), 0);
|
ax25_safe_print (stemp, strlen(stemp), 0);
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
strlcat (stemp, "\r\n", sizeof(stemp));
|
||||||
|
|
||||||
|
stats_uplink_bytes += strlen(stemp);
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
err = send (igate_sock, msg, strlen(msg), 0);
|
err = send (igate_sock, stemp, strlen(stemp), 0);
|
||||||
if (err == SOCKET_ERROR)
|
if (err == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
@ -1045,7 +1061,7 @@ static void send_msg_to_server (char *msg)
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
err = write (igate_sock, msg, strlen(msg));
|
err = write (igate_sock, stemp, strlen(stemp));
|
||||||
if (err <= 0)
|
if (err <= 0)
|
||||||
{
|
{
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
@ -1169,7 +1185,31 @@ static void * igate_recv_thread (void *arg)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have a complete message terminated by LF.
|
* We have a complete message terminated by LF.
|
||||||
|
*
|
||||||
|
* Remove CR LF from end.
|
||||||
|
* This is a record separator for the protocol, not part of the data.
|
||||||
|
* Should probably have an error if we don't have this.
|
||||||
*/
|
*/
|
||||||
|
if (len >=2 && message[len-1] == '\n') { message[len-1] = '\0'; len--; }
|
||||||
|
if (len >=1 && message[len-1] == '\r') { message[len-1] = '\0'; len--; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I've seen a case where the original RF packet had a trailing CR but
|
||||||
|
* after someone else sent it to the server and it came back to me, that
|
||||||
|
* CR was now a trailing space.
|
||||||
|
* At first I was tempted to trim a trailing space as well.
|
||||||
|
* By fixing this one case it might corrupt the data in other cases.
|
||||||
|
* We compensate for this by ignoring trailing spaces when performing
|
||||||
|
* the duplicate detection and removal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I've also seen a multiple trailing spaces like this.
|
||||||
|
* Notice how safe_print shows a trailing space in hexadecimal to make it obvious.
|
||||||
|
*
|
||||||
|
* W1CLA-1>APVR30,TCPIP*,qAC,T2TOKYO3:;IRLP-4942*141503z4218.46NI07108.24W0446325-146IDLE <0x20>
|
||||||
|
*/
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -1184,35 +1224,33 @@ static void * igate_recv_thread (void *arg)
|
||||||
* That way we can see login confirmation but not
|
* That way we can see login confirmation but not
|
||||||
* be bothered by the heart beat messages.
|
* be bothered by the heart beat messages.
|
||||||
*/
|
*/
|
||||||
#ifndef DEBUG
|
|
||||||
if ( ! ok_to_send) {
|
if ( ! ok_to_send) {
|
||||||
#endif
|
|
||||||
text_color_set(DW_COLOR_REC);
|
text_color_set(DW_COLOR_REC);
|
||||||
dw_printf ("[ig] ");
|
dw_printf ("[ig] ");
|
||||||
ax25_safe_print ((char *)message, len, 0);
|
ax25_safe_print ((char *)message, len, 0);
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
#ifndef DEBUG
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Convert to third party packet and transmit.
|
* Convert to third party packet and transmit.
|
||||||
|
*
|
||||||
|
* Future: might have ability to configure multiple transmit
|
||||||
|
* channels, each with own client side filtering and via path.
|
||||||
|
* Loop here over all configured channels.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
text_color_set(DW_COLOR_REC);
|
text_color_set(DW_COLOR_REC);
|
||||||
dw_printf ("\n[ig] ");
|
dw_printf ("\n[ig>tx] "); // formerly just [ig]
|
||||||
ax25_safe_print ((char *)message, len, 0);
|
ax25_safe_print ((char *)message, len, 0);
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
|
|
||||||
/*
|
int to_chan = save_igate_config_p->tx_chan;
|
||||||
* Remove CR LF from end.
|
|
||||||
*/
|
|
||||||
if (len >=2 && message[len-1] == '\n') { message[len-1] = '\0'; len--; }
|
|
||||||
if (len >=1 && message[len-1] == '\r') { message[len-1] = '\0'; len--; }
|
|
||||||
|
|
||||||
xmit_packet ((char*)message);
|
if (to_chan >= 0) {
|
||||||
|
xmit_packet ((char*)message, to_chan);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* while (1) */
|
} /* while (1) */
|
||||||
|
@ -1229,31 +1267,43 @@ static void * igate_recv_thread (void *arg)
|
||||||
* packet and send to transmit queue.
|
* packet and send to transmit queue.
|
||||||
*
|
*
|
||||||
* Inputs: message - As sent by the server.
|
* Inputs: message - As sent by the server.
|
||||||
|
* Any trailing CRLF should have been removed.
|
||||||
|
* Typical examples:
|
||||||
|
*
|
||||||
|
* KA1BTK-5>APDR13,TCPIP*,qAC,T2IRELAND:=4237.62N/07040.68W$/A=-00054 http://aprsdroid.org/
|
||||||
|
* N1HKO-10>APJI40,TCPIP*,qAC,N1HKO-JS:<IGATE,MSG_CNT=0,LOC_CNT=0
|
||||||
|
* K1RI-2>APWW10,WIDE1-1,WIDE2-1,qAS,K1RI:/221700h/9AmA<Ct3_ sT010/002g005t045r000p023P020h97b10148
|
||||||
|
* KC1BOS-2>T3PQ3S,WIDE1-1,WIDE2-1,qAR,W1TG-1:`c)@qh\>/"50}TinyTrak4 Mobile
|
||||||
|
*
|
||||||
|
* Notice how the final address in the header might not
|
||||||
|
* be a valid AX.25 address. We see a 9 character address
|
||||||
|
* (with no ssid) and an ssid of two letters.
|
||||||
|
* We don't care because we end up discarding them before
|
||||||
|
* repackaging to go over the radio.
|
||||||
|
*
|
||||||
|
* The "q construct" ( http://www.aprs-is.net/q.aspx ) provides
|
||||||
|
* a clue about the journey taken but I don't think we care here.
|
||||||
|
*
|
||||||
|
* to_chan - Radio channel for transmitting.
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void xmit_packet (char *message)
|
static void xmit_packet (char *message, int to_chan)
|
||||||
{
|
{
|
||||||
packet_t pp3;
|
packet_t pp3;
|
||||||
char payload[AX25_MAX_PACKET_LEN]; /* what is max len? */
|
char payload[AX25_MAX_PACKET_LEN]; /* what is max len? */
|
||||||
char *pinfo = NULL;
|
char *pinfo = NULL;
|
||||||
int info_len;
|
int info_len;
|
||||||
int to_chan = save_igate_config_p->tx_chan; /* Should be -1 if not configured for xmit!!! */
|
|
||||||
/* Future: Array of boolean to allow multiple xmit channels? */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Is IGate to Radio direction enabled?
|
|
||||||
*/
|
|
||||||
if (to_chan == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stats_tx_igate_packets++;
|
|
||||||
|
|
||||||
assert (to_chan >= 0 && to_chan < MAX_CHANS);
|
assert (to_chan >= 0 && to_chan < MAX_CHANS);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to parse it into a packet object.
|
* Try to parse it into a packet object.
|
||||||
|
* This will contain "q constructs" and we might see an address
|
||||||
|
* with two alphnumeric characters in the SSID so we must use
|
||||||
|
* the non-strict parsing.
|
||||||
|
*
|
||||||
* Bug: Up to 8 digipeaters are allowed in radio format.
|
* Bug: Up to 8 digipeaters are allowed in radio format.
|
||||||
* There is a potential of finding a larger number here.
|
* There is a potential of finding a larger number here.
|
||||||
*/
|
*/
|
||||||
|
@ -1268,6 +1318,9 @@ static void xmit_packet (char *message)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Apply our own packet filtering if configured.
|
* Apply our own packet filtering if configured.
|
||||||
|
* Do we want to do this before or after removing the VIA path?
|
||||||
|
* I suppose by doing it first, we have the possibility of
|
||||||
|
* filtering by stations along the way or the q construct.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
assert (to_chan >= 0 && to_chan < MAX_CHANS);
|
assert (to_chan >= 0 && to_chan < MAX_CHANS);
|
||||||
|
@ -1276,35 +1329,37 @@ static void xmit_packet (char *message)
|
||||||
|
|
||||||
if (pfilter(MAX_CHANS, to_chan, save_digi_config_p->filter_str[MAX_CHANS][to_chan], pp3) != 1) {
|
if (pfilter(MAX_CHANS, to_chan, save_digi_config_p->filter_str[MAX_CHANS][to_chan], pp3) != 1) {
|
||||||
|
|
||||||
// TODO1.2: take out debug message. One person liked it as a confirmation of what was going on.
|
text_color_set(DW_COLOR_INFO);
|
||||||
// Maybe it should be part of a more comprehensive debug facility?
|
|
||||||
//#if DEBUG
|
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
|
||||||
dw_printf ("Packet from IGate to channel %d was rejected by filter: %s\n", to_chan, save_digi_config_p->filter_str[MAX_CHANS][to_chan]);
|
dw_printf ("Packet from IGate to channel %d was rejected by filter: %s\n", to_chan, save_digi_config_p->filter_str[MAX_CHANS][to_chan]);
|
||||||
//#endif
|
|
||||||
ax25_delete (pp3);
|
ax25_delete (pp3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: Discard if qAX in path??? others?
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the VIA path.
|
* Remove the VIA path.
|
||||||
|
*
|
||||||
|
* For example, we might get something like this from the server.
|
||||||
|
* K1USN-1>APWW10,TCPIP*,qAC,N5JXS-F1:T#479,100,048,002,500,000,10000000<0x0d><0x0a>
|
||||||
|
*
|
||||||
|
* We want to reduce it to this before wrapping it as third party traffic.
|
||||||
|
* K1USN-1>APWW10:T#479,100,048,002,500,000,10000000<0x0d><0x0a>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (ax25_get_num_repeaters(pp3) > 0) {
|
while (ax25_get_num_repeaters(pp3) > 0) {
|
||||||
ax25_remove_addr (pp3, AX25_REPEATER_1);
|
ax25_remove_addr (pp3, AX25_REPEATER_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replace the VIA path with TCPIP and my call.
|
* Replace the VIA path with TCPIP and my call.
|
||||||
* Mark my call as having been used.
|
* Mark my call as having been used.
|
||||||
*/
|
*/
|
||||||
ax25_set_addr (pp3, AX25_REPEATER_1, "TCPIP");
|
ax25_set_addr (pp3, AX25_REPEATER_1, "TCPIP");
|
||||||
ax25_set_h (pp3, AX25_REPEATER_1);
|
ax25_set_h (pp3, AX25_REPEATER_1);
|
||||||
ax25_set_addr (pp3, AX25_REPEATER_2, save_audio_config_p->achan[save_igate_config_p->tx_chan].mycall);
|
ax25_set_addr (pp3, AX25_REPEATER_2, save_audio_config_p->achan[to_chan].mycall);
|
||||||
ax25_set_h (pp3, AX25_REPEATER_2);
|
ax25_set_h (pp3, AX25_REPEATER_2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1324,12 +1379,12 @@ static void xmit_packet (char *message)
|
||||||
/*
|
/*
|
||||||
* Encapsulate for sending over radio if no reason to drop it.
|
* Encapsulate for sending over radio if no reason to drop it.
|
||||||
*/
|
*/
|
||||||
if (ig_to_tx_allow (pp3)) {
|
if (ig_to_tx_allow (pp3, to_chan)) {
|
||||||
char radio [500];
|
char radio [500];
|
||||||
packet_t pradio;
|
packet_t pradio;
|
||||||
|
|
||||||
snprintf (radio, sizeof(radio), "%s>%s%d%d%s:}%s",
|
snprintf (radio, sizeof(radio), "%s>%s%d%d%s:}%s",
|
||||||
save_audio_config_p->achan[save_igate_config_p->tx_chan].mycall,
|
save_audio_config_p->achan[to_chan].mycall,
|
||||||
APP_TOCALL, MAJOR_VERSION, MINOR_VERSION,
|
APP_TOCALL, MAJOR_VERSION, MINOR_VERSION,
|
||||||
save_igate_config_p->tx_via,
|
save_igate_config_p->tx_via,
|
||||||
payload);
|
payload);
|
||||||
|
@ -1341,16 +1396,18 @@ static void xmit_packet (char *message)
|
||||||
|
|
||||||
if (pradio != NULL) {
|
if (pradio != NULL) {
|
||||||
|
|
||||||
|
stats_tx_igate_packets++;
|
||||||
|
|
||||||
#if ITEST
|
#if ITEST
|
||||||
text_color_set(DW_COLOR_XMIT);
|
text_color_set(DW_COLOR_XMIT);
|
||||||
dw_printf ("Xmit: %s\n", radio);
|
dw_printf ("Xmit: %s\n", radio);
|
||||||
ax25_delete (pradio);
|
ax25_delete (pradio);
|
||||||
#else
|
#else
|
||||||
/* This consumes packet so don't reference it again! */
|
/* This consumes packet so don't reference it again! */
|
||||||
tq_append (save_igate_config_p->tx_chan, TQ_PRIO_1_LO, pradio);
|
tq_append (to_chan, TQ_PRIO_1_LO, pradio);
|
||||||
#endif
|
#endif
|
||||||
stats_rf_xmit_packets++;
|
stats_rf_xmit_packets++;
|
||||||
ig_to_tx_remember (pp3);
|
ig_to_tx_remember (pp3, save_igate_config_p->tx_chan, 0); // correct. version before encapsulating it.
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
@ -1381,7 +1438,8 @@ static void xmit_packet (char *message)
|
||||||
*
|
*
|
||||||
* Name: rx_to_ig_allow
|
* Name: rx_to_ig_allow
|
||||||
*
|
*
|
||||||
* Purpose: Check whether this is a duplicate of another sent recently.
|
* Purpose: Check whether this is a duplicate of another
|
||||||
|
* recently received from RF and sent to the Server
|
||||||
*
|
*
|
||||||
* Input: pp - Pointer to packet object.
|
* Input: pp - Pointer to packet object.
|
||||||
*
|
*
|
||||||
|
@ -1427,9 +1485,28 @@ static void rx_to_ig_init (void)
|
||||||
|
|
||||||
static void rx_to_ig_remember (packet_t pp)
|
static void rx_to_ig_remember (packet_t pp)
|
||||||
{
|
{
|
||||||
|
|
||||||
rx2ig_time_stamp[rx2ig_insert_next] = time(NULL);
|
rx2ig_time_stamp[rx2ig_insert_next] = time(NULL);
|
||||||
rx2ig_checksum[rx2ig_insert_next] = ax25_dedupe_crc(pp);
|
rx2ig_checksum[rx2ig_insert_next] = ax25_dedupe_crc(pp);
|
||||||
|
|
||||||
|
if (s_debug >= 3) {
|
||||||
|
char src[AX25_MAX_ADDR_LEN];
|
||||||
|
char dest[AX25_MAX_ADDR_LEN];
|
||||||
|
unsigned char *pinfo;
|
||||||
|
int info_len;
|
||||||
|
|
||||||
|
ax25_get_addr_with_ssid(pp, AX25_SOURCE, src);
|
||||||
|
ax25_get_addr_with_ssid(pp, AX25_DESTINATION, dest);
|
||||||
|
info_len = ax25_get_info (pp, &pinfo);
|
||||||
|
|
||||||
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
dw_printf ("rx_to_ig_remember [%d] = %d %d \"%s>%s:%s\"\n",
|
||||||
|
rx2ig_insert_next,
|
||||||
|
(int)(rx2ig_time_stamp[rx2ig_insert_next]),
|
||||||
|
rx2ig_checksum[rx2ig_insert_next],
|
||||||
|
src, dest, pinfo);
|
||||||
|
}
|
||||||
|
|
||||||
rx2ig_insert_next++;
|
rx2ig_insert_next++;
|
||||||
if (rx2ig_insert_next >= RX2IG_HISTORY_MAX) {
|
if (rx2ig_insert_next >= RX2IG_HISTORY_MAX) {
|
||||||
rx2ig_insert_next = 0;
|
rx2ig_insert_next = 0;
|
||||||
|
@ -1442,11 +1519,35 @@ static int rx_to_ig_allow (packet_t pp)
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
|
if (s_debug >= 2) {
|
||||||
|
char src[AX25_MAX_ADDR_LEN];
|
||||||
|
char dest[AX25_MAX_ADDR_LEN];
|
||||||
|
unsigned char *pinfo;
|
||||||
|
int info_len;
|
||||||
|
|
||||||
|
ax25_get_addr_with_ssid(pp, AX25_SOURCE, src);
|
||||||
|
ax25_get_addr_with_ssid(pp, AX25_DESTINATION, dest);
|
||||||
|
info_len = ax25_get_info (pp, &pinfo);
|
||||||
|
|
||||||
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
dw_printf ("rx_to_ig_allow? %d \"%s>%s:%s\"\n", crc, src, dest, pinfo);
|
||||||
|
}
|
||||||
|
|
||||||
for (j=0; j<RX2IG_HISTORY_MAX; j++) {
|
for (j=0; j<RX2IG_HISTORY_MAX; j++) {
|
||||||
if (rx2ig_time_stamp[j] >= now - RX2IG_DEDUPE_TIME && rx2ig_checksum[j] == crc) {
|
if (rx2ig_checksum[j] == crc && rx2ig_time_stamp[j] >= now - RX2IG_DEDUPE_TIME) {
|
||||||
|
if (s_debug >= 2) {
|
||||||
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
// could be multiple entries and this might not be the most recent.
|
||||||
|
dw_printf ("rx_to_ig_allow? NO. Seen %d seconds ago.\n", (int)(now - rx2ig_time_stamp[j]));
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s_debug >= 2) {
|
||||||
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
dw_printf ("rx_to_ig_allow? YES\n");
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
} /* end rx_to_ig_allow */
|
} /* end rx_to_ig_allow */
|
||||||
|
@ -1462,6 +1563,12 @@ static int rx_to_ig_allow (packet_t pp)
|
||||||
*
|
*
|
||||||
* Inputs: pp - Pointer to a packet object.
|
* Inputs: pp - Pointer to a packet object.
|
||||||
*
|
*
|
||||||
|
* chan - Channel number where it is being transmitted.
|
||||||
|
* Duplicate detection needs to be separate for each radio channel.
|
||||||
|
*
|
||||||
|
* bydigi - True if transmitted by digipeater function. False for IGate.
|
||||||
|
* Why do we care about digpeating here? See discussion below.
|
||||||
|
*
|
||||||
*------------------------------------------------------------------------------
|
*------------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: ig_to_tx_allow
|
* Name: ig_to_tx_allow
|
||||||
|
@ -1471,6 +1578,8 @@ static int rx_to_ig_allow (packet_t pp)
|
||||||
*
|
*
|
||||||
* Input: pp - Pointer to packet object.
|
* Input: pp - Pointer to packet object.
|
||||||
*
|
*
|
||||||
|
* chan - Radio channel number where we want to transmit.
|
||||||
|
*
|
||||||
* Returns: True if it is OK to send.
|
* Returns: True if it is OK to send.
|
||||||
*
|
*
|
||||||
*------------------------------------------------------------------------------
|
*------------------------------------------------------------------------------
|
||||||
|
@ -1488,8 +1597,8 @@ static int rx_to_ig_allow (packet_t pp)
|
||||||
* This is the essentially the same as the pair of functions
|
* This is the essentially the same as the pair of functions
|
||||||
* above with one addition restriction.
|
* above with one addition restriction.
|
||||||
*
|
*
|
||||||
* The typical residential Internet connection is about 10,000
|
* The typical residential Internet connection is around 10,000
|
||||||
* times faster than the radio links we are using. It would
|
* to 50,000 times faster than the radio links we are using. It would
|
||||||
* be easy to completely saturate the radio channel if we are
|
* be easy to completely saturate the radio channel if we are
|
||||||
* not careful.
|
* not careful.
|
||||||
*
|
*
|
||||||
|
@ -1497,26 +1606,155 @@ static int rx_to_ig_allow (packet_t pp)
|
||||||
* number of packets sent during the past minute and past 5
|
* number of packets sent during the past minute and past 5
|
||||||
* minutes and stop sending if a limit is reached.
|
* minutes and stop sending if a limit is reached.
|
||||||
*
|
*
|
||||||
* Future? We might also want to avoid transmitting if the same packet
|
* More Discussion:
|
||||||
* was heard on the radio recently. If everything is kept in
|
|
||||||
* the same table, we'd need to distinguish between those from
|
|
||||||
* the IGate server and those heard on the radio.
|
|
||||||
* Those heard on the radio would not count toward the
|
|
||||||
* 1 and 5 minute rate limiting.
|
|
||||||
* Maybe even provide informative information such as -
|
|
||||||
* Tx IGate: Same packet heard recently from W1ABC and W9XYZ.
|
|
||||||
*
|
*
|
||||||
* Of course, the radio encapsulation would need to be removed
|
* Consider the following example.
|
||||||
* and only the 3rd party packet inside compared.
|
* I hear a packet from W1TG-1 three times over the radio then get the
|
||||||
|
* (almost) same thing twice from APRS-IS.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Digipeater N3LEE-10 audio level = 23(10/6) [NONE] __|||||||
|
||||||
|
* [0.5] W1TG-1>APU25N,N3LEE-10*,WIDE2-1:<IGATE,MSG_CNT=30,LOC_CNT=61<0x0d>
|
||||||
|
* Station Capabilities, Ambulance, UIview 32 bit apps
|
||||||
|
* IGATE,MSG_CNT=30,LOC_CNT=61
|
||||||
|
*
|
||||||
|
* [0H] W1TG-1>APU25N,N3LEE-10,WB2OSZ-14*:<IGATE,MSG_CNT=30,LOC_CNT=61<0x0d>
|
||||||
|
*
|
||||||
|
* Digipeater WIDE2 (probably N3LEE-4) audio level = 22(10/6) [NONE] __|||||||
|
||||||
|
* [0.5] W1TG-1>APU25N,N3LEE-10,N3LEE-4,WIDE2*:<IGATE,MSG_CNT=30,LOC_CNT=61<0x0d>
|
||||||
|
* Station Capabilities, Ambulance, UIview 32 bit apps
|
||||||
|
* IGATE,MSG_CNT=30,LOC_CNT=61
|
||||||
|
*
|
||||||
|
* Digipeater WIDE2 (probably AB1OC-10) audio level = 31(14/11) [SINGLE] ____:____
|
||||||
|
* [0.4] W1TG-1>APU25N,N3LEE-10,AB1OC-10,WIDE2*:<IGATE,MSG_CNT=30,LOC_CNT=61<0x0d>
|
||||||
|
* Station Capabilities, Ambulance, UIview 32 bit apps
|
||||||
|
* IGATE,MSG_CNT=30,LOC_CNT=61
|
||||||
|
*
|
||||||
|
* [ig] W1TG-1>APU25N,WIDE2-2,qAR,W1GLO-11:<IGATE,MSG_CNT=30,LOC_CNT=61
|
||||||
|
* [0L] WB2OSZ-14>APDW13,WIDE1-1:}W1TG-1>APU25N,TCPIP,WB2OSZ-14*:<IGATE,MSG_CNT=30,LOC_CNT=61
|
||||||
|
*
|
||||||
|
* [ig] W1TG-1>APU25N,K1FFK,WIDE2*,qAR,WB2ZII-15:<IGATE,MSG_CNT=30,LOC_CNT=61<0x20>
|
||||||
|
* [0L] WB2OSZ-14>APDW13,WIDE1-1:}W1TG-1>APU25N,TCPIP,WB2OSZ-14*:<IGATE,MSG_CNT=30,LOC_CNT=61<0x20>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The first one gets retransmitted by digipeating.
|
||||||
|
*
|
||||||
|
* Why are we getting the same thing twice from APRS-IS? Shouldn't remove duplicates?
|
||||||
|
* Look closely. The original packet, on RF, had a CR character at the end.
|
||||||
|
* At first I thought duplicate removal was broken but it turns out they
|
||||||
|
* are not exactly the same.
|
||||||
|
*
|
||||||
|
* The receive IGate spec says a packet should be cut at a CR.
|
||||||
|
* In one case it is removed as expected In another case, it is replaced by a trailing
|
||||||
|
* space character. Maybe someone thought non printable characters should be
|
||||||
|
* replaced by spaces???
|
||||||
|
*
|
||||||
|
* At first I was tempted to remove any trailing spaces to make up for the other
|
||||||
|
* IGate adding it. Two wrongs don't make a right. Trailing spaces are not that
|
||||||
|
* rare and removing them would corrupt the data. My new strategy is for
|
||||||
|
* the duplicate detection compare to ignore trailing space, CR, and LF.
|
||||||
|
*
|
||||||
|
* We already transmitted the same thing by the digipeater function so this should
|
||||||
|
* also go into memory for avoiding duplicates out of the transmit IGate.
|
||||||
|
*
|
||||||
|
* Future:
|
||||||
|
* Should the digipeater function avoid transmitting something if it
|
||||||
|
* was recently transmitted by the IGate funtion?
|
||||||
|
* This code is pretty much the same as dedupe.c. Maybe it could all
|
||||||
|
* be combined into one. Need to ponder this some more.
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Here is another complete example, with the "-diii" debugging option to show details.
|
||||||
|
|
||||||
|
|
||||||
|
We receive the signal directly from the source: (zzz.log 1011)
|
||||||
|
|
||||||
|
N1ZKO-7 audio level = 33(16/10) [NONE] ___||||||
|
||||||
|
[0.5] N1ZKO-7>T2TS7X,WIDE1-1,WIDE2-1:`c6wl!i[/>"4]}[scanning]=<0x0d>
|
||||||
|
MIC-E, Human, Kenwood TH-D72, In Service
|
||||||
|
N 42 43.7800, W 071 26.9100, 0 MPH, course 177, alt 230 ft
|
||||||
|
[scanning]
|
||||||
|
|
||||||
|
We did not send it to the IS server recently.
|
||||||
|
|
||||||
|
Rx IGate: Truncated information part at CR.
|
||||||
|
rx_to_ig_allow? 57185 "N1ZKO-7>T2TS7X:`c6wl!i[/>"4]}[scanning]="
|
||||||
|
rx_to_ig_allow? YES
|
||||||
|
|
||||||
|
Send it now and remember that fact.
|
||||||
|
|
||||||
|
[rx>ig] N1ZKO-7>T2TS7X,WIDE1-1,WIDE2-1,qAR,WB2OSZ-14:`c6wl!i[/>"4]}[scanning]=
|
||||||
|
rx_to_ig_remember [21] = 1447683040 57185 "N1ZKO-7>T2TS7X:`c6wl!i[/>"4]}[scanning]="
|
||||||
|
|
||||||
|
Digipeat it. Notice how it has a trailing CR.
|
||||||
|
TODO: Why is the CRC different? Content looks the same.
|
||||||
|
|
||||||
|
ig_to_tx_remember [38] = ch0 d1 1447683040 27598 "N1ZKO-7>T2TS7X:`c6wl!i[/>"4]}[scanning]=
"
|
||||||
|
[0H] N1ZKO-7>T2TS7X,WB2OSZ-14*,WIDE2-1:`c6wl!i[/>"4]}[scanning]=<0x0d>
|
||||||
|
|
||||||
|
Now we hear it again, thru a digipeater.
|
||||||
|
Not sure who. Was it UNCAN or was it someone else who doesn't use tracing?
|
||||||
|
See my rant in the User Guide about this.
|
||||||
|
|
||||||
|
Digipeater WIDE2 (probably UNCAN) audio level = 30(15/10) [NONE] __|||::__
|
||||||
|
[0.4] N1ZKO-7>T2TS7X,KB1POR-2,UNCAN,WIDE2*:`c6wl!i[/>"4]}[scanning]=<0x0d>
|
||||||
|
MIC-E, Human, Kenwood TH-D72, In Service
|
||||||
|
N 42 43.7800, W 071 26.9100, 0 MPH, course 177, alt 230 ft
|
||||||
|
[scanning]
|
||||||
|
|
||||||
|
Was sent to server recently so don't do it again.
|
||||||
|
|
||||||
|
Rx IGate: Truncated information part at CR.
|
||||||
|
rx_to_ig_allow? 57185 "N1ZKO-7>T2TS7X:`c6wl!i[/>"4]}[scanning]="
|
||||||
|
rx_to_ig_allow? NO. Seen 1 seconds ago.
|
||||||
|
Rx IGate: Drop duplicate of same packet seen recently.
|
||||||
|
|
||||||
|
We hear it a third time, by a different digipeater.
|
||||||
|
|
||||||
|
Digipeater WIDE1 (probably N3LEE-10) audio level = 23(12/6) [NONE] __|||||||
|
||||||
|
[0.5] N1ZKO-7>T2TS7X,N3LEE-10,WIDE1*,WIDE2-1:`c6wl!i[/>"4]}[scanning]=<0x0d>
|
||||||
|
MIC-E, Human, Kenwood TH-D72, In Service
|
||||||
|
N 42 43.7800, W 071 26.9100, 0 MPH, course 177, alt 230 ft
|
||||||
|
[scanning]
|
||||||
|
|
||||||
|
It's a duplicate, so don't send to server.
|
||||||
|
|
||||||
|
Rx IGate: Truncated information part at CR.
|
||||||
|
rx_to_ig_allow? 57185 "N1ZKO-7>T2TS7X:`c6wl!i[/>"4]}[scanning]="
|
||||||
|
rx_to_ig_allow? NO. Seen 2 seconds ago.
|
||||||
|
Rx IGate: Drop duplicate of same packet seen recently.
|
||||||
|
Digipeater: Drop redundant packet to channel 0.
|
||||||
|
|
||||||
|
The server sends it to us.
|
||||||
|
NOTICE: The CR at the end has been replaced by a space.
|
||||||
|
|
||||||
|
[ig>tx] N1ZKO-7>T2TS7X,K1FFK,WA2MJM-15*,qAR,WB2ZII-15:`c6wl!i[/>"4]}[scanning]=<0x20>
|
||||||
|
|
||||||
|
Should we transmit it?
|
||||||
|
No, we sent it recently by the digipeating function (note "bydigi=1").
|
||||||
|
|
||||||
|
DEBUG: ax25_dedupe_crc ignoring trailing space.
|
||||||
|
ig_to_tx_allow? ch0 27598 "N1ZKO-7>T2TS7X:`c6wl!i[/>"4]}[scanning]= "
|
||||||
|
ig_to_tx_allow? NO. Sent 4 seconds ago. bydigi=1
|
||||||
|
Tx IGate: Drop duplicate packet transmitted recently.
|
||||||
|
[0L] WB2OSZ-14>APDW13,WIDE1-1:}W1AST>TRPR4T,TCPIP,WB2OSZ-14*:`d=Ml!3>/"4N}
|
||||||
|
[rx>ig] #
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define IG2TX_DEDUPE_TIME 60 /* Do not send duplicate within 60 seconds. */
|
#define IG2TX_DEDUPE_TIME 60 /* Do not send duplicate within 60 seconds. */
|
||||||
#define IG2TX_HISTORY_MAX 50 /* Remember the last 50 sent from server to radio. */
|
#define IG2TX_HISTORY_MAX 50 /* Remember the last 50 sent from server to radio. */
|
||||||
|
|
||||||
|
/* Ideally this should be a critical region because */
|
||||||
|
/* it is being written by two threads but I'm not that concerned. */
|
||||||
|
|
||||||
static int ig2tx_insert_next;
|
static int ig2tx_insert_next;
|
||||||
static time_t ig2tx_time_stamp[IG2TX_HISTORY_MAX];
|
static time_t ig2tx_time_stamp[IG2TX_HISTORY_MAX];
|
||||||
static unsigned short ig2tx_checksum[IG2TX_HISTORY_MAX];
|
static unsigned short ig2tx_checksum[IG2TX_HISTORY_MAX];
|
||||||
|
static unsigned char ig2tx_chan[IG2TX_HISTORY_MAX];
|
||||||
|
static unsigned short ig2tx_bydigi[IG2TX_HISTORY_MAX];
|
||||||
|
|
||||||
static void ig_to_tx_init (void)
|
static void ig_to_tx_init (void)
|
||||||
{
|
{
|
||||||
|
@ -1524,15 +1762,40 @@ static void ig_to_tx_init (void)
|
||||||
for (n=0; n<IG2TX_HISTORY_MAX; n++) {
|
for (n=0; n<IG2TX_HISTORY_MAX; n++) {
|
||||||
ig2tx_time_stamp[n] = 0;
|
ig2tx_time_stamp[n] = 0;
|
||||||
ig2tx_checksum[n] = 0;
|
ig2tx_checksum[n] = 0;
|
||||||
|
ig2tx_chan[n] = 0xff;
|
||||||
|
ig2tx_bydigi[n] = 0;
|
||||||
}
|
}
|
||||||
ig2tx_insert_next = 0;
|
ig2tx_insert_next = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ig_to_tx_remember (packet_t pp)
|
void ig_to_tx_remember (packet_t pp, int chan, int bydigi)
|
||||||
{
|
{
|
||||||
ig2tx_time_stamp[ig2tx_insert_next] = time(NULL);
|
time_t now = time(NULL);
|
||||||
ig2tx_checksum[ig2tx_insert_next] = ax25_dedupe_crc(pp);
|
unsigned short crc = ax25_dedupe_crc(pp);
|
||||||
|
|
||||||
|
if (s_debug >= 3) {
|
||||||
|
char src[AX25_MAX_ADDR_LEN];
|
||||||
|
char dest[AX25_MAX_ADDR_LEN];
|
||||||
|
unsigned char *pinfo;
|
||||||
|
int info_len;
|
||||||
|
|
||||||
|
ax25_get_addr_with_ssid(pp, AX25_SOURCE, src);
|
||||||
|
ax25_get_addr_with_ssid(pp, AX25_DESTINATION, dest);
|
||||||
|
info_len = ax25_get_info (pp, &pinfo);
|
||||||
|
|
||||||
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
dw_printf ("ig_to_tx_remember [%d] = ch%d d%d %d %d \"%s>%s:%s\"\n",
|
||||||
|
ig2tx_insert_next,
|
||||||
|
chan, bydigi,
|
||||||
|
(int)(now), crc,
|
||||||
|
src, dest, pinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
ig2tx_time_stamp[ig2tx_insert_next] = now;
|
||||||
|
ig2tx_checksum[ig2tx_insert_next] = crc;
|
||||||
|
ig2tx_chan[ig2tx_insert_next] = chan;
|
||||||
|
ig2tx_bydigi[ig2tx_insert_next] = bydigi;
|
||||||
|
|
||||||
ig2tx_insert_next++;
|
ig2tx_insert_next++;
|
||||||
if (ig2tx_insert_next >= IG2TX_HISTORY_MAX) {
|
if (ig2tx_insert_next >= IG2TX_HISTORY_MAX) {
|
||||||
|
@ -1540,26 +1803,52 @@ static void ig_to_tx_remember (packet_t pp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ig_to_tx_allow (packet_t pp)
|
static int ig_to_tx_allow (packet_t pp, int chan)
|
||||||
{
|
{
|
||||||
unsigned short crc = ax25_dedupe_crc(pp);
|
unsigned short crc = ax25_dedupe_crc(pp);
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
int j;
|
int j;
|
||||||
int count_1, count_5;
|
int count_1, count_5;
|
||||||
|
|
||||||
|
if (s_debug >= 2) {
|
||||||
|
char src[AX25_MAX_ADDR_LEN];
|
||||||
|
char dest[AX25_MAX_ADDR_LEN];
|
||||||
|
unsigned char *pinfo;
|
||||||
|
int info_len;
|
||||||
|
|
||||||
|
ax25_get_addr_with_ssid(pp, AX25_SOURCE, src);
|
||||||
|
ax25_get_addr_with_ssid(pp, AX25_DESTINATION, dest);
|
||||||
|
info_len = ax25_get_info (pp, &pinfo);
|
||||||
|
|
||||||
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
dw_printf ("ig_to_tx_allow? ch%d %d \"%s>%s:%s\"\n", chan, crc, src, dest, pinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consider transmissions on this channel only by either digi or IGate. */
|
||||||
|
|
||||||
for (j=0; j<IG2TX_HISTORY_MAX; j++) {
|
for (j=0; j<IG2TX_HISTORY_MAX; j++) {
|
||||||
if (ig2tx_time_stamp[j] >= now - IG2TX_DEDUPE_TIME && ig2tx_checksum[j] == crc) {
|
if (ig2tx_checksum[j] == crc && ig2tx_chan[j] == chan && ig2tx_time_stamp[j] >= now - IG2TX_DEDUPE_TIME) {
|
||||||
|
if (s_debug >= 2) {
|
||||||
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
// could be multiple entries and this might not be the most recent.
|
||||||
|
dw_printf ("ig_to_tx_allow? NO. Sent %d seconds ago. bydigi=%d\n", (int)(now - ig2tx_time_stamp[j]), ig2tx_bydigi[j]);
|
||||||
|
}
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf ("Tx IGate: Drop duplicate packet transmitted recently.\n");
|
dw_printf ("Tx IGate: Drop duplicate packet transmitted recently.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* IGate transmit counts must not include digipeater transmissions. */
|
||||||
|
|
||||||
count_1 = 0;
|
count_1 = 0;
|
||||||
count_5 = 0;
|
count_5 = 0;
|
||||||
for (j=0; j<IG2TX_HISTORY_MAX; j++) {
|
for (j=0; j<IG2TX_HISTORY_MAX; j++) {
|
||||||
|
if (ig2tx_chan[j] == chan && ig2tx_bydigi[j] == 0) {
|
||||||
if (ig2tx_time_stamp[j] >= now - 60) count_1++;
|
if (ig2tx_time_stamp[j] >= now - 60) count_1++;
|
||||||
if (ig2tx_time_stamp[j] >= now - 300) count_5++;
|
if (ig2tx_time_stamp[j] >= now - 300) count_5++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (count_1 >= save_igate_config_p->tx_limit_1) {
|
if (count_1 >= save_igate_config_p->tx_limit_1) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
@ -1572,6 +1861,11 @@ static int ig_to_tx_allow (packet_t pp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s_debug >= 2) {
|
||||||
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
dw_printf ("ig_to_tx_allow? YES\n");
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
} /* end ig_to_tx_allow */
|
} /* end ig_to_tx_allow */
|
||||||
|
|
13
igate.h
13
igate.h
|
@ -55,13 +55,24 @@ struct igate_config_s {
|
||||||
int tx_limit_5; /* Max. packets to transmit in 5 minutes. */
|
int tx_limit_5; /* Max. packets to transmit in 5 minutes. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define IGATE_TX_LIMIT_1_DEFAULT 6
|
||||||
|
#define IGATE_TX_LIMIT_1_MAX 20
|
||||||
|
|
||||||
|
#define IGATE_TX_LIMIT_5_DEFAULT 20
|
||||||
|
#define IGATE_TX_LIMIT_5_MAX 80
|
||||||
|
|
||||||
|
|
||||||
/* Call this once at startup */
|
/* Call this once at startup */
|
||||||
|
|
||||||
void igate_init (struct audio_s *p_audio_config, struct igate_config_s *p_igate_config, struct digi_config_s *p_digi_config);
|
void igate_init (struct audio_s *p_audio_config, struct igate_config_s *p_igate_config, struct digi_config_s *p_digi_config, int debug_level);
|
||||||
|
|
||||||
/* Call this with each packet received from the radio. */
|
/* Call this with each packet received from the radio. */
|
||||||
|
|
||||||
void igate_send_rec_packet (int chan, packet_t recv_pp);
|
void igate_send_rec_packet (int chan, packet_t recv_pp);
|
||||||
|
|
||||||
|
/* This when digipeater transmits. Set bydigi to 1 . */
|
||||||
|
|
||||||
|
void ig_to_tx_remember (packet_t pp, int chan, int bydigi);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -82,6 +82,8 @@ g = GPS interface.
|
||||||
t = Tracker beacon.
|
t = Tracker beacon.
|
||||||
.P
|
.P
|
||||||
o = Output controls such as PTT and DCD.
|
o = Output controls such as PTT and DCD.
|
||||||
|
.P
|
||||||
|
i = IGate
|
||||||
.RE
|
.RE
|
||||||
.RE
|
.RE
|
||||||
.PD
|
.PD
|
||||||
|
|
3
xmit.c
3
xmit.c
|
@ -289,7 +289,6 @@ void xmit_init (struct audio_s *p_modem, int debug_xmit_packet)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Name: xmit_set_txdelay
|
* Name: xmit_set_txdelay
|
||||||
|
@ -606,6 +605,7 @@ static void xmit_ax25_frames (int c, int p, packet_t pp)
|
||||||
dw_printf ("%s", stemp); /* stations followed by : */
|
dw_printf ("%s", stemp); /* stations followed by : */
|
||||||
ax25_safe_print ((char *)pinfo, info_len, ! ax25_is_aprs(pp));
|
ax25_safe_print ((char *)pinfo, info_len, ! ax25_is_aprs(pp));
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
|
(void)ax25_check_addresses (pp);
|
||||||
|
|
||||||
/* Optional hex dump of packet. */
|
/* Optional hex dump of packet. */
|
||||||
|
|
||||||
|
@ -669,6 +669,7 @@ static void xmit_ax25_frames (int c, int p, packet_t pp)
|
||||||
dw_printf ("%s", stemp); /* stations followed by : */
|
dw_printf ("%s", stemp); /* stations followed by : */
|
||||||
ax25_safe_print ((char *)pinfo, info_len, ! ax25_is_aprs(pp));
|
ax25_safe_print ((char *)pinfo, info_len, ! ax25_is_aprs(pp));
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
|
(void)ax25_check_addresses (pp);
|
||||||
|
|
||||||
if (g_debug_xmit_packet) {
|
if (g_debug_xmit_packet) {
|
||||||
text_color_set(DW_COLOR_DEBUG);
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
|
Loading…
Reference in New Issue