mirror of https://github.com/wb2osz/direwolf.git
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:
parent
87d9fe00b8
commit
12cb9108d7
12
CHANGES.md
12
CHANGES.md
|
@ -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.
|
||||
|
||||
|
||||
----------
|
||||
|
|
6
audio.h
6
audio.h
|
@ -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
|
||||
|
||||
|
||||
/*
|
||||
|
|
43
ax25_pad.c
43
ax25_pad.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
*
|
||||
|
|
15
ax25_pad.h
15
ax25_pad.h
|
@ -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]);
|
||||
|
|
30
config.c
30
config.c
|
@ -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 ====================
|
||||
*/
|
||||
|
|
|
@ -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
214
igate.c
|
@ -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
|
||||
|
|
9
igate.h
9
igate.h
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue