New IGate "SATGATE" option to delay packets heard directly.

modified:   CHANGES.md
	modified:   audio.h
	modified:   ax25_pad.c
	modified:   ax25_pad.h
	modified:   config.c
	modified:   direwolf.c
	modified:   doc/User-Guide.pdf
	modified:   igate.c
	modified:   igate.h
This commit is contained in:
WB2OSZ 2016-01-30 10:36:15 -05:00
parent 87d9fe00b8
commit 12cb9108d7
9 changed files with 320 additions and 13 deletions

View File

@ -3,6 +3,16 @@
----------
## Version 1.3 -- Development snapshot K -- January 2016 ##
### New Feature: ###
- SATgate mode for IGate. Packets heard directly are delayed before being sent
to the Internet Server. This favors digipeated packets because the original
arrives later and gets dropped if there are duplicates.
----------
## Version 1.3 -- Development snapshot J -- January 2016 ##
### Bugs Fixed: ###
@ -10,7 +20,7 @@
- AGW network protocol now works properly for big-endian processors
such as PowerPC or MIPS.
- The Mac OSX build procedure is now better about locating the SDK.
- The Mac OSX build procedure is now better about locating the SDK.
----------

View File

@ -298,6 +298,12 @@ struct audio_s {
#define DEFAULT_SPACE_FREQ 2200
#define DEFAULT_BAUD 1200
/* Used for sanity checking in config file and command line options. */
/* 9600 is known to work. */
/* TODO: Is 19200 possible with a soundcard at 44100 samples/sec? */
#define MIN_BAUD 100
#define MAX_BAUD 10000
/*

View File

@ -219,7 +219,7 @@ int ax25memdebug_seq (packet_t this_p)
*------------------------------------------------------------------------------*/
static packet_t ax25_new (void)
packet_t ax25_new (void)
{
struct packet_s *this_p;
@ -1630,11 +1630,50 @@ packet_t ax25_get_nextp (packet_t this_p)
{
assert (this_p->magic1 == MAGIC);
assert (this_p->magic2 == MAGIC);
return (this_p->nextp);
}
/*------------------------------------------------------------------------------
*
* Name: ax25_set_release_time
*
* Purpose: Set release time
*
* Inputs: this_p - Current packet object.
*
* release_time - Time as returned by dtime_now().
*
*------------------------------------------------------------------------------*/
void ax25_set_release_time (packet_t this_p, double release_time)
{
assert (this_p->magic1 == MAGIC);
assert (this_p->magic2 == MAGIC);
this_p->release_time = release_time;
}
/*------------------------------------------------------------------------------
*
* Name: ax25_get_release_time
*
* Purpose: Get release time.
*
*------------------------------------------------------------------------------*/
double ax25_get_release_time (packet_t this_p)
{
assert (this_p->magic1 == MAGIC);
assert (this_p->magic2 == MAGIC);
return (this_p->release_time);
}
/*------------------------------------------------------------------
*

View File

@ -73,8 +73,12 @@
struct packet_s {
int magic1; /* for error checking. */
int seq; /* unique sequence number for debugging. */
double release_time; /* Time stamp in format returned by dtime_now(). */
/* When to release from the SATgate mode delay queue. */
#define MAGIC 0x41583235
struct packet_s *nextp; /* Pointer to next in queue. */
@ -145,6 +149,8 @@ typedef struct packet_s *packet_t;
#ifdef AX25_PAD_C /* Keep this hidden - implementation could change. */
extern packet_t ax25_new (void);
/*
* APRS always has one control octet of 0x03 but the more
* general AX.25 case is one or two control bytes depending on
@ -273,8 +279,10 @@ typedef struct alevel_s {
} alevel_t;
#ifndef AXTEST
// TODO: remove this?
#define AX25MEMDEBUG 1
#endif
#if AX25MEMDEBUG // to investigate a memory leak problem
@ -310,6 +318,8 @@ extern void ax25_delete (packet_t pp);
#endif
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);
@ -344,6 +354,9 @@ extern int ax25_get_dti (packet_t this_p);
extern packet_t ax25_get_nextp (packet_t this_p);
extern void ax25_set_release_time (packet_t this_p, double release_time);
extern double ax25_get_release_time (packet_t this_p);
extern void ax25_format_addrs (packet_t pp, char *);
extern int ax25_pack (packet_t pp, unsigned char result[AX25_MAX_PACKET_LEN]);

View File

@ -1121,7 +1121,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
continue;
}
n = atoi(t);
if (n >= 100 && n <= 10000) {
if (n >= MIN_BAUD && n <= MAX_BAUD) {
p_audio_config->achan[channel].baud = n;
if (n != 300 && n != 1200 && n != 9600) {
text_color_set(DW_COLOR_ERROR);
@ -3720,6 +3720,34 @@ void config_init (char *fname, struct audio_s *p_audio_config,
}
}
/*
* SATGATE - Special SATgate mode to delay packets heard directly.
*
* SATGATE [ n ]
*/
else if (strcasecmp(t, "SATGATE") == 0) {
t = split(NULL,0);
if (t != NULL) {
int n = atoi(t);
if (n >= MIN_SATGATE_DELAY && n <= MAX_SATGATE_DELAY) {
p_igate_config->satgate_delay = n;
}
else {
p_igate_config->satgate_delay = DEFAULT_SATGATE_DELAY;
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Unreasonable SATgate delay. Using default.\n", line);
}
}
else {
p_igate_config->satgate_delay = DEFAULT_SATGATE_DELAY;
}
}
/*
* ==================== All the left overs ====================
*/

View File

@ -1,7 +1,7 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2011, 2012, 2013, 2014, 2015 John Langner, WB2OSZ
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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
@ -231,7 +231,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\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "J", __DATE__);
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "K", __DATE__);
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
#if defined(ENABLE_GPSD) || defined(USE_HAMLIB)

