From e10814765539ef4db92c8d7095e8375e10421380 Mon Sep 17 00:00:00 2001 From: wb2osz Date: Fri, 25 Feb 2022 22:29:07 +0000 Subject: [PATCH] Fix ttgrid corner and various cleanups. --- src/aprs_tt.c | 20 ++++- src/atest.c | 2 +- src/ax25_pad.c | 7 +- src/config.c | 22 +++--- src/decode_aprs.c | 188 ++++++++++++++++++++++++++++++++++++++-------- src/decode_aprs.h | 12 ++- src/digipeater.c | 48 +++++++----- src/digipeater.h | 6 +- src/direwolf.c | 5 +- src/fx25_init.c | 31 ++++---- src/kiss_frame.c | 1 + src/latlong.c | 4 + src/pfilter.c | 2 +- src/symbols.c | 14 +++- 14 files changed, 270 insertions(+), 92 deletions(-) diff --git a/src/aprs_tt.c b/src/aprs_tt.c index 13246f7..7b12575 100644 --- a/src/aprs_tt.c +++ b/src/aprs_tt.c @@ -1283,13 +1283,26 @@ static int parse_location (char *e) lat0 = tt_config.ttloc_ptr[ipat].grid.lat0; lat9 = tt_config.ttloc_ptr[ipat].grid.lat9; + double yrange = lat9 - lat0; y = atof(ystr); - m_latitude = lat0 + y * (lat9-lat0) / (pow(10., strlen(ystr)) - 1.); - + double user_y_max = round(pow(10., strlen(ystr)) - 1.); // e.g. 999 for 3 digits + m_latitude = lat0 + yrange * y / user_y_max; +#if 0 + dw_printf ("TTLOC_GRID LAT min=%f, max=%f, range=%f\n", lat0, lat9, yrange); + dw_printf ("TTLOC_GRID LAT user_y=%f, user_y_max=%f\n", y, user_y_max); + dw_printf ("TTLOC_GRID LAT min + yrange * user_y / user_y_range = %f\n", m_latitude); +#endif lon0 = tt_config.ttloc_ptr[ipat].grid.lon0; lon9 = tt_config.ttloc_ptr[ipat].grid.lon9; + double xrange = lon9 - lon0; x = atof(xstr); - m_longitude = lon0 + x * (lon9-lon0) / (pow(10., strlen(xstr)) - 1.); + double user_x_max = round(pow(10., strlen(xstr)) - 1.); + m_longitude = lon0 + xrange * x / user_x_max; +#if 0 + dw_printf ("TTLOC_GRID LON min=%f, max=%f, range=%f\n", lon0, lon9, xrange); + dw_printf ("TTLOC_GRID LON user_x=%f, user_x_max=%f\n", x, user_x_max); + dw_printf ("TTLOC_GRID LON min + xrange * user_x / user_x_range = %f\n", m_longitude); +#endif m_dao[2] = e[0]; m_dao[3] = e[1]; @@ -1972,6 +1985,7 @@ static const struct { /* Latitude comes out ok, 37.9137 -> 55.82 min. */ /* Longitude -81.1254 -> 8.20 min */ { "B21234*A67979#", "679", "12", "7A", "", "", "12.3400", "56.1200", "!TB2!" }, + { "B533686*A67979#", "679", "12", "7A", "", "", "37.9222", "81.1143", "!TB5!" }, // TODO: should test other coordinate systems. diff --git a/src/atest.c b/src/atest.c index 910eecd..5f2dd05 100644 --- a/src/atest.c +++ b/src/atest.c @@ -886,7 +886,7 @@ void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alev decode_aprs_t A; - decode_aprs (&A, pp, 0); + decode_aprs (&A, pp, 0, 0); // Temp experiment to see how different systems set the RR bits in the source and destination. // log_rr_bits (&A, pp); diff --git a/src/ax25_pad.c b/src/ax25_pad.c index de49c08..b5d4763 100644 --- a/src/ax25_pad.c +++ b/src/ax25_pad.c @@ -350,8 +350,9 @@ void ax25_delete (packet_t this_p) * strict - True to enforce rules for packets sent over the air. * False to be more lenient for packets from IGate server. * - * Messages from an IGate server can have longer - * addresses after qAC. Up to 9 observed so far. + * Packets from an IGate server can have longer + * addresses after qAC. Up to 9 observed so far. + * The SSID can be 2 alphanumeric characters, not just 1 to 15. * * We can just truncate the name because we will only * end up discarding it. TODO: check on this. @@ -740,6 +741,7 @@ packet_t ax25_dup (packet_t copy_from) * alphanumeric characters for the SSID. * We also get messages like this from a server. * KB1POR>APU25N,TCPIP*,qAC,T2NUENGLD:... + * K1BOS-B>APOSB,TCPIP,WR2X-2*:... * * 2 (extra true) will complain if * is found at end. * @@ -1983,6 +1985,7 @@ void ax25_format_addrs (packet_t this_p, char *result) } ax25_get_addr_with_ssid (this_p, AX25_SOURCE, stemp); + // FIXME: For ALL strcat: Pass in sizeof result and use strlcat. strcat (result, stemp); strcat (result, ">"); diff --git a/src/config.c b/src/config.c index 4d1f0dd..fe44765 100644 --- a/src/config.c +++ b/src/config.c @@ -2397,10 +2397,9 @@ void config_init (char *fname, struct audio_s *p_audio_config, */ /* - * DIGIPEAT from-chan to-chan alias-pattern wide-pattern [ OFF|DROP|MARK|TRACE | NOID=alias ] + * DIGIPEAT from-chan to-chan alias-pattern wide-pattern [ OFF|DROP|MARK|TRACE | ATGP=alias ] * - * NOID is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters. - * The via path starts out as HOP7-7,HOP7-7 and we do not want tracing so it does not fill up. + * ATGP is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters. * DO NOT put this in the User Guide. On a need to know basis. */ @@ -2527,8 +2526,8 @@ void config_init (char *fname, struct audio_s *p_audio_config, p_digi_config->preempt[from_chan][to_chan] = PREEMPT_TRACE; t = split(NULL,0); } - else if (strncasecmp(t, "NOID=", 5) == 0) { - strlcpy (p_digi_config->noid[from_chan][to_chan], t+5, sizeof(p_digi_config->noid[from_chan][to_chan]));; + else if (strncasecmp(t, "ATGP=", 5) == 0) { + strlcpy (p_digi_config->atgp[from_chan][to_chan], t+5, sizeof(p_digi_config->atgp[from_chan][to_chan]));; t = split(NULL,0); } } @@ -3221,7 +3220,7 @@ void config_init (char *fname, struct audio_s *p_audio_config, t = split(NULL,0); if (t == NULL) { text_color_set(DW_COLOR_ERROR); - dw_printf ("Line %d: Missing latitude for TTGRID command.\n", line); + dw_printf ("Line %d: Missing minimum latitude for TTGRID command.\n", line); continue; } tl->grid.lat0 = parse_ll(t,LAT,line); @@ -3231,7 +3230,7 @@ void config_init (char *fname, struct audio_s *p_audio_config, t = split(NULL,0); if (t == NULL) { text_color_set(DW_COLOR_ERROR); - dw_printf ("Line %d: Missing longitude for TTGRID command.\n", line); + dw_printf ("Line %d: Missing minimum longitude for TTGRID command.\n", line); continue; } tl->grid.lon0 = parse_ll(t,LON,line); @@ -3241,7 +3240,7 @@ void config_init (char *fname, struct audio_s *p_audio_config, t = split(NULL,0); if (t == NULL) { text_color_set(DW_COLOR_ERROR); - dw_printf ("Line %d: Missing latitude for TTGRID command.\n", line); + dw_printf ("Line %d: Missing maximum latitude for TTGRID command.\n", line); continue; } tl->grid.lat9 = parse_ll(t,LAT,line); @@ -3251,13 +3250,16 @@ void config_init (char *fname, struct audio_s *p_audio_config, t = split(NULL,0); if (t == NULL) { text_color_set(DW_COLOR_ERROR); - dw_printf ("Line %d: Missing longitude for TTGRID command.\n", line); + dw_printf ("Line %d: Missing maximum longitude for TTGRID command.\n", line); continue; } - tl->grid.lon0 = parse_ll(t,LON,line); + tl->grid.lon9 = parse_ll(t,LON,line); /* temp debugging */ + // dw_printf ("CONFIG TTGRID min %f %f\n", tl->grid.lat0, tl->grid.lon0); + // dw_printf ("CONFIG TTGRID max %f %f\n", tl->grid.lat9, tl->grid.lon9); + //for (j=0; jttloc_len; j++) { // dw_printf ("debug ttloc %d/%d %s\n", j, p_tt_config->ttloc_size, // p_tt_config->ttloc_ptr[j].pattern); diff --git a/src/decode_aprs.c b/src/decode_aprs.c index b0860d8..ccdfa21 100644 --- a/src/decode_aprs.c +++ b/src/decode_aprs.c @@ -1,7 +1,7 @@ // // This file is part of Dire Wolf, an amateur radio packet TNC. // -// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2017 John Langner, WB2OSZ +// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2017, 2022 John Langner, WB2OSZ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -140,6 +140,11 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen); * * quiet - Suppress error messages. * + * third_party - True when parsing a third party header. + * (decode_aprs is called recursively.) + * This is mostly found when an IGate transmits a message + * that came via APRS-IS. + * * Outputs: A-> g_symbol_table, g_symbol_code, * g_lat, g_lon, * g_speed_mph, g_course, g_altitude_ft, @@ -151,16 +156,19 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen); * *------------------------------------------------------------------*/ -void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet) +void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, int third_party) { + //dw_printf ("DEBUG decode_aprs quiet=%d, third_party=%d\n", quiet, third_party); - char dest[AX25_MAX_ADDR_LEN]; + //char dest[AX25_MAX_ADDR_LEN]; unsigned char *pinfo; int info_len; info_len = ax25_get_info (pp, &pinfo); + //dw_printf ("DEBUG decode_aprs info=\"%s\"\n", pinfo); + memset (A, 0, sizeof (*A)); A->g_quiet = quiet; @@ -200,16 +208,26 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet) if (*pinfo == '}') { + //dw_printf ("DEBUG decode_aprs recursively process third party header\n"); + + // This must not be strict because the addresses in third party payload doesn't + // need to adhere to the AX.25 address format (i.e. 6 upper case alphanumeric.) + // SSID can be 2 alphanumeric characters. + // Addresses can include lower case, e.g. q contruct. + + // e.g. WR2X-2>APRS,WA1PLE-13*:} + // K1BOS-B>APOSB,TCPIP,WR2X-2*:@122015z4221.42ND07111.93W&/A=000000SharkRF openSPOT3 MMDVM446.025 MA/SW + packet_t pp_payload = ax25_from_text ((char*)pinfo+1, 0); if (pp_payload != NULL) { - decode_aprs (A, pp_payload, quiet); + decode_aprs (A, pp_payload, quiet, 1); // 1 means used recursively ax25_delete (pp_payload); return; } else { strlcpy (A->g_msg_type, "Third Party Header: Unable to parse payload.", sizeof(A->g_msg_type)); ax25_get_addr_with_ssid (pp, AX25_SOURCE, A->g_src); - ax25_get_addr_with_ssid (pp, AX25_DESTINATION, dest); + ax25_get_addr_with_ssid (pp, AX25_DESTINATION, A->g_dest); } } @@ -218,7 +236,10 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet) */ ax25_get_addr_with_ssid (pp, AX25_SOURCE, A->g_src); - ax25_get_addr_with_ssid (pp, AX25_DESTINATION, dest); + ax25_get_addr_with_ssid (pp, AX25_DESTINATION, A->g_dest); + + //dw_printf ("DEBUG decode_aprs source=%s, dest=%s\n", A->g_src, A->g_dest); + /* * Report error if the information part contains a nul character. @@ -260,7 +281,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet) break; default: - decode_tocall (A, dest); + decode_tocall (A, A->g_dest); break; } @@ -316,7 +337,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet) break; - case ':': /* Message: for one person, a group, or a bulletin. */ + case ':': /* "Message" (special APRS meaning): for one person, a group, or a bulletin. */ /* Directed Station Query */ /* Telemetry metadata. */ @@ -402,7 +423,17 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet) if (A->g_symbol_table == ' ' || A->g_symbol_code == ' ') { - symbols_from_dest_or_src (*pinfo, A->g_src, dest, &A->g_symbol_table, &A->g_symbol_code); + // A symbol on a "message" makes no sense and confuses people. + // Third party too. Set from the payload. + // Maybe eliminate for a couple others. + + //dw_printf ("DEBUG decode_aprs@end1 third_party=%d, symbol_table=%c, symbol_code=%c, *pinfo=%c\n", third_party, A->g_symbol_table, A->g_symbol_code, *pinfo); + + if (*pinfo != ':' && *pinfo != '}') { + symbols_from_dest_or_src (*pinfo, A->g_src, A->g_dest, &A->g_symbol_table, &A->g_symbol_code); + } + + //dw_printf ("DEBUG decode_aprs@end2 third_party=%d, symbol_table=%c, symbol_code=%c, *pinfo=%c\n", third_party, A->g_symbol_table, A->g_symbol_code, *pinfo); } } /* end decode_aprs */ @@ -410,8 +441,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet) void decode_aprs_print (decode_aprs_t *A) { - char stemp[200]; - //char tmp2[2]; + char stemp[500]; double absll; char news; int deg; @@ -419,11 +449,10 @@ void decode_aprs_print (decode_aprs_t *A) { char s_lat[30]; char s_lon[30]; int n; - char symbol_description[100]; /* * First line has: - * - message type + * - packet type * - object name * - symbol * - manufacturer/application @@ -432,28 +461,53 @@ void decode_aprs_print (decode_aprs_t *A) { */ strlcpy (stemp, A->g_msg_type, sizeof(stemp)); + //dw_printf ("DEBUG decode_aprs_print stemp1=%s\n", stemp); + if (strlen(A->g_name) > 0) { strlcat (stemp, ", \"", sizeof(stemp)); strlcat (stemp, A->g_name, sizeof(stemp)); strlcat (stemp, "\"", sizeof(stemp)); } + //dw_printf ("DEBUG decode_aprs_print stemp2=%s\n", stemp); + + //dw_printf ("DEBUG decode_aprs_print symbol_code=%c=0x%02x\n", A->g_symbol_code, A->g_symbol_code); + if (A->g_symbol_code != ' ') { - symbols_get_description (A->g_symbol_table, A->g_symbol_code, symbol_description, sizeof(symbol_description)); + char symbol_description[100]; + symbols_get_description (A->g_symbol_table, A->g_symbol_code, symbol_description, sizeof(symbol_description)); + + //dw_printf ("DEBUG decode_aprs_print symbol_description_description=%s\n", symbol_description); + strlcat (stemp, ", ", sizeof(stemp)); strlcat (stemp, symbol_description, sizeof(stemp)); } + //dw_printf ("DEBUG decode_aprs_print stemp3=%s mfr=%s\n", stemp, A->g_mfr); + if (strlen(A->g_mfr) > 0) { - strlcat (stemp, ", ", sizeof(stemp)); - strlcat (stemp, A->g_mfr, sizeof(stemp)); + if (strcmp(A->g_dest, "APRS") == 0) { + strlcat (stemp, "\nUse of \"APRS\" in the destination field is obsolete.", sizeof(stemp)); + strlcat (stemp, " You can help to improve the quality of APRS signals.", sizeof(stemp)); + strlcat (stemp, "\nTell the sender (", sizeof(stemp)); + strlcat (stemp, A->g_src, sizeof(stemp)); + strlcat (stemp, ") to use the proper product code from", sizeof(stemp)); + strlcat (stemp, " http://www.aprs.org/aprs11/tocalls.txt", sizeof(stemp)); + } + else { + strlcat (stemp, ", ", sizeof(stemp)); + strlcat (stemp, A->g_mfr, sizeof(stemp)); + } } + //dw_printf ("DEBUG decode_aprs_print stemp4=%s\n", stemp); + if (strlen(A->g_mic_e_status) > 0) { strlcat (stemp, ", ", sizeof(stemp)); strlcat (stemp, A->g_mic_e_status, sizeof(stemp)); } + //dw_printf ("DEBUG decode_aprs_print stemp5=%s\n", stemp); if (A->g_power > 0) { char phg[100]; @@ -1120,7 +1174,7 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int char sym_table_id; } *p; - char dest[10]; + char dest[12]; int ch; int n; int offset; @@ -1379,7 +1433,7 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int // Last Updated Dec. 2021 -// This does not change very often but I'm wondering if we could simply parse +// This does not change very often but I'm wondering if we could parse // http://www.aprs.org/aprs12/mic-e-types.txt similar to how we use tocalls.txt. if (isT(*pfirst)) { @@ -1511,13 +1565,18 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int * :xxxxxxxxx:EQNS. Telemetry metadata, Equation Coefficients * :xxxxxxxxx:BITS. Telemetry metadata, Bit Sense/Project Name * :xxxxxxxxx:? Directed Station Query - * :xxxxxxxxx:ack Message acknowledged (received) - * :xxxxxxxxx:rej Message rejected (unable to accept) + * :xxxxxxxxx:ackNNNN Message acknowledged (received) + * :xxxxxxxxx:rejNNNNN Message rejected (unable to accept) * * :xxxxxxxxx: ... Message with no message number. * (Text may not contain the { character because * it indicates beginning of optional message number.) - * :xxxxxxxxx: ... {num Message with message number. + * :xxxxxxxxx: ... {NNNNN Message with message number, 1 to 5 alphanumeric. + * :xxxxxxxxx: ... {mm} Message with new style message number. + * :xxxxxxxxx: ... {mm}aa Message with new style message number and ack. + * + * + * Reference: See new message id style: http://www.aprs.org/aprs11/replyacks.txt * *------------------------------------------------------------------*/ @@ -1528,8 +1587,10 @@ static void aprs_message (decode_aprs_t *A, unsigned char *info, int ilen, int q char dti; /* : */ char addressee[9]; char colon; /* : */ - char message[73]; /* 0-67 characters for message */ - /* Optional { followed by 1-5 characters for message number */ + char message[256-1-9-1]; /* Officially up to 67 characters for message text. */ + /* Relaxing seemingly arbitrary restriction here; it doesn't need to fit on a punched card. */ + /* Wouldn't surprize me if others did not pay attention to the limit. */ + /* Optional { followed by 1-5 alphanumeric characters for message number */ /* If the first character is '?' it is a Directed Station Query. */ } *p; @@ -1651,25 +1712,84 @@ static void aprs_message (decode_aprs_t *A, unsigned char *info, int ilen, int q /* ack or rej? Message number is required for these. */ - else if (strncmp(p->message,"ack",3) == 0) { + else if (strncasecmp(p->message,"ack",3) == 0) { + if (strncmp(p->message,"ack",3) != 0) { + text_color_set(DW_COLOR_ERROR); + dw_printf("ERROR: \"%s\" must be lower case \"ack\"\n", p->message); + } strlcpy (A->g_message_number, p->message + 3, sizeof(A->g_message_number)); - snprintf (A->g_msg_type, sizeof(A->g_msg_type), "ACK message %s for \"%s\"", A->g_message_number, addressee); + if (strlen(A->g_message_number) == 0) { + text_color_set(DW_COLOR_ERROR); + dw_printf("ERROR: Message number is missing after \"ack\".\n"); + } + if (strlen(A->g_message_number) >= 3 && A->g_message_number[2] == '}') A->g_message_number[2] = '\0'; + snprintf (A->g_msg_type, sizeof(A->g_msg_type), "\"%s\" ACKnowledged message number \"%s\" from \"%s\"", A->g_src, A->g_message_number, addressee); A->g_message_subtype = message_subtype_ack; } - else if (strncmp(p->message,"rej",3) == 0) { + else if (strncasecmp(p->message,"rej",3) == 0) { + if (strncmp(p->message,"rej",3) != 0) { + text_color_set(DW_COLOR_ERROR); + dw_printf("ERROR: \"%s\" must be lower case \"rej\"\n", p->message); + } strlcpy (A->g_message_number, p->message + 3, sizeof(A->g_message_number)); - snprintf (A->g_msg_type, sizeof(A->g_msg_type), "REJ message %s for \"%s\"", A->g_message_number, addressee); + if (strlen(A->g_message_number) == 0) { + text_color_set(DW_COLOR_ERROR); + dw_printf("ERROR: Message number is missing after \"rej\".\n"); + } + if (strlen(A->g_message_number) >= 3 && A->g_message_number[2] == '}') A->g_message_number[2] = '\0'; + snprintf (A->g_msg_type, sizeof(A->g_msg_type), "\"%s\" REJected message number \"%s\" from \"%s\"", A->g_src, A->g_message_number, addressee); A->g_message_subtype = message_subtype_ack; } -/* message number is optional here. */ +// Message to a particular station or a bulletin. +// message number is optional here. +// Test cases. Wrap in third party too. +// A>B::WA1XYX-15:Howdy y'all +// A>B::WA1XYX-15:Howdy y'all{12345 +// A>B::WA1XYX-15:Howdy y'all{12} +// A>B::WA1XYX-15:Howdy y'all{12}34 +// A>B::WA1XYX-15:Howdy y'all{toolong +// X>Y:}A>B::WA1XYX-15:Howdy y'all +// X>Y:}A>B::WA1XYX-15:Howdy y'all{12345 +// X>Y:}A>B::WA1XYX-15:Howdy y'all{12} +// X>Y:}A>B::WA1XYX-15:Howdy y'all{12}34 +// X>Y:}A>B::WA1XYX-15:Howdy y'all{toolong else { + // Look for message number. char *pno = strchr(p->message, '{'); if (pno != NULL) { + *pno = '\0'; + int mlen = strlen(pno+1); + if (mlen < 1 || mlen > 5) { + text_color_set(DW_COLOR_ERROR); + dw_printf("Message number \"%s\" has length outside range of 1 to 5.\n", pno+1); + } strlcpy (A->g_message_number, pno+1, sizeof(A->g_message_number)); + // TODO: Complain if not alphanumeric. + + char ack[8] = ""; + + if (mlen >= 3 && A->g_message_number[2] == '}') { + // New (1999) style. + A->g_message_number[2] = '\0'; + strlcpy (ack, A->g_message_number + 3, sizeof(ack)); + } + + if (strlen(ack) > 0) { + // With ACK. Message number should be 2 characters. + snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message, number \"%s\", from \"%s\" to \"%s\", with ACK for \"%s\"", A->g_message_number, A->g_src, addressee, ack); + } + else { + // Message number can be 1-5 characters. + snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message, number \"%s\", from \"%s\" to \"%s\"", A->g_message_number, A->g_src, addressee); + } } - snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message %s for \"%s\"", A->g_message_number, addressee); + else { + // No message number. + snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message, with no number, from \"%s\" to \"%s\"", A->g_src, addressee); + } + A->g_message_subtype = message_subtype_message; /* No location so don't use process_comment () */ @@ -2389,10 +2509,12 @@ static void aprs_telemetry (decode_aprs_t *A, char *info, int ilen, int quiet) static void aprs_user_defined (decode_aprs_t *A, char *info, int ilen) { - if (strncmp(info, "{tt", 3) == 0) { // Historical. Should probably use DT. + if (strncmp(info, "{tt", 3) == 0 || // Historical. + strncmp(info, "{DT", 3) == 0) { // Official after registering {D* aprs_raw_touch_tone (A, info, ilen); } - else if (strncmp(info, "{mc", 3) == 0) { // Historical. Should probably use DM. + else if (strncmp(info, "{mc", 3) == 0 || // Historical. + strncmp(info, "{DM", 3) == 0) { // Official after registering {D* aprs_morse_code (A, info, ilen); } else if (info[0] == '{' && info[1] == USER_DEF_USER_ID && info[2] == USER_DEF_TYPE_AIS) { @@ -4993,7 +5115,7 @@ int main (int argc, char *argv[]) ax25_safe_print ((char *)pinfo, info_len, 1); // Display non-ASCII to hexadecimal. dw_printf ("\n"); - decode_aprs (&A, pp, 0); // Extract information into structure. + decode_aprs (&A, pp, 0, 0); // Extract information into structure. decode_aprs_print (&A); // Now print it in human readable format. @@ -5014,7 +5136,7 @@ int main (int argc, char *argv[]) if (pp != NULL) { decode_aprs_t A; - decode_aprs (&A, pp, 0); // Extract information into structure. + decode_aprs (&A, pp, 0, 0); // Extract information into structure. decode_aprs_print (&A); // Now print it in human readable format. diff --git a/src/decode_aprs.h b/src/decode_aprs.h index 7ff3e87..eb27921 100644 --- a/src/decode_aprs.h +++ b/src/decode_aprs.h @@ -26,9 +26,11 @@ typedef struct decode_aprs_s { char g_src[AX25_MAX_ADDR_LEN]; - char g_msg_type[60]; /* APRS data type. Telemetry descriptions get pretty long. */ + char g_dest[AX25_MAX_ADDR_LEN]; + + char g_msg_type[80]; /* APRS data type description. Telemetry descriptions get pretty long. */ /* Putting msg in the name was a poor choice because */ - /* "message" has a specific meaning. Rename it someday. */ + /* "message" has a specific meaning. Rename it to data_type someday. FIXME */ char g_symbol_table; /* The Symbol Table Identifier character selects one */ /* of the two Symbol Tables, or it may be used as */ @@ -77,7 +79,9 @@ typedef struct decode_aprs_s { message_subtype_directed_query } g_message_subtype; /* Various cases of the overloaded "message." */ - char g_message_number[8]; /* Message number. Should be 1 - 5 characters if used. */ + char g_message_number[8]; /* Message number. Should be 1 - 5 alphanumeric characters if used. */ + /* Addendum 1.1 has new format {mm} or {mm}aa with only two */ + /* characters for message number and an ack riding piggyback. */ float g_speed_mph; /* Speed in MPH. */ /* The APRS transmission uses knots so watch out for */ @@ -140,7 +144,7 @@ typedef struct decode_aprs_s { -extern void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet); +extern void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, int third_party); extern void decode_aprs_print (decode_aprs_t *A); diff --git a/src/digipeater.c b/src/digipeater.c index 36cdbae..9463f5d 100644 --- a/src/digipeater.c +++ b/src/digipeater.c @@ -73,7 +73,7 @@ static packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, char *mycall_xmit, - regex_t *uidigi, regex_t *uitrace, int to_chan, enum preempt_e preempt, char *noid, char *type_filter); + regex_t *uidigi, regex_t *uitrace, int to_chan, enum preempt_e preempt, char *atgp, char *type_filter); /* @@ -176,7 +176,7 @@ void digipeater (int from_chan, packet_t pp) save_audio_config_p->achan[to_chan].mycall, &save_digi_config_p->alias[from_chan][to_chan], &save_digi_config_p->wide[from_chan][to_chan], to_chan, save_digi_config_p->preempt[from_chan][to_chan], - save_digi_config_p->noid[from_chan][to_chan], + save_digi_config_p->atgp[from_chan][to_chan], save_digi_config_p->filter_str[from_chan][to_chan]); if (result != NULL) { dedupe_remember (pp, to_chan); @@ -203,7 +203,7 @@ void digipeater (int from_chan, packet_t pp) save_audio_config_p->achan[to_chan].mycall, &save_digi_config_p->alias[from_chan][to_chan], &save_digi_config_p->wide[from_chan][to_chan], to_chan, save_digi_config_p->preempt[from_chan][to_chan], - save_digi_config_p->noid[from_chan][to_chan], + save_digi_config_p->atgp[from_chan][to_chan], save_digi_config_p->filter_str[from_chan][to_chan]); if (result != NULL) { dedupe_remember (pp, to_chan); @@ -246,7 +246,7 @@ void digipeater (int from_chan, packet_t pp) * * preempt - Option for "preemptive" digipeating. * - * noid - No tracing if this matches alias prefix. + * atgp - No tracing if this matches alias prefix. * Hack added for special needs of ATGP. * * filter_str - Filter expression string or NULL. @@ -267,7 +267,7 @@ void digipeater (int from_chan, packet_t pp) static packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, char *mycall_xmit, - regex_t *alias, regex_t *wide, int to_chan, enum preempt_e preempt, char *noid, char *filter_str) + regex_t *alias, regex_t *wide, int to_chan, enum preempt_e preempt, char *atgp, char *filter_str) { char source[AX25_MAX_ADDR_LEN]; int ssid; @@ -483,22 +483,34 @@ static packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, ch err = regexec(wide,repeater,0,NULL,0); if (err == 0) { -// Special hack added for ATGP to behave like UIFLOOD NOID in some TNCs. -// More than 8 digipeater hops are required so tracing is disabled. +// Special hack added for ATGP to behave like some combination of options in some old TNC +// so the via path does not continue to grow and exceed the 8 available positions. - if (strlen(noid) > 0 && strncasecmp(repeater, noid, strlen(noid)) == 0) { + if (strlen(atgp) > 0 && strncasecmp(repeater, atgp, strlen(atgp)) == 0) { if (ssid >= 1 && ssid <= 7) { packet_t result; + // Usual routine for digipeater. + result = ax25_dup (pp); assert (result != NULL); - if (ssid == 1) { + ssid = ssid - 1; + ax25_set_ssid(result, r, ssid); // could be zero. + if (ssid == 0) { ax25_set_h (result, r); } - ax25_set_ssid(result, r, ssid-1); // could be zero. + // Now remove all used digi addresses, insert own, and mark it used. + +///////////////////////////////////////////// LOOK HERE///////////////////////////////////////////// + + while (ax25_get_num_addr(result) >= 3 && ax25_get_h(result,AX25_REPEATER_1) == 1) { + ax25_remove_addr (result, AX25_REPEATER_1); + } + ax25_insert_addr (result, AX25_REPEATER_1, mycall_xmit); + ax25_set_h (result, AX25_REPEATER_1); return (result); } } @@ -620,7 +632,7 @@ static int failed; static enum preempt_e preempt = PREEMPT_OFF; -static char config_noid[AX25_MAX_ADDR_LEN] = "HOP"; +static char config_atgp[AX25_MAX_ADDR_LEN] = "HOP"; static void test (char *in, char *out) @@ -686,7 +698,7 @@ static void test (char *in, char *out) //TODO: Add filtering to test. // V - result = digipeat_match (0, pp, mycall, mycall, &alias_re, &wide_re, 0, preempt, config_noid, NULL); + result = digipeat_match (0, pp, mycall, mycall, &alias_re, &wide_re, 0, preempt, config_atgp, NULL); if (result != NULL) { @@ -928,18 +940,18 @@ int main (int argc, char *argv[]) preempt = PREEMPT_OFF; // Shouldn't make a difference here. test ( "W1ABC>TEST51,HOP7-7,HOP7-7:stuff1", - "W1ABC>TEST51,HOP7-6,HOP7-7:stuff1"); + "W1ABC>TEST51,WB2OSZ-9*,HOP7-6,HOP7-7:stuff1"); - test ( "W1ABC>TEST52,HOP7-1,HOP7-7:stuff2", - "W1ABC>TEST52,HOP7*,HOP7-7:stuff2"); + test ( "W1ABC>TEST52,ABCD*,HOP7-1,HOP7-7:stuff2", + "W1ABC>TEST52,WB2OSZ-9*,HOP7-7:stuff2"); test ( "W1ABC>TEST52,HOP7*,HOP7-7:stuff3", - "W1ABC>TEST52,HOP7*,HOP7-6:stuff3"); + "W1ABC>TEST52,WB2OSZ-9*,HOP7-6:stuff3"); test ( "W1ABC>TEST52,HOP7*,HOP7-1:stuff4", - "W1ABC>TEST52,HOP7,HOP7*:stuff4"); + "W1ABC>TEST52,WB2OSZ-9*:stuff4"); - test ( "W1ABC>TEST52,HOP7,HOP7*:stuff", + test ( "W1ABC>TEST52,HOP7,HOP7*:stuff5", ""); diff --git a/src/digipeater.h b/src/digipeater.h index f45d54f..5c84976 100644 --- a/src/digipeater.h +++ b/src/digipeater.h @@ -1,5 +1,4 @@ - #ifndef DIGIPEATER_H #define DIGIPEATER_H 1 @@ -38,11 +37,10 @@ struct digi_config_s { enum preempt_e { PREEMPT_OFF, PREEMPT_DROP, PREEMPT_MARK, PREEMPT_TRACE } preempt[MAX_CHANS][MAX_CHANS]; - // NOID is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters. - // The via path starts out as HOP7-7,HOP7-7 and we do not want tracing so it does not fill up. + // ATGP is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters. // DO NOT put this in the User Guide. On a need to know basis. - char noid[MAX_CHANS][MAX_CHANS][AX25_MAX_ADDR_LEN]; + char atgp[MAX_CHANS][MAX_CHANS][AX25_MAX_ADDR_LEN]; char *filter_str[MAX_CHANS+1][MAX_CHANS+1]; // NULL or optional Packet Filter strings such as "t/m". diff --git a/src/direwolf.c b/src/direwolf.c index 146ca5f..c7d79c0 100644 --- a/src/direwolf.c +++ b/src/direwolf.c @@ -299,7 +299,7 @@ int main (int argc, char *argv[]) text_color_init(t_opt); text_color_set(DW_COLOR_INFO); //dw_printf ("Dire Wolf version %d.%d (%s) Beta Test 4\n", MAJOR_VERSION, MINOR_VERSION, __DATE__); - dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "D", __DATE__); + dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "E", __DATE__); //dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION); @@ -322,6 +322,7 @@ int main (int argc, char *argv[]) #if __WIN32__ + //setlinebuf (stdout); setvbuf??? SetConsoleCtrlHandler ((PHANDLER_ROUTINE)cleanup_win, TRUE); #else setlinebuf (stdout); @@ -1425,7 +1426,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev // we still want to decode it for logging and other processing. // Just be quiet about errors if "-qd" is set. - decode_aprs (&A, pp, q_d_opt); + decode_aprs (&A, pp, q_d_opt, 0); if ( ! q_d_opt ) { diff --git a/src/fx25_init.c b/src/fx25_init.c index 3defca3..2844fb9 100644 --- a/src/fx25_init.c +++ b/src/fx25_init.c @@ -410,19 +410,25 @@ struct rs *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigne return NULL; /* Can't have more roots than symbol values! */ rs = (struct rs *)calloc(1,sizeof(struct rs)); + if (rs == NULL) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("FATAL ERROR: Out of memory.\n"); + exit (EXIT_FAILURE); + } rs->mm = symsize; rs->nn = (1<alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); + rs->alpha_to = (DTYPE *)calloc((rs->nn+1),sizeof(DTYPE)); if(rs->alpha_to == NULL){ - free(rs); - return NULL; + text_color_set(DW_COLOR_ERROR); + dw_printf ("FATAL ERROR: Out of memory.\n"); + exit (EXIT_FAILURE); } - rs->index_of = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); + rs->index_of = (DTYPE *)calloc((rs->nn+1),sizeof(DTYPE)); if(rs->index_of == NULL){ - free(rs->alpha_to); - free(rs); - return NULL; + text_color_set(DW_COLOR_ERROR); + dw_printf ("FATAL ERROR: Out of memory.\n"); + exit (EXIT_FAILURE); } /* Generate Galois field lookup tables */ @@ -446,14 +452,13 @@ struct rs *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigne } /* Form RS code generator polynomial from its roots */ - rs->genpoly = (DTYPE *)malloc(sizeof(DTYPE)*(nroots+1)); + rs->genpoly = (DTYPE *)calloc((nroots+1),sizeof(DTYPE)); if(rs->genpoly == NULL){ - free(rs->alpha_to); - free(rs->index_of); - free(rs); - return NULL; + text_color_set(DW_COLOR_ERROR); + dw_printf ("FATAL ERROR: Out of memory.\n"); + exit (EXIT_FAILURE); } - rs->fcr = fcr; + rs->fcr = fcr; rs->prim = prim; rs->nroots = nroots; diff --git a/src/kiss_frame.c b/src/kiss_frame.c index 1d49809..862fb71 100644 --- a/src/kiss_frame.c +++ b/src/kiss_frame.c @@ -107,6 +107,7 @@ void hex_dump (unsigned char *p, int len) offset = 0; while (len > 0) { n = len < 16 ? len : 16; + // FIXME: Is there some reason not to use dw_printf here? printf (" %03x: ", offset); for (i=0; i= 1) { @@ -197,6 +198,7 @@ void longitude_to_str (double dlong, int ambiguity, char *slong) // Assumes slong can hold 9 characters + nul. // Degrees must be exactly 3 digits, with leading zero, if needed. + // FIXME: Should pass in sizeof slong and use snprintf sprintf (slong, "%03d%s%c", ideg, smin, hemi); /* @@ -372,6 +374,7 @@ void latitude_to_nmea (double dlat, char *slat, char *hemi) ideg++; } + // FIXME: Should pass in sizeof slat and use snprintf sprintf (slat, "%02d%s", ideg, smin); } /* end latitude_to_str */ @@ -433,6 +436,7 @@ void longitude_to_nmea (double dlong, char *slong, char *hemi) ideg++; } + // FIXME: Should pass in sizeof slong and use snprintf sprintf (slong, "%03d%s", ideg, smin); } /* end longitude_to_nmea */ diff --git a/src/pfilter.c b/src/pfilter.c index d67dd58..9ae3fe8 100644 --- a/src/pfilter.c +++ b/src/pfilter.c @@ -235,7 +235,7 @@ int pfilter (int from_chan, int to_chan, char *filter, packet_t pp, int is_aprs) pfstate.is_aprs = is_aprs; if (is_aprs) { - decode_aprs (&pfstate.decoded, pp, 1); + decode_aprs (&pfstate.decoded, pp, 1, 0); } next_token(&pfstate); diff --git a/src/symbols.c b/src/symbols.c index 68d393c..b947465 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -352,10 +352,22 @@ void symbols_init (void) char stuff[200]; int j; +// Feb. 2022 - Noticed that some lines have - rather than =. + +// LD = LIght Rail or Subway (new Aug 2014) +// SD = Seaport Depot (new Aug 2014) +// DIGIPEATERS +// /# - Generic digipeater +// 1# - WIDE1-1 digipeater + + #define GOOD_LINE(x) (strlen(x) > 6 && \ (x[COL1_OVERLAY] == '/' || x[COL1_OVERLAY] == '\\' || isupper(x[COL1_OVERLAY]) || isdigit(x[COL1_OVERLAY])) \ && x[COL2_SYMBOL] >= '!' && x[COL2_SYMBOL] <= '~' \ - && x[COL3_SP] == ' ' && x[COL4_EQUAL] == '=' && x[COL5_SP] == ' ' && x[COL6_DESC] != ' ') + && x[COL3_SP] == ' ' \ + && (x[COL4_EQUAL] == '=' || x[COL4_EQUAL] == '-') \ + && x[COL5_SP] == ' ' \ + && x[COL6_DESC] != ' ') if (new_sym_ptr != NULL) { return; /* was called already. */