diff --git a/server.c b/server.c index 70e3af3..0a35178 100644 --- a/server.c +++ b/server.c @@ -1,7 +1,7 @@ // // This file is part of Dire Wolf, an amateur radio packet TNC. // -// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 John Langner, WB2OSZ +// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017 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 @@ -59,6 +59,8 @@ * * 'y' Ask Outstanding frames waiting on a Port (new in 1.2) * + * 'Y' How many frames waiting for transmit for a particular station (new in 1.5) + * * 'C' Connect, Start an AX.25 Connection (new in 1.4) * * 'v' Connect VIA, Start an AX.25 circuit thru digipeaters (new in 1.4) @@ -92,6 +94,8 @@ * * 'y' Outstanding frames waiting on a Port (new in 1.2) * + * 'Y' How many frames waiting for transmit for a particular station (new in 1.5) + * * 'C' AX.25 Connection Received (new in 1.4) * * 'D' Connected AX.25 Data (new in 1.4) @@ -1259,16 +1263,20 @@ static THREAD_F cmd_listen_thread (void *arg) } /* - * Take some precautions to guard against bad data - * which could cause problems later. + * Take some precautions to guard against bad data which could cause problems later. */ + if (cmd.hdr.portx < 0 || cmd.hdr.portx >= MAX_CHANS) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("\nInvalid port number, %d, in command '%c', from AGW client application %d.\n", + cmd.hdr.portx, cmd.hdr.datakind, client); + cmd.hdr.portx = 0; // avoid subscript out of bounds, try to keep going. + } /* - * Call to/from must not exceeed 9 characters. + * Call to/from fields are 10 bytes but contents must not exceeed 9 characters. * It's not guaranteed that unused bytes will contain 0 so we * don't issue error message in this case. */ - cmd.hdr.call_from[sizeof(cmd.hdr.call_from)-1] = '\0'; cmd.hdr.call_to[sizeof(cmd.hdr.call_to)-1] = '\0'; @@ -1455,6 +1463,7 @@ static THREAD_F cmd_listen_thread (void *arg) // YAAC asks for this. // Fake it to keep application happy. + // TODO: Supply real values instead of just faking it. reply.on_air_baud_rate = 0; reply.traffic_level = 1; @@ -1842,6 +1851,7 @@ static THREAD_F cmd_listen_thread (void *arg) case 'y': /* Ask Outstanding frames waiting on a Port */ + /* Number of frames sitting in transmit queue for specified channel. */ { struct { struct agwpe_s hdr; @@ -1856,7 +1866,40 @@ static THREAD_F cmd_listen_thread (void *arg) int n = 0; if (cmd.hdr.portx >= 0 && cmd.hdr.portx < MAX_CHANS) { - n = tq_count (cmd.hdr.portx, TQ_PRIO_0_HI) + tq_count (cmd.hdr.portx, TQ_PRIO_1_LO); + n = tq_count (cmd.hdr.portx, -1, "", ""); + } + reply.data_NETLE = host2netle(n); + + send_to_client (client, &reply); + } + break; + + case 'Y': /* How Many Outstanding frames wait for tx for a particular station */ + + /* Number of frames sitting in transmit queue for given channel, */ + /* source (optional) and destination addresses. */ + { + char source[AX25_MAX_ADDR_LEN]; + char dest[AX25_MAX_ADDR_LEN]; + + struct { + struct agwpe_s hdr; + int data_NETLE; // Little endian order. + } reply; + + strlcpy (source, cmd.hdr.call_from, sizeof(source)); + strlcpy (dest, cmd.hdr.call_to, sizeof(dest)); + + memset (&reply, 0, sizeof(reply)); + reply.hdr.portx = cmd.hdr.portx; /* Reply with same port number, addresses. */ + reply.hdr.datakind = 'Y'; + strlcpy (reply.hdr.call_from, source, sizeof(reply.hdr.call_from)); + strlcpy (reply.hdr.call_to, dest, sizeof(reply.hdr.call_to)); + reply.hdr.data_len_NETLE = host2netle(4); + + int n = 0; + if (cmd.hdr.portx >= 0 && cmd.hdr.portx < MAX_CHANS) { + n = tq_count (cmd.hdr.portx, -1, source, dest); } reply.data_NETLE = host2netle(n); diff --git a/tq.c b/tq.c index fa787c7..d805a74 100644 --- a/tq.c +++ b/tq.c @@ -281,7 +281,7 @@ void tq_append (int chan, int prio, packet_t pp) * Implementing the 6PACK protocol is probably the proper solution. */ - if (ax25_is_aprs(pp) && tq_count(chan,prio) > 100) { + if (ax25_is_aprs(pp) && tq_count(chan,prio,"","") > 100) { text_color_set(DW_COLOR_ERROR); dw_printf ("Transmit packet queue for channel %d is too long. Discarding packet.\n", chan); dw_printf ("Perhaps the channel is so busy there is no opportunity to send.\n"); @@ -458,7 +458,7 @@ void lm_data_request (int chan, int prio, packet_t pp) * Is transmit queue out of control? */ - if (tq_count(chan,prio) > 250) { + if (tq_count(chan,prio,"","") > 250) { text_color_set(DW_COLOR_ERROR); dw_printf ("Warning: Transmit packet queue for channel %d is extremely long.\n", chan); dw_printf ("Perhaps the channel is so busy there is no opportunity to send.\n"); @@ -913,35 +913,67 @@ static int tq_is_empty (int chan) * Name: tq_count * * Purpose: Return count of the number of packets in the specified transmit queue. + * This is used only for queries from KISS or AWG client applications. * * Inputs: chan - Channel, 0 is first. * * prio - Priority, use TQ_PRIO_0_HI or TQ_PRIO_1_LO. + * Specify -1 for total of both. + * + * source - If specified, count only those with this source address. + * + * dest - If specified, count only those with this destination address. * * Returns: Number of items in specified queue. * *--------------------------------------------------------------------*/ -int tq_count (int chan, int prio) +int tq_count (int chan, int prio, char *source, char *dest) { packet_t p; int n; + if (prio == -1) { + return (tq_count(chan, TQ_PRIO_0_HI, source, dest) + + tq_count(chan, TQ_PRIO_1_LO, source, dest)); + } -/* Don't bother with critical section. */ -/* Only used for debugging a problem. */ + + // Array bounds check. FIXME: TODO: should have internal error instead of dying. + + assert (chan >= 0 && chan < MAX_CHANS); + assert (prio >= 0 && prio < TQ_NUM_PRIO); + + // Don't want lists being rearranged while we are traversing them. + + dw_mutex_lock (&tq_mutex); n = 0; p = queue_head[chan][prio]; while (p != NULL) { - n++; + int count_it = 1; + + if (source != NULL && *source != '\0') { + char frame_source[AX25_MAX_ADDR_LEN]; + ax25_get_addr_with_ssid (p, AX25_SOURCE, frame_source); + if (strcmp(source,frame_source) != 0) count_it = 0; + } + if (count_it && dest != NULL && *dest != '\0') { + char frame_dest[AX25_MAX_ADDR_LEN]; + ax25_get_addr_with_ssid (p, AX25_DESTINATION, frame_dest); + if (strcmp(dest,frame_dest) != 0) count_it = 0; + } + + if (count_it) n++; p = ax25_get_nextp(p); } + dw_mutex_unlock (&tq_mutex); + #if DEBUG text_color_set(DW_COLOR_DEBUG); - dw_printf ("tq_count(%d,%d) returns %d\n", chan, prio, n); + dw_printf ("tq_count(%d, %d, \"%s\", \"%s\") returns %d\n", chan, prio, source, dest, n); #endif return (n); diff --git a/tq.h b/tq.h index 4b5beb8..471fd5d 100644 --- a/tq.h +++ b/tq.h @@ -34,7 +34,7 @@ packet_t tq_remove (int chan, int prio); packet_t tq_peek (int chan, int prio); -int tq_count (int chan, int prio); +int tq_count (int chan, int prio, char *source, char *dest); #endif