Binary file not shown.

214
igate.c
View File

@ -1,7 +1,7 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2013, 2014, 2015 John Langner, WB2OSZ
// Copyright (C) 2013, 2014, 2015, 2016 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
@ -33,6 +33,9 @@
* APRS iGate properties
* http://wiki.ham.fi/APRS_iGate_properties
*
* SATgate mode.
* http://www.tapr.org/pipermail/aprssig/2016-January/045283.html
*
*---------------------------------------------------------------*/
/*------------------------------------------------------------------
@ -97,16 +100,25 @@
#include "igate.h"
#include "latlong.h"
#include "pfilter.h"
#include "dtime_now.h"
#if __WIN32__
static unsigned __stdcall connnect_thread (void *arg);
static unsigned __stdcall igate_recv_thread (void *arg);
static unsigned __stdcall satgate_delay_thread (void *arg);
#else
static void * connnect_thread (void *arg);
static void * igate_recv_thread (void *arg);
static void * satgate_delay_thread (void *arg);
#endif
static dw_mutex_t dp_mutex; /* Critical section for delayed packet queue. */
static packet_t dp_queue_head;
static void satgate_delay_packet (packet_t pp, int chan);
static void send_packet_to_server (packet_t pp, int chan);
static void send_msg_to_server (const char *msg);
static void xmit_packet (char *message, int chan);
@ -380,12 +392,15 @@ void igate_init (struct audio_s *p_audio_config, struct igate_config_s *p_igate_
#if __WIN32__
HANDLE connnect_th;
HANDLE cmd_recv_th;
HANDLE satgate_delay_th;
#else
pthread_t connect_listen_tid;
pthread_t cmd_listen_tid;
pthread_t satgate_delay_tid;
int e;
#endif
s_debug = debug_level;
dp_queue_head = NULL;
#if DEBUGx
text_color_set(DW_COLOR_DEBUG);
@ -467,7 +482,31 @@ void igate_init (struct audio_s *p_audio_config, struct igate_config_s *p_igate_
return;
}
#endif
}
/*
* This lets delayed packets continue after specified amount of time.
*/
if (p_igate_config->satgate_delay > 0) {
#if __WIN32__
satgate_delay_th = (HANDLE)_beginthreadex (NULL, 0, satgate_delay_thread, NULL, 0, NULL);
if (satgate_delay_th == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Internal error: Could not create SATgate delay thread\n");
return;
}
#else
e = pthread_create (&satgate_delay_tid, NULL, satgate_delay_thread, NULL);
if (e != 0) {
text_color_set(DW_COLOR_ERROR);
perror("Internal error: Could not create SATgate delay thread");
return;
}
#endif
dw_mutex_init(&dp_mutex);
}
} /* end igate_init */
/*-------------------------------------------------------------------
@ -816,7 +855,6 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
int n;
unsigned char *pinfo;
char *p;
char msg[IGATE_MAX_MSG];
int info_len;
@ -970,6 +1008,52 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
// TODO: Should we drop raw touch tone data object type generated here?
/*
* If the SATgate mode is enabled, see if it should be delayed.
* The rule is if we hear it directly and it has at least one
* digipeater so there is potential of being re-transmitted.
* (Digis are all unused if we are hearing it directly from source.)
*/
if (save_igate_config_p->satgate_delay > 0 &&
ax25_get_heard(pp) == AX25_SOURCE &&
ax25_get_num_repeaters(pp) > 0) {
satgate_delay_packet (pp, chan);
}
else {
send_packet_to_server (pp, chan);
}
} /* end igate_send_rec_packet */
/*-------------------------------------------------------------------
*
* Name: send_packet_to_server
*
* Purpose: Convert to text and send to the IGate server.
*
* Inputs: pp - Packet object.
*
* chan - Radio channel where it was received.
*
* Description: Duplicate detection is handled here.
* Suppress if same was sent recently.
*
*--------------------------------------------------------------------*/
static void send_packet_to_server (packet_t pp, int chan)
{
unsigned char *pinfo;
int info_len;
char msg[IGATE_MAX_MSG];
info_len = ax25_get_info (pp, &pinfo);
(void)(info_len);
/*
* Do not relay if a duplicate of something sent recently.
*/
@ -1004,9 +1088,7 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
ax25_delete (pp);
} /* end igate_send_rec_packet */
} /* end send_packet_to_server */
@ -1259,6 +1341,126 @@ static void * igate_recv_thread (void *arg)
} /* end igate_recv_thread */
/*-------------------------------------------------------------------
*
* Name: satgate_delay_packet
*
* Purpose: Put packet into holding area for a while rather than
* sending it immediately to the IS server.
*
* Inputs: pp - Packet object.
*
* chan - Radio channel where received.
*
* Outputs: Appended to queue.
*
* Description: If we hear a packet directly and the same one digipeated,
* we only send the first to the APRS IS due to duplicate removal.
* It may be desirable to favor the digipeated packet over the
* original. For this situation, we have an option which delays
* a packet if we hear it directly and the via path is not empty.
* We know we heard it directly if none of the digipeater
* addresses have been used.
* This way the digipeated packet will go first.
* The original is sent about 10 seconds later.
* Duplicate removal will drop the original if there is no
* corresponding digipeated version.
*
*--------------------------------------------------------------------*/
static void satgate_delay_packet (packet_t pp, int chan)
{
packet_t pnext, plast;
//if (s_debug >= 1) {
text_color_set(DW_COLOR_INFO);
dw_printf ("Rx IGate: SATgate mode, delay packet heard directly.\n");
//}
ax25_set_release_time (pp, dtime_now() + save_igate_config_p->satgate_delay);
//TODO: save channel too.
dw_mutex_lock (&dp_mutex);
if (dp_queue_head == NULL) {
dp_queue_head = pp;
}
else {
plast = dp_queue_head;
while ((pnext = ax25_get_nextp(plast)) != NULL) {
plast = pnext;
}
ax25_set_nextp (plast, pp);
}
dw_mutex_unlock (&dp_mutex);
} /* end satgate_delay_packet */
/*-------------------------------------------------------------------
*
* Name: satgate_delay_thread
*
* Purpose: Release packet when specified release time has arrived.
*
* Inputs: dp_queue_head - Queue of packets.
*
* Outputs: Sent to APRS IS.
*
* Description: For simplicity we'll just poll each second.
* Release the packet when its time has arrived.
*
*--------------------------------------------------------------------*/
#if __WIN32__
static unsigned __stdcall satgate_delay_thread (void *arg)
#else
static void * satgate_delay_thread (void *arg)
#endif
{
double release_time;
int chan = 0; // TODO: get receive channel somehow.
// only matters if multi channel with different names.
while (1) {
SLEEP_SEC (1);
/* Don't need critical region just to peek */
if (dp_queue_head != NULL) {
double now = dtime_now();
release_time = ax25_get_release_time (dp_queue_head);
#if 0
text_color_set(DW_COLOR_DEBUG);
dw_printf ("SATgate: %.1f sec remaining\n", release_time - now);
#endif
if (now > release_time) {
packet_t pp;
dw_mutex_lock (&dp_mutex);
pp = dp_queue_head;
dp_queue_head = ax25_get_nextp(pp);
dw_mutex_unlock (&dp_mutex);
ax25_set_nextp (pp, NULL);
send_packet_to_server (pp, chan);
}
} /* if something in queue */
} /* while (1) */
return (0);
} /* end satgate_delay_thread */
/*-------------------------------------------------------------------
*
* Name: xmit_packet

View File

@ -20,6 +20,7 @@
#define DEFAULT_IGATE_PORT 14580
struct igate_config_s {
/*
@ -53,6 +54,10 @@ struct igate_config_s {
int tx_limit_1; /* Max. packets to transmit in 1 minute. */
int tx_limit_5; /* Max. packets to transmit in 5 minutes. */
/*
* Special SATgate mode to delay packets heard directly.
*/
int satgate_delay; /* seconds. 0 to disable. */
};
@ -62,6 +67,10 @@ struct igate_config_s {
#define IGATE_TX_LIMIT_5_DEFAULT 20
#define IGATE_TX_LIMIT_5_MAX 80
#define DEFAULT_SATGATE_DELAY 10
#define MIN_SATGATE_DELAY 5
#define MAX_SATGATE_DELAY 30
/* Call this once at startup */